Skip to content

Commit 08e1190

Browse files
authored
Add v4 container metadata handler to ecs-agent module (#3720)
1 parent 8a88e1c commit 08e1190

File tree

13 files changed

+814
-34
lines changed

13 files changed

+814
-34
lines changed

ecs-agent/logger/field/constants.go

+35-34
Original file line numberDiff line numberDiff line change
@@ -14,38 +14,39 @@
1414
package field
1515

1616
const (
17-
TaskID = "task"
18-
TaskARN = "taskARN"
19-
Container = "container"
20-
DockerId = "dockerId"
21-
ManagedAgent = "managedAgent"
22-
KnownStatus = "knownStatus"
23-
KnownSent = "knownSent"
24-
DesiredStatus = "desiredStatus"
25-
SentStatus = "sentStatus"
26-
FailedStatus = "failedStatus"
27-
Sequence = "seqnum"
28-
Reason = "reason"
29-
Status = "status"
30-
RuntimeID = "runtimeID"
31-
Elapsed = "elapsed"
32-
Resource = "resource"
33-
Error = "error"
34-
Event = "event"
35-
Image = "image"
36-
Volume = "volume"
37-
Time = "time"
38-
NetworkMode = "networkMode"
39-
Cluster = "cluster"
40-
ServiceName = "ServiceName"
41-
TaskProtection = "TaskProtection"
42-
ImageID = "imageID"
43-
ImageNames = "imageNames"
44-
ImageSizeBytes = "imageSizeBytes"
45-
ImagePulledAt = "imagePulledAt"
46-
ImageLastUsedAt = "imageLastUsedAt"
47-
ImagePullSucceeded = "imagePullSucceeded"
48-
ContainerName = "containerName"
49-
ContainerImage = "containerImage"
50-
ContainerExitCode = "containerExitCode"
17+
TaskID = "task"
18+
TaskARN = "taskARN"
19+
Container = "container"
20+
DockerId = "dockerId"
21+
ManagedAgent = "managedAgent"
22+
KnownStatus = "knownStatus"
23+
KnownSent = "knownSent"
24+
DesiredStatus = "desiredStatus"
25+
SentStatus = "sentStatus"
26+
FailedStatus = "failedStatus"
27+
Sequence = "seqnum"
28+
Reason = "reason"
29+
Status = "status"
30+
RuntimeID = "runtimeID"
31+
Elapsed = "elapsed"
32+
Resource = "resource"
33+
Error = "error"
34+
Event = "event"
35+
Image = "image"
36+
Volume = "volume"
37+
Time = "time"
38+
NetworkMode = "networkMode"
39+
Cluster = "cluster"
40+
ServiceName = "ServiceName"
41+
TaskProtection = "TaskProtection"
42+
ImageID = "imageID"
43+
ImageNames = "imageNames"
44+
ImageSizeBytes = "imageSizeBytes"
45+
ImagePulledAt = "imagePulledAt"
46+
ImageLastUsedAt = "imageLastUsedAt"
47+
ImagePullSucceeded = "imagePullSucceeded"
48+
ContainerName = "containerName"
49+
ContainerImage = "containerImage"
50+
ContainerExitCode = "containerExitCode"
51+
TMDSEndpointContainerID = "tmdsEndpointContainerID"
5152
)

ecs-agent/metrics/constants.go

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
package metrics
14+
15+
const (
16+
// MetadataServer
17+
metadataServerMetricNamespace = "MetadataServer"
18+
GetCredentialsMetricName = metadataServerMetricNamespace + ".GetCredentials"
19+
CrashErrorMetricName = metadataServerMetricNamespace + ".Crash"
20+
ShutdownErrorMetricName = metadataServerMetricNamespace + ".ShutdownError"
21+
InternalServerErrorMetricName = metadataServerMetricNamespace + ".InternalServerError"
22+
GetTaskProtectionMetricName = metadataServerMetricNamespace + ".GetTaskProtection"
23+
UpdateTaskProtectionMetricName = metadataServerMetricNamespace + ".UpdateTaskProtection"
24+
AuthConfigMetricName = metadataServerMetricNamespace + ".AuthConfig"
25+
)

ecs-agent/metrics/generate_mocks.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
14+
//go:generate mockgen -destination=mocks/mock_entry.go -copyright_file=../../scripts/copyright_file . EntryFactory,Entry
15+
16+
package metrics

ecs-agent/metrics/metrics.go

+13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
114
package metrics
215

316
// EntryFactory specifies the factory interface for creating new Metric Entry objects.

ecs-agent/metrics/mocks/mock_entry.go

+154
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ecs-agent/tmds/handlers/utils/helpers.go

+21
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package utils
1515

1616
import (
17+
"encoding/json"
1718
"fmt"
1819
"net/http"
1920

@@ -69,6 +70,22 @@ type ErrorMessage struct {
6970
HTTPErrorCode int
7071
}
7172

73+
// Marshals the provided response to JSON and writes it to the ResponseWriter with the provided
74+
// status code and application/json Content-Type header.
75+
// Writes an empty JSON '{}' response if JSON marshaling fails and logs the error.
76+
func WriteJSONResponse(
77+
w http.ResponseWriter,
78+
httpStatusCode int,
79+
response interface{},
80+
requestType string,
81+
) {
82+
responseJSON, err := json.Marshal(response)
83+
if e := WriteResponseIfMarshalError(w, err); e != nil {
84+
return
85+
}
86+
WriteJSONToResponse(w, httpStatusCode, responseJSON, requestType)
87+
}
88+
7289
// WriteJSONToResponse writes the header, JSON response to a ResponseWriter, and
7390
// log the error if necessary.
7491
func WriteJSONToResponse(w http.ResponseWriter, httpStatusCode int, responseJSON []byte, requestType string) {
@@ -133,3 +150,7 @@ func LimitReachedHandler(auditLogger audit.AuditLogger) func(http.ResponseWriter
133150
auditLogger.Log(logRequest, http.StatusTooManyRequests, "")
134151
}
135152
}
153+
154+
func Is5XXStatus(statusCode int) bool {
155+
return 500 <= statusCode && statusCode <= 599
156+
}

ecs-agent/tmds/handlers/utils/helpers_test.go

+44
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ package utils
1818

1919
import (
2020
"encoding/json"
21+
"fmt"
2122
"io/ioutil"
2223
"net/http"
2324
"net/http/httptest"
2425
"testing"
2526

2627
mock_audit "github.com/aws/amazon-ecs-agent/ecs-agent/logger/audit/mocks"
2728
"github.com/aws/amazon-ecs-agent/ecs-agent/logger/audit/request"
29+
"github.com/aws/amazon-ecs-agent/ecs-agent/tmds/handlers/response"
2830
"github.com/golang/mock/gomock"
2931
"github.com/stretchr/testify/assert"
3032
"github.com/stretchr/testify/require"
@@ -83,6 +85,32 @@ func TestWriteJSONToResponse(t *testing.T) {
8385
assert.Equal(t, `"Unable to get task arn from request"`, bodyString)
8486
}
8587

88+
// Tests that WriteJSONResponse marshals the provided response to JSON and writes it to
89+
// the response writer.
90+
func TestWriteJSONResponse(t *testing.T) {
91+
recorder := httptest.NewRecorder()
92+
res := response.PortResponse{ContainerPort: 8080, Protocol: "TCP", HostPort: 80, HostIp: "IP"}
93+
WriteJSONResponse(recorder, http.StatusOK, res, RequestTypeTaskMetadata)
94+
95+
var actualResponse response.PortResponse
96+
err := json.Unmarshal(recorder.Body.Bytes(), &actualResponse)
97+
require.NoError(t, err)
98+
99+
assert.Equal(t, http.StatusOK, recorder.Code)
100+
assert.Equal(t, res, actualResponse)
101+
}
102+
103+
// Tests that an empty JSON response is written by WriteJSONResponse if the provided response
104+
// is not convertible to JSON.
105+
func TestWriteJSONResponseError(t *testing.T) {
106+
recorder := httptest.NewRecorder()
107+
res := func(k string) string { return k }
108+
WriteJSONResponse(recorder, http.StatusOK, res, RequestTypeTaskMetadata)
109+
110+
assert.Equal(t, http.StatusInternalServerError, recorder.Code)
111+
assert.Equal(t, "{}", recorder.Body.String())
112+
}
113+
86114
func TestValueFromRequest(t *testing.T) {
87115
r, _ := http.NewRequest("GET", "/v1/credentials?id=credid", nil)
88116
val, ok := ValueFromRequest(r, "id")
@@ -108,3 +136,19 @@ func TestLimitReachHandler(t *testing.T) {
108136
recorder := httptest.NewRecorder()
109137
handler.ServeHTTP(recorder, req)
110138
}
139+
140+
func TestIs5XXStatus(t *testing.T) {
141+
yes := []int{500, 501, 550, http.StatusInternalServerError, http.StatusServiceUnavailable, 580, 599}
142+
for _, y := range yes {
143+
t.Run(fmt.Sprintf("yes %d", y), func(t *testing.T) {
144+
assert.True(t, Is5XXStatus(y))
145+
})
146+
}
147+
148+
no := []int{http.StatusTooEarly, http.StatusBadRequest, http.StatusTooManyRequests, 400, 450, 600, 200, 301}
149+
for _, n := range no {
150+
t.Run(fmt.Sprintf("no %d", n), func(t *testing.T) {
151+
assert.False(t, Is5XXStatus(n))
152+
})
153+
}
154+
}

0 commit comments

Comments
 (0)