diff --git a/provider/docker/docker.go b/provider/docker/docker.go index c31ff7a04..b2128bbfc 100644 --- a/provider/docker/docker.go +++ b/provider/docker/docker.go @@ -523,6 +523,11 @@ func (p *Provider) containerFilter(container dockerData) bool { return false } + if len(p.getFrontendRule(container)) == 0 { + log.Debugf("Filtering container with empty frontend rule %s", container.Name) + return false + } + return true } @@ -537,11 +542,10 @@ func (p *Provider) getFrontendRule(container dockerData) string { if label, err := getLabel(container, "traefik.frontend.rule"); err == nil { return label } - if labels, err := getLabels(container, []string{"com.docker.compose.project", "com.docker.compose.service"}); err == nil { - return "Host:" + p.getSubDomain(labels["com.docker.compose.service"]+"."+labels["com.docker.compose.project"]) + "." + p.Domain + if len(p.Domain) > 0 { + return "Host:" + p.getSubDomain(container.ServiceName) + "." + p.Domain } - - return "Host:" + p.getSubDomain(container.ServiceName) + "." + p.Domain + return "" } func (p *Provider) getBackend(container dockerData) string { diff --git a/provider/docker/docker_test.go b/provider/docker/docker_test.go index 30746b73b..5f9fa42f0 100644 --- a/provider/docker/docker_test.go +++ b/provider/docker/docker_test.go @@ -8,6 +8,7 @@ import ( "github.com/containous/traefik/types" docker "github.com/docker/engine-api/types" + "github.com/docker/engine-api/types/container" "github.com/docker/go-connections/nat" ) @@ -488,127 +489,300 @@ func TestDockerGetLabels(t *testing.T) { func TestDockerTraefikFilter(t *testing.T) { containers := []struct { - container docker.ContainerJSON - exposedByDefault bool - expected bool + container docker.ContainerJSON + expected bool + provider *Provider }{ { - container: containerJSON(), - exposedByDefault: true, - expected: false, + container: docker.ContainerJSON{ + ContainerJSONBase: &docker.ContainerJSONBase{ + Name: "container", + }, + Config: &container.Config{}, + NetworkSettings: &docker.NetworkSettings{}, + }, + expected: false, + provider: &Provider{ + Domain: "test", + ExposedByDefault: true, + }, }, { - container: containerJSON( - labels(map[string]string{ - "traefik.enable": "false", - }), - ports(nat.PortMap{ - "80/tcp": {}, - }), - ), - exposedByDefault: true, - expected: false, + container: docker.ContainerJSON{ + ContainerJSONBase: &docker.ContainerJSONBase{ + Name: "container", + }, + Config: &container.Config{ + Labels: map[string]string{ + "traefik.enable": "false", + }, + }, + NetworkSettings: &docker.NetworkSettings{ + NetworkSettingsBase: docker.NetworkSettingsBase{ + Ports: nat.PortMap{ + "80/tcp": {}, + }, + }, + }, + }, + provider: &Provider{ + Domain: "test", + ExposedByDefault: true, + }, + expected: false, }, { - container: containerJSON( - labels(map[string]string{ - "traefik.frontend.rule": "Host:foo.bar", - }), - ports(nat.PortMap{ - "80/tcp": {}, - }), - ), - exposedByDefault: true, - expected: true, + container: docker.ContainerJSON{ + ContainerJSONBase: &docker.ContainerJSONBase{ + Name: "container", + }, + Config: &container.Config{ + Labels: map[string]string{ + "traefik.frontend.rule": "Host:foo.bar", + }, + }, + NetworkSettings: &docker.NetworkSettings{ + NetworkSettingsBase: docker.NetworkSettingsBase{ + Ports: nat.PortMap{ + "80/tcp": {}, + }, + }, + }, + }, + provider: &Provider{ + Domain: "test", + ExposedByDefault: true, + }, + expected: true, }, { - container: containerJSON( - ports(nat.PortMap{ - "80/tcp": {}, - "443/tcp": {}, - }), - ), - exposedByDefault: true, - expected: true, + container: docker.ContainerJSON{ + ContainerJSONBase: &docker.ContainerJSONBase{ + Name: "container-multi-ports", + }, + Config: &container.Config{}, + NetworkSettings: &docker.NetworkSettings{ + NetworkSettingsBase: docker.NetworkSettingsBase{ + Ports: nat.PortMap{ + "80/tcp": {}, + "443/tcp": {}, + }, + }, + }, + }, + provider: &Provider{ + Domain: "test", + ExposedByDefault: true, + }, + expected: true, }, { - container: containerJSON( - ports(nat.PortMap{ - "80/tcp": {}, - }), - ), - exposedByDefault: true, - expected: true, + container: docker.ContainerJSON{ + ContainerJSONBase: &docker.ContainerJSONBase{ + Name: "container", + }, + Config: &container.Config{}, + NetworkSettings: &docker.NetworkSettings{ + NetworkSettingsBase: docker.NetworkSettingsBase{ + Ports: nat.PortMap{ + "80/tcp": {}, + }, + }, + }, + }, + provider: &Provider{ + Domain: "test", + ExposedByDefault: true, + }, + expected: true, }, { - container: containerJSON( - labels(map[string]string{ - "traefik.port": "80", - }), - ports(nat.PortMap{ - "80/tcp": {}, - "443/tcp": {}, - }), - ), - exposedByDefault: true, - expected: true, + container: docker.ContainerJSON{ + ContainerJSONBase: &docker.ContainerJSONBase{ + Name: "container", + }, + Config: &container.Config{ + Labels: map[string]string{ + "traefik.port": "80", + }, + }, + NetworkSettings: &docker.NetworkSettings{ + NetworkSettingsBase: docker.NetworkSettingsBase{ + Ports: nat.PortMap{ + "80/tcp": {}, + "443/tcp": {}, + }, + }, + }, + }, + provider: &Provider{ + Domain: "test", + ExposedByDefault: true, + }, + expected: true, }, { - container: containerJSON( - labels(map[string]string{ - "traefik.enable": "true", - }), - ports(nat.PortMap{ - "80/tcp": {}, - }), - ), - exposedByDefault: true, - expected: true, + container: docker.ContainerJSON{ + ContainerJSONBase: &docker.ContainerJSONBase{ + Name: "container", + }, + Config: &container.Config{ + Labels: map[string]string{ + "traefik.enable": "true", + }, + }, + NetworkSettings: &docker.NetworkSettings{ + NetworkSettingsBase: docker.NetworkSettingsBase{ + Ports: nat.PortMap{ + "80/tcp": {}, + }, + }, + }, + }, + provider: &Provider{ + Domain: "test", + ExposedByDefault: true, + }, + expected: true, }, { - container: containerJSON( - labels(map[string]string{ - "traefik.enable": "anything", - }), - ports(nat.PortMap{ - "80/tcp": {}, - }), - ), - exposedByDefault: true, - expected: true, + container: docker.ContainerJSON{ + ContainerJSONBase: &docker.ContainerJSONBase{ + Name: "container", + }, + Config: &container.Config{ + Labels: map[string]string{ + "traefik.enable": "anything", + }, + }, + NetworkSettings: &docker.NetworkSettings{ + NetworkSettingsBase: docker.NetworkSettingsBase{ + Ports: nat.PortMap{ + "80/tcp": {}, + }, + }, + }, + }, + provider: &Provider{ + Domain: "test", + ExposedByDefault: true, + }, + expected: true, }, { - container: containerJSON( - labels(map[string]string{ - "traefik.frontend.rule": "Host:foo.bar", - }), - ports(nat.PortMap{ - "80/tcp": {}, - }), - ), - exposedByDefault: true, - expected: true, + container: docker.ContainerJSON{ + ContainerJSONBase: &docker.ContainerJSONBase{ + Name: "container", + }, + Config: &container.Config{ + Labels: map[string]string{ + "traefik.frontend.rule": "Host:foo.bar", + }, + }, + NetworkSettings: &docker.NetworkSettings{ + NetworkSettingsBase: docker.NetworkSettingsBase{ + Ports: nat.PortMap{ + "80/tcp": {}, + }, + }, + }, + }, + provider: &Provider{ + Domain: "test", + ExposedByDefault: true, + }, + expected: true, }, { - container: containerJSON( - ports(nat.PortMap{ - "80/tcp": {}, - }), - ), - exposedByDefault: false, - expected: false, + container: docker.ContainerJSON{ + ContainerJSONBase: &docker.ContainerJSONBase{ + Name: "container", + }, + Config: &container.Config{}, + NetworkSettings: &docker.NetworkSettings{ + NetworkSettingsBase: docker.NetworkSettingsBase{ + Ports: nat.PortMap{ + "80/tcp": {}, + }, + }, + }, + }, + provider: &Provider{ + Domain: "test", + ExposedByDefault: false, + }, + expected: false, }, { - container: containerJSON( - labels(map[string]string{ - "traefik.enable": "true", - }), - ports(nat.PortMap{ - "80/tcp": {}, - }), - ), - exposedByDefault: false, - expected: true, + container: docker.ContainerJSON{ + ContainerJSONBase: &docker.ContainerJSONBase{ + Name: "container", + }, + Config: &container.Config{ + Labels: map[string]string{ + "traefik.enable": "true", + }, + }, + NetworkSettings: &docker.NetworkSettings{ + NetworkSettingsBase: docker.NetworkSettingsBase{ + Ports: nat.PortMap{ + "80/tcp": {}, + }, + }, + }, + }, + provider: &Provider{ + Domain: "test", + ExposedByDefault: false, + }, + expected: true, + }, + { + container: docker.ContainerJSON{ + ContainerJSONBase: &docker.ContainerJSONBase{ + Name: "container", + }, + Config: &container.Config{ + Labels: map[string]string{ + "traefik.enable": "true", + }, + }, + NetworkSettings: &docker.NetworkSettings{ + NetworkSettingsBase: docker.NetworkSettingsBase{ + Ports: nat.PortMap{ + "80/tcp": {}, + }, + }, + }, + }, + provider: &Provider{ + ExposedByDefault: false, + }, + expected: false, + }, + { + container: docker.ContainerJSON{ + ContainerJSONBase: &docker.ContainerJSONBase{ + Name: "container", + }, + Config: &container.Config{ + Labels: map[string]string{ + "traefik.enable": "true", + "traefik.frontend.rule": "Host:i.love.this.host", + }, + }, + NetworkSettings: &docker.NetworkSettings{ + NetworkSettingsBase: docker.NetworkSettingsBase{ + Ports: nat.PortMap{ + "80/tcp": {}, + }, + }, + }, + }, + provider: &Provider{ + ExposedByDefault: false, + }, + expected: true, }, } @@ -616,12 +790,10 @@ func TestDockerTraefikFilter(t *testing.T) { e := e t.Run(strconv.Itoa(containerID), func(t *testing.T) { t.Parallel() - provider := Provider{} - provider.ExposedByDefault = e.exposedByDefault dockerData := parseContainer(e.container) - actual := provider.containerFilter(dockerData) + actual := e.provider.containerFilter(dockerData) if actual != e.expected { - t.Errorf("expected %v for %+v (%+v, %+v), got %+v", e.expected, e.container, e.container.NetworkSettings, e.container.ContainerJSONBase, actual) + t.Errorf("expected %v for %+v, got %+v", e.expected, e, actual) } }) } diff --git a/provider/docker/swarm_test.go b/provider/docker/swarm_test.go index 56cfb8acf..b757118ba 100644 --- a/provider/docker/swarm_test.go +++ b/provider/docker/swarm_test.go @@ -503,86 +503,122 @@ func TestSwarmGetLabels(t *testing.T) { func TestSwarmTraefikFilter(t *testing.T) { services := []struct { - service swarm.Service - exposedByDefault bool - expected bool - networks map[string]*docker.NetworkResource + service swarm.Service + expected bool + networks map[string]*docker.NetworkResource + provider *Provider }{ { - service: swarmService(), - exposedByDefault: true, - expected: false, - networks: map[string]*docker.NetworkResource{}, + service: swarmService(), + expected: false, + networks: map[string]*docker.NetworkResource{}, + provider: &Provider{ + SwarmMode: true, + Domain: "test", + ExposedByDefault: true, + }, }, { service: swarmService(serviceLabels(map[string]string{ "traefik.enable": "false", "traefik.port": "80", })), - exposedByDefault: true, - expected: false, - networks: map[string]*docker.NetworkResource{}, + expected: false, + networks: map[string]*docker.NetworkResource{}, + provider: &Provider{ + SwarmMode: true, + Domain: "test", + ExposedByDefault: true, + }, }, { service: swarmService(serviceLabels(map[string]string{ "traefik.frontend.rule": "Host:foo.bar", "traefik.port": "80", })), - exposedByDefault: true, - expected: true, - networks: map[string]*docker.NetworkResource{}, + expected: true, + networks: map[string]*docker.NetworkResource{}, + provider: &Provider{ + SwarmMode: true, + Domain: "test", + ExposedByDefault: true, + }, }, { service: swarmService(serviceLabels(map[string]string{ "traefik.port": "80", })), - exposedByDefault: true, - expected: true, - networks: map[string]*docker.NetworkResource{}, + expected: true, + networks: map[string]*docker.NetworkResource{}, + provider: &Provider{ + SwarmMode: true, + Domain: "test", + ExposedByDefault: true, + }, }, { service: swarmService(serviceLabels(map[string]string{ "traefik.enable": "true", "traefik.port": "80", })), - exposedByDefault: true, - expected: true, - networks: map[string]*docker.NetworkResource{}, + expected: true, + networks: map[string]*docker.NetworkResource{}, + provider: &Provider{ + SwarmMode: true, + Domain: "test", + ExposedByDefault: true, + }, }, { service: swarmService(serviceLabels(map[string]string{ "traefik.enable": "anything", "traefik.port": "80", })), - exposedByDefault: true, - expected: true, - networks: map[string]*docker.NetworkResource{}, + expected: true, + networks: map[string]*docker.NetworkResource{}, + provider: &Provider{ + SwarmMode: true, + Domain: "test", + ExposedByDefault: true, + }, }, { service: swarmService(serviceLabels(map[string]string{ "traefik.frontend.rule": "Host:foo.bar", "traefik.port": "80", })), - exposedByDefault: true, - expected: true, - networks: map[string]*docker.NetworkResource{}, + expected: true, + networks: map[string]*docker.NetworkResource{}, + provider: &Provider{ + SwarmMode: true, + Domain: "test", + ExposedByDefault: true, + }, }, { service: swarmService(serviceLabels(map[string]string{ "traefik.port": "80", })), - exposedByDefault: false, - expected: false, - networks: map[string]*docker.NetworkResource{}, + expected: false, + networks: map[string]*docker.NetworkResource{}, + provider: &Provider{ + SwarmMode: true, + Domain: "test", + ExposedByDefault: false, + }, }, { service: swarmService(serviceLabels(map[string]string{ "traefik.enable": "true", "traefik.port": "80", })), - exposedByDefault: false, - expected: true, - networks: map[string]*docker.NetworkResource{}, + expected: true, + networks: map[string]*docker.NetworkResource{}, + provider: &Provider{ + SwarmMode: true, + Domain: "test", + ExposedByDefault: false, + }, }, } @@ -591,11 +627,7 @@ func TestSwarmTraefikFilter(t *testing.T) { t.Run(strconv.Itoa(serviceID), func(t *testing.T) { t.Parallel() dockerData := parseService(e.service, e.networks) - provider := &Provider{ - SwarmMode: true, - } - provider.ExposedByDefault = e.exposedByDefault - actual := provider.containerFilter(dockerData) + actual := e.provider.containerFilter(dockerData) if actual != e.expected { t.Errorf("expected %v for %+v, got %+v", e.expected, e, actual) }