Skip to content

Commit 4e8633c

Browse files
committed
Include IPv6 address in TMDS v4 container metadata response
1 parent 1a770f8 commit 4e8633c

2 files changed

Lines changed: 157 additions & 2 deletions

File tree

agent/handlers/task_server_setup_test.go

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ import (
6666
smithy "github.com/aws/smithy-go"
6767
smithyhttp "github.com/aws/smithy-go/transport/http"
6868
"github.com/docker/docker/api/types"
69+
"github.com/docker/docker/api/types/network"
6970
"github.com/golang/mock/gomock"
7071
"github.com/gorilla/mux"
7172
"github.com/stretchr/testify/assert"
@@ -542,6 +543,90 @@ func standardHostTask() *apitask.Task {
542543
return task
543544
}
544545

546+
func standardBridgeTask() *apitask.Task {
547+
container1 = &apicontainer.Container{
548+
Name: containerName,
549+
Image: imageName,
550+
ImageID: imageID,
551+
DesiredStatusUnsafe: apicontainerstatus.ContainerRunning,
552+
KnownStatusUnsafe: apicontainerstatus.ContainerRunning,
553+
CPU: cpu,
554+
Memory: memory,
555+
Type: apicontainer.ContainerNormal,
556+
KnownPortBindingsUnsafe: []apicontainer.PortBinding{
557+
{
558+
ContainerPort: containerPort,
559+
Protocol: apicontainer.TransportProtocolTCP,
560+
},
561+
},
562+
NetworkModeUnsafe: bridgeMode,
563+
NetworkSettingsUnsafe: &types.NetworkSettings{
564+
DefaultNetworkSettings: types.DefaultNetworkSettings{
565+
IPAddress: bridgeIPAddr,
566+
},
567+
},
568+
}
569+
container1.SetLabels(labels)
570+
return &apitask.Task{
571+
Arn: taskARN,
572+
Associations: []apitask.Association{association},
573+
Containers: []*apicontainer.Container{container1},
574+
Family: family,
575+
Version: version,
576+
DesiredStatusUnsafe: apitaskstatus.TaskRunning,
577+
KnownStatusUnsafe: apitaskstatus.TaskRunning,
578+
CPU: cpu,
579+
Memory: memory,
580+
PullStartedAtUnsafe: now,
581+
PullStoppedAtUnsafe: now,
582+
ExecutionStoppedAtUnsafe: now,
583+
LaunchType: "EC2",
584+
NetworkMode: bridgeMode,
585+
}
586+
}
587+
588+
func standardBridgeDockerContainer() *apicontainer.DockerContainer {
589+
return &apicontainer.DockerContainer{
590+
DockerID: containerID,
591+
DockerName: containerName,
592+
Container: standardBridgeTask().Containers[0],
593+
}
594+
}
595+
596+
func standardV4BridgeContainerResponse() *v4.ContainerResponse {
597+
return &v4.ContainerResponse{
598+
ContainerResponse: &v2.ContainerResponse{ID: containerID,
599+
Name: containerName,
600+
DockerName: containerName,
601+
Image: imageName,
602+
ImageID: imageID,
603+
DesiredStatus: statusRunning,
604+
KnownStatus: statusRunning,
605+
Limits: v2.LimitsResponse{
606+
CPU: aws.Float64(cpu),
607+
Memory: aws.Int64(memory),
608+
},
609+
Type: containerType,
610+
Labels: labels,
611+
Ports: []tmdsresponse.PortResponse{
612+
{
613+
ContainerPort: containerPort,
614+
Protocol: containerPortProtocol,
615+
},
616+
},
617+
},
618+
Networks: []v4.Network{
619+
{
620+
Network: tmdsresponse.Network{
621+
NetworkMode: bridgeMode,
622+
IPv4Addresses: []string{bridgeIPAddr},
623+
},
624+
NetworkInterfaceProperties: v4.NetworkInterfaceProperties{},
625+
},
626+
},
627+
}
628+
}
629+
545630
// Returns a standard v2 task response. This getter function protects against tests mutating the
546631
// response.
547632
func expectedTaskResponse() v2.TaskResponse {
@@ -2002,6 +2087,55 @@ func TestV4ContainerMetadata(t *testing.T) {
20022087
expectedResponseBody: expectedV4BridgeContainerResponse,
20032088
})
20042089
})
2090+
t.Run("happy case bridge mode including IPv6 from network settings", func(t *testing.T) {
2091+
bridgeTask := standardBridgeTask()
2092+
bridgeContainer := standardBridgeDockerContainer()
2093+
networkSettings := bridgeContainer.Container.GetNetworkSettings()
2094+
networkSettings.GlobalIPv6Address = "5:6:7:8::"
2095+
bridgeContainer.Container.SetNetworkSettings(networkSettings)
2096+
2097+
expectedResponse := standardV4BridgeContainerResponse()
2098+
expectedNetwork := expectedResponse.Networks[0]
2099+
expectedNetwork.Network.IPv6Addresses = []string{"5:6:7:8::"}
2100+
expectedResponse.Networks = []v4.Network{{Network: expectedNetwork.Network}}
2101+
2102+
testTMDSRequest(t, TMDSTestCase[v4.ContainerResponse]{
2103+
path: v4BasePath + v3EndpointID,
2104+
setStateExpectations: func(state *mock_dockerstate.MockTaskEngineState) {
2105+
state.EXPECT().ContainerByID(containerID).Return(bridgeContainer, true).AnyTimes()
2106+
state.EXPECT().DockerIDByV3EndpointID(v3EndpointID).Return(containerID, true)
2107+
state.EXPECT().TaskByID(containerID).Return(bridgeTask, true)
2108+
},
2109+
expectedStatusCode: http.StatusOK,
2110+
expectedResponseBody: *expectedResponse,
2111+
})
2112+
})
2113+
t.Run("happy case bridge mode including IPv6 from docker networks", func(t *testing.T) {
2114+
bridgeTask := standardBridgeTask()
2115+
bridgeContainer := standardBridgeDockerContainer()
2116+
bridgeContainer.Container.SetNetworkSettings(&types.NetworkSettings{
2117+
Networks: map[string]*network.EndpointSettings{
2118+
"bridge": {IPAddress: "1.2.3.4", GlobalIPv6Address: "5:6:7:8::"},
2119+
},
2120+
})
2121+
2122+
expectedResponse := standardV4BridgeContainerResponse()
2123+
expectedNetwork := expectedResponse.Networks[0]
2124+
expectedNetwork.Network.IPv4Addresses = []string{"1.2.3.4"}
2125+
expectedNetwork.Network.IPv6Addresses = []string{"5:6:7:8::"}
2126+
expectedResponse.Networks = []v4.Network{{Network: expectedNetwork.Network}}
2127+
2128+
testTMDSRequest(t, TMDSTestCase[v4.ContainerResponse]{
2129+
path: v4BasePath + v3EndpointID,
2130+
setStateExpectations: func(state *mock_dockerstate.MockTaskEngineState) {
2131+
state.EXPECT().ContainerByID(containerID).Return(bridgeContainer, true).AnyTimes()
2132+
state.EXPECT().DockerIDByV3EndpointID(v3EndpointID).Return(containerID, true)
2133+
state.EXPECT().TaskByID(containerID).Return(bridgeTask, true)
2134+
},
2135+
expectedStatusCode: http.StatusOK,
2136+
expectedResponseBody: *expectedResponse,
2137+
})
2138+
})
20052139
}
20062140

20072141
func TestV4TaskMetadata(t *testing.T) {

agent/handlers/v4/container_metadata_handler.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func GetContainerNetworkMetadata(containerID string, state dockerstate.TaskEngin
3737
// We get the NetworkMode (Network interface name) from the HostConfig because this
3838
// this is the network with which the container is created
3939
ipv4AddressFromSettings := settings.IPAddress
40+
ipv6AddressFromSettings := settings.GlobalIPv6Address
4041
networkModeFromHostConfig := dockerContainer.Container.GetNetworkMode()
4142

4243
// Extensive Network information is not available for Docker API versions 1.17-1.20
@@ -46,12 +47,32 @@ func GetContainerNetworkMetadata(containerID string, state dockerstate.TaskEngin
4647
for modeFromSettings, containerNetwork := range settings.Networks {
4748
networkMode := modeFromSettings
4849
ipv4Addresses := []string{containerNetwork.IPAddress}
49-
network := tmdsv4.Network{Network: tmdsresponse.Network{NetworkMode: networkMode, IPv4Addresses: ipv4Addresses}}
50+
var ipv6Addresses []string
51+
if containerNetwork.GlobalIPv6Address != "" {
52+
ipv6Addresses = []string{containerNetwork.GlobalIPv6Address}
53+
}
54+
network := tmdsv4.Network{
55+
Network: tmdsresponse.Network{
56+
NetworkMode: networkMode,
57+
IPv4Addresses: ipv4Addresses,
58+
IPv6Addresses: ipv6Addresses,
59+
},
60+
}
5061
networks = append(networks, network)
5162
}
5263
} else {
5364
ipv4Addresses := []string{ipv4AddressFromSettings}
54-
network := tmdsv4.Network{Network: tmdsresponse.Network{NetworkMode: networkModeFromHostConfig, IPv4Addresses: ipv4Addresses}}
65+
var ipv6Addresses []string
66+
if ipv6AddressFromSettings != "" {
67+
ipv6Addresses = []string{ipv6AddressFromSettings}
68+
}
69+
network := tmdsv4.Network{
70+
Network: tmdsresponse.Network{
71+
NetworkMode: networkModeFromHostConfig,
72+
IPv4Addresses: ipv4Addresses,
73+
IPv6Addresses: ipv6Addresses,
74+
},
75+
}
5576
networks = append(networks, network)
5677
}
5778
return networks, nil

0 commit comments

Comments
 (0)