diff --git a/provider/consul_catalog.go b/provider/consul_catalog.go index 937f69aeb..ee3695135 100644 --- a/provider/consul_catalog.go +++ b/provider/consul_catalog.go @@ -2,6 +2,7 @@ package provider import ( "errors" + "strconv" "strings" "text/template" "time" @@ -123,6 +124,26 @@ func (provider *ConsulCatalog) getFrontendRule(service serviceUpdate) string { return "Host:" + service.ServiceName + "." + provider.Domain } +func (provider *ConsulCatalog) getBackendAddress(node *api.ServiceEntry) string { + if node.Service.Address != "" { + return node.Service.Address + } + return node.Node.Address +} + +func (provider *ConsulCatalog) getBackendName(node *api.ServiceEntry, index int) string { + serviceName := node.Service.Service + "--" + node.Service.Address + "--" + strconv.Itoa(node.Service.Port) + if len(node.Service.Tags) > 0 { + serviceName += "--" + strings.Join(node.Service.Tags, "--") + } + serviceName = strings.Replace(serviceName, ".", "-", -1) + serviceName = strings.Replace(serviceName, "=", "-", -1) + + // unique int at the end + serviceName += "--" + strconv.Itoa(index) + return serviceName +} + func (provider *ConsulCatalog) getAttribute(name string, tags []string, defaultValue string) string { for _, tag := range tags { if strings.Index(strings.ToLower(tag), DefaultConsulCatalogTagPrefix+".") == 0 { @@ -136,11 +157,12 @@ func (provider *ConsulCatalog) getAttribute(name string, tags []string, defaultV func (provider *ConsulCatalog) buildConfig(catalog []catalogUpdate) *types.Configuration { var FuncMap = template.FuncMap{ - "getBackend": provider.getBackend, - "getFrontendRule": provider.getFrontendRule, - "getAttribute": provider.getAttribute, - "getEntryPoints": provider.getEntryPoints, - "replace": replace, + "getBackend": provider.getBackend, + "getFrontendRule": provider.getFrontendRule, + "getBackendName": provider.getBackendName, + "getBackendAddress": provider.getBackendAddress, + "getAttribute": provider.getAttribute, + "getEntryPoints": provider.getEntryPoints, } allNodes := []*api.ServiceEntry{} diff --git a/provider/consul_catalog_test.go b/provider/consul_catalog_test.go index 4f967ae60..eea48bc7c 100644 --- a/provider/consul_catalog_test.go +++ b/provider/consul_catalog_test.go @@ -82,6 +82,88 @@ func TestConsulCatalogGetAttribute(t *testing.T) { } } +func TestConsulCatalogGetBackendAddress(t *testing.T) { + provider := &ConsulCatalog{ + Domain: "localhost", + } + + services := []struct { + node *api.ServiceEntry + expected string + }{ + { + node: &api.ServiceEntry{ + Node: &api.Node{ + Address: "10.1.0.1", + }, + Service: &api.AgentService{ + Address: "10.2.0.1", + }, + }, + expected: "10.2.0.1", + }, + { + node: &api.ServiceEntry{ + Node: &api.Node{ + Address: "10.1.0.1", + }, + Service: &api.AgentService{ + Address: "", + }, + }, + expected: "10.1.0.1", + }, + } + + for _, e := range services { + actual := provider.getBackendAddress(e.node) + if actual != e.expected { + t.Fatalf("expected %q, got %q", e.expected, actual) + } + } +} + +func TestConsulCatalogGetBackendName(t *testing.T) { + provider := &ConsulCatalog{ + Domain: "localhost", + } + + services := []struct { + node *api.ServiceEntry + expected string + }{ + { + node: &api.ServiceEntry{ + Service: &api.AgentService{ + Service: "api", + Address: "10.0.0.1", + Port: 80, + Tags: []string{}, + }, + }, + expected: "api--10-0-0-1--80--0", + }, + { + node: &api.ServiceEntry{ + Service: &api.AgentService{ + Service: "api", + Address: "10.0.0.1", + Port: 80, + Tags: []string{"traefik.weight=42", "traefik.enable=true"}, + }, + }, + expected: "api--10-0-0-1--80--traefik-weight-42--traefik-enable-true--1", + }, + } + + for i, e := range services { + actual := provider.getBackendName(e.node, i) + if actual != e.expected { + t.Fatalf("expected %q, got %q", e.expected, actual) + } + } +} + func TestConsulCatalogBuildConfig(t *testing.T) { provider := &ConsulCatalog{ Domain: "localhost", @@ -154,7 +236,7 @@ func TestConsulCatalogBuildConfig(t *testing.T) { expectedBackends: map[string]*types.Backend{ "backend-test": { Servers: map[string]types.Server{ - "test--127-0-0-1--80": { + "test--127-0-0-1--80--traefik-backend-weight-42--random-foo-bar--traefik-backend-passHostHeader-true--traefik-protocol-https--0": { URL: "https://127.0.0.1:80", Weight: 42, }, diff --git a/templates/consul_catalog.tmpl b/templates/consul_catalog.tmpl index a6fe4dad3..69feab01a 100644 --- a/templates/consul_catalog.tmpl +++ b/templates/consul_catalog.tmpl @@ -1,9 +1,9 @@ [backends] -{{range .Nodes}} - {{if ne (getAttribute "enable" .Service.Tags "true") "false"}} - [backends.backend-{{getBackend .}}.servers.{{.Service.Service | replace "." "-"}}--{{.Service.Address | replace "." "-"}}--{{.Service.Port}}] - url = "{{getAttribute "protocol" .Service.Tags "http"}}://{{.Service.Address}}:{{.Service.Port}}" - {{$weight := getAttribute "backend.weight" .Service.Tags ""}} +{{range $index, $node := .Nodes}} + {{if ne (getAttribute "enable" $node.Service.Tags "true") "false"}} + [backends.backend-{{getBackend $node}}.servers.{{getBackendName $node $index}}] + url = "{{getAttribute "protocol" $node.Service.Tags "http"}}://{{getBackendAddress $node}}:{{$node.Service.Port}}" + {{$weight := getAttribute "backend.weight" $node.Service.Tags ""}} {{with $weight}} weight = {{$weight}} {{end}} @@ -25,7 +25,8 @@ {{end}} {{end}} -[frontends]{{range .Services}} +[frontends] +{{range .Services}} [frontends.frontend-{{.ServiceName}}] backend = "backend-{{.ServiceName}}" passHostHeader = {{getAttribute "frontend.passHostHeader" .Attributes "false"}}