diff --git a/agent/handlers/task_server_setup_test.go b/agent/handlers/task_server_setup_test.go index 5b7d714cc5d..02cfe20080a 100644 --- a/agent/handlers/task_server_setup_test.go +++ b/agent/handlers/task_server_setup_test.go @@ -39,7 +39,6 @@ import ( mock_dockerstate "github.com/aws/amazon-ecs-agent/agent/engine/dockerstate/mocks" task_protection_v1 "github.com/aws/amazon-ecs-agent/agent/handlers/agentapi/taskprotection/v1/handlers" v3 "github.com/aws/amazon-ecs-agent/agent/handlers/v3" - v4 "github.com/aws/amazon-ecs-agent/agent/handlers/v4" "github.com/aws/amazon-ecs-agent/agent/stats" mock_stats "github.com/aws/amazon-ecs-agent/agent/stats/mock" agentutils "github.com/aws/amazon-ecs-agent/agent/utils" @@ -51,6 +50,8 @@ import ( "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/utils" tmdsv1 "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v1" v2 "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v2" + v4 "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v4/state" + "github.com/aws/aws-sdk-go/aws" "github.com/docker/docker/api/types" "github.com/golang/mock/gomock" diff --git a/agent/handlers/v4/container_metadata_handler.go b/agent/handlers/v4/container_metadata_handler.go index 39a7756f2d9..c74580e38fb 100644 --- a/agent/handlers/v4/container_metadata_handler.go +++ b/agent/handlers/v4/container_metadata_handler.go @@ -22,6 +22,8 @@ import ( v3 "github.com/aws/amazon-ecs-agent/agent/handlers/v3" tmdsresponse "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/response" "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/utils" + tmdsv4 "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v4/state" + "github.com/cihub/seelog" "github.com/pkg/errors" ) @@ -62,7 +64,7 @@ func ContainerMetadataHandler(state dockerstate.TaskEngineState) func(http.Respo } // GetContainerResponse gets container response for v4 metadata -func GetContainerResponse(containerID string, state dockerstate.TaskEngineState) (*ContainerResponse, error) { +func GetContainerResponse(containerID string, state dockerstate.TaskEngineState) (*tmdsv4.ContainerResponse, error) { containerResponse, err := NewContainerResponse(containerID, state) if err != nil { seelog.Errorf("Unable to get container metadata for container '%s'", containerID) @@ -79,7 +81,7 @@ func GetContainerResponse(containerID string, state dockerstate.TaskEngineState) } // GetContainerNetworkMetadata returns the network metadata for the container -func GetContainerNetworkMetadata(containerID string, state dockerstate.TaskEngineState) ([]Network, error) { +func GetContainerNetworkMetadata(containerID string, state dockerstate.TaskEngineState) ([]tmdsv4.Network, error) { dockerContainer, ok := state.ContainerByID(containerID) if !ok { return nil, errors.Errorf("unable to find container '%s'", containerID) @@ -98,17 +100,17 @@ func GetContainerNetworkMetadata(containerID string, state dockerstate.TaskEngin // Extensive Network information is not available for Docker API versions 1.17-1.20 // Instead we only get the details of the first network - networks := make([]Network, 0) + networks := make([]tmdsv4.Network, 0) if len(settings.Networks) > 0 { for modeFromSettings, containerNetwork := range settings.Networks { networkMode := modeFromSettings ipv4Addresses := []string{containerNetwork.IPAddress} - network := Network{Network: tmdsresponse.Network{NetworkMode: networkMode, IPv4Addresses: ipv4Addresses}} + network := tmdsv4.Network{Network: tmdsresponse.Network{NetworkMode: networkMode, IPv4Addresses: ipv4Addresses}} networks = append(networks, network) } } else { ipv4Addresses := []string{ipv4AddressFromSettings} - network := Network{Network: tmdsresponse.Network{NetworkMode: networkModeFromHostConfig, IPv4Addresses: ipv4Addresses}} + network := tmdsv4.Network{Network: tmdsresponse.Network{NetworkMode: networkModeFromHostConfig, IPv4Addresses: ipv4Addresses}} networks = append(networks, network) } return networks, nil diff --git a/agent/handlers/v4/response.go b/agent/handlers/v4/response.go index 3e2c3af1279..b33da9b01ed 100644 --- a/agent/handlers/v4/response.go +++ b/agent/handlers/v4/response.go @@ -22,61 +22,11 @@ import ( apieni "github.com/aws/amazon-ecs-agent/ecs-agent/api/eni" tmdsresponse "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/response" "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/utils" - tmdsv2 "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v2" + tmdsv4 "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v4/state" + "github.com/pkg/errors" ) -// TaskResponse is the v4 Task response. It augments the v4 Container response -// with the v2 task response object. -type TaskResponse struct { - *tmdsv2.TaskResponse - Containers []ContainerResponse `json:"Containers,omitempty"` - VPCID string `json:"VPCID,omitempty"` - ServiceName string `json:"ServiceName,omitempty"` -} - -// ContainerResponse is the v4 Container response. It augments the v4 Network response -// with the v2 container response object. -type ContainerResponse struct { - *tmdsv2.ContainerResponse - Networks []Network `json:"Networks,omitempty"` -} - -// Network is the v4 Network response. It adds a bunch of information about network -// interface(s) on top of what is supported by v4. -// See `NetworkInterfaceProperties` for more details. -type Network struct { - tmdsresponse.Network - // NetworkInterfaceProperties specifies additional properties of the network - // of the network interface that are exposed via the metadata server. - // We currently populate this only for the `awsvpc` networking mode. - NetworkInterfaceProperties -} - -// NetworkInterfaceProperties represents additional properties we may want to expose via -// task metadata about the network interface that's attached to the container/task. We -// mostly use this to populate data about ENIs for tasks launched with `awsvpc` mode. -type NetworkInterfaceProperties struct { - // AttachmentIndex reflects the `index` specified by the customer (if any) - // while creating the task with `awsvpc` mode. - AttachmentIndex *int `json:"AttachmentIndex,omitempty"` - // MACAddress is the MAC address of the network interface. - MACAddress string `json:"MACAddress,omitempty"` - // IPv4SubnetCIDRBlock is the IPv4 CIDR address block associated with the interface's subnet. - IPV4SubnetCIDRBlock string `json:"IPv4SubnetCIDRBlock,omitempty"` - // IPv6SubnetCIDRBlock is the IPv6 CIDR address block associated with the interface's subnet. - IPv6SubnetCIDRBlock string `json:"IPv6SubnetCIDRBlock,omitempty"` - // DomainNameServers specifies the nameserver IP addresses for the network interface. - DomainNameServers []string `json:"DomainNameServers,omitempty"` - // DomainNameSearchList specifies the search list for the domain name lookup for - // the network interface. - DomainNameSearchList []string `json:"DomainNameSearchList,omitempty"` - // PrivateDNSName is the dns name assigned to this network interface. - PrivateDNSName string `json:"PrivateDNSName,omitempty"` - // SubnetGatewayIPV4Address is the IPv4 gateway address for the network interface. - SubnetGatewayIPV4Address string `json:"SubnetGatewayIpv4Address,omitempty"` -} - // NewTaskResponse creates a new v4 response object for the task. It augments v2 task response // with additional network interface fields. func NewTaskResponse( @@ -89,14 +39,14 @@ func NewTaskResponse( containerInstanceARN string, serviceName string, propagateTags bool, -) (*TaskResponse, error) { +) (*tmdsv4.TaskResponse, error) { // Construct the v2 response first. v2Resp, err := v2.NewTaskResponse(taskARN, state, ecsClient, cluster, az, containerInstanceARN, propagateTags, true) if err != nil { return nil, err } - var containers []ContainerResponse + var containers []tmdsv4.ContainerResponse // Convert each container response into v4 container response. for i, container := range v2Resp.Containers { networks, err := toV4NetworkResponse(container.Networks, func() (*apitask.Task, bool) { @@ -105,13 +55,13 @@ func NewTaskResponse( if err != nil { return nil, err } - containers = append(containers, ContainerResponse{ + containers = append(containers, tmdsv4.ContainerResponse{ ContainerResponse: &v2Resp.Containers[i], Networks: networks, }) } - return &TaskResponse{ + return &tmdsv4.TaskResponse{ TaskResponse: v2Resp, Containers: containers, VPCID: vpcID, @@ -124,7 +74,7 @@ func NewTaskResponse( func NewContainerResponse( containerID string, state dockerstate.TaskEngineState, -) (*ContainerResponse, error) { +) (*tmdsv4.ContainerResponse, error) { // Construct the v2 response first. container, err := v2.NewContainerResponseFromState(containerID, state, true) if err != nil { @@ -137,7 +87,7 @@ func NewContainerResponse( if err != nil { return nil, err } - return &ContainerResponse{ + return &tmdsv4.ContainerResponse{ ContainerResponse: container, Networks: networks, }, nil @@ -150,10 +100,10 @@ func NewContainerResponse( func toV4NetworkResponse( networks []tmdsresponse.Network, lookup func() (*apitask.Task, bool), -) ([]Network, error) { - var resp []Network +) ([]tmdsv4.Network, error) { + var resp []tmdsv4.Network for _, network := range networks { - respNetwork := Network{Network: network} + respNetwork := tmdsv4.Network{Network: network} if network.NetworkMode == utils.NetworkModeAWSVPC { task, ok := lookup() if !ok { @@ -173,7 +123,7 @@ func toV4NetworkResponse( // newNetworkInterfaceProperties creates the NetworkInterfaceProperties object for a given // task. -func newNetworkInterfaceProperties(task *apitask.Task) (NetworkInterfaceProperties, error) { +func newNetworkInterfaceProperties(task *apitask.Task) (tmdsv4.NetworkInterfaceProperties, error) { eni := task.GetPrimaryENI() var attachmentIndexPtr *int @@ -182,7 +132,7 @@ func newNetworkInterfaceProperties(task *apitask.Task) (NetworkInterfaceProperti attachmentIndexPtr = &vpcIndex } - return NetworkInterfaceProperties{ + return tmdsv4.NetworkInterfaceProperties{ // TODO this is hard-coded to `0` for now. Once backend starts populating // `Index` field for an ENI, we should set it as per that. Since we // only support 1 ENI per task anyway, setting it to `0` is acceptable @@ -202,9 +152,9 @@ func newNetworkInterfaceProperties(task *apitask.Task) (NetworkInterfaceProperti func NewPulledContainerResponse( dockerContainer *apicontainer.DockerContainer, eni *apieni.ENI, -) ContainerResponse { +) tmdsv4.ContainerResponse { resp := v2.NewContainerResponse(dockerContainer, eni, true) - return ContainerResponse{ + return tmdsv4.ContainerResponse{ ContainerResponse: &resp, } } diff --git a/agent/handlers/v4/task_metadata_handler.go b/agent/handlers/v4/task_metadata_handler.go index e00743c3e92..341336eb78d 100644 --- a/agent/handlers/v4/task_metadata_handler.go +++ b/agent/handlers/v4/task_metadata_handler.go @@ -22,6 +22,8 @@ import ( "github.com/aws/amazon-ecs-agent/agent/engine/dockerstate" v3 "github.com/aws/amazon-ecs-agent/agent/handlers/v3" "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/utils" + tmdsv4 "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v4/state" + "github.com/cihub/seelog" ) @@ -70,7 +72,7 @@ func TaskMetadataHandler(state dockerstate.TaskEngineState, ecsClient api.ECSCli // for non-awsvpc task mode if !task.IsNetworkModeAWSVPC() { // fill in non-awsvpc network details for container responses here - responses := make([]ContainerResponse, 0) + responses := make([]tmdsv4.ContainerResponse, 0) for _, containerResponse := range taskResponse.Containers { networks, err := GetContainerNetworkMetadata(containerResponse.ID, state) if err != nil { diff --git a/agent/vendor/github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v4/state/response.go b/agent/vendor/github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v4/state/response.go new file mode 100644 index 00000000000..e0f80b4d81e --- /dev/null +++ b/agent/vendor/github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v4/state/response.go @@ -0,0 +1,69 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"). You may +// not use this file except in compliance with the License. A copy of the +// License is located at +// +// http://aws.amazon.com/apache2.0/ +// +// or in the "license" file accompanying this file. This file is distributed +// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +// express or implied. See the License for the specific language governing +// permissions and limitations under the License. +package state + +import ( + "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/response" + v2 "github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v2" +) + +// TaskResponse is the v4 Task response. It augments the v4 Container response +// with the v2 task response object. +type TaskResponse struct { + *v2.TaskResponse + Containers []ContainerResponse `json:"Containers,omitempty"` + VPCID string `json:"VPCID,omitempty"` + ServiceName string `json:"ServiceName,omitempty"` +} + +// ContainerResponse is the v4 Container response. It augments the v4 Network response +// with the v2 container response object. +type ContainerResponse struct { + *v2.ContainerResponse + Networks []Network `json:"Networks,omitempty"` +} + +// Network is the v4 Network response. It adds a bunch of information about network +// interface(s) on top of what is supported by v4. +// See `NetworkInterfaceProperties` for more details. +type Network struct { + response.Network + // NetworkInterfaceProperties specifies additional properties of the network + // of the network interface that are exposed via the metadata server. + // We currently populate this only for the `awsvpc` networking mode. + NetworkInterfaceProperties +} + +// NetworkInterfaceProperties represents additional properties we may want to expose via +// task metadata about the network interface that's attached to the container/task. We +// mostly use this to populate data about ENIs for tasks launched with `awsvpc` mode. +type NetworkInterfaceProperties struct { + // AttachmentIndex reflects the `index` specified by the customer (if any) + // while creating the task with `awsvpc` mode. + AttachmentIndex *int `json:"AttachmentIndex,omitempty"` + // MACAddress is the MAC address of the network interface. + MACAddress string `json:"MACAddress,omitempty"` + // IPv4SubnetCIDRBlock is the IPv4 CIDR address block associated with the interface's subnet. + IPV4SubnetCIDRBlock string `json:"IPv4SubnetCIDRBlock,omitempty"` + // IPv6SubnetCIDRBlock is the IPv6 CIDR address block associated with the interface's subnet. + IPv6SubnetCIDRBlock string `json:"IPv6SubnetCIDRBlock,omitempty"` + // DomainNameServers specifies the nameserver IP addresses for the network interface. + DomainNameServers []string `json:"DomainNameServers,omitempty"` + // DomainNameSearchList specifies the search list for the domain name lookup for + // the network interface. + DomainNameSearchList []string `json:"DomainNameSearchList,omitempty"` + // PrivateDNSName is the dns name assigned to this network interface. + PrivateDNSName string `json:"PrivateDNSName,omitempty"` + // SubnetGatewayIPV4Address is the IPv4 gateway address for the network interface. + SubnetGatewayIPV4Address string `json:"SubnetGatewayIpv4Address,omitempty"` +} diff --git a/agent/vendor/modules.txt b/agent/vendor/modules.txt index 7cc462bf84c..5deee948ce5 100644 --- a/agent/vendor/modules.txt +++ b/agent/vendor/modules.txt @@ -25,6 +25,7 @@ github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/response github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/utils github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v1 github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v2 +github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/v4/state github.com/aws/amazon-ecs-agent/ecs-agent/tmds/logging github.com/aws/amazon-ecs-agent/ecs-agent/tmds/utils/mux github.com/aws/amazon-ecs-agent/ecs-agent/utils