diff --git a/agent/api/ecsclient/client.go b/agent/api/ecsclient/client.go index 39e8e21fde..9638f4c2e5 100644 --- a/agent/api/ecsclient/client.go +++ b/agent/api/ecsclient/client.go @@ -413,7 +413,7 @@ func (client *APIECSClient) SubmitTaskStateChange(change api.TaskStateChange) er containerEvents := make([]*ecs.ContainerStateChange, len(change.Containers)) for i, containerEvent := range change.Containers { - containerEvents[i] = client.buildContainerStateChangePayload(containerEvent) + containerEvents[i] = client.buildContainerStateChangePayload(containerEvent, client.config.IPv6PortBindingExcluded.Enabled()) } req.Containers = containerEvents @@ -454,7 +454,7 @@ func (client *APIECSClient) buildManagedAgentStateChangePayload(change api.Manag } } -func (client *APIECSClient) buildContainerStateChangePayload(change api.ContainerStateChange) *ecs.ContainerStateChange { +func (client *APIECSClient) buildContainerStateChangePayload(change api.ContainerStateChange, iPv6PortBindingExcluded bool) *ecs.ContainerStateChange { statechange := &ecs.ContainerStateChange{ ContainerName: aws.String(change.ContainerName), } @@ -487,19 +487,25 @@ func (client *APIECSClient) buildContainerStateChangePayload(change api.Containe exitCode := int64(aws.IntValue(change.ExitCode)) statechange.ExitCode = aws.Int64(exitCode) } - networkBindings := make([]*ecs.NetworkBinding, len(change.PortBindings)) - for i, binding := range change.PortBindings { + + networkBindings := []*ecs.NetworkBinding{} + for _, binding := range change.PortBindings { + if binding.BindIP == "::" && iPv6PortBindingExcluded { + seelog.Debugf("To exclude IPv6 port bindings: %v as IPv6 port bindings is requested to be excluded", binding) + continue + } + hostPort := int64(binding.HostPort) containerPort := int64(binding.ContainerPort) bindIP := binding.BindIP protocol := binding.Protocol.String() - networkBindings[i] = &ecs.NetworkBinding{ + networkBindings = append(networkBindings, &ecs.NetworkBinding{ BindIP: aws.String(bindIP), ContainerPort: aws.Int64(containerPort), HostPort: aws.Int64(hostPort), Protocol: aws.String(protocol), - } + }) } statechange.NetworkBindings = networkBindings @@ -507,7 +513,7 @@ func (client *APIECSClient) buildContainerStateChangePayload(change api.Containe } func (client *APIECSClient) SubmitContainerStateChange(change api.ContainerStateChange) error { - pl := client.buildContainerStateChangePayload(change) + pl := client.buildContainerStateChangePayload(change, client.config.IPv6PortBindingExcluded.Enabled()) if pl == nil { return nil } diff --git a/agent/api/ecsclient/client_test.go b/agent/api/ecsclient/client_test.go index 532251eb65..23fc74f0bf 100644 --- a/agent/api/ecsclient/client_test.go +++ b/agent/api/ecsclient/client_test.go @@ -84,9 +84,10 @@ func NewMockClient(ctrl *gomock.Controller, return NewMockClientWithConfig(ctrl, ec2Metadata, additionalAttributes, &config.Config{ - Cluster: configuredCluster, - AWSRegion: "us-east-1", - InstanceAttributes: additionalAttributes, + Cluster: configuredCluster, + AWSRegion: "us-east-1", + InstanceAttributes: additionalAttributes, + IPv6PortBindingExcluded: config.BooleanDefaultTrue{Value: config.ExplicitlyEnabled}, }) } diff --git a/agent/config/config.go b/agent/config/config.go index bf6f38a178..31ffa84044 100644 --- a/agent/config/config.go +++ b/agent/config/config.go @@ -591,6 +591,7 @@ func environmentConfig() (Config, error) { FSxWindowsFileServerCapable: parseFSxWindowsFileServerCapability(), External: parseBooleanDefaultFalseConfig("ECS_EXTERNAL"), EnableRuntimeStats: parseBooleanDefaultFalseConfig("ECS_ENABLE_RUNTIME_STATS"), + IPv6PortBindingExcluded: parseBooleanDefaultTrueConfig("ECS_EXCLUDE_IPV6_PORTBINDING"), }, err } @@ -623,6 +624,7 @@ func (cfg *Config) String() string { "ContainerCreateTimeout: %v, "+ "DependentContainersPullUpfront: %v, "+ "TaskCPUMemLimit: %v, "+ + "IPv6PortBindingExcluded: %v, "+ "%s", cfg.Cluster, cfg.AWSRegion, @@ -640,6 +642,7 @@ func (cfg *Config) String() string { cfg.ContainerCreateTimeout, cfg.DependentContainersPullUpfront, cfg.TaskCPUMemLimit, + cfg.IPv6PortBindingExcluded, cfg.platformString(), ) } diff --git a/agent/config/config_test.go b/agent/config/config_test.go index 929020e7af..49485dd003 100644 --- a/agent/config/config_test.go +++ b/agent/config/config_test.go @@ -157,6 +157,7 @@ func TestEnvironmentConfig(t *testing.T) { defer setTestEnv("ECS_CGROUP_CPU_PERIOD", "") defer setTestEnv("ECS_PULL_DEPENDENT_CONTAINERS_UPFRONT", "true")() defer setTestEnv("ECS_ENABLE_RUNTIME_STATS", "true")() + defer setTestEnv("ECS_EXCLUDE_IPV6_PORTBINDING", "true")() additionalLocalRoutesJSON := `["1.2.3.4/22","5.6.7.8/32"]` setTestEnv("ECS_AWSVPC_ADDITIONAL_LOCAL_ROUTES", additionalLocalRoutesJSON) setTestEnv("ECS_ENABLE_CONTAINER_METADATA", "true") @@ -214,6 +215,7 @@ func TestEnvironmentConfig(t *testing.T) { assert.Equal(t, []string{"efsAuth"}, conf.VolumePluginCapabilities) assert.True(t, conf.DependentContainersPullUpfront.Enabled(), "Wrong value for DependentContainersPullUpfront") assert.True(t, conf.EnableRuntimeStats.Enabled(), "Wrong value for EnableRuntimeStats") + assert.True(t, conf.IPv6PortBindingExcluded.Enabled(), "Wrong value for IPv6PortBindingExcluded") } func TestTrimWhitespaceWhenCreating(t *testing.T) { diff --git a/agent/config/config_unix.go b/agent/config/config_unix.go index 6692b8770d..679d6dd115 100644 --- a/agent/config/config_unix.go +++ b/agent/config/config_unix.go @@ -97,6 +97,7 @@ func DefaultConfig() Config { FSxWindowsFileServerCapable: false, RuntimeStatsLogFile: defaultRuntimeStatsLogFile, EnableRuntimeStats: BooleanDefaultFalse{Value: NotSet}, + IPv6PortBindingExcluded: BooleanDefaultTrue{Value: ExplicitlyEnabled}, } } diff --git a/agent/config/config_unix_test.go b/agent/config/config_unix_test.go index e073b82d5e..f2a7c27d05 100644 --- a/agent/config/config_unix_test.go +++ b/agent/config/config_unix_test.go @@ -72,6 +72,7 @@ func TestConfigDefault(t *testing.T) { assert.False(t, cfg.DependentContainersPullUpfront.Enabled(), "Default DependentContainersPullUpfront set incorrectly") assert.False(t, cfg.PollMetrics.Enabled(), "ECS_POLL_METRICS default should be false") assert.False(t, cfg.EnableRuntimeStats.Enabled(), "Default EnableRuntimeStats set incorrectly") + assert.False(t, cfg.IPv6PortBindingExcluded.Enabled(), "Default IPv6PortBindingExcluded set incorrectly") } // TestConfigFromFile tests the configuration can be read from file diff --git a/agent/config/config_windows.go b/agent/config/config_windows.go index 16c99caf09..cb3f60ea72 100644 --- a/agent/config/config_windows.go +++ b/agent/config/config_windows.go @@ -136,6 +136,7 @@ func DefaultConfig() Config { CNIPluginsPath: filepath.Join(ecsBinaryDir, defaultCNIPluginDirName), RuntimeStatsLogFile: filepath.Join(ecsRoot, defaultRuntimeStatsLogFile), EnableRuntimeStats: BooleanDefaultFalse{Value: NotSet}, + IPv6PortBindingExcluded: BooleanDefaultTrue{Value: ExplicitlyEnabled}, } } diff --git a/agent/config/config_windows_test.go b/agent/config/config_windows_test.go index 45f403c9c0..d4e91f88f2 100644 --- a/agent/config/config_windows_test.go +++ b/agent/config/config_windows_test.go @@ -69,6 +69,7 @@ func TestConfigDefault(t *testing.T) { assert.Equal(t, DefaultImagePullTimeout, cfg.ImagePullTimeout, "Default ImagePullTimeout set incorrectly") assert.False(t, cfg.DependentContainersPullUpfront.Enabled(), "Default DependentContainersPullUpfront set incorrectly") assert.False(t, cfg.EnableRuntimeStats.Enabled(), "Default EnableRuntimeStats set incorrectly") + assert.True(t, cfg.IPv6PortBindingExcluded.Enabled(), "Default IPv6PortBindingExcluded set incorrectly") } func TestConfigIAMTaskRolesReserves80(t *testing.T) { diff --git a/agent/config/types.go b/agent/config/types.go index d2b5c46d66..22152cb7d2 100644 --- a/agent/config/types.go +++ b/agent/config/types.go @@ -349,4 +349,8 @@ type Config struct { // EnableRuntimeStats specifies if pprof should be enabled through the agent introspection port. By default, this configuration // is set to false and can be overridden by means of the ECS_ENABLE_RUNTIME_STATS environment variable. EnableRuntimeStats BooleanDefaultFalse + + // IPv6PortBindingExcluded specifies whether agent should exclude IPv6 port bindings reported from docker. This configuration + // is set to true by default, and can be overridden by the ECS_EXCLUDE_IPV6_PORTBINDING environment variable. + IPv6PortBindingExcluded BooleanDefaultTrue }