package docker import ( "reflect" "strconv" "testing" "github.com/containous/traefik/types" docker "github.com/docker/docker/api/types" "github.com/docker/go-connections/nat" ) func TestDockerGetServiceProtocol(t *testing.T) { provider := &Provider{} containers := []struct { container docker.ContainerJSON expected string }{ { container: containerJSON(), expected: "http", }, { container: containerJSON(labels(map[string]string{ types.LabelProtocol: "https", })), expected: "https", }, { container: containerJSON(labels(map[string]string{ "traefik.myservice.protocol": "https", })), expected: "https", }, } for containerID, e := range containers { e := e t.Run(strconv.Itoa(containerID), func(t *testing.T) { t.Parallel() dockerData := parseContainer(e.container) actual := provider.getServiceProtocol(dockerData, "myservice") if actual != e.expected { t.Fatalf("expected %q, got %q", e.expected, actual) } }) } } func TestDockerGetServiceWeight(t *testing.T) { provider := &Provider{} containers := []struct { container docker.ContainerJSON expected string }{ { container: containerJSON(), expected: "0", }, { container: containerJSON(labels(map[string]string{ types.LabelWeight: "200", })), expected: "200", }, { container: containerJSON(labels(map[string]string{ "traefik.myservice.weight": "31337", })), expected: "31337", }, } for containerID, e := range containers { e := e t.Run(strconv.Itoa(containerID), func(t *testing.T) { t.Parallel() dockerData := parseContainer(e.container) actual := provider.getServiceWeight(dockerData, "myservice") if actual != e.expected { t.Fatalf("expected %q, got %q", e.expected, actual) } }) } } func TestDockerGetServicePort(t *testing.T) { provider := &Provider{} containers := []struct { container docker.ContainerJSON expected string }{ { container: containerJSON(), expected: "", }, { container: containerJSON(labels(map[string]string{ types.LabelPort: "2500", })), expected: "2500", }, { container: containerJSON(labels(map[string]string{ "traefik.myservice.port": "1234", })), expected: "1234", }, } for containerID, e := range containers { e := e t.Run(strconv.Itoa(containerID), func(t *testing.T) { t.Parallel() dockerData := parseContainer(e.container) actual := provider.getServicePort(dockerData, "myservice") if actual != e.expected { t.Fatalf("expected %q, got %q", e.expected, actual) } }) } } func TestDockerGetServiceFrontendRule(t *testing.T) { provider := &Provider{} containers := []struct { container docker.ContainerJSON expected string }{ { container: containerJSON(name("foo")), expected: "", }, { container: containerJSON(labels(map[string]string{ types.LabelFrontendRule: "Path:/helloworld", })), expected: "Path:/helloworld", }, { container: containerJSON(labels(map[string]string{ "traefik.myservice.frontend.rule": "Path:/mycustomservicepath", })), expected: "Path:/mycustomservicepath", }, } for containerID, e := range containers { e := e t.Run(strconv.Itoa(containerID), func(t *testing.T) { t.Parallel() dockerData := parseContainer(e.container) actual := provider.getServiceFrontendRule(dockerData, "myservice") if actual != e.expected { t.Fatalf("expected %q, got %q", e.expected, actual) } }) } } func TestDockerGetServiceBackend(t *testing.T) { provider := &Provider{} containers := []struct { container docker.ContainerJSON expected string }{ { container: containerJSON(name("foo")), expected: "foo-foo-myservice", }, { container: containerJSON(labels(map[string]string{ types.LabelBackend: "another-backend", })), expected: "fake-another-backend-myservice", }, { container: containerJSON(labels(map[string]string{ "traefik.myservice.frontend.backend": "custom-backend", })), expected: "fake-custom-backend", }, } for containerID, e := range containers { e := e t.Run(strconv.Itoa(containerID), func(t *testing.T) { t.Parallel() dockerData := parseContainer(e.container) actual := provider.getServiceBackend(dockerData, "myservice") if actual != e.expected { t.Fatalf("expected %q, got %q", e.expected, actual) } }) } } func TestDockerGetServicePriority(t *testing.T) { provider := &Provider{} containers := []struct { container docker.ContainerJSON expected string }{ { container: containerJSON(), expected: "0", }, { container: containerJSON(labels(map[string]string{ types.LabelFrontendPriority: "33", })), expected: "33", }, { container: containerJSON(labels(map[string]string{ "traefik.myservice.frontend.priority": "2503", })), expected: "2503", }, } for containerID, e := range containers { e := e t.Run(strconv.Itoa(containerID), func(t *testing.T) { t.Parallel() dockerData := parseContainer(e.container) actual := provider.getServicePriority(dockerData, "myservice") if actual != e.expected { t.Fatalf("expected %q, got %q", e.expected, actual) } }) } } func TestDockerGetServicePassHostHeader(t *testing.T) { provider := &Provider{} containers := []struct { container docker.ContainerJSON expected string }{ { container: containerJSON(), expected: "true", }, { container: containerJSON(labels(map[string]string{ types.LabelFrontendPassHostHeader: "false", })), expected: "false", }, { container: containerJSON(labels(map[string]string{ "traefik.myservice.frontend.passHostHeader": "false", })), expected: "false", }, } for containerID, e := range containers { e := e t.Run(strconv.Itoa(containerID), func(t *testing.T) { t.Parallel() dockerData := parseContainer(e.container) actual := provider.getServicePassHostHeader(dockerData, "myservice") if actual != e.expected { t.Fatalf("expected %q, got %q", e.expected, actual) } }) } } func TestDockerGetServiceEntryPoints(t *testing.T) { provider := &Provider{} containers := []struct { container docker.ContainerJSON expected []string }{ { container: containerJSON(), expected: []string{}, }, { container: containerJSON(labels(map[string]string{ types.LabelFrontendEntryPoints: "http,https", })), expected: []string{"http", "https"}, }, { container: containerJSON(labels(map[string]string{ "traefik.myservice.frontend.entryPoints": "http,https", })), expected: []string{"http", "https"}, }, } for containerID, e := range containers { e := e t.Run(strconv.Itoa(containerID), func(t *testing.T) { t.Parallel() dockerData := parseContainer(e.container) actual := provider.getServiceEntryPoints(dockerData, "myservice") if !reflect.DeepEqual(actual, e.expected) { t.Fatalf("expected %q, got %q for container %q", e.expected, actual, dockerData.Name) } }) } } func TestDockerLoadDockerServiceConfig(t *testing.T) { cases := []struct { containers []docker.ContainerJSON expectedFrontends map[string]*types.Frontend expectedBackends map[string]*types.Backend }{ { containers: []docker.ContainerJSON{}, expectedFrontends: map[string]*types.Frontend{}, expectedBackends: map[string]*types.Backend{}, }, { containers: []docker.ContainerJSON{ containerJSON( name("foo"), labels(map[string]string{ "traefik.service.port": "2503", "traefik.service.frontend.entryPoints": "http,https", "traefik.service.frontend.auth.basic": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", "traefik.service.frontend.redirect": "https", }), ports(nat.PortMap{ "80/tcp": {}, }), withNetwork("bridge", ipv4("127.0.0.1")), ), }, expectedFrontends: map[string]*types.Frontend{ "frontend-foo-foo-service": { Backend: "backend-foo-foo-service", PassHostHeader: true, EntryPoints: []string{"http", "https"}, BasicAuth: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, Redirect: "https", Routes: map[string]types.Route{ "service-service": { Rule: "Host:foo.docker.localhost", }, }, }, }, expectedBackends: map[string]*types.Backend{ "backend-foo-foo-service": { Servers: map[string]types.Server{ "service-0": { URL: "http://127.0.0.1:2503", Weight: 0, }, }, CircuitBreaker: nil, }, }, }, { containers: []docker.ContainerJSON{ containerJSON( name("test1"), labels(map[string]string{ "traefik.service.port": "2503", "traefik.service.protocol": "https", "traefik.service.weight": "80", "traefik.service.frontend.backend": "foobar", "traefik.service.frontend.passHostHeader": "false", "traefik.service.frontend.rule": "Path:/mypath", "traefik.service.frontend.priority": "5000", "traefik.service.frontend.entryPoints": "http,https,ws", "traefik.service.frontend.auth.basic": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0", "traefik.service.frontend.redirect": "https", }), ports(nat.PortMap{ "80/tcp": {}, }), withNetwork("bridge", ipv4("127.0.0.1")), ), containerJSON( name("test2"), labels(map[string]string{ "traefik.anotherservice.port": "8079", "traefik.anotherservice.weight": "33", "traefik.anotherservice.frontend.rule": "Path:/anotherpath", }), ports(nat.PortMap{ "80/tcp": {}, }), withNetwork("bridge", ipv4("127.0.0.1")), ), }, expectedFrontends: map[string]*types.Frontend{ "frontend-test1-foobar": { Backend: "backend-test1-foobar", PassHostHeader: false, Priority: 5000, EntryPoints: []string{"http", "https", "ws"}, BasicAuth: []string{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"}, Redirect: "https", Routes: map[string]types.Route{ "service-service": { Rule: "Path:/mypath", }, }, }, "frontend-test2-test2-anotherservice": { Backend: "backend-test2-test2-anotherservice", PassHostHeader: true, EntryPoints: []string{}, BasicAuth: []string{}, Redirect: "", Routes: map[string]types.Route{ "service-anotherservice": { Rule: "Path:/anotherpath", }, }, }, }, expectedBackends: map[string]*types.Backend{ "backend-test1-foobar": { Servers: map[string]types.Server{ "service-0": { URL: "https://127.0.0.1:2503", Weight: 80, }, }, CircuitBreaker: nil, }, "backend-test2-test2-anotherservice": { Servers: map[string]types.Server{ "service-0": { URL: "http://127.0.0.1:8079", Weight: 33, }, }, CircuitBreaker: nil, }, }, }, } provider := &Provider{ Domain: "docker.localhost", ExposedByDefault: true, } for caseID, c := range cases { c := c t.Run(strconv.Itoa(caseID), func(t *testing.T) { t.Parallel() var dockerDataList []dockerData for _, container := range c.containers { dockerData := parseContainer(container) dockerDataList = append(dockerDataList, dockerData) } actualConfig := provider.loadDockerConfig(dockerDataList) // Compare backends if !reflect.DeepEqual(actualConfig.Backends, c.expectedBackends) { t.Fatalf("expected %#v, got %#v", c.expectedBackends, actualConfig.Backends) } if !reflect.DeepEqual(actualConfig.Frontends, c.expectedFrontends) { t.Fatalf("expected %#v, got %#v", c.expectedFrontends, actualConfig.Frontends) } }) } }