Factorize labels managements.
This commit is contained in:
parent
21f6f81914
commit
f804053736
6 changed files with 192 additions and 137 deletions
|
@ -8,13 +8,26 @@ import (
|
||||||
|
|
||||||
"github.com/BurntSushi/ty/fun"
|
"github.com/BurntSushi/ty/fun"
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
|
"github.com/containous/traefik/log"
|
||||||
"github.com/containous/traefik/provider"
|
"github.com/containous/traefik/provider"
|
||||||
"github.com/containous/traefik/provider/label"
|
"github.com/containous/traefik/provider/label"
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// buildConfiguration fills the config template with the given instances
|
// buildConfiguration fills the config template with the given instances
|
||||||
func (p *Provider) buildConfigurationV2(services map[string][]ecsInstance) (*types.Configuration, error) {
|
func (p *Provider) buildConfigurationV2(instances []ecsInstance) (*types.Configuration, error) {
|
||||||
|
services := make(map[string][]ecsInstance)
|
||||||
|
for _, instance := range instances {
|
||||||
|
if p.filterInstance(instance) {
|
||||||
|
if serviceInstances, ok := services[instance.Name]; ok {
|
||||||
|
services[instance.Name] = append(serviceInstances, instance)
|
||||||
|
} else {
|
||||||
|
services[instance.Name] = []ecsInstance{instance}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var ecsFuncMap = template.FuncMap{
|
var ecsFuncMap = template.FuncMap{
|
||||||
// Backend functions
|
// Backend functions
|
||||||
"getHost": getHost,
|
"getHost": getHost,
|
||||||
|
@ -48,6 +61,35 @@ func (p *Provider) buildConfigurationV2(services map[string][]ecsInstance) (*typ
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) filterInstance(i ecsInstance) bool {
|
||||||
|
if labelPort := label.GetStringValue(i.TraefikLabels, label.TraefikPort, ""); len(i.container.NetworkBindings) == 0 && labelPort == "" {
|
||||||
|
log.Debugf("Filtering ecs instance without port %s (%s)", i.Name, i.ID)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.machine == nil || i.machine.State == nil || i.machine.State.Name == nil {
|
||||||
|
log.Debugf("Filtering ecs instance with missing ec2 information %s (%s)", i.Name, i.ID)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if aws.StringValue(i.machine.State.Name) != ec2.InstanceStateNameRunning {
|
||||||
|
log.Debugf("Filtering ecs instance with an incorrect state %s (%s) (state = %s)", i.Name, i.ID, aws.StringValue(i.machine.State.Name))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.machine.PrivateIpAddress == nil {
|
||||||
|
log.Debugf("Filtering ecs instance without an ip address %s (%s)", i.Name, i.ID)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isEnabled(i, p.ExposedByDefault) {
|
||||||
|
log.Debugf("Filtering disabled ecs instance %s (%s)", i.Name, i.ID)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Provider) getFrontendRule(i ecsInstance) string {
|
func (p *Provider) getFrontendRule(i ecsInstance) string {
|
||||||
defaultRule := "Host:" + strings.ToLower(strings.Replace(i.Name, "_", "-", -1)) + "." + p.Domain
|
defaultRule := "Host:" + strings.ToLower(strings.Replace(i.Name, "_", "-", -1)) + "." + p.Domain
|
||||||
return label.GetStringValue(i.TraefikLabels, label.TraefikFrontendRule, defaultRule)
|
return label.GetStringValue(i.TraefikLabels, label.TraefikFrontendRule, defaultRule)
|
||||||
|
|
|
@ -4,9 +4,9 @@ import (
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *Provider) buildConfiguration(services map[string][]ecsInstance) (*types.Configuration, error) {
|
func (p *Provider) buildConfiguration(instances []ecsInstance) (*types.Configuration, error) {
|
||||||
if p.TemplateVersion == 1 {
|
if p.TemplateVersion == 1 {
|
||||||
return p.buildConfigurationV1(services)
|
return p.buildConfigurationV1(instances)
|
||||||
}
|
}
|
||||||
return p.buildConfigurationV2(services)
|
return p.buildConfigurationV2(instances)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,21 +15,24 @@ import (
|
||||||
|
|
||||||
func TestBuildConfiguration(t *testing.T) {
|
func TestBuildConfiguration(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
services map[string][]ecsInstance
|
instances []ecsInstance
|
||||||
expected *types.Configuration
|
expected *types.Configuration
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "config parsed successfully",
|
desc: "config parsed successfully",
|
||||||
services: map[string][]ecsInstance{
|
instances: []ecsInstance{
|
||||||
"testing": {{
|
{
|
||||||
Name: "instance",
|
Name: "instance",
|
||||||
ID: "1",
|
ID: "1",
|
||||||
containerDefinition: &ecs.ContainerDefinition{
|
containerDefinition: &ecs.ContainerDefinition{
|
||||||
DockerLabels: map[string]*string{},
|
DockerLabels: map[string]*string{},
|
||||||
},
|
},
|
||||||
machine: &ec2.Instance{
|
machine: &ec2.Instance{
|
||||||
|
State: &ec2.InstanceState{
|
||||||
|
Name: aws.String(ec2.InstanceStateNameRunning),
|
||||||
|
},
|
||||||
PrivateIpAddress: aws.String("10.0.0.1"),
|
PrivateIpAddress: aws.String("10.0.0.1"),
|
||||||
},
|
},
|
||||||
container: &ecs.Container{
|
container: &ecs.Container{
|
||||||
|
@ -37,11 +40,11 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
HostPort: aws.Int64(1337),
|
HostPort: aws.Int64(1337),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}},
|
},
|
||||||
},
|
},
|
||||||
expected: &types.Configuration{
|
expected: &types.Configuration{
|
||||||
Backends: map[string]*types.Backend{
|
Backends: map[string]*types.Backend{
|
||||||
"backend-testing": {
|
"backend-instance": {
|
||||||
Servers: map[string]types.Server{
|
Servers: map[string]types.Server{
|
||||||
"server-instance-1": {
|
"server-instance-1": {
|
||||||
URL: "http://10.0.0.1:1337",
|
URL: "http://10.0.0.1:1337",
|
||||||
|
@ -49,11 +52,11 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Frontends: map[string]*types.Frontend{
|
Frontends: map[string]*types.Frontend{
|
||||||
"frontend-testing": {
|
"frontend-instance": {
|
||||||
EntryPoints: []string{},
|
EntryPoints: []string{},
|
||||||
Backend: "backend-testing",
|
Backend: "backend-instance",
|
||||||
Routes: map[string]types.Route{
|
Routes: map[string]types.Route{
|
||||||
"route-frontend-testing": {
|
"route-frontend-instance": {
|
||||||
Rule: "Host:instance.",
|
Rule: "Host:instance.",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -65,8 +68,8 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "config parsed successfully with health check labels",
|
desc: "config parsed successfully with health check labels",
|
||||||
services: map[string][]ecsInstance{
|
instances: []ecsInstance{
|
||||||
"testing": {{
|
{
|
||||||
Name: "instance",
|
Name: "instance",
|
||||||
ID: "1",
|
ID: "1",
|
||||||
containerDefinition: &ecs.ContainerDefinition{
|
containerDefinition: &ecs.ContainerDefinition{
|
||||||
|
@ -75,6 +78,9 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
label.TraefikBackendHealthCheckInterval: aws.String("1s"),
|
label.TraefikBackendHealthCheckInterval: aws.String("1s"),
|
||||||
}},
|
}},
|
||||||
machine: &ec2.Instance{
|
machine: &ec2.Instance{
|
||||||
|
State: &ec2.InstanceState{
|
||||||
|
Name: aws.String(ec2.InstanceStateNameRunning),
|
||||||
|
},
|
||||||
PrivateIpAddress: aws.String("10.0.0.1"),
|
PrivateIpAddress: aws.String("10.0.0.1"),
|
||||||
},
|
},
|
||||||
container: &ecs.Container{
|
container: &ecs.Container{
|
||||||
|
@ -82,11 +88,11 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
HostPort: aws.Int64(1337),
|
HostPort: aws.Int64(1337),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}},
|
},
|
||||||
},
|
},
|
||||||
expected: &types.Configuration{
|
expected: &types.Configuration{
|
||||||
Backends: map[string]*types.Backend{
|
Backends: map[string]*types.Backend{
|
||||||
"backend-testing": {
|
"backend-instance": {
|
||||||
HealthCheck: &types.HealthCheck{
|
HealthCheck: &types.HealthCheck{
|
||||||
Path: "/health",
|
Path: "/health",
|
||||||
Interval: "1s",
|
Interval: "1s",
|
||||||
|
@ -98,11 +104,11 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Frontends: map[string]*types.Frontend{
|
Frontends: map[string]*types.Frontend{
|
||||||
"frontend-testing": {
|
"frontend-instance": {
|
||||||
EntryPoints: []string{},
|
EntryPoints: []string{},
|
||||||
Backend: "backend-testing",
|
Backend: "backend-instance",
|
||||||
Routes: map[string]types.Route{
|
Routes: map[string]types.Route{
|
||||||
"route-frontend-testing": {
|
"route-frontend-instance": {
|
||||||
Rule: "Host:instance.",
|
Rule: "Host:instance.",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -114,8 +120,8 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "when all labels are set",
|
desc: "when all labels are set",
|
||||||
services: map[string][]ecsInstance{
|
instances: []ecsInstance{
|
||||||
"testing-instance": {{
|
{
|
||||||
Name: "testing-instance",
|
Name: "testing-instance",
|
||||||
ID: "6",
|
ID: "6",
|
||||||
containerDefinition: &ecs.ContainerDefinition{
|
containerDefinition: &ecs.ContainerDefinition{
|
||||||
|
@ -193,6 +199,9 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
label.Prefix + label.BaseFrontendRateLimit + "bar." + label.SuffixRateLimitBurst: aws.String("9"),
|
label.Prefix + label.BaseFrontendRateLimit + "bar." + label.SuffixRateLimitBurst: aws.String("9"),
|
||||||
}},
|
}},
|
||||||
machine: &ec2.Instance{
|
machine: &ec2.Instance{
|
||||||
|
State: &ec2.InstanceState{
|
||||||
|
Name: aws.String(ec2.InstanceStateNameRunning),
|
||||||
|
},
|
||||||
PrivateIpAddress: aws.String("10.0.0.1"),
|
PrivateIpAddress: aws.String("10.0.0.1"),
|
||||||
},
|
},
|
||||||
container: &ecs.Container{
|
container: &ecs.Container{
|
||||||
|
@ -200,7 +209,7 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
HostPort: aws.Int64(1337),
|
HostPort: aws.Int64(1337),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}},
|
},
|
||||||
},
|
},
|
||||||
expected: &types.Configuration{
|
expected: &types.Configuration{
|
||||||
Backends: map[string]*types.Backend{
|
Backends: map[string]*types.Backend{
|
||||||
|
@ -351,11 +360,11 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
p := &Provider{}
|
p := &Provider{ExposedByDefault: true}
|
||||||
|
|
||||||
services := fakeLoadTraefikLabels(test.services)
|
instances := fakeLoadTraefikLabels(test.instances)
|
||||||
|
|
||||||
got, err := p.buildConfiguration(services)
|
got, err := p.buildConfiguration(instances)
|
||||||
assert.Equal(t, test.err, err) // , err.Error()
|
assert.Equal(t, test.err, err) // , err.Error()
|
||||||
assert.Equal(t, test.expected, got, test.desc)
|
assert.Equal(t, test.expected, got, test.desc)
|
||||||
})
|
})
|
||||||
|
@ -363,27 +372,6 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterInstance(t *testing.T) {
|
func TestFilterInstance(t *testing.T) {
|
||||||
nilPrivateIP := simpleEcsInstance(map[string]*string{})
|
|
||||||
nilPrivateIP.machine.PrivateIpAddress = nil
|
|
||||||
|
|
||||||
nilMachine := simpleEcsInstance(map[string]*string{})
|
|
||||||
nilMachine.machine = nil
|
|
||||||
|
|
||||||
nilMachineState := simpleEcsInstance(map[string]*string{})
|
|
||||||
nilMachineState.machine.State = nil
|
|
||||||
|
|
||||||
nilMachineStateName := simpleEcsInstance(map[string]*string{})
|
|
||||||
nilMachineStateName.machine.State.Name = nil
|
|
||||||
|
|
||||||
invalidMachineState := simpleEcsInstance(map[string]*string{})
|
|
||||||
invalidMachineState.machine.State.Name = aws.String(ec2.InstanceStateNameStopped)
|
|
||||||
|
|
||||||
noNetwork := simpleEcsInstanceNoNetwork(map[string]*string{})
|
|
||||||
|
|
||||||
noNetworkWithLabel := simpleEcsInstanceNoNetwork(map[string]*string{
|
|
||||||
label.TraefikPort: aws.String("80"),
|
|
||||||
})
|
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
instanceInfo ecsInstance
|
instanceInfo ecsInstance
|
||||||
|
@ -419,44 +407,66 @@ func TestFilterInstance(t *testing.T) {
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Instance with nil private ip and exposed by default enabled should be filtered",
|
desc: "Instance with nil private ip and exposed by default enabled should be filtered",
|
||||||
instanceInfo: nilPrivateIP,
|
instanceInfo: func() ecsInstance {
|
||||||
|
nilPrivateIP := simpleEcsInstance(map[string]*string{})
|
||||||
|
nilPrivateIP.machine.PrivateIpAddress = nil
|
||||||
|
return nilPrivateIP
|
||||||
|
}(),
|
||||||
exposedByDefault: true,
|
exposedByDefault: true,
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Instance with nil machine and exposed by default enabled should be filtered",
|
desc: "Instance with nil machine and exposed by default enabled should be filtered",
|
||||||
instanceInfo: nilMachine,
|
instanceInfo: func() ecsInstance {
|
||||||
|
nilMachine := simpleEcsInstance(map[string]*string{})
|
||||||
|
nilMachine.machine = nil
|
||||||
|
return nilMachine
|
||||||
|
}(),
|
||||||
exposedByDefault: true,
|
exposedByDefault: true,
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Instance with nil machine state and exposed by default enabled should be filtered",
|
desc: "Instance with nil machine state and exposed by default enabled should be filtered",
|
||||||
instanceInfo: nilMachineState,
|
instanceInfo: func() ecsInstance {
|
||||||
|
nilMachineState := simpleEcsInstance(map[string]*string{})
|
||||||
|
nilMachineState.machine.State = nil
|
||||||
|
return nilMachineState
|
||||||
|
}(),
|
||||||
exposedByDefault: true,
|
exposedByDefault: true,
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Instance with nil machine state name and exposed by default enabled should be filtered",
|
desc: "Instance with nil machine state name and exposed by default enabled should be filtered",
|
||||||
instanceInfo: nilMachineStateName,
|
instanceInfo: func() ecsInstance {
|
||||||
|
nilMachineStateName := simpleEcsInstance(map[string]*string{})
|
||||||
|
nilMachineStateName.machine.State.Name = nil
|
||||||
|
return nilMachineStateName
|
||||||
|
}(),
|
||||||
exposedByDefault: true,
|
exposedByDefault: true,
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Instance with invalid machine state and exposed by default enabled should be filtered",
|
desc: "Instance with invalid machine state and exposed by default enabled should be filtered",
|
||||||
instanceInfo: invalidMachineState,
|
instanceInfo: func() ecsInstance {
|
||||||
|
invalidMachineState := simpleEcsInstance(map[string]*string{})
|
||||||
|
invalidMachineState.machine.State.Name = aws.String(ec2.InstanceStateNameStopped)
|
||||||
|
return invalidMachineState
|
||||||
|
}(),
|
||||||
exposedByDefault: true,
|
exposedByDefault: true,
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Instance with no port mappings should be filtered",
|
desc: "Instance with no port mappings should be filtered",
|
||||||
instanceInfo: noNetwork,
|
instanceInfo: simpleEcsInstanceNoNetwork(map[string]*string{}),
|
||||||
exposedByDefault: true,
|
exposedByDefault: true,
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Instance with no port mapping and with label should not be filtered",
|
desc: "Instance with no port mapping and with label should not be filtered",
|
||||||
instanceInfo: noNetworkWithLabel,
|
instanceInfo: simpleEcsInstanceNoNetwork(map[string]*string{
|
||||||
|
label.TraefikPort: aws.String("80"),
|
||||||
|
}),
|
||||||
exposedByDefault: true,
|
exposedByDefault: true,
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
|
@ -470,6 +480,7 @@ func TestFilterInstance(t *testing.T) {
|
||||||
prov := &Provider{
|
prov := &Provider{
|
||||||
ExposedByDefault: test.exposedByDefault,
|
ExposedByDefault: test.exposedByDefault,
|
||||||
}
|
}
|
||||||
|
|
||||||
actual := prov.filterInstance(test.instanceInfo)
|
actual := prov.filterInstance(test.instanceInfo)
|
||||||
assert.Equal(t, test.expected, actual)
|
assert.Equal(t, test.expected, actual)
|
||||||
})
|
})
|
||||||
|
@ -756,15 +767,11 @@ func simpleEcsInstanceNoNetwork(labels map[string]*string) ecsInstance {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func fakeLoadTraefikLabels(services map[string][]ecsInstance) map[string][]ecsInstance {
|
func fakeLoadTraefikLabels(instances []ecsInstance) []ecsInstance {
|
||||||
result := make(map[string][]ecsInstance)
|
var result []ecsInstance
|
||||||
for name, srcInstances := range services {
|
for _, instance := range instances {
|
||||||
var instances []ecsInstance
|
instance.TraefikLabels = aws.StringValueMap(instance.containerDefinition.DockerLabels)
|
||||||
for _, instance := range srcInstances {
|
result = append(result, instance)
|
||||||
instance.TraefikLabels = aws.StringValueMap(instance.containerDefinition.DockerLabels)
|
|
||||||
instances = append(instances, instance)
|
|
||||||
}
|
|
||||||
result[name] = instances
|
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
"github.com/containous/traefik/log"
|
"github.com/containous/traefik/log"
|
||||||
"github.com/containous/traefik/provider/label"
|
"github.com/containous/traefik/provider/label"
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
|
@ -12,7 +13,18 @@ import (
|
||||||
|
|
||||||
// buildConfiguration fills the config template with the given instances
|
// buildConfiguration fills the config template with the given instances
|
||||||
// Deprecated
|
// Deprecated
|
||||||
func (p *Provider) buildConfigurationV1(services map[string][]ecsInstance) (*types.Configuration, error) {
|
func (p *Provider) buildConfigurationV1(instances []ecsInstance) (*types.Configuration, error) {
|
||||||
|
services := make(map[string][]ecsInstance)
|
||||||
|
for _, instance := range instances {
|
||||||
|
if p.filterInstanceV1(instance) {
|
||||||
|
if serviceInstances, ok := services[instance.Name]; ok {
|
||||||
|
services[instance.Name] = append(serviceInstances, instance)
|
||||||
|
} else {
|
||||||
|
services[instance.Name] = []ecsInstance{instance}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var ecsFuncMap = template.FuncMap{
|
var ecsFuncMap = template.FuncMap{
|
||||||
// Backend functions
|
// Backend functions
|
||||||
"getHost": getHost,
|
"getHost": getHost,
|
||||||
|
@ -45,6 +57,35 @@ func (p *Provider) buildConfigurationV1(services map[string][]ecsInstance) (*typ
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) filterInstanceV1(i ecsInstance) bool {
|
||||||
|
if labelPort := getStringValueV1(i, label.TraefikPort, ""); len(i.container.NetworkBindings) == 0 && labelPort == "" {
|
||||||
|
log.Debugf("Filtering ecs instance without port %s (%s)", i.Name, i.ID)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.machine == nil || i.machine.State == nil || i.machine.State.Name == nil {
|
||||||
|
log.Debugf("Filtering ecs instance in an missing ec2 information %s (%s)", i.Name, i.ID)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if aws.StringValue(i.machine.State.Name) != ec2.InstanceStateNameRunning {
|
||||||
|
log.Debugf("Filtering ecs instance in an incorrect state %s (%s) (state = %s)", i.Name, i.ID, aws.StringValue(i.machine.State.Name))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if i.machine.PrivateIpAddress == nil {
|
||||||
|
log.Debugf("Filtering ecs instance without an ip address %s (%s)", i.Name, i.ID)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isEnabled(i, p.ExposedByDefault) {
|
||||||
|
log.Debugf("Filtering disabled ecs instance %s (%s)", i.Name, i.ID)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Deprecated
|
// TODO: Deprecated
|
||||||
// replaced by Stickiness
|
// replaced by Stickiness
|
||||||
// Deprecated
|
// Deprecated
|
||||||
|
|
|
@ -13,21 +13,24 @@ import (
|
||||||
|
|
||||||
func TestBuildConfigurationV1(t *testing.T) {
|
func TestBuildConfigurationV1(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
services map[string][]ecsInstance
|
instances []ecsInstance
|
||||||
expected *types.Configuration
|
expected *types.Configuration
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "config parsed successfully",
|
desc: "config parsed successfully",
|
||||||
services: map[string][]ecsInstance{
|
instances: []ecsInstance{
|
||||||
"testing": {{
|
{
|
||||||
Name: "testing",
|
Name: "testing",
|
||||||
ID: "1",
|
ID: "1",
|
||||||
containerDefinition: &ecs.ContainerDefinition{
|
containerDefinition: &ecs.ContainerDefinition{
|
||||||
DockerLabels: map[string]*string{},
|
DockerLabels: map[string]*string{},
|
||||||
},
|
},
|
||||||
machine: &ec2.Instance{
|
machine: &ec2.Instance{
|
||||||
|
State: &ec2.InstanceState{
|
||||||
|
Name: aws.String(ec2.InstanceStateNameRunning),
|
||||||
|
},
|
||||||
PrivateIpAddress: aws.String("10.0.0.1"),
|
PrivateIpAddress: aws.String("10.0.0.1"),
|
||||||
},
|
},
|
||||||
container: &ecs.Container{
|
container: &ecs.Container{
|
||||||
|
@ -35,7 +38,7 @@ func TestBuildConfigurationV1(t *testing.T) {
|
||||||
HostPort: aws.Int64(1337),
|
HostPort: aws.Int64(1337),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}},
|
},
|
||||||
},
|
},
|
||||||
expected: &types.Configuration{
|
expected: &types.Configuration{
|
||||||
Backends: map[string]*types.Backend{
|
Backends: map[string]*types.Backend{
|
||||||
|
@ -66,8 +69,8 @@ func TestBuildConfigurationV1(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "config parsed successfully with health check labels",
|
desc: "config parsed successfully with health check labels",
|
||||||
services: map[string][]ecsInstance{
|
instances: []ecsInstance{
|
||||||
"testing": {{
|
{
|
||||||
Name: "testing",
|
Name: "testing",
|
||||||
ID: "1",
|
ID: "1",
|
||||||
containerDefinition: &ecs.ContainerDefinition{
|
containerDefinition: &ecs.ContainerDefinition{
|
||||||
|
@ -76,6 +79,9 @@ func TestBuildConfigurationV1(t *testing.T) {
|
||||||
label.TraefikBackendHealthCheckInterval: aws.String("1s"),
|
label.TraefikBackendHealthCheckInterval: aws.String("1s"),
|
||||||
}},
|
}},
|
||||||
machine: &ec2.Instance{
|
machine: &ec2.Instance{
|
||||||
|
State: &ec2.InstanceState{
|
||||||
|
Name: aws.String(ec2.InstanceStateNameRunning),
|
||||||
|
},
|
||||||
PrivateIpAddress: aws.String("10.0.0.1"),
|
PrivateIpAddress: aws.String("10.0.0.1"),
|
||||||
},
|
},
|
||||||
container: &ecs.Container{
|
container: &ecs.Container{
|
||||||
|
@ -83,7 +89,7 @@ func TestBuildConfigurationV1(t *testing.T) {
|
||||||
HostPort: aws.Int64(1337),
|
HostPort: aws.Int64(1337),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}},
|
},
|
||||||
},
|
},
|
||||||
expected: &types.Configuration{
|
expected: &types.Configuration{
|
||||||
Backends: map[string]*types.Backend{
|
Backends: map[string]*types.Backend{
|
||||||
|
@ -118,8 +124,8 @@ func TestBuildConfigurationV1(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "when all labels are set",
|
desc: "when all labels are set",
|
||||||
services: map[string][]ecsInstance{
|
instances: []ecsInstance{
|
||||||
"testing-instance": {{
|
{
|
||||||
Name: "testing-instance",
|
Name: "testing-instance",
|
||||||
ID: "6",
|
ID: "6",
|
||||||
containerDefinition: &ecs.ContainerDefinition{
|
containerDefinition: &ecs.ContainerDefinition{
|
||||||
|
@ -144,6 +150,9 @@ func TestBuildConfigurationV1(t *testing.T) {
|
||||||
label.TraefikFrontendRule: aws.String("Host:traefik.io"),
|
label.TraefikFrontendRule: aws.String("Host:traefik.io"),
|
||||||
}},
|
}},
|
||||||
machine: &ec2.Instance{
|
machine: &ec2.Instance{
|
||||||
|
State: &ec2.InstanceState{
|
||||||
|
Name: aws.String(ec2.InstanceStateNameRunning),
|
||||||
|
},
|
||||||
PrivateIpAddress: aws.String("10.0.0.1"),
|
PrivateIpAddress: aws.String("10.0.0.1"),
|
||||||
},
|
},
|
||||||
container: &ecs.Container{
|
container: &ecs.Container{
|
||||||
|
@ -151,7 +160,7 @@ func TestBuildConfigurationV1(t *testing.T) {
|
||||||
HostPort: aws.Int64(1337),
|
HostPort: aws.Int64(1337),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}},
|
},
|
||||||
},
|
},
|
||||||
expected: &types.Configuration{
|
expected: &types.Configuration{
|
||||||
Backends: map[string]*types.Backend{
|
Backends: map[string]*types.Backend{
|
||||||
|
@ -204,11 +213,11 @@ func TestBuildConfigurationV1(t *testing.T) {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
provider := &Provider{}
|
provider := &Provider{ExposedByDefault: true}
|
||||||
|
|
||||||
services := fakeLoadTraefikLabels(test.services)
|
instances := fakeLoadTraefikLabels(test.instances)
|
||||||
|
|
||||||
got, err := provider.buildConfigurationV1(services)
|
got, err := provider.buildConfigurationV1(instances)
|
||||||
assert.Equal(t, test.err, err) // , err.Error()
|
assert.Equal(t, test.err, err) // , err.Error()
|
||||||
assert.Equal(t, test.expected, got, test.desc)
|
assert.Equal(t, test.expected, got, test.desc)
|
||||||
})
|
})
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/BurntSushi/ty/fun"
|
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
"github.com/aws/aws-sdk-go/aws/defaults"
|
"github.com/aws/aws-sdk-go/aws/defaults"
|
||||||
|
@ -19,7 +18,6 @@ import (
|
||||||
"github.com/containous/traefik/job"
|
"github.com/containous/traefik/job"
|
||||||
"github.com/containous/traefik/log"
|
"github.com/containous/traefik/log"
|
||||||
"github.com/containous/traefik/provider"
|
"github.com/containous/traefik/provider"
|
||||||
"github.com/containous/traefik/provider/label"
|
|
||||||
"github.com/containous/traefik/safe"
|
"github.com/containous/traefik/safe"
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
)
|
)
|
||||||
|
@ -105,7 +103,6 @@ func (p *Provider) createClient() (*awsClient, error) {
|
||||||
// Provide allows the ecs provider to provide configurations to traefik
|
// Provide allows the ecs provider to provide configurations to traefik
|
||||||
// using the given configuration channel.
|
// using the given configuration channel.
|
||||||
func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
|
func (p *Provider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, constraints types.Constraints) error {
|
||||||
|
|
||||||
p.Constraints = append(p.Constraints, constraints...)
|
p.Constraints = append(p.Constraints, constraints...)
|
||||||
|
|
||||||
handleCanceled := func(ctx context.Context, err error) error {
|
handleCanceled := func(ctx context.Context, err error) error {
|
||||||
|
@ -179,26 +176,6 @@ func wrapAws(ctx context.Context, req *request.Request) error {
|
||||||
return req.Send()
|
return req.Send()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) loadECSConfig(ctx context.Context, client *awsClient) (*types.Configuration, error) {
|
|
||||||
instances, err := p.listInstances(ctx, client)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
instances = fun.Filter(p.filterInstance, instances).([]ecsInstance)
|
|
||||||
|
|
||||||
services := make(map[string][]ecsInstance)
|
|
||||||
|
|
||||||
for _, instance := range instances {
|
|
||||||
if serviceInstances, ok := services[instance.Name]; ok {
|
|
||||||
services[instance.Name] = append(serviceInstances, instance)
|
|
||||||
} else {
|
|
||||||
services[instance.Name] = []ecsInstance{instance}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return p.buildConfiguration(services)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find all running Provider tasks in a cluster, also collect the task definitions (for docker labels)
|
// Find all running Provider tasks in a cluster, also collect the task definitions (for docker labels)
|
||||||
// and the EC2 instance data
|
// and the EC2 instance data
|
||||||
func (p *Provider) listInstances(ctx context.Context, client *awsClient) ([]ecsInstance, error) {
|
func (p *Provider) listInstances(ctx context.Context, client *awsClient) ([]ecsInstance, error) {
|
||||||
|
@ -401,34 +378,13 @@ func (p *Provider) lookupTaskDefinitions(ctx context.Context, client *awsClient,
|
||||||
return taskDefinitions, nil
|
return taskDefinitions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) filterInstance(i ecsInstance) bool {
|
func (p *Provider) loadECSConfig(ctx context.Context, client *awsClient) (*types.Configuration, error) {
|
||||||
|
instances, err := p.listInstances(ctx, client)
|
||||||
if labelPort := getStringValueV1(i, label.TraefikPort, ""); len(i.container.NetworkBindings) == 0 && labelPort == "" {
|
if err != nil {
|
||||||
log.Debugf("Filtering ecs instance without port %s (%s)", i.Name, i.ID)
|
return nil, err
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if i.machine == nil || i.machine.State == nil || i.machine.State.Name == nil {
|
return p.buildConfiguration(instances)
|
||||||
log.Debugf("Filtering ecs instance in an missing ec2 information %s (%s)", i.Name, i.ID)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if aws.StringValue(i.machine.State.Name) != ec2.InstanceStateNameRunning {
|
|
||||||
log.Debugf("Filtering ecs instance in an incorrect state %s (%s) (state = %s)", i.Name, i.ID, aws.StringValue(i.machine.State.Name))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if i.machine.PrivateIpAddress == nil {
|
|
||||||
log.Debugf("Filtering ecs instance without an ip address %s (%s)", i.Name, i.ID)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isEnabled(i, p.ExposedByDefault) {
|
|
||||||
log.Debugf("Filtering disabled ecs instance %s (%s)", i.Name, i.ID)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provider expects no more than 100 parameters be passed to a DescribeTask call; thus, pack
|
// Provider expects no more than 100 parameters be passed to a DescribeTask call; thus, pack
|
||||||
|
|
Loading…
Reference in a new issue