Skip to content

Commit

Permalink
add container metadata to introspection response
Browse files Browse the repository at this point in the history
  • Loading branch information
singholt committed Sep 26, 2023
1 parent dd25e3f commit 35ce9cf
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 84 deletions.
16 changes: 16 additions & 0 deletions agent/handlers/v1/response.go
Expand Up @@ -14,6 +14,8 @@
package v1

import (
"time"

apicontainer "github.com/aws/amazon-ecs-agent/agent/api/container"
apitask "github.com/aws/amazon-ecs-agent/agent/api/task"
"github.com/aws/amazon-ecs-agent/agent/engine/dockerstate"
Expand Down Expand Up @@ -49,6 +51,10 @@ type ContainerResponse struct {
DockerID string `json:"DockerId"`
DockerName string `json:"DockerName"`
Name string `json:"Name"`
Image string `json:"Image"`
ImageID string `json:"ImageID"`
CreatedAt *time.Time `json:"CreatedAt,omitempty"`
StartedAt *time.Time `json:"StartedAt,omitempty"`
Ports []tmdsresponse.PortResponse `json:"Ports,omitempty"`
Networks []tmdsresponse.Network `json:"Networks,omitempty"`
Volumes []tmdsresponse.VolumeResponse `json:"Volumes,omitempty"`
Expand Down Expand Up @@ -89,6 +95,8 @@ func NewContainerResponse(dockerContainer *apicontainer.DockerContainer, eni *ni
container := dockerContainer.Container
resp := ContainerResponse{
Name: container.Name,
Image: container.Image,
ImageID: container.ImageID,
DockerID: dockerContainer.DockerID,
DockerName: dockerContainer.DockerName,
}
Expand All @@ -105,6 +113,14 @@ func NewContainerResponse(dockerContainer *apicontainer.DockerContainer, eni *ni
},
}
}
if createdAt := container.GetCreatedAt(); !createdAt.IsZero() {
createdAt = createdAt.UTC()
resp.CreatedAt = &createdAt
}
if startedAt := container.GetStartedAt(); !startedAt.IsZero() {
startedAt = startedAt.UTC()
resp.StartedAt = &startedAt
}
return resp
}

Expand Down
155 changes: 71 additions & 84 deletions agent/handlers/v1/response_test.go
Expand Up @@ -19,11 +19,13 @@ package v1
import (
"encoding/json"
"testing"
"time"

apicontainer "github.com/aws/amazon-ecs-agent/agent/api/container"
apitask "github.com/aws/amazon-ecs-agent/agent/api/task"
apitaskstatus "github.com/aws/amazon-ecs-agent/agent/api/task/status"
ni "github.com/aws/amazon-ecs-agent/ecs-agent/netlib/model/networkinterface"
"github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/response"

"github.com/docker/docker/api/types"
"github.com/stretchr/testify/assert"
Expand All @@ -33,53 +35,68 @@ const (
taskARN = "t1"
family = "sleep"
version = "1"
status = "RUNNING"
containerID = "cid"
containerName = "sleepy"
imageName = "busybox"
imageID = "busyboxID"
networkMode = "awsvpc"
eniIPv4Address = "10.0.0.2"
port = 80
protocol = "tcp"
volName = "volume1"
volSource = "/var/lib/volume1"
volDestination = "/volume"
)

func TestTaskResponse(t *testing.T) {
expectedTaskResponseMap := map[string]interface{}{
"Arn": "t1",
"DesiredStatus": "RUNNING",
"KnownStatus": "RUNNING",
"Family": "sleep",
"Version": "1",
"Containers": []interface{}{
map[string]interface{}{
"DockerId": "cid",
"DockerName": "sleepy",
"Name": "sleepy",
"Ports": []interface{}{
map[string]interface{}{
// The number should be float here, because when we unmarshal
// something and we don't specify the number type, it will be
// set to float.
"ContainerPort": float64(80),
"Protocol": "tcp",
"HostPort": float64(80),
},
},
"Networks": []interface{}{
map[string]interface{}{
"NetworkMode": "awsvpc",
"IPv4Addresses": []interface{}{"10.0.0.2"},
},
},
"Volumes": []interface{}{
map[string]interface{}{
"DockerName": volName,
"Source": volSource,
"Destination": volDestination,
},
},
},
var (
containerTime = time.Now()
containerTimeUTC = containerTime.UTC()
expectedPortResponse = response.PortResponse{
ContainerPort: port,
Protocol: protocol,
HostPort: port,
}
expectedNetworkResponse = response.Network{
NetworkMode: networkMode,
IPv4Addresses: []string{eniIPv4Address},
}
expectedVolumeResponse = response.VolumeResponse{
DockerName: volName,
Source: volSource,
Destination: volDestination,
}
expectedContainerResponse = ContainerResponse{
DockerID: containerID,
DockerName: containerName,
Name: containerName,
Image: imageName,
ImageID: imageID,
CreatedAt: &containerTimeUTC,
StartedAt: &containerTimeUTC,
Ports: []response.PortResponse{
expectedPortResponse,
},
Networks: []response.Network{
expectedNetworkResponse,
},
Volumes: []response.VolumeResponse{
expectedVolumeResponse,
},
}
expectedTaskResponse = TaskResponse{
Arn: taskARN,
DesiredStatus: status,
KnownStatus: status,
Family: family,
Version: version,
Containers: []ContainerResponse{
expectedContainerResponse,
},
}
)

func TestTaskResponse(t *testing.T) {
task := &apitask.Task{
Arn: taskARN,
Family: family,
Expand All @@ -98,7 +115,9 @@ func TestTaskResponse(t *testing.T) {
}

container := &apicontainer.Container{
Name: containerName,
Name: containerName,
Image: imageName,
ImageID: imageID,
Ports: []apicontainer.PortBinding{
{
ContainerPort: 80,
Expand All @@ -114,6 +133,9 @@ func TestTaskResponse(t *testing.T) {
},
}

container.SetCreatedAt(containerTime)
container.SetStartedAt(containerTime)

containerNameToDockerContainer := map[string]*apicontainer.DockerContainer{
taskARN: {
DockerID: containerID,
Expand All @@ -124,45 +146,17 @@ func TestTaskResponse(t *testing.T) {

taskResponse := NewTaskResponse(task, containerNameToDockerContainer)

taskResponseJSON, err := json.Marshal(taskResponse)
_, err := json.Marshal(taskResponse)
assert.NoError(t, err)

taskResponseMap := make(map[string]interface{})

json.Unmarshal(taskResponseJSON, &taskResponseMap)

assert.Equal(t, expectedTaskResponseMap, taskResponseMap)
assert.Equal(t, expectedTaskResponse, *taskResponse)
}

func TestContainerResponse(t *testing.T) {
expectedContainerResponseMap := map[string]interface{}{
"DockerId": "cid",
"DockerName": "sleepy",
"Name": "sleepy",
"Ports": []interface{}{
map[string]interface{}{
"ContainerPort": float64(80),
"Protocol": "tcp",
"HostPort": float64(80),
},
},
"Networks": []interface{}{
map[string]interface{}{
"NetworkMode": "awsvpc",
"IPv4Addresses": []interface{}{"10.0.0.2"},
},
},
"Volumes": []interface{}{
map[string]interface{}{
"DockerName": volName,
"Source": volSource,
"Destination": volDestination,
},
},
}

container := &apicontainer.Container{
Name: containerName,
Name: containerName,
Image: imageName,
ImageID: imageID,
Ports: []apicontainer.PortBinding{
{
ContainerPort: 80,
Expand All @@ -178,6 +172,9 @@ func TestContainerResponse(t *testing.T) {
},
}

container.SetCreatedAt(containerTime)
container.SetStartedAt(containerTime)

dockerContainer := &apicontainer.DockerContainer{
DockerID: containerID,
DockerName: containerName,
Expand All @@ -194,14 +191,10 @@ func TestContainerResponse(t *testing.T) {

containerResponse := NewContainerResponse(dockerContainer, eni)

containerResponseJSON, err := json.Marshal(containerResponse)
_, err := json.Marshal(containerResponse)
assert.NoError(t, err)

containerResponseMap := make(map[string]interface{})

json.Unmarshal(containerResponseJSON, &containerResponseMap)

assert.Equal(t, expectedContainerResponseMap, containerResponseMap)
assert.Equal(t, expectedContainerResponse, containerResponse)
}

func TestPortBindingsResponse(t *testing.T) {
Expand All @@ -221,10 +214,7 @@ func TestPortBindingsResponse(t *testing.T) {
}

PortBindingsResponse := NewPortBindingsResponse(dockerContainer, nil)

assert.Equal(t, uint16(80), PortBindingsResponse[0].ContainerPort)
assert.Equal(t, uint16(80), PortBindingsResponse[0].HostPort)
assert.Equal(t, "tcp", PortBindingsResponse[0].Protocol)
assert.Equal(t, expectedPortResponse, PortBindingsResponse[0])
}

func TestVolumesResponse(t *testing.T) {
Expand All @@ -244,8 +234,5 @@ func TestVolumesResponse(t *testing.T) {
}

VolumesResponse := NewVolumesResponse(dockerContainer)

assert.Equal(t, volName, VolumesResponse[0].DockerName)
assert.Equal(t, volSource, VolumesResponse[0].Source)
assert.Equal(t, volDestination, VolumesResponse[0].Destination)
assert.Equal(t, expectedVolumeResponse, VolumesResponse[0])
}

0 comments on commit 35ce9cf

Please sign in to comment.