@@ -648,6 +648,49 @@ func expectedTaskResponse() v2.TaskResponse {
648648 }
649649}
650650
651+ // standardV4ContainerResponseAWSVPC returns a standard TMDS v4 container response for testing.
652+ // The response corresponds to the standard awsvpc container defined in this package.
653+ func standardV4ContainerResponseAWSVPC () * v4.ContainerResponse {
654+ return & v4.ContainerResponse {
655+ ContainerResponse : & v2.ContainerResponse {
656+ ID : containerID ,
657+ Name : containerName ,
658+ DockerName : containerName ,
659+ Image : imageName ,
660+ ImageID : imageID ,
661+ DesiredStatus : statusRunning ,
662+ KnownStatus : statusRunning ,
663+ ContainerARN : "arn:aws:ecs:ap-northnorth-1:NNN:container/NNNNNNNN-aaaa-4444-bbbb-00000000000" ,
664+ Limits : v2.LimitsResponse {
665+ CPU : aws .Float64 (cpu ),
666+ Memory : aws .Int64 (memory ),
667+ },
668+ Type : containerType ,
669+ Labels : labels ,
670+ Ports : []tmdsresponse.PortResponse {
671+ {
672+ ContainerPort : containerPort ,
673+ Protocol : containerPortProtocol ,
674+ HostPort : containerPort ,
675+ },
676+ },
677+ },
678+ Networks : []v4.Network {{
679+ Network : tmdsresponse.Network {
680+ NetworkMode : utils .NetworkModeAWSVPC ,
681+ IPv4Addresses : []string {eniIPv4Address },
682+ },
683+ NetworkInterfaceProperties : v4.NetworkInterfaceProperties {
684+ AttachmentIndex : & attachmentIndexVar ,
685+ IPV4SubnetCIDRBlock : iPv4SubnetCIDRBlock ,
686+ MACAddress : macAddress ,
687+ PrivateDNSName : privateDNSName ,
688+ SubnetGatewayIPV4Address : subnetGatewayIpv4Address ,
689+ }},
690+ },
691+ }
692+ }
693+
651694// Creates a v4 ContainerResponse given a v2 ContainerResponse and v4 networks
652695func v4ContainerResponseFromV2 (
653696 v2ContainerResponse v2.ContainerResponse , networks []v4.Network ) v4.ContainerResponse {
@@ -2040,6 +2083,65 @@ func TestV4ContainerMetadata(t *testing.T) {
20402083 expectedResponseBody : expectedV4ContainerResponse ,
20412084 })
20422085 })
2086+ t .Run ("happy case awsvpc task - dual stack case" , func (t * testing.T ) {
2087+ testTMDSRequest (t , TMDSTestCase [v4.ContainerResponse ]{
2088+ path : v4BasePath + v3EndpointID ,
2089+ setStateExpectations : func (state * mock_dockerstate.MockTaskEngineState ) {
2090+ task := standardTask ()
2091+ task .ENIs [0 ].SubnetGatewayIPV4Address = "1.2.3.1/24"
2092+ task .ENIs [0 ].SubnetGatewayIPV6Address = "8:3:1:1:1::/64"
2093+ task .ENIs [0 ].IPV4Addresses = []* ni.IPV4Address {{Address : "1.2.3.5" }}
2094+ task .ENIs [0 ].IPV6Addresses = []* ni.IPV6Address {{Address : "8:3:1:1:a::" }}
2095+ gomock .InOrder (
2096+ state .EXPECT ().DockerIDByV3EndpointID (v3EndpointID ).Return (containerID , true ),
2097+ state .EXPECT ().ContainerByID (containerID ).Return (dockerContainer , true ).AnyTimes (),
2098+ state .EXPECT ().TaskByID (containerID ).Return (task , true ).Times (2 ),
2099+ state .EXPECT ().ContainerByID (containerID ).Return (dockerContainer , true ).AnyTimes (),
2100+ )
2101+ },
2102+ expectedStatusCode : http .StatusOK ,
2103+ expectedResponseBody : func () v4.ContainerResponse {
2104+ response := standardV4ContainerResponseAWSVPC ()
2105+ response .Networks [0 ].SubnetGatewayIPV4Address = "1.2.3.1/24"
2106+ // subnet gateway IPv6 address not populated for dual-stack ENIs for historical reasons
2107+ response .Networks [0 ].SubnetGatewayIPV6Address = ""
2108+ response .Networks [0 ].IPV4SubnetCIDRBlock = "1.2.3.0/24"
2109+ response .Networks [0 ].IPv6SubnetCIDRBlock = "8:3:1:1::/64"
2110+ response .Networks [0 ].IPv4Addresses = []string {"1.2.3.5" }
2111+ response .Networks [0 ].IPv6Addresses = []string {"8:3:1:1:a::" }
2112+ return * response
2113+ }(),
2114+ })
2115+ })
2116+ t .Run ("happy case awsvpc task - IPv6-only case" , func (t * testing.T ) {
2117+ testTMDSRequest (t , TMDSTestCase [v4.ContainerResponse ]{
2118+ path : v4BasePath + v3EndpointID ,
2119+ setStateExpectations : func (state * mock_dockerstate.MockTaskEngineState ) {
2120+ task := standardTask ()
2121+ task .ENIs [0 ].SubnetGatewayIPV4Address = ""
2122+ task .ENIs [0 ].SubnetGatewayIPV6Address = "8:3:1:1::/48"
2123+ task .ENIs [0 ].IPV4Addresses = nil
2124+ task .ENIs [0 ].IPV6Addresses = []* ni.IPV6Address {{Address : "8:3:1:9::" }}
2125+ gomock .InOrder (
2126+ state .EXPECT ().DockerIDByV3EndpointID (v3EndpointID ).Return (containerID , true ),
2127+ state .EXPECT ().ContainerByID (containerID ).Return (dockerContainer , true ).AnyTimes (),
2128+ state .EXPECT ().TaskByID (containerID ).Return (task , true ).Times (2 ),
2129+ state .EXPECT ().ContainerByID (containerID ).Return (dockerContainer , true ).AnyTimes (),
2130+ )
2131+ },
2132+ expectedStatusCode : http .StatusOK ,
2133+ expectedResponseBody : func () v4.ContainerResponse {
2134+ response := standardV4ContainerResponseAWSVPC ()
2135+ response .Networks [0 ].SubnetGatewayIPV4Address = ""
2136+ response .Networks [0 ].SubnetGatewayIPV6Address = "8:3:1:1::/48"
2137+ response .Networks [0 ].IPV4SubnetCIDRBlock = ""
2138+ response .Networks [0 ].IPv6SubnetCIDRBlock = "8:3:1::/48"
2139+ response .Networks [0 ].IPv4Addresses = nil
2140+ response .Networks [0 ].IPv6Addresses = []string {"8:3:1:9::" }
2141+ return * response
2142+ }(),
2143+ })
2144+ })
20432145 t .Run ("bridge mode container not found during network population" , func (t * testing.T ) {
20442146 testTMDSRequest (t , TMDSTestCase [string ]{
20452147 path : v4BasePath + v3EndpointID ,
0 commit comments