Allow binding ECS container port
This commit is contained in:
parent
12c713b187
commit
0d262561d1
5 changed files with 89 additions and 28 deletions
|
@ -68,7 +68,7 @@ func (p *Provider) filterInstance(i ecsInstance) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if labelPort := label.GetStringValue(i.TraefikLabels, label.TraefikPort, ""); i.machine.port == 0 && labelPort == "" {
|
if labelPort := label.GetStringValue(i.TraefikLabels, label.TraefikPort, ""); len(i.machine.ports) == 0 && labelPort == "" {
|
||||||
log.Debugf("Filtering ecs instance without port %s (%s)", i.Name, i.ID)
|
log.Debugf("Filtering ecs instance without port %s (%s)", i.Name, i.ID)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -119,9 +119,17 @@ func getHost(i ecsInstance) string {
|
||||||
|
|
||||||
func getPort(i ecsInstance) string {
|
func getPort(i ecsInstance) string {
|
||||||
if value := label.GetStringValue(i.TraefikLabels, label.TraefikPort, ""); len(value) > 0 {
|
if value := label.GetStringValue(i.TraefikLabels, label.TraefikPort, ""); len(value) > 0 {
|
||||||
|
port, err := strconv.ParseInt(value, 10, 64)
|
||||||
|
if err == nil {
|
||||||
|
for _, mapping := range i.machine.ports {
|
||||||
|
if port == mapping.hostPort || port == mapping.containerPort {
|
||||||
|
return strconv.FormatInt(mapping.hostPort, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
return strconv.FormatInt(i.machine.port, 10)
|
}
|
||||||
|
return strconv.FormatInt(i.machine.ports[0].hostPort, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterFrontends(instances []ecsInstance) []ecsInstance {
|
func filterFrontends(instances []ecsInstance) []ecsInstance {
|
||||||
|
|
|
@ -32,7 +32,7 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
machine: &machine{
|
machine: &machine{
|
||||||
state: ec2.InstanceStateNameRunning,
|
state: ec2.InstanceStateNameRunning,
|
||||||
privateIP: "10.0.0.1",
|
privateIP: "10.0.0.1",
|
||||||
port: 1337,
|
ports: []portMapping{{hostPort: 1337}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -75,7 +75,7 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
machine: &machine{
|
machine: &machine{
|
||||||
state: ec2.InstanceStateNameRunning,
|
state: ec2.InstanceStateNameRunning,
|
||||||
privateIP: "10.0.0.1",
|
privateIP: "10.0.0.1",
|
||||||
port: 1337,
|
ports: []portMapping{{hostPort: 1337}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -195,7 +195,7 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
machine: &machine{
|
machine: &machine{
|
||||||
state: ec2.InstanceStateNameRunning,
|
state: ec2.InstanceStateNameRunning,
|
||||||
privateIP: "10.0.0.1",
|
privateIP: "10.0.0.1",
|
||||||
port: 1337,
|
ports: []portMapping{{hostPort: 1337}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -435,7 +435,7 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
machine: &machine{
|
machine: &machine{
|
||||||
state: ec2.InstanceStateNameRunning,
|
state: ec2.InstanceStateNameRunning,
|
||||||
privateIP: "10.0.0.1",
|
privateIP: "10.0.0.1",
|
||||||
port: 1337,
|
ports: []portMapping{{hostPort: 1337}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -522,7 +522,7 @@ func TestBuildConfiguration(t *testing.T) {
|
||||||
machine: &machine{
|
machine: &machine{
|
||||||
state: ec2.InstanceStateNameRunning,
|
state: ec2.InstanceStateNameRunning,
|
||||||
privateIP: "10.2.2.1",
|
privateIP: "10.2.2.1",
|
||||||
port: 1337,
|
ports: []portMapping{{hostPort: 1337}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -876,6 +876,27 @@ func TestGetPort(t *testing.T) {
|
||||||
label.TraefikPort: aws.String("80"),
|
label.TraefikPort: aws.String("80"),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "Container label should provide exposed port",
|
||||||
|
expected: "6536",
|
||||||
|
instanceInfo: simpleEcsInstanceDynamicPorts(map[string]*string{
|
||||||
|
label.TraefikPort: aws.String("8080"),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Wrong port container label should provide default exposed port",
|
||||||
|
expected: "9000",
|
||||||
|
instanceInfo: simpleEcsInstanceDynamicPorts(map[string]*string{
|
||||||
|
label.TraefikPort: aws.String("9000"),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "Invalid port container label should provide default exposed port",
|
||||||
|
expected: "6535",
|
||||||
|
instanceInfo: simpleEcsInstanceDynamicPorts(map[string]*string{
|
||||||
|
label.TraefikPort: aws.String("foo"),
|
||||||
|
}),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
|
@ -987,7 +1008,7 @@ func makeEcsInstance(containerDef *ecs.ContainerDefinition) ecsInstance {
|
||||||
machine: &machine{
|
machine: &machine{
|
||||||
state: ec2.InstanceStateNameRunning,
|
state: ec2.InstanceStateNameRunning,
|
||||||
privateIP: "10.0.0.0",
|
privateIP: "10.0.0.0",
|
||||||
port: 1337,
|
ports: []portMapping{{hostPort: 1337}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1003,7 +1024,7 @@ func simpleEcsInstance(labels map[string]*string) ecsInstance {
|
||||||
Name: aws.String("http"),
|
Name: aws.String("http"),
|
||||||
DockerLabels: labels,
|
DockerLabels: labels,
|
||||||
})
|
})
|
||||||
instance.machine.port = 80
|
instance.machine.ports = []portMapping{{hostPort: 80}}
|
||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1012,7 +1033,25 @@ func simpleEcsInstanceNoNetwork(labels map[string]*string) ecsInstance {
|
||||||
Name: aws.String("http"),
|
Name: aws.String("http"),
|
||||||
DockerLabels: labels,
|
DockerLabels: labels,
|
||||||
})
|
})
|
||||||
instance.machine.port = 0
|
instance.machine.ports = []portMapping{}
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
|
||||||
|
func simpleEcsInstanceDynamicPorts(labels map[string]*string) ecsInstance {
|
||||||
|
instance := makeEcsInstance(&ecs.ContainerDefinition{
|
||||||
|
Name: aws.String("http"),
|
||||||
|
DockerLabels: labels,
|
||||||
|
})
|
||||||
|
instance.machine.ports = []portMapping{
|
||||||
|
{
|
||||||
|
containerPort: 80,
|
||||||
|
hostPort: 6535,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
containerPort: 8080,
|
||||||
|
hostPort: 6536,
|
||||||
|
},
|
||||||
|
}
|
||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ func (p *Provider) filterInstanceV1(i ecsInstance) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if labelPort := getStringValueV1(i, label.TraefikPort, ""); i.machine.port == 0 && labelPort == "" {
|
if labelPort := getStringValueV1(i, label.TraefikPort, ""); len(i.machine.ports) == 0 && labelPort == "" {
|
||||||
log.Debugf("Filtering ecs instance without port %s (%s)", i.Name, i.ID)
|
log.Debugf("Filtering ecs instance without port %s (%s)", i.Name, i.ID)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ func TestBuildConfigurationV1(t *testing.T) {
|
||||||
machine: &machine{
|
machine: &machine{
|
||||||
state: ec2.InstanceStateNameRunning,
|
state: ec2.InstanceStateNameRunning,
|
||||||
privateIP: "10.0.0.1",
|
privateIP: "10.0.0.1",
|
||||||
port: 1337,
|
ports: []portMapping{{hostPort: 1337}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -76,7 +76,7 @@ func TestBuildConfigurationV1(t *testing.T) {
|
||||||
machine: &machine{
|
machine: &machine{
|
||||||
state: ec2.InstanceStateNameRunning,
|
state: ec2.InstanceStateNameRunning,
|
||||||
privateIP: "10.0.0.1",
|
privateIP: "10.0.0.1",
|
||||||
port: 1337,
|
ports: []portMapping{{hostPort: 1337}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -142,7 +142,7 @@ func TestBuildConfigurationV1(t *testing.T) {
|
||||||
machine: &machine{
|
machine: &machine{
|
||||||
state: ec2.InstanceStateNameRunning,
|
state: ec2.InstanceStateNameRunning,
|
||||||
privateIP: "10.0.0.1",
|
privateIP: "10.0.0.1",
|
||||||
port: 1337,
|
ports: []portMapping{{hostPort: 1337}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -219,7 +219,7 @@ func TestBuildConfigurationV1(t *testing.T) {
|
||||||
machine: &machine{
|
machine: &machine{
|
||||||
state: ec2.InstanceStateNameRunning,
|
state: ec2.InstanceStateNameRunning,
|
||||||
privateIP: "10.0.0.1",
|
privateIP: "10.0.0.1",
|
||||||
port: 1337,
|
ports: []portMapping{{hostPort: 1337}},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
Name: "testing-instance-v2",
|
Name: "testing-instance-v2",
|
||||||
|
@ -248,7 +248,7 @@ func TestBuildConfigurationV1(t *testing.T) {
|
||||||
machine: &machine{
|
machine: &machine{
|
||||||
state: ec2.InstanceStateNameRunning,
|
state: ec2.InstanceStateNameRunning,
|
||||||
privateIP: "10.0.0.2",
|
privateIP: "10.0.0.2",
|
||||||
port: 1337,
|
ports: []portMapping{{hostPort: 1337}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -48,11 +48,16 @@ type ecsInstance struct {
|
||||||
TraefikLabels map[string]string
|
TraefikLabels map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type portMapping struct {
|
||||||
|
containerPort int64
|
||||||
|
hostPort int64
|
||||||
|
}
|
||||||
|
|
||||||
type machine struct {
|
type machine struct {
|
||||||
name string
|
name string
|
||||||
state string
|
state string
|
||||||
privateIP string
|
privateIP string
|
||||||
port int64
|
ports []portMapping
|
||||||
}
|
}
|
||||||
|
|
||||||
type awsClient struct {
|
type awsClient struct {
|
||||||
|
@ -203,8 +208,7 @@ func (p *Provider) listInstances(ctx context.Context, client *awsClient) ([]ecsI
|
||||||
} else if p.Cluster != "" {
|
} else if p.Cluster != "" {
|
||||||
// TODO: Deprecated configuration - Need to be removed in the future
|
// TODO: Deprecated configuration - Need to be removed in the future
|
||||||
clusters = Clusters{p.Cluster}
|
clusters = Clusters{p.Cluster}
|
||||||
log.Warn("Deprecated configuration found: ecs.cluster " +
|
log.Warn("Deprecated configuration found: ecs.cluster. Please use ecs.clusters instead.")
|
||||||
"Please use ecs.clusters instead.")
|
|
||||||
} else {
|
} else {
|
||||||
clusters = p.Clusters
|
clusters = p.Clusters
|
||||||
}
|
}
|
||||||
|
@ -280,23 +284,33 @@ func (p *Provider) listInstances(ctx context.Context, client *awsClient) ([]ecsI
|
||||||
|
|
||||||
var mach *machine
|
var mach *machine
|
||||||
if aws.StringValue(task.LaunchType) == ecs.LaunchTypeFargate {
|
if aws.StringValue(task.LaunchType) == ecs.LaunchTypeFargate {
|
||||||
var hostPort int64
|
var ports []portMapping
|
||||||
if len(containerDefinition.PortMappings) > 0 && containerDefinition.PortMappings[0] != nil {
|
for _, mapping := range containerDefinition.PortMappings {
|
||||||
hostPort = aws.Int64Value(containerDefinition.PortMappings[0].HostPort)
|
if mapping != nil {
|
||||||
|
ports = append(ports, portMapping{
|
||||||
|
hostPort: aws.Int64Value(mapping.HostPort),
|
||||||
|
containerPort: aws.Int64Value(mapping.ContainerPort),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mach = &machine{
|
mach = &machine{
|
||||||
privateIP: aws.StringValue(container.NetworkInterfaces[0].PrivateIpv4Address),
|
privateIP: aws.StringValue(container.NetworkInterfaces[0].PrivateIpv4Address),
|
||||||
port: hostPort,
|
ports: ports,
|
||||||
state: aws.StringValue(task.LastStatus),
|
state: aws.StringValue(task.LastStatus),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var hostPort int64
|
var ports []portMapping
|
||||||
if len(container.NetworkBindings) > 0 && container.NetworkBindings[0] != nil {
|
for _, mapping := range container.NetworkBindings {
|
||||||
hostPort = aws.Int64Value(container.NetworkBindings[0].HostPort)
|
if mapping != nil {
|
||||||
|
ports = append(ports, portMapping{
|
||||||
|
hostPort: aws.Int64Value(mapping.HostPort),
|
||||||
|
containerPort: aws.Int64Value(mapping.ContainerPort),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mach = &machine{
|
mach = &machine{
|
||||||
privateIP: aws.StringValue(containerInstance.PrivateIpAddress),
|
privateIP: aws.StringValue(containerInstance.PrivateIpAddress),
|
||||||
port: hostPort,
|
ports: ports,
|
||||||
state: aws.StringValue(containerInstance.State.Name),
|
state: aws.StringValue(containerInstance.State.Name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue