Skip to content
This repository has been archived by the owner on Aug 4, 2022. It is now read-only.

Commit

Permalink
Completed migration of existing template to explicit methods
Browse files Browse the repository at this point in the history
  • Loading branch information
lawrencegripper committed Jan 9, 2018
1 parent 438aafc commit 5b00db2
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 37 deletions.
43 changes: 43 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package servicefabric

import (
"math"
"text/template"

"github.com/containous/traefik/provider/label"
Expand All @@ -24,6 +25,24 @@ func (p *Provider) buildConfiguration(sfClient sfClient) (*types.Configuration,
"doesAppParamContain": doesAppParamContain, // FIXME unused
"filterServicesByLabelValue": filterServicesByLabelValue, // FIXME unused

// Backend functions
"getWeight": getFuncServiceStringLabel(label.TraefikWeight, label.DefaultWeight),
"getProtocol": getFuncServiceStringLabel(label.TraefikProtocol, label.DefaultProtocol),
"hasHealthCheckLabels": hasFuncService(label.TraefikBackendHealthCheckPath),
"getHealthCheckPath": getFuncServiceStringLabel(label.TraefikBackendHealthCheckPath, ""),
"getHealthCheckPort": getFuncServiceStringLabel(label.TraefikBackendHealthCheckPort, "0"),
"getHealthCheckInterval": getFuncServiceStringLabel(label.TraefikBackendHealthCheckInterval, ""),
"hasCircuitBreakerLabel": hasFuncService(label.TraefikBackendCircuitBreakerExpression),
"getCircuitBreakerExpression": getFuncServiceStringLabel(label.TraefikBackendCircuitBreakerExpression, label.DefaultCircuitBreakerExpression),
"hasLoadBalancerLabel": hasLoadBalancerLabel,
"getLoadBalancerMethod": getFuncServiceStringLabel(label.TraefikBackendLoadBalancerMethod, label.DefaultBackendLoadBalancerMethod),
"hasMaxConnLabels": hasMaxConnLabels,
"getMaxConnAmount": getFuncServiceStringLabel(label.TraefikBackendMaxConnAmount, string(math.MaxInt64)),
"getMaxConnExtractorFunc": getFuncServiceStringLabel(label.TraefikBackendMaxConnExtractorFunc, label.DefaultBackendMaxconnExtractorFunc),
"getSticky": getFuncBoolLabel(label.TraefikBackendLoadBalancerSticky, false),
"hasStickinessLabel": hasFuncService(label.TraefikBackendLoadBalancerStickiness),
"getStickinessCookieName": getFuncServiceStringLabel(label.TraefikBackendLoadBalancerStickinessCookieName, label.DefaultBackendLoadbalancerStickinessCookieName),

// Frontend Functions
"getPriority": getFuncServiceStringLabel(label.TraefikFrontendPriority, label.DefaultFrontendPriority),
"hasRequestHeaders": hasFuncService(label.TraefikFrontendRequestHeaders),
Expand All @@ -34,12 +53,18 @@ func (p *Provider) buildConfiguration(sfClient sfClient) (*types.Configuration,
"getPassTLSCert": getFuncBoolLabel(label.TraefikFrontendPassTLSCert, false),
"hasEntryPoints": hasFuncService(label.TraefikFrontendEntryPoints),
"getEntryPoints": getFuncServiceSliceStringLabel(label.TraefikFrontendEntryPoints),
"hasBasicAuth": hasFuncService(label.TraefikFrontendAuthBasic),
"getBasicAuth": getFuncServiceSliceStringLabel(label.TraefikFrontendAuthBasic),
"getWhitelistSourceRange": getFuncServiceSliceStringLabel(label.TraefikFrontendWhitelistSourceRange),
"hasRedirect": hasRedirect,
"getRedirectEntryPoint": getFuncServiceStringLabel(label.TraefikFrontendRedirectEntryPoint, label.DefaultFrontendRedirectEntryPoint),
"getRedirectRegex": getFuncServiceStringLabel(label.TraefikFrontendRedirectRegex, ""),
"getRedirectReplacement": getFuncServiceStringLabel(label.TraefikFrontendRedirectReplacement, ""),
"getFrontendRules": getFuncServiceLabelWithPrefix(label.TraefikFrontendRule),

// SF Service Grouping
"getGroupedServices": getFuncServicesGroupedByLabel(TraefikSFGroupName),
"getGroupedWeight": getFuncServiceStringLabel(TraefikSFGroupWeight, "1"),
}

services, err := getClusterServices(sfClient)
Expand All @@ -56,7 +81,25 @@ func (p *Provider) buildConfiguration(sfClient sfClient) (*types.Configuration,
return p.GetConfiguration(tmpl, sfFuncMap, templateObjects)
}

func getFrontendRules(services ServiceItemExtended) map[string]string {
return getServiceLabelsWithPrefix(services, label.TraefikFrontendRule)
}

func hasRedirect(service ServiceItemExtended) bool {
return label.Has(service.Labels, label.TraefikFrontendRedirectEntryPoint) ||
label.Has(service.Labels, label.TraefikFrontendRedirectReplacement) && label.Has(service.Labels, label.TraefikFrontendRedirectRegex)
}

func hasLoadBalancerLabel(service ServiceItemExtended) bool {
method := label.Has(service.Labels, label.TraefikBackendLoadBalancerMethod)
sticky := label.Has(service.Labels, label.TraefikBackendLoadBalancerSticky)
stickiness := label.Has(service.Labels, label.TraefikBackendLoadBalancerStickiness)
cookieName := label.Has(service.Labels, label.TraefikBackendLoadBalancerStickinessCookieName)
return method || sticky || stickiness || cookieName
}

func hasMaxConnLabels(service ServiceItemExtended) bool {
mca := label.Has(service.Labels, label.TraefikBackendMaxConnAmount)
mcef := label.Has(service.Labels, label.TraefikBackendMaxConnExtractorFunc)
return mca && mcef
}
18 changes: 18 additions & 0 deletions labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import (
"github.com/containous/traefik/provider/label"
)

// SF Specific Traefik Labels
const (
TraefikSFGroupName = "Traefik.SF.GroupName"
TraefikSFGroupWeight = "Traefik.SF.GroupWeight"
)

func getFuncBoolLabel(labelName string, defaultValue bool) func(service ServiceItemExtended) bool {
return func(service ServiceItemExtended) bool {
return label.GetBoolValue(service.Labels, labelName, defaultValue)
Expand Down Expand Up @@ -44,6 +50,18 @@ func getFuncServiceMapLabel(labelName string) func(service ServiceItemExtended)
}
}

func getFuncServiceLabelWithPrefix(labelName string) func(service ServiceItemExtended) map[string]string {
return func(service ServiceItemExtended) map[string]string {
return getServiceLabelsWithPrefix(service, labelName)
}
}

func getFuncServicesGroupedByLabel(labelName string) func(services []ServiceItemExtended) map[string][]ServiceItemExtended {
return func(services []ServiceItemExtended) map[string][]ServiceItemExtended {
return getServices(services, labelName)
}
}

func getServiceLabelsWithPrefix(service ServiceItemExtended, prefix string) map[string]string {
results := make(map[string]string)
for k, v := range service.Labels {
Expand Down
90 changes: 81 additions & 9 deletions servicefabric_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ var instances = &sf.InstanceItemsPage{
ReplicaStatus: "Ready",
ServiceKind: "Stateless",
},
ID: "131497042182378182",
ID: "1",
},
{ //Include a failed service in test data
ReplicaItemBase: &sf.ReplicaItemBase{
Expand All @@ -91,7 +91,7 @@ var instances = &sf.InstanceItemsPage{
ReplicaStatus: "Down", // status is currently down.
ServiceKind: "Stateless",
},
ID: "131497042182378183",
ID: "2",
},
},
}
Expand Down Expand Up @@ -200,7 +200,7 @@ func TestServicesPresentInConfig(t *testing.T) {
desc: "Backend server has url 'http://localhost:8081'",
check: func(c types.Configuration) bool {
backend := config.Backends["fabric:/TestApplication/TestService"]
return backend.Servers["131497042182378182"].URL == "http://localhost:8081"
return backend.Servers["1"].URL == "http://localhost:8081"
},
},
}
Expand Down Expand Up @@ -243,7 +243,7 @@ func TestFrontendLabelConfig(t *testing.T) {
desc: "Has whitelistSourceRange set",
labels: map[string]string{
label.TraefikEnable: "true",
label.TraefikFrontendWhitelistSourceRange: "[\"10.0.0.1\", \"10.0.0.2\"]",
label.TraefikFrontendWhitelistSourceRange: "10.0.0.1, 10.0.0.2",
},
validate: func(f types.Frontend) bool {
if len(f.WhitelistSourceRange) != 2 {
Expand All @@ -264,10 +264,10 @@ func TestFrontendLabelConfig(t *testing.T) {
desc: "Has basicAuth set",
labels: map[string]string{
label.TraefikEnable: "true",
label.TraefikFrontendAuthBasic: "[\"USER:HASH\"]",
label.TraefikFrontendAuthBasic: "USER1:HASH1, USER2:HASH2",
},
validate: func(f types.Frontend) bool {
return len(f.BasicAuth) == 1 && f.BasicAuth[0] == "USER:HASH"
return len(f.BasicAuth) == 2 && f.BasicAuth[0] == "USER1:HASH1"
},
},
{
Expand Down Expand Up @@ -329,7 +329,7 @@ func TestFrontendLabelConfig(t *testing.T) {
label.TraefikFrontendRule + ".default": "Path: /",
},
validate: func(f types.Frontend) bool {
return len(f.Routes) == 1 && f.Routes["frontend.rule.default"].Rule == "Path: /"
return len(f.Routes) == 1 && f.Routes[label.TraefikFrontendRule+".default"].Rule == "Path: /"
},
},
}
Expand Down Expand Up @@ -390,6 +390,7 @@ func TestBackendLabelConfig(t *testing.T) {
labels: map[string]string{
label.TraefikEnable: "true",
label.TraefikBackendHealthCheckPath: "/hc",
label.TraefikBackendHealthCheckPort: "9000",
label.TraefikBackendHealthCheckInterval: "1337s",
},
validate: func(b types.Backend) bool {
Expand All @@ -402,8 +403,8 @@ func TestBackendLabelConfig(t *testing.T) {
{
desc: "Has circuit breaker set",
labels: map[string]string{
label.TraefikEnable: "true",
label.TraefikBackendCircuitBreaker: "NetworkErrorRatio() > 0.5",
label.TraefikEnable: "true",
label.TraefikBackendCircuitBreakerExpression: "NetworkErrorRatio() > 0.5",
},
validate: func(b types.Backend) bool {
if b.CircuitBreaker == nil {
Expand Down Expand Up @@ -485,6 +486,77 @@ func TestBackendLabelConfig(t *testing.T) {
}
}

func TestGroupedServices(t *testing.T) {
groupName := "groupedbackends"
groupWeight := "154"

provider := Provider{}
client := &clientMock{
applications: apps,
services: services,
partitions: partitions,
replicas: nil,
instances: instances,
labels: map[string]string{
label.TraefikEnable: "true",
TraefikSFGroupName: groupName,
TraefikSFGroupWeight: groupWeight,
},
}
config, err := requestConfig(provider, client)
if err != nil {
t.Error(err)
}
if err != nil {
t.Error(err)
}

if len(config.Frontends) != 2 {
t.Log(getJSON(config))
t.Log("Incorrect count of frontends present in the config")
t.FailNow()
}

if len(config.Backends) != 2 {
t.Log(getJSON(config))
t.Log("Incorrect count of backends present in the config")
t.FailNow()
}

frontend, exists := config.Frontends[groupName]

if !exists {
t.Log(getJSON(config))
t.Log("Missing frontend for grouped service")
t.FailNow()
}

if frontend.Priority == 50 && frontend.Backend == groupName {
t.Log("Frontend exists for group")
}

backend, exists := config.Backends[groupName]
if !exists {
t.Log(getJSON(config))
t.Log("Missing backend for grouped service")
t.FailNow()
}

if len(backend.Servers) != 1 {
t.Log(getJSON(config))
t.Log("Incorrect number of backend servers on grouped service")
t.FailNow()
}

for _, server := range backend.Servers {
if server.Weight != 154 {
t.Log(getJSON(config))
t.Log("Incorrect weight on grouped service")
t.FailNow()
}
}
}

func TestIsPrimary(t *testing.T) {
testCases := []struct {
desc string
Expand Down
62 changes: 34 additions & 28 deletions servicefabric_tmpl.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package servicefabric

const tmpl = `
{{$groupedServiceMap := getServices .Services "backend.group.name"}}
[backends]
{{range $aggName, $aggServices := $groupedServiceMap }}
{{range $aggName, $aggServices := getGroupedServices .Services }}
[backends."{{$aggName}}"]
{{range $service := $aggServices}}
{{range $partition := $service.Partitions}}
{{range $instance := $partition.Instances}}
[backends."{{$aggName}}".servers."{{$service.ID}}-{{$instance.ID}}"]
url = "{{getDefaultEndpoint $instance}}"
weight = {{getLabelValue $service "backend.group.weight" "1"}}
weight = {{getGroupedWeight $service}}
{{end}}
{{end}}
{{end}}
Expand All @@ -21,33 +20,36 @@ const tmpl = `
{{if eq $partition.ServiceKind "Stateless"}}
[backends."{{$service.Name}}"]
[backends."{{$service.Name}}".LoadBalancer]
{{if hasLabel $service "backend.loadbalancer.method"}}
method = "{{getLabelValue $service "backend.loadbalancer.method" "" }}"
{{else}}
method = "drr"
{{if hasLoadBalancerLabel $service}}
method = "{{getLoadBalancerMethod $service }}"
{{end}}
{{if hasLabel $service "backend.healthcheck.path"}}
{{if hasHealthCheckLabels $service}}
[backends."{{$service.Name}}".healthcheck]
path = "{{getLabelValue $service "backend.healthcheck.path" ""}}"
interval = "{{getLabelValue $service "backend.healthcheck.interval" "10s"}}"
path = "{{getHealthCheckPath $service}}"
interval = "{{getHealthCheckInterval $service }}"
port = {{getHealthCheckPort $service}}
{{end}}
{{if hasLabel $service "backend.loadbalancer.stickiness"}}
{{if hasStickinessLabel $service}}
[backends."{{$service.Name}}".LoadBalancer.stickiness]
{{end}}
{{if hasLabel $service "backend.circuitbreaker"}}
[backends."{{$service.Name}}".circuitbreaker]
expression = "{{getLabelValue $service "backend.circuitbreaker" ""}}"
sticky = {{getSticky $service}}
{{if hasStickinessLabel $service}}
[backends."{{$service.Name}}".loadBalancer.stickiness]
cookieName = "{{getStickinessCookieName $service}}"
{{end}}
{{if hasLabel $service "backend.maxconn.amount"}}
[backends."{{$service.Name}}".maxconn]
amount = {{getLabelValue $service "backend.maxconn.amount" ""}}
{{if hasLabel $service "backend.maxconn.extractorfunc"}}
extractorfunc = "{{getLabelValue $service "backend.maxconn.extractorfunc" ""}}"
{{end}}
{{if hasCircuitBreakerLabel $service}}
[backends."{{$service.Name}}".circuitBreaker]
expression = "{{getCircuitBreakerExpression $service}}"
{{end}}
{{if hasMaxConnLabels $service}}
[backends."{{$service.Name}}".maxConn]
amount = {{getMaxConnAmount $service}}
extractorFunc = "{{getMaxConnExtractorFunc $service}}"
{{end}}
{{range $instance := $partition.Instances}}
Expand Down Expand Up @@ -78,14 +80,14 @@ const tmpl = `
{{end}}
[frontends]
{{range $groupName, $groupServices := $groupedServiceMap}}
{{range $groupName, $groupServices := getGroupedServices .Services}}
{{$service := index $groupServices 0}}
[frontends."{{$groupName}}"]
backend = "{{$groupName}}"
priority = {{ getPriority $service }}
priority = 50
{{range $key, $value := getLabelsWithPrefix $service "frontend.rule"}}
{{range $key, $value := getFrontendRules $service}}
[frontends."{{$groupName}}".routes."{{$key}}"]
rule = "{{$value}}"
{{end}}
Expand All @@ -102,14 +104,18 @@ const tmpl = `
passTLSCert = {{getPassTLSCert $service}}
{{if hasLabel $service "frontend.whitelistSourceRange"}}
whitelistSourceRange = {{getLabelValue $service "frontend.whitelistSourceRange" ""}}
{{if getWhitelistSourceRange $service}}
whitelistSourceRange = [{{range getWhitelistSourceRange $service}}
"{{.}}",
{{end}}]
{{end}}
priority = {{ getPriority $service }}
{{if hasLabel $service "frontend.auth.basic"}}
basicAuth = {{getLabelValue $service "frontend.auth.basic" ""}}
{{if hasBasicAuth $service}}
basicAuth = [{{range getBasicAuth $service }}
"{{.}}",
{{end}}]
{{end}}
{{if hasEntryPoints $service}}
Expand All @@ -130,7 +136,7 @@ const tmpl = `
{{end}}
{{end}}
{{range $key, $value := getLabelsWithPrefix $service "frontend.rule"}}
{{range $key, $value := getFrontendRules $service}}
[frontends."frontend-{{$frontend}}".routes."{{$key}}"]
rule = "{{$value}}"
{{end}}
Expand Down

0 comments on commit 5b00db2

Please sign in to comment.