diff --git a/sdk-extensions/aws/src/main/java/io/opentelemetry/sdk/extension/aws/resource/EcsResource.java b/sdk-extensions/aws/src/main/java/io/opentelemetry/sdk/extension/aws/resource/EcsResource.java index 913439eda34..e3894329761 100644 --- a/sdk-extensions/aws/src/main/java/io/opentelemetry/sdk/extension/aws/resource/EcsResource.java +++ b/sdk-extensions/aws/src/main/java/io/opentelemetry/sdk/extension/aws/resource/EcsResource.java @@ -5,15 +5,21 @@ package io.opentelemetry.sdk.extension.aws.resource; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; -import java.net.InetAddress; -import java.net.UnknownHostException; +import java.io.IOException; +import java.util.Collections; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.Nullable; /** * A factory for a {@link Resource} which provides information about the current ECS container if @@ -21,7 +27,7 @@ */ public final class EcsResource { private static final Logger logger = Logger.getLogger(EcsResource.class.getName()); - + private static final JsonFactory JSON_FACTORY = new JsonFactory(); private static final String ECS_METADATA_KEY_V4 = "ECS_CONTAINER_METADATA_URI_V4"; private static final String ECS_METADATA_KEY_V3 = "ECS_CONTAINER_METADATA_URI"; @@ -36,38 +42,182 @@ public static Resource get() { } private static Resource buildResource() { - return buildResource(System.getenv(), new DockerHelper()); + return buildResource(System.getenv(), new SimpleHttpClient()); } // Visible for testing - static Resource buildResource(Map sysEnv, DockerHelper dockerHelper) { - if (!isOnEcs(sysEnv)) { - return Resource.empty(); + static Resource buildResource(Map sysEnv, SimpleHttpClient httpClient) { + // Note: If V4 is set V3 is set as well, so check V4 first. + String ecsMetadataUrl = + sysEnv.getOrDefault(ECS_METADATA_KEY_V4, sysEnv.getOrDefault(ECS_METADATA_KEY_V3, "")); + if (!ecsMetadataUrl.isEmpty()) { + AttributesBuilder attrBuilders = Attributes.builder(); + parseUrl(httpClient, ecsMetadataUrl, attrBuilders); + // For TaskARN, Family, Revision. + // May put the same attribute twice but that shouldn't matter. + parseUrl(httpClient, ecsMetadataUrl + "/task", attrBuilders); + return Resource.create(attrBuilders.build(), ResourceAttributes.SCHEMA_URL); } + // Not running on ECS + return Resource.empty(); + } - AttributesBuilder attrBuilders = Attributes.builder(); + static void parseUrl(SimpleHttpClient httpClient, String url, AttributesBuilder attrBuilders) { + String json = httpClient.fetchString("GET", url, Collections.emptyMap(), null); + if (json.isEmpty()) { + return; + } attrBuilders.put(ResourceAttributes.CLOUD_PROVIDER, ResourceAttributes.CloudProviderValues.AWS); attrBuilders.put( ResourceAttributes.CLOUD_PLATFORM, ResourceAttributes.CloudPlatformValues.AWS_ECS); - try { - String hostName = InetAddress.getLocalHost().getHostName(); - attrBuilders.put(ResourceAttributes.CONTAINER_NAME, hostName); - } catch (UnknownHostException e) { - logger.log(Level.WARNING, "Could not get docker container name from hostname.", e); + try (JsonParser parser = JSON_FACTORY.createParser(json)) { + parser.nextToken(); + LogGroupArnBuilder logGroupArnBuilder = new LogGroupArnBuilder(); + parseResponse(parser, attrBuilders, logGroupArnBuilder); + logGroupArnBuilder.putLogGroupArnInAttributesBuilder(attrBuilders); + } catch (IOException e) { + logger.log(Level.WARNING, "Can't get ECS metadata", e); } + } - String containerId = dockerHelper.getContainerId(); - if (containerId != null && !containerId.isEmpty()) { - attrBuilders.put(ResourceAttributes.CONTAINER_ID, containerId); + static void parseResponse( + JsonParser parser, AttributesBuilder attrBuilders, LogGroupArnBuilder logGroupArnBuilder) + throws IOException { + if (!parser.isExpectedStartObjectToken()) { + logger.log(Level.WARNING, "Couldn't parse ECS metadata, invalid JSON"); + return; + } + while (parser.nextToken() != JsonToken.END_OBJECT) { + String value = parser.nextTextValue(); + switch (parser.getCurrentName()) { + case "DockerId": + attrBuilders.put(ResourceAttributes.CONTAINER_ID, value); + break; + case "DockerName": + attrBuilders.put(ResourceAttributes.CONTAINER_NAME, value); + break; + case "ContainerARN": + attrBuilders.put(ResourceAttributes.AWS_ECS_CONTAINER_ARN, value); + logGroupArnBuilder.setContainerArn(value); + break; + case "Image": + DockerImage parsedImage = DockerImage.parse(value); + if (parsedImage != null) { + attrBuilders.put(ResourceAttributes.CONTAINER_IMAGE_NAME, parsedImage.getRepository()); + attrBuilders.put(ResourceAttributes.CONTAINER_IMAGE_TAG, parsedImage.getTag()); + } + break; + case "ImageID": + attrBuilders.put("aws.ecs.container.image.id", value); + break; + case "LogOptions": + // Recursively parse LogOptions + parseResponse(parser, attrBuilders, logGroupArnBuilder); + break; + case "awslogs-group": + attrBuilders.put(ResourceAttributes.AWS_LOG_GROUP_NAMES, value); + logGroupArnBuilder.setLogGroupName(value); + break; + case "awslogs-stream": + attrBuilders.put(ResourceAttributes.AWS_LOG_STREAM_NAMES, value); + break; + case "awslogs-region": + logGroupArnBuilder.setRegion(value); + break; + case "TaskARN": + attrBuilders.put(ResourceAttributes.AWS_ECS_TASK_ARN, value); + break; + case "Family": + attrBuilders.put(ResourceAttributes.AWS_ECS_TASK_FAMILY, value); + break; + case "Revision": + attrBuilders.put(ResourceAttributes.AWS_ECS_TASK_REVISION, value); + break; + default: + parser.skipChildren(); + break; + } } - - return Resource.create(attrBuilders.build(), ResourceAttributes.SCHEMA_URL); } - private static boolean isOnEcs(Map sysEnv) { - return !sysEnv.getOrDefault(ECS_METADATA_KEY_V3, "").isEmpty() - || !sysEnv.getOrDefault(ECS_METADATA_KEY_V4, "").isEmpty(); + private EcsResource() {} + + /** + * This builder can piece together a log group ARN from region, account and group name as the ARN + * isn't part of the ECS metadata. + * + *

If we just set AWS_LOG_GROUP_NAMES then the CloudWatch X-Ray traces view displays "An error + * occurred fetching your data". That's why it's important we set the ARN. + */ + private static class LogGroupArnBuilder { + + @Nullable String region; + @Nullable String account; + @Nullable String logGroupName; + + void setRegion(@Nullable String region) { + this.region = region; + } + + void setLogGroupName(@Nullable String logGroupName) { + this.logGroupName = logGroupName; + } + + void setContainerArn(@Nullable String containerArn) { + if (containerArn != null) { + account = containerArn.split(":")[4]; + } + } + + void putLogGroupArnInAttributesBuilder(AttributesBuilder attributesBuilder) { + if (region == null || account == null || logGroupName == null) { + return; + } + attributesBuilder.put( + ResourceAttributes.AWS_LOG_GROUP_ARNS, + "arn:aws:logs:" + region + ":" + account + ":log-group:" + logGroupName); + } } - private EcsResource() {} + /** This can parse a Docker image name into its parts: repository, tag and sha256. */ + private static class DockerImage { + + private static final Pattern imagePattern = + Pattern.compile( + "^(?([^/\\s]+/)?([^:\\s]+))(:(?[^@\\s]+))?(@sha256:(?\\d+))?$"); + + final String repository; + final String tag; + + private DockerImage(String repository, String tag) { + this.repository = repository; + this.tag = tag; + } + + String getRepository() { + return repository; + } + + String getTag() { + return tag; + } + + @Nullable + static DockerImage parse(@Nullable String image) { + if (image == null || image.isEmpty()) { + return null; + } + Matcher matcher = imagePattern.matcher(image); + if (!matcher.matches()) { + logger.log(Level.WARNING, "Couldn't parse image '" + image + "'"); + return null; + } + String repository = matcher.group("repository"); + String tag = matcher.group("tag"); + if (tag == null || tag.isEmpty()) { + tag = "latest"; + } + return new DockerImage(repository, tag); + } + } } diff --git a/sdk-extensions/aws/src/test/java/io/opentelemetry/sdk/extension/aws/resource/EcsResourceTest.java b/sdk-extensions/aws/src/test/java/io/opentelemetry/sdk/extension/aws/resource/EcsResourceTest.java index 7ac1a81122c..18e0fcbe4e9 100644 --- a/sdk-extensions/aws/src/test/java/io/opentelemetry/sdk/extension/aws/resource/EcsResourceTest.java +++ b/sdk-extensions/aws/src/test/java/io/opentelemetry/sdk/extension/aws/resource/EcsResourceTest.java @@ -9,12 +9,15 @@ import static org.assertj.core.api.Assertions.entry; import static org.mockito.Mockito.when; +import com.google.common.io.Resources; +import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; -import java.net.InetAddress; -import java.net.UnknownHostException; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.ServiceLoader; @@ -28,14 +31,19 @@ class EcsResourceTest { private static final String ECS_METADATA_KEY_V4 = "ECS_CONTAINER_METADATA_URI_V4"; private static final String ECS_METADATA_KEY_V3 = "ECS_CONTAINER_METADATA_URI"; - @Mock private DockerHelper mockDockerHelper; + @Mock private SimpleHttpClient mockHttpClient; @Test - void testCreateAttributes() throws UnknownHostException { - when(mockDockerHelper.getContainerId()).thenReturn("0123456789A"); + void testCreateAttributesV3() throws IOException { Map mockSysEnv = new HashMap<>(); mockSysEnv.put(ECS_METADATA_KEY_V3, "ecs_metadata_v3_uri"); - Resource resource = EcsResource.buildResource(mockSysEnv, mockDockerHelper); + when(mockHttpClient.fetchString("GET", "ecs_metadata_v3_uri", Collections.emptyMap(), null)) + .thenReturn(readResourceJson("ecs-container-metadata-v3.json")); + when(mockHttpClient.fetchString( + "GET", "ecs_metadata_v3_uri/task", Collections.emptyMap(), null)) + .thenReturn(readResourceJson("ecs-task-metadata-v3.json")); + + Resource resource = EcsResource.buildResource(mockSysEnv, mockHttpClient); Attributes attributes = resource.getAttributes(); assertThat(resource.getSchemaUrl()).isEqualTo(ResourceAttributes.SCHEMA_URL); @@ -43,30 +51,77 @@ void testCreateAttributes() throws UnknownHostException { .containsOnly( entry(ResourceAttributes.CLOUD_PROVIDER, "aws"), entry(ResourceAttributes.CLOUD_PLATFORM, "aws_ecs"), - entry(ResourceAttributes.CONTAINER_NAME, InetAddress.getLocalHost().getHostName()), - entry(ResourceAttributes.CONTAINER_ID, "0123456789A")); - } - - @Test - void testNotOnEcs() { - Map mockSysEnv = new HashMap<>(); - mockSysEnv.put(ECS_METADATA_KEY_V3, ""); - mockSysEnv.put(ECS_METADATA_KEY_V4, ""); - Attributes attributes = EcsResource.buildResource(mockSysEnv, mockDockerHelper).getAttributes(); - assertThat(attributes).isEmpty(); + entry(ResourceAttributes.CONTAINER_NAME, "ecs-nginx-5-nginx-curl-ccccb9f49db0dfe0d901"), + entry( + ResourceAttributes.CONTAINER_ID, + "43481a6ce4842eec8fe72fc28500c6b52edcc0917f105b83379f88cac1ff3946"), + entry(ResourceAttributes.CONTAINER_IMAGE_NAME, "nrdlngr/nginx-curl"), + entry(ResourceAttributes.CONTAINER_IMAGE_TAG, "latest"), + entry( + AttributeKey.stringKey("aws.ecs.container.image.id"), + "sha256:2e00ae64383cfc865ba0a2ba37f61b50a120d2d9378559dcd458dc0de47bc165"), + entry( + ResourceAttributes.AWS_ECS_TASK_ARN, + "arn:aws:ecs:us-east-2:012345678910:task/9781c248-0edd-4cdb-9a93-f63cb662a5d3"), + entry(ResourceAttributes.AWS_ECS_TASK_FAMILY, "nginx"), + entry(ResourceAttributes.AWS_ECS_TASK_REVISION, "5")); } @Test - void testContainerIdMissing() throws UnknownHostException { - when(mockDockerHelper.getContainerId()).thenReturn(""); + void testCreateAttributesV4() throws IOException { Map mockSysEnv = new HashMap<>(); mockSysEnv.put(ECS_METADATA_KEY_V4, "ecs_metadata_v4_uri"); - Attributes attributes = EcsResource.buildResource(mockSysEnv, mockDockerHelper).getAttributes(); + when(mockHttpClient.fetchString("GET", "ecs_metadata_v4_uri", Collections.emptyMap(), null)) + .thenReturn(readResourceJson("ecs-container-metadata-v4.json")); + when(mockHttpClient.fetchString( + "GET", "ecs_metadata_v4_uri/task", Collections.emptyMap(), null)) + .thenReturn(readResourceJson("ecs-task-metadata-v4.json")); + + Resource resource = EcsResource.buildResource(mockSysEnv, mockHttpClient); + Attributes attributes = resource.getAttributes(); + + assertThat(resource.getSchemaUrl()).isEqualTo(ResourceAttributes.SCHEMA_URL); assertThat(attributes) .containsOnly( entry(ResourceAttributes.CLOUD_PROVIDER, "aws"), entry(ResourceAttributes.CLOUD_PLATFORM, "aws_ecs"), - entry(ResourceAttributes.CONTAINER_NAME, InetAddress.getLocalHost().getHostName())); + entry(ResourceAttributes.CONTAINER_NAME, "ecs-curltest-24-curl-cca48e8dcadd97805600"), + entry( + ResourceAttributes.CONTAINER_ID, + "ea32192c8553fbff06c9340478a2ff089b2bb5646fb718b4ee206641c9086d66"), + entry( + ResourceAttributes.CONTAINER_IMAGE_NAME, + "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest"), + entry(ResourceAttributes.CONTAINER_IMAGE_TAG, "latest"), + entry( + AttributeKey.stringKey("aws.ecs.container.image.id"), + "sha256:d691691e9652791a60114e67b365688d20d19940dde7c4736ea30e660d8d3553"), + entry( + ResourceAttributes.AWS_ECS_CONTAINER_ARN, + "arn:aws:ecs:us-west-2:111122223333:container/0206b271-b33f-47ab-86c6-a0ba208a70a9"), + entry( + ResourceAttributes.AWS_LOG_GROUP_NAMES, Collections.singletonList("/ecs/metadata")), + entry( + ResourceAttributes.AWS_LOG_GROUP_ARNS, + Collections.singletonList( + "arn:aws:logs:us-west-2:111122223333:log-group:/ecs/metadata")), + entry( + ResourceAttributes.AWS_LOG_STREAM_NAMES, + Collections.singletonList("ecs/curl/8f03e41243824aea923aca126495f665")), + entry( + ResourceAttributes.AWS_ECS_TASK_ARN, + "arn:aws:ecs:us-west-2:111122223333:task/default/158d1c8083dd49d6b527399fd6414f5c"), + entry(ResourceAttributes.AWS_ECS_TASK_FAMILY, "curltest"), + entry(ResourceAttributes.AWS_ECS_TASK_REVISION, "26")); + } + + @Test + void testNotOnEcs() { + Map mockSysEnv = new HashMap<>(); + mockSysEnv.put(ECS_METADATA_KEY_V3, ""); + mockSysEnv.put(ECS_METADATA_KEY_V4, ""); + Attributes attributes = EcsResource.buildResource(mockSysEnv, mockHttpClient).getAttributes(); + assertThat(attributes).isEmpty(); } @Test @@ -76,4 +131,8 @@ void inServiceLoader() { assertThat(ServiceLoader.load(ResourceProvider.class)) .anyMatch(EcsResourceProvider.class::isInstance); } + + String readResourceJson(String resourceName) throws IOException { + return Resources.toString(Resources.getResource(resourceName), StandardCharsets.UTF_8); + } } diff --git a/sdk-extensions/aws/src/test/resources/ecs-container-metadata-v3.json b/sdk-extensions/aws/src/test/resources/ecs-container-metadata-v3.json new file mode 100644 index 00000000000..2e89ffe591a --- /dev/null +++ b/sdk-extensions/aws/src/test/resources/ecs-container-metadata-v3.json @@ -0,0 +1,31 @@ +{ + "DockerId": "43481a6ce4842eec8fe72fc28500c6b52edcc0917f105b83379f88cac1ff3946", + "Name": "nginx-curl", + "DockerName": "ecs-nginx-5-nginx-curl-ccccb9f49db0dfe0d901", + "Image": "nrdlngr/nginx-curl", + "ImageID": "sha256:2e00ae64383cfc865ba0a2ba37f61b50a120d2d9378559dcd458dc0de47bc165", + "Labels": { + "com.amazonaws.ecs.cluster": "default", + "com.amazonaws.ecs.container-name": "nginx-curl", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-2:012345678910:task/9781c248-0edd-4cdb-9a93-f63cb662a5d3", + "com.amazonaws.ecs.task-definition-family": "nginx", + "com.amazonaws.ecs.task-definition-version": "5" + }, + "DesiredStatus": "RUNNING", + "KnownStatus": "RUNNING", + "Limits": { + "CPU": 512, + "Memory": 512 + }, + "CreatedAt": "2018-02-01T20:55:10.554941919Z", + "StartedAt": "2018-02-01T20:55:11.064236631Z", + "Type": "NORMAL", + "Networks": [ + { + "NetworkMode": "awsvpc", + "IPv4Addresses": [ + "10.0.2.106" + ] + } + ] +} \ No newline at end of file diff --git a/sdk-extensions/aws/src/test/resources/ecs-container-metadata-v4.json b/sdk-extensions/aws/src/test/resources/ecs-container-metadata-v4.json new file mode 100644 index 00000000000..d5db49bbf4c --- /dev/null +++ b/sdk-extensions/aws/src/test/resources/ecs-container-metadata-v4.json @@ -0,0 +1,44 @@ +{ + "DockerId": "ea32192c8553fbff06c9340478a2ff089b2bb5646fb718b4ee206641c9086d66", + "Name": "curl", + "DockerName": "ecs-curltest-24-curl-cca48e8dcadd97805600", + "Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest", + "ImageID": "sha256:d691691e9652791a60114e67b365688d20d19940dde7c4736ea30e660d8d3553", + "Labels": { + "com.amazonaws.ecs.cluster": "default", + "com.amazonaws.ecs.container-name": "curl", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/8f03e41243824aea923aca126495f665", + "com.amazonaws.ecs.task-definition-family": "curltest", + "com.amazonaws.ecs.task-definition-version": "24" + }, + "DesiredStatus": "RUNNING", + "KnownStatus": "RUNNING", + "Limits": { + "CPU": 10, + "Memory": 128 + }, + "CreatedAt": "2020-10-02T00:15:07.620912337Z", + "StartedAt": "2020-10-02T00:15:08.062559351Z", + "Type": "NORMAL", + "LogDriver": "awslogs", + "LogOptions": { + "awslogs-create-group": "true", + "awslogs-group": "/ecs/metadata", + "awslogs-region": "us-west-2", + "awslogs-stream": "ecs/curl/8f03e41243824aea923aca126495f665" + }, + "ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/0206b271-b33f-47ab-86c6-a0ba208a70a9", + "Networks": [ + { + "NetworkMode": "awsvpc", + "IPv4Addresses": [ + "10.0.2.100" + ], + "AttachmentIndex": 0, + "MACAddress": "0e:9e:32:c7:48:85", + "IPv4SubnetCIDRBlock": "10.0.2.0/24", + "PrivateDNSName": "ip-10-0-2-100.us-west-2.compute.internal", + "SubnetGatewayIpv4Address": "10.0.2.1/24" + } + ] +} \ No newline at end of file diff --git a/sdk-extensions/aws/src/test/resources/ecs-task-metadata-v3.json b/sdk-extensions/aws/src/test/resources/ecs-task-metadata-v3.json new file mode 100644 index 00000000000..69b724075e4 --- /dev/null +++ b/sdk-extensions/aws/src/test/resources/ecs-task-metadata-v3.json @@ -0,0 +1,75 @@ +{ + "Cluster": "default", + "TaskARN": "arn:aws:ecs:us-east-2:012345678910:task/9781c248-0edd-4cdb-9a93-f63cb662a5d3", + "Family": "nginx", + "Revision": "5", + "DesiredStatus": "RUNNING", + "KnownStatus": "RUNNING", + "Containers": [ + { + "DockerId": "731a0d6a3b4210e2448339bc7015aaa79bfe4fa256384f4102db86ef94cbbc4c", + "Name": "~internal~ecs~pause", + "DockerName": "ecs-nginx-5-internalecspause-acc699c0cbf2d6d11700", + "Image": "amazon/amazon-ecs-pause:0.1.0", + "ImageID": "", + "Labels": { + "com.amazonaws.ecs.cluster": "default", + "com.amazonaws.ecs.container-name": "~internal~ecs~pause", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-2:012345678910:task/9781c248-0edd-4cdb-9a93-f63cb662a5d3", + "com.amazonaws.ecs.task-definition-family": "nginx", + "com.amazonaws.ecs.task-definition-version": "5" + }, + "DesiredStatus": "RESOURCES_PROVISIONED", + "KnownStatus": "RESOURCES_PROVISIONED", + "Limits": { + "CPU": 0, + "Memory": 0 + }, + "CreatedAt": "2018-02-01T20:55:08.366329616Z", + "StartedAt": "2018-02-01T20:55:09.058354915Z", + "Type": "CNI_PAUSE", + "Networks": [ + { + "NetworkMode": "awsvpc", + "IPv4Addresses": [ + "10.0.2.106" + ] + } + ] + }, + { + "DockerId": "43481a6ce4842eec8fe72fc28500c6b52edcc0917f105b83379f88cac1ff3946", + "Name": "nginx-curl", + "DockerName": "ecs-nginx-5-nginx-curl-ccccb9f49db0dfe0d901", + "Image": "nrdlngr/nginx-curl", + "ImageID": "sha256:2e00ae64383cfc865ba0a2ba37f61b50a120d2d9378559dcd458dc0de47bc165", + "Labels": { + "com.amazonaws.ecs.cluster": "default", + "com.amazonaws.ecs.container-name": "nginx-curl", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-2:012345678910:task/9781c248-0edd-4cdb-9a93-f63cb662a5d3", + "com.amazonaws.ecs.task-definition-family": "nginx", + "com.amazonaws.ecs.task-definition-version": "5" + }, + "DesiredStatus": "RUNNING", + "KnownStatus": "RUNNING", + "Limits": { + "CPU": 512, + "Memory": 512 + }, + "CreatedAt": "2018-02-01T20:55:10.554941919Z", + "StartedAt": "2018-02-01T20:55:11.064236631Z", + "Type": "NORMAL", + "Networks": [ + { + "NetworkMode": "awsvpc", + "IPv4Addresses": [ + "10.0.2.106" + ] + } + ] + } + ], + "PullStartedAt": "2018-02-01T20:55:09.372495529Z", + "PullStoppedAt": "2018-02-01T20:55:10.552018345Z", + "AvailabilityZone": "us-east-2b" +} \ No newline at end of file diff --git a/sdk-extensions/aws/src/test/resources/ecs-task-metadata-v4.json b/sdk-extensions/aws/src/test/resources/ecs-task-metadata-v4.json new file mode 100644 index 00000000000..c8043a74511 --- /dev/null +++ b/sdk-extensions/aws/src/test/resources/ecs-task-metadata-v4.json @@ -0,0 +1,94 @@ +{ + "Cluster": "default", + "TaskARN": "arn:aws:ecs:us-west-2:111122223333:task/default/158d1c8083dd49d6b527399fd6414f5c", + "Family": "curltest", + "Revision": "26", + "DesiredStatus": "RUNNING", + "KnownStatus": "RUNNING", + "PullStartedAt": "2020-10-02T00:43:06.202617438Z", + "PullStoppedAt": "2020-10-02T00:43:06.31288465Z", + "AvailabilityZone": "us-west-2d", + "LaunchType": "EC2", + "Containers": [ + { + "DockerId": "598cba581fe3f939459eaba1e071d5c93bb2c49b7d1ba7db6bb19deeb70d8e38", + "Name": "~internal~ecs~pause", + "DockerName": "ecs-curltest-26-internalecspause-e292d586b6f9dade4a00", + "Image": "amazon/amazon-ecs-pause:0.1.0", + "ImageID": "", + "Labels": { + "com.amazonaws.ecs.cluster": "default", + "com.amazonaws.ecs.container-name": "~internal~ecs~pause", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/158d1c8083dd49d6b527399fd6414f5c", + "com.amazonaws.ecs.task-definition-family": "curltest", + "com.amazonaws.ecs.task-definition-version": "26" + }, + "DesiredStatus": "RESOURCES_PROVISIONED", + "KnownStatus": "RESOURCES_PROVISIONED", + "Limits": { + "CPU": 0, + "Memory": 0 + }, + "CreatedAt": "2020-10-02T00:43:05.602352471Z", + "StartedAt": "2020-10-02T00:43:06.076707576Z", + "Type": "CNI_PAUSE", + "Networks": [ + { + "NetworkMode": "awsvpc", + "IPv4Addresses": [ + "10.0.2.61" + ], + "AttachmentIndex": 0, + "MACAddress": "0e:10:e2:01:bd:91", + "IPv4SubnetCIDRBlock": "10.0.2.0/24", + "PrivateDNSName": "ip-10-0-2-61.us-west-2.compute.internal", + "SubnetGatewayIpv4Address": "10.0.2.1/24" + } + ] + }, + { + "DockerId": "ee08638adaaf009d78c248913f629e38299471d45fe7dc944d1039077e3424ca", + "Name": "curl", + "DockerName": "ecs-curltest-26-curl-a0e7dba5aca6d8cb2e00", + "Image": "111122223333.dkr.ecr.us-west-2.amazonaws.com/curltest:latest", + "ImageID": "sha256:d691691e9652791a60114e67b365688d20d19940dde7c4736ea30e660d8d3553", + "Labels": { + "com.amazonaws.ecs.cluster": "default", + "com.amazonaws.ecs.container-name": "curl", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-west-2:111122223333:task/default/158d1c8083dd49d6b527399fd6414f5c", + "com.amazonaws.ecs.task-definition-family": "curltest", + "com.amazonaws.ecs.task-definition-version": "26" + }, + "DesiredStatus": "RUNNING", + "KnownStatus": "RUNNING", + "Limits": { + "CPU": 10, + "Memory": 128 + }, + "CreatedAt": "2020-10-02T00:43:06.326590752Z", + "StartedAt": "2020-10-02T00:43:06.767535449Z", + "Type": "NORMAL", + "LogDriver": "awslogs", + "LogOptions": { + "awslogs-create-group": "true", + "awslogs-group": "/ecs/metadata", + "awslogs-region": "us-west-2", + "awslogs-stream": "ecs/curl/158d1c8083dd49d6b527399fd6414f5c" + }, + "ContainerARN": "arn:aws:ecs:us-west-2:111122223333:container/abb51bdd-11b4-467f-8f6c-adcfe1fe059d", + "Networks": [ + { + "NetworkMode": "awsvpc", + "IPv4Addresses": [ + "10.0.2.61" + ], + "AttachmentIndex": 0, + "MACAddress": "0e:10:e2:01:bd:91", + "IPv4SubnetCIDRBlock": "10.0.2.0/24", + "PrivateDNSName": "ip-10-0-2-61.us-west-2.compute.internal", + "SubnetGatewayIpv4Address": "10.0.2.1/24" + } + ] + } + ] +} \ No newline at end of file