From 3f293ee25b7fdb5b3290e2918ca8216bb1898fe8 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Sat, 15 Apr 2017 15:49:53 +0200 Subject: [PATCH] =?UTF-8?q?Move=20docker=20provider=20to=20its=20own=20pac?= =?UTF-8?q?kage=20=F0=9F=91=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Makes it simpler to manage :) Signed-off-by: Vincent Demeester --- configuration.go | 5 +- provider/consul_catalog.go | 4 +- provider/{ => docker}/docker.go | 251 ++++++++++++++------------- provider/{ => docker}/docker_test.go | 0 provider/docker/docker_unix.go | 8 + provider/docker/docker_windows.go | 6 + provider/docker_unix.go | 8 - provider/docker_windows.go | 6 - provider/ecs.go | 2 +- provider/eureka.go | 2 +- provider/kubernetes.go | 2 +- provider/kv.go | 2 +- provider/marathon.go | 2 +- provider/mesos.go | 2 +- provider/provider.go | 6 +- provider/provider_test.go | 10 +- provider/rancher.go | 8 +- 17 files changed, 163 insertions(+), 161 deletions(-) rename provider/{ => docker}/docker.go (73%) rename provider/{ => docker}/docker_test.go (100%) create mode 100644 provider/docker/docker_unix.go create mode 100644 provider/docker/docker_windows.go delete mode 100644 provider/docker_unix.go delete mode 100644 provider/docker_windows.go diff --git a/configuration.go b/configuration.go index dca77f806..27381a01e 100644 --- a/configuration.go +++ b/configuration.go @@ -12,6 +12,7 @@ import ( "github.com/containous/flaeg" "github.com/containous/traefik/acme" "github.com/containous/traefik/provider" + "github.com/containous/traefik/provider/docker" "github.com/containous/traefik/types" ) @@ -40,7 +41,7 @@ type GlobalConfiguration struct { IdleTimeout flaeg.Duration `description:"maximum amount of time an idle (keep-alive) connection will remain idle before closing itself."` InsecureSkipVerify bool `description:"Disable SSL certificate verification"` Retry *Retry `description:"Enable retry sending request if network error"` - Docker *provider.Docker `description:"Enable Docker backend"` + Docker *docker.Provider `description:"Enable Docker backend"` File *provider.File `description:"Enable File backend"` Web *WebProvider `description:"Enable Web backend"` Marathon *provider.Marathon `description:"Enable Marathon backend"` @@ -328,7 +329,7 @@ type Retry struct { // NewTraefikDefaultPointersConfiguration creates a TraefikConfiguration with pointers default values func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration { //default Docker - var defaultDocker provider.Docker + var defaultDocker docker.Provider defaultDocker.Watch = true defaultDocker.ExposedByDefault = true defaultDocker.Endpoint = "unix:///var/run/docker.sock" diff --git a/provider/consul_catalog.go b/provider/consul_catalog.go index 981ecda74..77d8e6667 100644 --- a/provider/consul_catalog.go +++ b/provider/consul_catalog.go @@ -176,7 +176,7 @@ func (provider *ConsulCatalog) getBackendName(node *api.ServiceEntry, index int) serviceName := strings.ToLower(node.Service.Service) + "--" + node.Service.Address + "--" + strconv.Itoa(node.Service.Port) for _, tag := range node.Service.Tags { - serviceName += "--" + normalize(tag) + serviceName += "--" + Normalize(tag) } serviceName = strings.Replace(serviceName, ".", "-", -1) @@ -246,7 +246,7 @@ func (provider *ConsulCatalog) buildConfig(catalog []catalogUpdate) *types.Confi Nodes: allNodes, } - configuration, err := provider.getConfiguration("templates/consul_catalog.tmpl", FuncMap, templateObjects) + configuration, err := provider.GetConfiguration("templates/consul_catalog.tmpl", FuncMap, templateObjects) if err != nil { log.WithError(err).Error("Failed to create config") } diff --git a/provider/docker.go b/provider/docker/docker.go similarity index 73% rename from provider/docker.go rename to provider/docker/docker.go index 408e21b0a..5c8d49c94 100644 --- a/provider/docker.go +++ b/provider/docker/docker.go @@ -1,4 +1,4 @@ -package provider +package docker import ( "context" @@ -6,6 +6,7 @@ import ( "math" "net" "net/http" + "regexp" "strconv" "strings" "text/template" @@ -15,6 +16,7 @@ import ( "github.com/cenk/backoff" "github.com/containous/traefik/job" "github.com/containous/traefik/log" + "github.com/containous/traefik/provider" "github.com/containous/traefik/safe" "github.com/containous/traefik/types" "github.com/containous/traefik/version" @@ -28,30 +30,29 @@ import ( "github.com/docker/go-connections/nat" "github.com/docker/go-connections/sockets" "github.com/vdemeester/docker-events" - "regexp" ) const ( - // SwarmAPIVersion is a constant holding the version of the Docker API traefik will use + // SwarmAPIVersion is a constant holding the version of the Provider API traefik will use SwarmAPIVersion string = "1.24" // SwarmDefaultWatchTime is the duration of the interval when polling docker SwarmDefaultWatchTime = 15 * time.Second ) -var _ Provider = (*Docker)(nil) +var _ provider.Provider = (*Provider)(nil) -// Docker holds configurations of the Docker provider. -type Docker struct { - BaseProvider `mapstructure:",squash"` - Endpoint string `description:"Docker server endpoint. Can be a tcp or a unix socket endpoint"` - Domain string `description:"Default domain used"` - TLS *ClientTLS `description:"Enable Docker TLS support"` - ExposedByDefault bool `description:"Expose containers by default"` - UseBindPortIP bool `description:"Use the ip address from the bound port, rather than from the inner network"` - SwarmMode bool `description:"Use Docker on Swarm Mode"` +// Provider holds configurations of the Provider p. +type Provider struct { + provider.BaseProvider `mapstructure:",squash"` + Endpoint string `description:"Provider server endpoint. Can be a tcp or a unix socket endpoint"` + Domain string `description:"Default domain used"` + TLS *provider.ClientTLS `description:"Enable Provider TLS support"` + ExposedByDefault bool `description:"Expose containers by default"` + UseBindPortIP bool `description:"Use the ip address from the bound port, rather than from the inner network"` + SwarmMode bool `description:"Use Provider on Swarm Mode"` } -// dockerData holds the need data to the Docker provider +// dockerData holds the need data to the Provider p type dockerData struct { ServiceName string Name string @@ -60,14 +61,14 @@ type dockerData struct { Health string } -// NetworkSettings holds the networks data to the Docker provider +// NetworkSettings holds the networks data to the Provider p type networkSettings struct { NetworkMode dockercontainertypes.NetworkMode Ports nat.PortMap Networks map[string]*networkData } -// Network holds the network data to the Docker provider +// Network holds the network data to the Provider p type networkData struct { Name string Addr string @@ -76,20 +77,20 @@ type networkData struct { ID string } -func (provider *Docker) createClient() (client.APIClient, error) { +func (p *Provider) createClient() (client.APIClient, error) { var httpClient *http.Client httpHeaders := map[string]string{ "User-Agent": "Traefik " + version.Version, } - if provider.TLS != nil { - config, err := provider.TLS.CreateTLSConfig() + if p.TLS != nil { + config, err := p.TLS.CreateTLSConfig() if err != nil { return nil, err } tr := &http.Transport{ TLSClientConfig: config, } - proto, addr, _, err := client.ParseHost(provider.Endpoint) + proto, addr, _, err := client.ParseHost(p.Endpoint) if err != nil { return nil, err } @@ -102,25 +103,25 @@ func (provider *Docker) createClient() (client.APIClient, error) { } var version string - if provider.SwarmMode { + if p.SwarmMode { version = SwarmAPIVersion } else { version = DockerAPIVersion } - return client.NewClient(provider.Endpoint, version, httpClient, httpHeaders) + return client.NewClient(p.Endpoint, version, httpClient, httpHeaders) } -// Provide allows the provider to provide configurations to traefik +// Provide allows the p to provide configurations to traefik // using the given configuration channel. -func (provider *Docker) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { - provider.Constraints = append(provider.Constraints, constraints...) +func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error { + p.Constraints = append(p.Constraints, constraints...) // TODO register this routine in pool, and watch for stop channel safe.Go(func() { operation := func() error { var err error - dockerClient, err := provider.createClient() + dockerClient, err := p.createClient() if err != nil { log.Errorf("Failed to create a client for docker, error: %s", err) return err @@ -128,10 +129,10 @@ func (provider *Docker) Provide(configurationChan chan<- types.ConfigMessage, po ctx := context.Background() version, err := dockerClient.ServerVersion(ctx) - log.Debugf("Docker connection established with docker %s (API %s)", version.Version, version.APIVersion) + log.Debugf("Provider connection established with docker %s (API %s)", version.Version, version.APIVersion) var dockerDataList []dockerData - if provider.SwarmMode { - dockerDataList, err = provider.listServices(ctx, dockerClient) + if p.SwarmMode { + dockerDataList, err = p.listServices(ctx, dockerClient) if err != nil { log.Errorf("Failed to list services for docker swarm mode, error %s", err) return err @@ -144,26 +145,26 @@ func (provider *Docker) Provide(configurationChan chan<- types.ConfigMessage, po } } - configuration := provider.loadDockerConfig(dockerDataList) + configuration := p.loadDockerConfig(dockerDataList) configurationChan <- types.ConfigMessage{ ProviderName: "docker", Configuration: configuration, } - if provider.Watch { + if p.Watch { ctx, cancel := context.WithCancel(ctx) - if provider.SwarmMode { + if p.SwarmMode { // TODO: This need to be change. Linked to Swarm events docker/docker#23827 ticker := time.NewTicker(SwarmDefaultWatchTime) pool.Go(func(stop chan bool) { for { select { case <-ticker.C: - services, err := provider.listServices(ctx, dockerClient) + services, err := p.listServices(ctx, dockerClient) if err != nil { log.Errorf("Failed to list services for docker, error %s", err) return } - configuration := provider.loadDockerConfig(services) + configuration := p.loadDockerConfig(services) if configuration != nil { configurationChan <- types.ConfigMessage{ ProviderName: "docker", @@ -196,7 +197,7 @@ func (provider *Docker) Provide(configurationChan chan<- types.ConfigMessage, po } eventHandler := events.NewHandler(events.ByAction) startStopHandle := func(m eventtypes.Message) { - log.Debugf("Docker event received %+v", m) + log.Debugf("Provider event received %+v", m) containers, err := listContainers(ctx, dockerClient) if err != nil { log.Errorf("Failed to list containers for docker, error %s", err) @@ -204,7 +205,7 @@ func (provider *Docker) Provide(configurationChan chan<- types.ConfigMessage, po cancel() return } - configuration := provider.loadDockerConfig(containers) + configuration := p.loadDockerConfig(containers) if configuration != nil { configurationChan <- types.ConfigMessage{ ProviderName: "docker", @@ -227,7 +228,7 @@ func (provider *Docker) Provide(configurationChan chan<- types.ConfigMessage, po return nil } notify := func(err error, time time.Duration) { - log.Errorf("Docker connection error %+v, retrying in %s", err, time) + log.Errorf("Provider connection error %+v, retrying in %s", err, time) } err := backoff.RetryNotify(safe.OperationWithRecover(operation), job.NewBackOff(backoff.NewExponentialBackOff()), notify) if err != nil { @@ -238,50 +239,50 @@ func (provider *Docker) Provide(configurationChan chan<- types.ConfigMessage, po return nil } -func (provider *Docker) loadDockerConfig(containersInspected []dockerData) *types.Configuration { +func (p *Provider) loadDockerConfig(containersInspected []dockerData) *types.Configuration { var DockerFuncMap = template.FuncMap{ - "getBackend": provider.getBackend, - "getIPAddress": provider.getIPAddress, - "getPort": provider.getPort, - "getWeight": provider.getWeight, - "getDomain": provider.getDomain, - "getProtocol": provider.getProtocol, - "getPassHostHeader": provider.getPassHostHeader, - "getPriority": provider.getPriority, - "getEntryPoints": provider.getEntryPoints, - "getFrontendRule": provider.getFrontendRule, - "hasCircuitBreakerLabel": provider.hasCircuitBreakerLabel, - "getCircuitBreakerExpression": provider.getCircuitBreakerExpression, - "hasLoadBalancerLabel": provider.hasLoadBalancerLabel, - "getLoadBalancerMethod": provider.getLoadBalancerMethod, - "hasMaxConnLabels": provider.hasMaxConnLabels, - "getMaxConnAmount": provider.getMaxConnAmount, - "getMaxConnExtractorFunc": provider.getMaxConnExtractorFunc, - "getSticky": provider.getSticky, - "getIsBackendLBSwarm": provider.getIsBackendLBSwarm, - "hasServices": provider.hasServices, - "getServiceNames": provider.getServiceNames, - "getServicePort": provider.getServicePort, - "getServiceWeight": provider.getServiceWeight, - "getServiceProtocol": provider.getServiceProtocol, - "getServiceEntryPoints": provider.getServiceEntryPoints, - "getServiceFrontendRule": provider.getServiceFrontendRule, - "getServicePassHostHeader": provider.getServicePassHostHeader, - "getServicePriority": provider.getServicePriority, - "getServiceBackend": provider.getServiceBackend, + "getBackend": p.getBackend, + "getIPAddress": p.getIPAddress, + "getPort": p.getPort, + "getWeight": p.getWeight, + "getDomain": p.getDomain, + "getProtocol": p.getProtocol, + "getPassHostHeader": p.getPassHostHeader, + "getPriority": p.getPriority, + "getEntryPoints": p.getEntryPoints, + "getFrontendRule": p.getFrontendRule, + "hasCircuitBreakerLabel": p.hasCircuitBreakerLabel, + "getCircuitBreakerExpression": p.getCircuitBreakerExpression, + "hasLoadBalancerLabel": p.hasLoadBalancerLabel, + "getLoadBalancerMethod": p.getLoadBalancerMethod, + "hasMaxConnLabels": p.hasMaxConnLabels, + "getMaxConnAmount": p.getMaxConnAmount, + "getMaxConnExtractorFunc": p.getMaxConnExtractorFunc, + "getSticky": p.getSticky, + "getIsBackendLBSwarm": p.getIsBackendLBSwarm, + "hasServices": p.hasServices, + "getServiceNames": p.getServiceNames, + "getServicePort": p.getServicePort, + "getServiceWeight": p.getServiceWeight, + "getServiceProtocol": p.getServiceProtocol, + "getServiceEntryPoints": p.getServiceEntryPoints, + "getServiceFrontendRule": p.getServiceFrontendRule, + "getServicePassHostHeader": p.getServicePassHostHeader, + "getServicePriority": p.getServicePriority, + "getServiceBackend": p.getServiceBackend, } // filter containers filteredContainers := fun.Filter(func(container dockerData) bool { - return provider.containerFilter(container) + return p.containerFilter(container) }, containersInspected).([]dockerData) frontends := map[string][]dockerData{} backends := map[string]dockerData{} servers := map[string][]dockerData{} for _, container := range filteredContainers { - frontendName := provider.getFrontendName(container) + frontendName := p.getFrontendName(container) frontends[frontendName] = append(frontends[frontendName], container) - backendName := provider.getBackend(container) + backendName := p.getBackend(container) backends[backendName] = container servers[backendName] = append(servers[backendName], container) } @@ -297,17 +298,17 @@ func (provider *Docker) loadDockerConfig(containersInspected []dockerData) *type frontends, backends, servers, - provider.Domain, + p.Domain, } - configuration, err := provider.getConfiguration("templates/docker.tmpl", DockerFuncMap, templateObjects) + configuration, err := p.GetConfiguration("templates/docker.tmpl", DockerFuncMap, templateObjects) if err != nil { log.Error(err) } return configuration } -func (provider *Docker) hasCircuitBreakerLabel(container dockerData) bool { +func (p *Provider) hasCircuitBreakerLabel(container dockerData) bool { if _, err := getLabel(container, "traefik.backend.circuitbreaker.expression"); err != nil { return false } @@ -323,7 +324,7 @@ var servicesPropertiesRegexp = regexp.MustCompile(`^traefik\.(?P.* type labelServiceProperties map[string]map[string]string // Check if for the given container, we find labels that are defining services -func (provider *Docker) hasServices(container dockerData) bool { +func (p *Provider) hasServices(container dockerData) bool { return len(extractServicesLabels(container.Labels)) > 0 } @@ -358,7 +359,7 @@ func getContainerServiceLabel(container dockerData, serviceName string, entry st } // Gets array of service names for a given container -func (provider *Docker) getServiceNames(container dockerData) []string { +func (p *Provider) getServiceNames(container dockerData) []string { labelServiceProperties := extractServicesLabels(container.Labels) keys := make([]string, 0, len(labelServiceProperties)) for k := range labelServiceProperties { @@ -368,73 +369,73 @@ func (provider *Docker) getServiceNames(container dockerData) []string { } // Extract entrypoints from labels for a given service and a given docker container -func (provider *Docker) getServiceEntryPoints(container dockerData, serviceName string) []string { +func (p *Provider) getServiceEntryPoints(container dockerData, serviceName string) []string { if entryPoints, ok := getContainerServiceLabel(container, serviceName, "frontend.entryPoints"); ok { return strings.Split(entryPoints, ",") } - return provider.getEntryPoints(container) + return p.getEntryPoints(container) } // Extract passHostHeader from labels for a given service and a given docker container -func (provider *Docker) getServicePassHostHeader(container dockerData, serviceName string) string { +func (p *Provider) getServicePassHostHeader(container dockerData, serviceName string) string { if servicePassHostHeader, ok := getContainerServiceLabel(container, serviceName, "frontend.passHostHeader"); ok { return servicePassHostHeader } - return provider.getPassHostHeader(container) + return p.getPassHostHeader(container) } // Extract priority from labels for a given service and a given docker container -func (provider *Docker) getServicePriority(container dockerData, serviceName string) string { +func (p *Provider) getServicePriority(container dockerData, serviceName string) string { if value, ok := getContainerServiceLabel(container, serviceName, "frontend.priority"); ok { return value } - return provider.getPriority(container) + return p.getPriority(container) } // Extract backend from labels for a given service and a given docker container -func (provider *Docker) getServiceBackend(container dockerData, serviceName string) string { +func (p *Provider) getServiceBackend(container dockerData, serviceName string) string { if value, ok := getContainerServiceLabel(container, serviceName, "frontend.backend"); ok { return value } - return provider.getBackend(container) + "-" + normalize(serviceName) + return p.getBackend(container) + "-" + provider.Normalize(serviceName) } // Extract rule from labels for a given service and a given docker container -func (provider *Docker) getServiceFrontendRule(container dockerData, serviceName string) string { +func (p *Provider) getServiceFrontendRule(container dockerData, serviceName string) string { if value, ok := getContainerServiceLabel(container, serviceName, "frontend.rule"); ok { return value } - return provider.getFrontendRule(container) + return p.getFrontendRule(container) } // Extract port from labels for a given service and a given docker container -func (provider *Docker) getServicePort(container dockerData, serviceName string) string { +func (p *Provider) getServicePort(container dockerData, serviceName string) string { if value, ok := getContainerServiceLabel(container, serviceName, "port"); ok { return value } - return provider.getPort(container) + return p.getPort(container) } // Extract weight from labels for a given service and a given docker container -func (provider *Docker) getServiceWeight(container dockerData, serviceName string) string { +func (p *Provider) getServiceWeight(container dockerData, serviceName string) string { if value, ok := getContainerServiceLabel(container, serviceName, "weight"); ok { return value } - return provider.getWeight(container) + return p.getWeight(container) } // Extract protocol from labels for a given service and a given docker container -func (provider *Docker) getServiceProtocol(container dockerData, serviceName string) string { +func (p *Provider) getServiceProtocol(container dockerData, serviceName string) string { if value, ok := getContainerServiceLabel(container, serviceName, "protocol"); ok { return value } - return provider.getProtocol(container) + return p.getProtocol(container) } -func (provider *Docker) hasLoadBalancerLabel(container dockerData) bool { +func (p *Provider) hasLoadBalancerLabel(container dockerData) bool { _, errMethod := getLabel(container, "traefik.backend.loadbalancer.method") _, errSticky := getLabel(container, "traefik.backend.loadbalancer.sticky") if errMethod != nil && errSticky != nil { @@ -443,7 +444,7 @@ func (provider *Docker) hasLoadBalancerLabel(container dockerData) bool { return true } -func (provider *Docker) hasMaxConnLabels(container dockerData) bool { +func (p *Provider) hasMaxConnLabels(container dockerData) bool { if _, err := getLabel(container, "traefik.backend.maxconn.amount"); err != nil { return false } @@ -453,21 +454,21 @@ func (provider *Docker) hasMaxConnLabels(container dockerData) bool { return true } -func (provider *Docker) getCircuitBreakerExpression(container dockerData) string { +func (p *Provider) getCircuitBreakerExpression(container dockerData) string { if label, err := getLabel(container, "traefik.backend.circuitbreaker.expression"); err == nil { return label } return "NetworkErrorRatio() > 1" } -func (provider *Docker) getLoadBalancerMethod(container dockerData) string { +func (p *Provider) getLoadBalancerMethod(container dockerData) string { if label, err := getLabel(container, "traefik.backend.loadbalancer.method"); err == nil { return label } return "wrr" } -func (provider *Docker) getMaxConnAmount(container dockerData) int64 { +func (p *Provider) getMaxConnAmount(container dockerData) int64 { if label, err := getLabel(container, "traefik.backend.maxconn.amount"); err == nil { i, errConv := strconv.ParseInt(label, 10, 64) if errConv != nil { @@ -479,27 +480,27 @@ func (provider *Docker) getMaxConnAmount(container dockerData) int64 { return math.MaxInt64 } -func (provider *Docker) getMaxConnExtractorFunc(container dockerData) string { +func (p *Provider) getMaxConnExtractorFunc(container dockerData) string { if label, err := getLabel(container, "traefik.backend.maxconn.extractorfunc"); err == nil { return label } return "request.host" } -func (provider *Docker) containerFilter(container dockerData) bool { +func (p *Provider) containerFilter(container dockerData) bool { _, err := strconv.Atoi(container.Labels["traefik.port"]) if len(container.NetworkSettings.Ports) == 0 && err != nil { log.Debugf("Filtering container without port and no traefik.port label %s", container.Name) return false } - if !isContainerEnabled(container, provider.ExposedByDefault) { + if !isContainerEnabled(container, p.ExposedByDefault) { log.Debugf("Filtering disabled container %s", container.Name) return false } constraintTags := strings.Split(container.Labels["traefik.tags"], ",") - if ok, failingConstraint := provider.MatchConstraints(constraintTags); !ok { + if ok, failingConstraint := p.MatchConstraints(constraintTags); !ok { if failingConstraint != nil { log.Debugf("Container %v pruned by '%v' constraint", container.Name, failingConstraint.String()) } @@ -514,35 +515,35 @@ func (provider *Docker) containerFilter(container dockerData) bool { return true } -func (provider *Docker) getFrontendName(container dockerData) string { +func (p *Provider) getFrontendName(container dockerData) string { // Replace '.' with '-' in quoted keys because of this issue https://github.com/BurntSushi/toml/issues/78 - return normalize(provider.getFrontendRule(container)) + return provider.Normalize(p.getFrontendRule(container)) } // GetFrontendRule returns the frontend rule for the specified container, using // it's label. It returns a default one (Host) if the label is not present. -func (provider *Docker) getFrontendRule(container dockerData) string { +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:" + provider.getSubDomain(labels["com.docker.compose.service"]+"."+labels["com.docker.compose.project"]) + "." + provider.Domain + return "Host:" + p.getSubDomain(labels["com.docker.compose.service"]+"."+labels["com.docker.compose.project"]) + "." + p.Domain } - return "Host:" + provider.getSubDomain(container.ServiceName) + "." + provider.Domain + return "Host:" + p.getSubDomain(container.ServiceName) + "." + p.Domain } -func (provider *Docker) getBackend(container dockerData) string { +func (p *Provider) getBackend(container dockerData) string { if label, err := getLabel(container, "traefik.backend"); err == nil { - return normalize(label) + return provider.Normalize(label) } if labels, err := getLabels(container, []string{"com.docker.compose.project", "com.docker.compose.service"}); err == nil { - return normalize(labels["com.docker.compose.service"] + "_" + labels["com.docker.compose.project"]) + return provider.Normalize(labels["com.docker.compose.service"] + "_" + labels["com.docker.compose.project"]) } - return normalize(container.ServiceName) + return provider.Normalize(container.ServiceName) } -func (provider *Docker) getIPAddress(container dockerData) string { +func (p *Provider) getIPAddress(container dockerData) string { if label, err := getLabel(container, "traefik.docker.network"); err == nil && label != "" { networkSettings := container.NetworkSettings if networkSettings.Networks != nil { @@ -561,8 +562,8 @@ func (provider *Docker) getIPAddress(container dockerData) string { return "127.0.0.1" } - if provider.UseBindPortIP { - port := provider.getPort(container) + if p.UseBindPortIP { + port := p.getPort(container) for netport, portBindings := range container.NetworkSettings.Ports { if string(netport) == port+"/TCP" || string(netport) == port+"/UDP" { for _, p := range portBindings { @@ -578,7 +579,7 @@ func (provider *Docker) getIPAddress(container dockerData) string { return "" } -func (provider *Docker) getPort(container dockerData) string { +func (p *Provider) getPort(container dockerData) string { if label, err := getLabel(container, "traefik.port"); err == nil { return label } @@ -588,56 +589,56 @@ func (provider *Docker) getPort(container dockerData) string { return "" } -func (provider *Docker) getWeight(container dockerData) string { +func (p *Provider) getWeight(container dockerData) string { if label, err := getLabel(container, "traefik.weight"); err == nil { return label } return "0" } -func (provider *Docker) getSticky(container dockerData) string { +func (p *Provider) getSticky(container dockerData) string { if label, err := getLabel(container, "traefik.backend.loadbalancer.sticky"); err == nil { return label } return "false" } -func (provider *Docker) getIsBackendLBSwarm(container dockerData) string { +func (p *Provider) getIsBackendLBSwarm(container dockerData) string { if label, err := getLabel(container, "traefik.backend.loadbalancer.swarm"); err == nil { return label } return "false" } -func (provider *Docker) getDomain(container dockerData) string { +func (p *Provider) getDomain(container dockerData) string { if label, err := getLabel(container, "traefik.domain"); err == nil { return label } - return provider.Domain + return p.Domain } -func (provider *Docker) getProtocol(container dockerData) string { +func (p *Provider) getProtocol(container dockerData) string { if label, err := getLabel(container, "traefik.protocol"); err == nil { return label } return "http" } -func (provider *Docker) getPassHostHeader(container dockerData) string { +func (p *Provider) getPassHostHeader(container dockerData) string { if passHostHeader, err := getLabel(container, "traefik.frontend.passHostHeader"); err == nil { return passHostHeader } return "true" } -func (provider *Docker) getPriority(container dockerData) string { +func (p *Provider) getPriority(container dockerData) string { if priority, err := getLabel(container, "traefik.frontend.priority"); err == nil { return priority } return "0" } -func (provider *Docker) getEntryPoints(container dockerData) []string { +func (p *Provider) getEntryPoints(container dockerData) []string { if entryPoints, err := getLabel(container, "traefik.frontend.entryPoints"); err == nil { return strings.Split(entryPoints, ",") } @@ -736,11 +737,11 @@ func parseContainer(container dockertypes.ContainerJSON) dockerData { } // Escape beginning slash "/", convert all others to dash "-", and convert underscores "_" to dash "-" -func (provider *Docker) getSubDomain(name string) string { +func (p *Provider) getSubDomain(name string) string { return strings.Replace(strings.Replace(strings.TrimPrefix(name, "/"), "/", "-", -1), "_", "-", -1) } -func (provider *Docker) listServices(ctx context.Context, dockerClient client.APIClient) ([]dockerData, error) { +func (p *Provider) listServices(ctx context.Context, dockerClient client.APIClient) ([]dockerData, error) { serviceList, err := dockerClient.ServiceList(ctx, dockertypes.ServiceListOptions{}) if err != nil { return []dockerData{}, err @@ -765,7 +766,7 @@ func (provider *Docker) listServices(ctx context.Context, dockerClient client.AP for _, service := range serviceList { dockerData := parseService(service, networkMap) - useSwarmLB, _ := strconv.ParseBool(provider.getIsBackendLBSwarm(dockerData)) + useSwarmLB, _ := strconv.ParseBool(p.getIsBackendLBSwarm(dockerData)) isGlobalSvc := service.Spec.Mode.Global != nil if useSwarmLB { diff --git a/provider/docker_test.go b/provider/docker/docker_test.go similarity index 100% rename from provider/docker_test.go rename to provider/docker/docker_test.go diff --git a/provider/docker/docker_unix.go b/provider/docker/docker_unix.go new file mode 100644 index 000000000..cfb97121b --- /dev/null +++ b/provider/docker/docker_unix.go @@ -0,0 +1,8 @@ +// +build !windows + +package docker + +const ( + // DockerAPIVersion is a constant holding the version of the Provider API traefik will use + DockerAPIVersion string = "1.21" +) diff --git a/provider/docker/docker_windows.go b/provider/docker/docker_windows.go new file mode 100644 index 000000000..ff0a873cb --- /dev/null +++ b/provider/docker/docker_windows.go @@ -0,0 +1,6 @@ +package docker + +const ( + // DockerAPIVersion is a constant holding the version of the Provider API traefik will use + DockerAPIVersion string = "1.24" +) diff --git a/provider/docker_unix.go b/provider/docker_unix.go deleted file mode 100644 index 8f901f7b4..000000000 --- a/provider/docker_unix.go +++ /dev/null @@ -1,8 +0,0 @@ -// +build !windows - -package provider - -const ( - // DockerAPIVersion is a constant holding the version of the Docker API traefik will use - DockerAPIVersion string = "1.21" -) diff --git a/provider/docker_windows.go b/provider/docker_windows.go deleted file mode 100644 index dc351fc2a..000000000 --- a/provider/docker_windows.go +++ /dev/null @@ -1,6 +0,0 @@ -package provider - -const ( - // DockerAPIVersion is a constant holding the version of the Docker API traefik will use - DockerAPIVersion string = "1.24" -) diff --git a/provider/ecs.go b/provider/ecs.go index a8426b43d..7089f3c24 100644 --- a/provider/ecs.go +++ b/provider/ecs.go @@ -182,7 +182,7 @@ func (provider *ECS) loadECSConfig(ctx context.Context, client *awsClient) (*typ instances = fun.Filter(provider.filterInstance, instances).([]ecsInstance) - return provider.getConfiguration("templates/ecs.tmpl", ecsFuncMap, struct { + return provider.GetConfiguration("templates/ecs.tmpl", ecsFuncMap, struct { Instances []ecsInstance }{ instances, diff --git a/provider/eureka.go b/provider/eureka.go index 29329a31d..c935e5630 100644 --- a/provider/eureka.go +++ b/provider/eureka.go @@ -108,7 +108,7 @@ func (provider *Eureka) buildConfiguration() (*types.Configuration, error) { applications.Applications, } - configuration, err := provider.getConfiguration("templates/eureka.tmpl", EurekaFuncMap, templateObjects) + configuration, err := provider.GetConfiguration("templates/eureka.tmpl", EurekaFuncMap, templateObjects) if err != nil { log.Error(err) } diff --git a/provider/kubernetes.go b/provider/kubernetes.go index 18f89d6de..6ccdb94bf 100644 --- a/provider/kubernetes.go +++ b/provider/kubernetes.go @@ -320,7 +320,7 @@ func (provider *Kubernetes) getPassHostHeader() bool { func (provider *Kubernetes) loadConfig(templateObjects types.Configuration) *types.Configuration { var FuncMap = template.FuncMap{} - configuration, err := provider.getConfiguration("templates/kubernetes.tmpl", FuncMap, templateObjects) + configuration, err := provider.GetConfiguration("templates/kubernetes.tmpl", FuncMap, templateObjects) if err != nil { log.Error(err) } diff --git a/provider/kv.go b/provider/kv.go index 9c99781c7..376c1aa5c 100644 --- a/provider/kv.go +++ b/provider/kv.go @@ -130,7 +130,7 @@ func (provider *Kv) loadConfig() *types.Configuration { "Last": provider.last, } - configuration, err := provider.getConfiguration("templates/kv.tmpl", KvFuncMap, templateObjects) + configuration, err := provider.GetConfiguration("templates/kv.tmpl", KvFuncMap, templateObjects) if err != nil { log.Error(err) } diff --git a/provider/marathon.go b/provider/marathon.go index eef95124d..db58b41f9 100644 --- a/provider/marathon.go +++ b/provider/marathon.go @@ -183,7 +183,7 @@ func (provider *Marathon) loadMarathonConfig() *types.Configuration { provider.Domain, } - configuration, err := provider.getConfiguration("templates/marathon.tmpl", MarathonFuncMap, templateObjects) + configuration, err := provider.GetConfiguration("templates/marathon.tmpl", MarathonFuncMap, templateObjects) if err != nil { log.Error(err) } diff --git a/provider/mesos.go b/provider/mesos.go index 1835266b3..23536f38e 100644 --- a/provider/mesos.go +++ b/provider/mesos.go @@ -167,7 +167,7 @@ func (provider *Mesos) loadMesosConfig() *types.Configuration { provider.Domain, } - configuration, err := provider.getConfiguration("templates/mesos.tmpl", mesosFuncMap, templateObjects) + configuration, err := provider.GetConfiguration("templates/mesos.tmpl", mesosFuncMap, templateObjects) if err != nil { log.Error(err) } diff --git a/provider/provider.go b/provider/provider.go index 2782d3513..e354c5277 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -51,7 +51,7 @@ func (p *BaseProvider) MatchConstraints(tags []string) (bool, *types.Constraint) return true, nil } -func (p *BaseProvider) getConfiguration(defaultTemplateFile string, funcMap template.FuncMap, templateObjects interface{}) (*types.Configuration, error) { +func (p *BaseProvider) GetConfiguration(defaultTemplateFile string, funcMap template.FuncMap, templateObjects interface{}) (*types.Configuration, error) { var ( buf []byte err error @@ -60,7 +60,7 @@ func (p *BaseProvider) getConfiguration(defaultTemplateFile string, funcMap temp var defaultFuncMap = template.FuncMap{ "replace": replace, "tolower": strings.ToLower, - "normalize": normalize, + "Normalize": Normalize, "split": split, "contains": contains, } @@ -112,7 +112,7 @@ func split(sep, s string) []string { return strings.Split(s, sep) } -func normalize(name string) string { +func Normalize(name string) string { fargs := func(c rune) bool { return !unicode.IsLetter(c) && !unicode.IsNumber(c) } diff --git a/provider/provider_test.go b/provider/provider_test.go index 79c757755..c57a59e68 100644 --- a/provider/provider_test.go +++ b/provider/provider_test.go @@ -91,7 +91,7 @@ func TestConfigurationErrors(t *testing.T) { } for _, invalid := range invalids { - configuration, err := invalid.provider.getConfiguration(invalid.defaultTemplate, invalid.funcMap, nil) + configuration, err := invalid.provider.GetConfiguration(invalid.defaultTemplate, invalid.funcMap, nil) if err == nil || !strings.Contains(err.Error(), invalid.expectedError) { t.Fatalf("should have generate an error with %q, got %v", invalid.expectedError, err) } @@ -136,7 +136,7 @@ func TestGetConfiguration(t *testing.T) { }, nil, } - configuration, err := provider.getConfiguration(templateFile.Name(), nil, nil) + configuration, err := provider.GetConfiguration(templateFile.Name(), nil, nil) if err != nil { t.Fatalf("Shouldn't have error out, got %v", err) } @@ -198,7 +198,7 @@ func TestGetConfigurationReturnsCorrectMaxConnConfiguration(t *testing.T) { }, nil, } - configuration, err := provider.getConfiguration(templateFile.Name(), nil, nil) + configuration, err := provider.GetConfiguration(templateFile.Name(), nil, nil) if err != nil { t.Fatalf("Shouldn't have error out, got %v", err) } @@ -345,7 +345,7 @@ func TestDefaultFuncMap(t *testing.T) { weight = 1 [frontends] - [frontends.{{normalize "frontend/1"}}] + [frontends.{{Normalize "frontend/1"}}] {{ $backend := "backend1/test/value" | split "/" }} {{ $backendid := index $backend 1 }} {{ if "backend1" | contains "backend" }} @@ -366,7 +366,7 @@ func TestDefaultFuncMap(t *testing.T) { }, nil, } - configuration, err := provider.getConfiguration(templateFile.Name(), nil, nil) + configuration, err := provider.GetConfiguration(templateFile.Name(), nil, nil) if err != nil { t.Fatalf("Shouldn't have error out, got %v", err) } diff --git a/provider/rancher.go b/provider/rancher.go index 72b2231d4..3b2b95e8b 100644 --- a/provider/rancher.go +++ b/provider/rancher.go @@ -79,7 +79,7 @@ func (provider *Rancher) getFrontendRule(service rancherData) string { func (provider *Rancher) getFrontendName(service rancherData) string { // Replace '.' with '-' in quoted keys because of this issue https://github.com/BurntSushi/toml/issues/78 - return normalize(provider.getFrontendRule(service)) + return Normalize(provider.getFrontendRule(service)) } // Backend Labels @@ -122,9 +122,9 @@ func (provider *Rancher) getSticky(service rancherData) string { func (provider *Rancher) getBackend(service rancherData) string { if label, err := getServiceLabel(service, "traefik.backend"); err == nil { - return normalize(label) + return Normalize(label) } - return normalize(service.Name) + return Normalize(service.Name) } // Generall Application Stuff @@ -436,7 +436,7 @@ func (provider *Rancher) loadRancherConfig(services []rancherData) *types.Config provider.Domain, } - configuration, err := provider.getConfiguration("templates/rancher.tmpl", RancherFuncMap, templateObjects) + configuration, err := provider.GetConfiguration("templates/rancher.tmpl", RancherFuncMap, templateObjects) if err != nil { log.Error(err) }