From 6ac05f5c991c6015ab9754b48f8bb9afeb8e9441 Mon Sep 17 00:00:00 2001 From: Ian Kerins Date: Sun, 27 Apr 2025 23:43:36 -0400 Subject: [PATCH] Add tooling to update task metadata API fixtures The task metadata API fixtures I've previously created in this repository were sourced from real ECS tasks managed by AWS CDK. But how to reproduce that was left as an exercise to the reader. Here, I am adding a CDK app and instructions that will enable anybody with an AWS account and the willingness to install NodeJS and some other tools on their computer to update the fixtures. I have updated the fixtures by following the instructions I added to the README. There are few substantive changes from the previous fixtures, but there is a fair amount of churn, much of which is unavoidable (timestamps, autoincrementing version numbers, etc), but some of which can be eliminated through some new simple sorting of the API responses, which should reduce churn going forward. Signed-off-by: Ian Kerins --- .gitignore | 2 + .../testdata/fixtures/ec2_task_metadata.json | 286 +++++++++-------- .../testdata/fixtures/ec2_task_stats.json | 288 ++++++++++++------ .../fixtures/fargate_task_metadata.json | 161 +++++----- .../testdata/fixtures/fargate_task_stats.json | 254 +++++++-------- .../testdata/snapshots/ec2_metrics.txt | 35 ++- .../testdata/snapshots/fargate_metrics.txt | 32 +- go.mod | 24 +- go.sum | 53 +++- tools/cdk/README.md | 71 +++++ tools/cdk/cdk.json | 72 +++++ tools/cdk/main.go | 206 +++++++++++++ 12 files changed, 1010 insertions(+), 474 deletions(-) create mode 100644 tools/cdk/README.md create mode 100644 tools/cdk/cdk.json create mode 100644 tools/cdk/main.go diff --git a/.gitignore b/.gitignore index 107bc8d..54e8f0c 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,5 @@ dependencies-stamp *.tar.gz /vendor .idea + +cdk.out diff --git a/ecscollector/testdata/fixtures/ec2_task_metadata.json b/ecscollector/testdata/fixtures/ec2_task_metadata.json index 5c7f869..a188a1a 100644 --- a/ecscollector/testdata/fixtures/ec2_task_metadata.json +++ b/ecscollector/testdata/fixtures/ec2_task_metadata.json @@ -1,229 +1,259 @@ { - "Cluster": "prom-ecs-exporter-sandbox", - "TaskARN": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-sandbox/506f22fab0414cde856201584703fed9", - "Family": "prom-ecs-exporter-sandbox-main-ec2", - "Revision": "13", + "Cluster": "prom-ecs-exporter-fixtures", + "TaskARN": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-fixtures/1e76d951e76c4ea5ad410966ffde3bdb", + "Family": "ecs-exporter-fixtures-ec2", + "Revision": "4", "DesiredStatus": "RUNNING", "KnownStatus": "RUNNING", - "PullStartedAt": "2025-02-27T05:09:52.332595252Z", - "PullStoppedAt": "2025-02-27T05:10:01.206072368Z", + "Limits": { + "Memory": 256 + }, + "PullStartedAt": "2025-04-28T02:04:56.203269242Z", + "PullStoppedAt": "2025-04-28T02:05:03.516794491Z", "AvailabilityZone": "us-east-1a", "LaunchType": "EC2", "Containers": [ { - "DockerId": "213e1203f4bb72af185724d937e698d2724acf35b57ec2dd5f3c963adbd2d38c", - "Name": "nonessential", - "DockerName": "ecs-prom-ecs-exporter-sandbox-main-ec2-13-nonessential-9c9ab8aeb0e0dbdca601", - "Image": "alpine", - "ImageID": "sha256:8d591b0b7dea080ea3be9e12ae563eebf9869168ffced1cb25b2470a3d9fe15e", + "DockerId": "559f4af51a2f85286138de04fbe2892348128ed55dbf24033bc6a1a3eb6f1d7f", + "Name": "ecs-exporter", + "DockerName": "ecs-ecs-exporter-fixtures-ec2-4-ecs-exporter-f8a886e3c3d191f72100", + "Image": "quay.io/prometheuscommunity/ecs-exporter:v0.4.0", + "ImageID": "sha256:bedb26ec39cf3d7fac4602a633a275df7227c84b3e4b320712b60a510416420f", "Labels": { - "com.amazonaws.ecs.cluster": "prom-ecs-exporter-sandbox", - "com.amazonaws.ecs.container-name": "nonessential", - "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-sandbox/506f22fab0414cde856201584703fed9", - "com.amazonaws.ecs.task-definition-family": "prom-ecs-exporter-sandbox-main-ec2", - "com.amazonaws.ecs.task-definition-version": "13" + "com.amazonaws.ecs.cluster": "prom-ecs-exporter-fixtures", + "com.amazonaws.ecs.container-name": "ecs-exporter", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-fixtures/1e76d951e76c4ea5ad410966ffde3bdb", + "com.amazonaws.ecs.task-definition-family": "ecs-exporter-fixtures-ec2", + "com.amazonaws.ecs.task-definition-version": "4" }, "DesiredStatus": "RUNNING", - "KnownStatus": "STOPPED", - "ExitCode": 0, + "KnownStatus": "RUNNING", "Limits": { "CPU": 128, - "Memory": 256 + "Memory": 128 }, - "CreatedAt": "2025-02-27T05:09:54.959587312Z", - "StartedAt": "2025-02-27T05:09:56.392336771Z", - "FinishedAt": "2025-02-27T05:09:56.409399983Z", + "CreatedAt": "2025-04-28T02:05:03.535090427Z", + "StartedAt": "2025-04-28T02:05:03.749856806Z", "Type": "NORMAL", "Volumes": [ { - "Source": "/var/lib/ecs/deps/execute-command/config/amazon-ssm-agent-Orvj12YkCf4DKDu1cHTOVj7smDviWx1T4Kg3Q_IdNYA=.json", - "Destination": "/ecs-execute-command-636764d0-0d77-44c1-96b2-207c74034dff/configuration/amazon-ssm-agent.json" + "Source": "/var/lib/ecs/deps/execute-command/bin/3.3.1802.0/amazon-ssm-agent", + "Destination": "/ecs-execute-command-c475367c-67a3-4a69-83e1-03d6d897e13e/amazon-ssm-agent" }, { - "Source": "/var/lib/ecs/deps/execute-command/config/seelog-gEZ-TIvHAyOLfMC5wiWRofgDMlDzaCZ6zcswnAoop84=.xml", - "Destination": "/ecs-execute-command-636764d0-0d77-44c1-96b2-207c74034dff/configuration/seelog.xml" + "Source": "/var/lib/ecs/deps/execute-command/bin/3.3.1802.0/ssm-agent-worker", + "Destination": "/ecs-execute-command-c475367c-67a3-4a69-83e1-03d6d897e13e/ssm-agent-worker" }, { - "Source": "/var/lib/ecs/deps/execute-command/certs/tls-ca-bundle.pem", - "Destination": "/ecs-execute-command-636764d0-0d77-44c1-96b2-207c74034dff/certs/amazon-ssm-agent.crt" + "Source": "/var/lib/ecs/deps/execute-command/bin/3.3.1802.0/ssm-session-worker", + "Destination": "/ecs-execute-command-c475367c-67a3-4a69-83e1-03d6d897e13e/ssm-session-worker" }, { - "Source": "/var/log/ecs/exec/506f22fab0414cde856201584703fed9/nonessential", - "Destination": "/var/log/amazon/ssm" + "Source": "/var/lib/ecs/deps/execute-command/config/amazon-ssm-agent-Orvj12YkCf4DKDu1cHTOVj7smDviWx1T4Kg3Q_IdNYA=.json", + "Destination": "/ecs-execute-command-c475367c-67a3-4a69-83e1-03d6d897e13e/configuration/amazon-ssm-agent.json" }, { - "Source": "/var/lib/ecs/deps/execute-command/bin/3.3.1802.0/amazon-ssm-agent", - "Destination": "/ecs-execute-command-636764d0-0d77-44c1-96b2-207c74034dff/amazon-ssm-agent" + "Source": "/var/lib/ecs/deps/execute-command/config/seelog-gEZ-TIvHAyOLfMC5wiWRofgDMlDzaCZ6zcswnAoop84=.xml", + "Destination": "/ecs-execute-command-c475367c-67a3-4a69-83e1-03d6d897e13e/configuration/seelog.xml" }, { - "Source": "/var/lib/ecs/deps/execute-command/bin/3.3.1802.0/ssm-agent-worker", - "Destination": "/ecs-execute-command-636764d0-0d77-44c1-96b2-207c74034dff/ssm-agent-worker" + "Source": "/var/lib/ecs/deps/execute-command/certs/tls-ca-bundle.pem", + "Destination": "/ecs-execute-command-c475367c-67a3-4a69-83e1-03d6d897e13e/certs/amazon-ssm-agent.crt" }, { - "Source": "/var/lib/ecs/deps/execute-command/bin/3.3.1802.0/ssm-session-worker", - "Destination": "/ecs-execute-command-636764d0-0d77-44c1-96b2-207c74034dff/ssm-session-worker" + "Source": "/var/log/ecs/exec/1e76d951e76c4ea5ad410966ffde3bdb/ecs-exporter", + "Destination": "/var/log/amazon/ssm" } ], - "ContainerARN": "arn:aws:ecs:us-east-1:829490980523:container/prom-ecs-exporter-sandbox/506f22fab0414cde856201584703fed9/80b5fc27-0113-4b4f-83a4-f3d4b4b2b016", + "ContainerARN": "arn:aws:ecs:us-east-1:829490980523:container/prom-ecs-exporter-fixtures/1e76d951e76c4ea5ad410966ffde3bdb/7af5aa98-978a-4b49-b808-e0f2f24238c2", "Networks": [ { - "NetworkMode": "bridge", + "NetworkMode": "awsvpc", "IPv4Addresses": [ - "" - ] + "10.0.178.177" + ], + "AttachmentIndex": 0, + "MACAddress": "0a:ff:c0:bd:cb:53", + "IPv4SubnetCIDRBlock": "10.0.128.0/17", + "PrivateDNSName": "ip-10-0-178-177.ec2.internal", + "SubnetGatewayIpv4Address": "10.0.128.1/17" } ] }, { - "DockerId": "01cf1f3208005cda71d5ac936ded65d2ecc0a8cc8ff8a82d2e00410bf4fbbd6d", - "Name": "ecs-exporter", - "DockerName": "ecs-prom-ecs-exporter-sandbox-main-ec2-13-ecs-exporter-e2aeb1e6be8998c72300", - "Image": "quay.io/prometheuscommunity/ecs-exporter:main", - "ImageID": "sha256:1585460bf5becf755c9f45fa931283546ca62e2d51bb638010c8958158d144bc", - "Ports": [ - { - "ContainerPort": 9779, - "Protocol": "tcp", - "HostPort": 32768, - "HostIp": "0.0.0.0" - }, - { - "ContainerPort": 9779, - "Protocol": "tcp", - "HostPort": 32768, - "HostIp": "::" - } - ], + "DockerId": "d3b4c06f3fe8614d958ed27f7f3e40adc3b252793399741a92f0935fb60fb5a8", + "Name": "main", + "DockerName": "ecs-ecs-exporter-fixtures-ec2-4-main-c0d28ea4b8e4b68e2500", + "Image": "alpine", + "ImageID": "sha256:8d591b0b7dea080ea3be9e12ae563eebf9869168ffced1cb25b2470a3d9fe15e", "Labels": { - "com.amazonaws.ecs.cluster": "prom-ecs-exporter-sandbox", - "com.amazonaws.ecs.container-name": "ecs-exporter", - "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-sandbox/506f22fab0414cde856201584703fed9", - "com.amazonaws.ecs.task-definition-family": "prom-ecs-exporter-sandbox-main-ec2", - "com.amazonaws.ecs.task-definition-version": "13" + "com.amazonaws.ecs.cluster": "prom-ecs-exporter-fixtures", + "com.amazonaws.ecs.container-name": "main", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-fixtures/1e76d951e76c4ea5ad410966ffde3bdb", + "com.amazonaws.ecs.task-definition-family": "ecs-exporter-fixtures-ec2", + "com.amazonaws.ecs.task-definition-version": "4" }, "DesiredStatus": "RUNNING", "KnownStatus": "RUNNING", "Limits": { - "CPU": 128, - "Memory": 256 + "CPU": 2, + "Memory": 0 }, - "CreatedAt": "2025-02-27T05:10:00.313953836Z", - "StartedAt": "2025-02-27T05:10:02.731563327Z", + "CreatedAt": "2025-04-28T02:04:56.308600111Z", + "StartedAt": "2025-04-28T02:04:56.505535488Z", "Type": "NORMAL", "Volumes": [ { - "Source": "/var/lib/ecs/deps/execute-command/config/seelog-gEZ-TIvHAyOLfMC5wiWRofgDMlDzaCZ6zcswnAoop84=.xml", - "Destination": "/ecs-execute-command-36dfb910-8e80-47b9-8b3a-12c7308123b2/configuration/seelog.xml" + "Source": "/var/lib/ecs/deps/execute-command/bin/3.3.1802.0/amazon-ssm-agent", + "Destination": "/ecs-execute-command-41acb996-dcb3-4bbf-b998-6fd60e92b9f9/amazon-ssm-agent" }, { - "Source": "/var/lib/ecs/deps/execute-command/certs/tls-ca-bundle.pem", - "Destination": "/ecs-execute-command-36dfb910-8e80-47b9-8b3a-12c7308123b2/certs/amazon-ssm-agent.crt" + "Source": "/var/lib/ecs/deps/execute-command/bin/3.3.1802.0/ssm-agent-worker", + "Destination": "/ecs-execute-command-41acb996-dcb3-4bbf-b998-6fd60e92b9f9/ssm-agent-worker" }, { - "Source": "/var/log/ecs/exec/506f22fab0414cde856201584703fed9/ecs-exporter", - "Destination": "/var/log/amazon/ssm" + "Source": "/var/lib/ecs/deps/execute-command/bin/3.3.1802.0/ssm-session-worker", + "Destination": "/ecs-execute-command-41acb996-dcb3-4bbf-b998-6fd60e92b9f9/ssm-session-worker" }, { - "Source": "/var/lib/ecs/deps/execute-command/bin/3.3.1802.0/amazon-ssm-agent", - "Destination": "/ecs-execute-command-36dfb910-8e80-47b9-8b3a-12c7308123b2/amazon-ssm-agent" + "Source": "/var/lib/ecs/deps/execute-command/config/amazon-ssm-agent-Orvj12YkCf4DKDu1cHTOVj7smDviWx1T4Kg3Q_IdNYA=.json", + "Destination": "/ecs-execute-command-41acb996-dcb3-4bbf-b998-6fd60e92b9f9/configuration/amazon-ssm-agent.json" }, { - "Source": "/var/lib/ecs/deps/execute-command/bin/3.3.1802.0/ssm-agent-worker", - "Destination": "/ecs-execute-command-36dfb910-8e80-47b9-8b3a-12c7308123b2/ssm-agent-worker" + "Source": "/var/lib/ecs/deps/execute-command/config/seelog-gEZ-TIvHAyOLfMC5wiWRofgDMlDzaCZ6zcswnAoop84=.xml", + "Destination": "/ecs-execute-command-41acb996-dcb3-4bbf-b998-6fd60e92b9f9/configuration/seelog.xml" }, { - "Source": "/var/lib/ecs/deps/execute-command/bin/3.3.1802.0/ssm-session-worker", - "Destination": "/ecs-execute-command-36dfb910-8e80-47b9-8b3a-12c7308123b2/ssm-session-worker" + "Source": "/var/lib/ecs/deps/execute-command/certs/tls-ca-bundle.pem", + "Destination": "/ecs-execute-command-41acb996-dcb3-4bbf-b998-6fd60e92b9f9/certs/amazon-ssm-agent.crt" }, { - "Source": "/var/lib/ecs/deps/execute-command/config/amazon-ssm-agent-Orvj12YkCf4DKDu1cHTOVj7smDviWx1T4Kg3Q_IdNYA=.json", - "Destination": "/ecs-execute-command-36dfb910-8e80-47b9-8b3a-12c7308123b2/configuration/amazon-ssm-agent.json" + "Source": "/var/log/ecs/exec/1e76d951e76c4ea5ad410966ffde3bdb/main", + "Destination": "/var/log/amazon/ssm" } ], - "LogDriver": "awslogs", - "LogOptions": { - "awslogs-group": "EcsExporterCdkStack-promecsexportersandboxmainec2taskdefinitionpromecsexportersandboxmainec2ecsexporterLogGroup874A22EF-y3iGqSSTf3sz", - "awslogs-region": "us-east-1", - "awslogs-stream": "ecs-exporter/ecs-exporter/506f22fab0414cde856201584703fed9" - }, - "ContainerARN": "arn:aws:ecs:us-east-1:829490980523:container/prom-ecs-exporter-sandbox/506f22fab0414cde856201584703fed9/5fba1957-462a-48b2-9295-8602b69e00be", + "ContainerARN": "arn:aws:ecs:us-east-1:829490980523:container/prom-ecs-exporter-fixtures/1e76d951e76c4ea5ad410966ffde3bdb/e09dd682-65fd-4d9f-a2bd-2707fd62fb7e", "Networks": [ { - "NetworkMode": "bridge", + "NetworkMode": "awsvpc", "IPv4Addresses": [ - "172.17.0.2" - ] + "10.0.178.177" + ], + "AttachmentIndex": 0, + "MACAddress": "0a:ff:c0:bd:cb:53", + "IPv4SubnetCIDRBlock": "10.0.128.0/17", + "PrivateDNSName": "ip-10-0-178-177.ec2.internal", + "SubnetGatewayIpv4Address": "10.0.128.1/17" } ] }, { - "DockerId": "6b80adab0733f579594eccae31e5b0056b9544b805450ad6e278fed7f5e1c5ba", - "Name": "prometheus", - "DockerName": "ecs-prom-ecs-exporter-sandbox-main-ec2-13-prometheus-86f1e9bab7a8e9a65400", - "Image": "prom/prometheus:v3.1.0", - "ImageID": "sha256:f3d60e89ba2d4a402d1c62dccdab300f81579355e0744670c55b9ba282f3b56d", + "DockerId": "74d72daf3420705c7038b9f11295b4d951ca32c4f71f1ff6e3abe58202abc093", + "Name": "nonessential", + "DockerName": "ecs-ecs-exporter-fixtures-ec2-4-nonessential-94b3bf8585e3e8bec001", + "Image": "alpine", + "ImageID": "sha256:8d591b0b7dea080ea3be9e12ae563eebf9869168ffced1cb25b2470a3d9fe15e", "Labels": { - "com.amazonaws.ecs.cluster": "prom-ecs-exporter-sandbox", - "com.amazonaws.ecs.container-name": "prometheus", - "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-sandbox/506f22fab0414cde856201584703fed9", - "com.amazonaws.ecs.task-definition-family": "prom-ecs-exporter-sandbox-main-ec2", - "com.amazonaws.ecs.task-definition-version": "13" + "com.amazonaws.ecs.cluster": "prom-ecs-exporter-fixtures", + "com.amazonaws.ecs.container-name": "nonessential", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-fixtures/1e76d951e76c4ea5ad410966ffde3bdb", + "com.amazonaws.ecs.task-definition-family": "ecs-exporter-fixtures-ec2", + "com.amazonaws.ecs.task-definition-version": "4" }, "DesiredStatus": "RUNNING", - "KnownStatus": "RUNNING", + "KnownStatus": "STOPPED", + "ExitCode": 0, "Limits": { "CPU": 128, - "Memory": 256 + "Memory": 128 }, - "CreatedAt": "2025-02-27T05:10:01.22383376Z", - "StartedAt": "2025-02-27T05:10:02.730952683Z", + "CreatedAt": "2025-04-28T02:04:56.297553357Z", + "StartedAt": "2025-04-28T02:04:56.520475713Z", + "FinishedAt": "2025-04-28T02:04:56.518937243Z", "Type": "NORMAL", "Volumes": [ { - "DockerName": "b4c23c0b1e1cea0ddfeab13122e911c7f52eb67720d3ffb43adba63b817e6a1e", - "Source": "/var/lib/docker/volumes/b4c23c0b1e1cea0ddfeab13122e911c7f52eb67720d3ffb43adba63b817e6a1e/_data", - "Destination": "/prometheus" + "Source": "/var/lib/ecs/deps/execute-command/certs/tls-ca-bundle.pem", + "Destination": "/ecs-execute-command-e70b4983-0ed3-4602-8110-e8b7c82a6e3e/certs/amazon-ssm-agent.crt" + }, + { + "Source": "/var/log/ecs/exec/1e76d951e76c4ea5ad410966ffde3bdb/nonessential", + "Destination": "/var/log/amazon/ssm" }, { "Source": "/var/lib/ecs/deps/execute-command/bin/3.3.1802.0/amazon-ssm-agent", - "Destination": "/ecs-execute-command-12f856a9-3af4-4de7-ab82-671147b2a114/amazon-ssm-agent" + "Destination": "/ecs-execute-command-e70b4983-0ed3-4602-8110-e8b7c82a6e3e/amazon-ssm-agent" }, { "Source": "/var/lib/ecs/deps/execute-command/bin/3.3.1802.0/ssm-agent-worker", - "Destination": "/ecs-execute-command-12f856a9-3af4-4de7-ab82-671147b2a114/ssm-agent-worker" + "Destination": "/ecs-execute-command-e70b4983-0ed3-4602-8110-e8b7c82a6e3e/ssm-agent-worker" }, { "Source": "/var/lib/ecs/deps/execute-command/bin/3.3.1802.0/ssm-session-worker", - "Destination": "/ecs-execute-command-12f856a9-3af4-4de7-ab82-671147b2a114/ssm-session-worker" + "Destination": "/ecs-execute-command-e70b4983-0ed3-4602-8110-e8b7c82a6e3e/ssm-session-worker" }, { "Source": "/var/lib/ecs/deps/execute-command/config/amazon-ssm-agent-Orvj12YkCf4DKDu1cHTOVj7smDviWx1T4Kg3Q_IdNYA=.json", - "Destination": "/ecs-execute-command-12f856a9-3af4-4de7-ab82-671147b2a114/configuration/amazon-ssm-agent.json" + "Destination": "/ecs-execute-command-e70b4983-0ed3-4602-8110-e8b7c82a6e3e/configuration/amazon-ssm-agent.json" }, { "Source": "/var/lib/ecs/deps/execute-command/config/seelog-gEZ-TIvHAyOLfMC5wiWRofgDMlDzaCZ6zcswnAoop84=.xml", - "Destination": "/ecs-execute-command-12f856a9-3af4-4de7-ab82-671147b2a114/configuration/seelog.xml" - }, - { - "Source": "/var/lib/ecs/deps/execute-command/certs/tls-ca-bundle.pem", - "Destination": "/ecs-execute-command-12f856a9-3af4-4de7-ab82-671147b2a114/certs/amazon-ssm-agent.crt" - }, - { - "Source": "/var/log/ecs/exec/506f22fab0414cde856201584703fed9/prometheus", - "Destination": "/var/log/amazon/ssm" + "Destination": "/ecs-execute-command-e70b4983-0ed3-4602-8110-e8b7c82a6e3e/configuration/seelog.xml" } ], - "ContainerARN": "arn:aws:ecs:us-east-1:829490980523:container/prom-ecs-exporter-sandbox/506f22fab0414cde856201584703fed9/7ae35d49-867b-468f-afef-916925db8dca", + "ContainerARN": "arn:aws:ecs:us-east-1:829490980523:container/prom-ecs-exporter-fixtures/1e76d951e76c4ea5ad410966ffde3bdb/b6d4de7e-b022-4721-abd5-4a432ecd6797", + "Networks": [ + { + "NetworkMode": "awsvpc", + "IPv4Addresses": [ + "10.0.178.177" + ], + "AttachmentIndex": 0, + "MACAddress": "0a:ff:c0:bd:cb:53", + "IPv4SubnetCIDRBlock": "10.0.128.0/17", + "PrivateDNSName": "ip-10-0-178-177.ec2.internal", + "SubnetGatewayIpv4Address": "10.0.128.1/17" + } + ] + }, + { + "DockerId": "b14a1fde2922565d8820e6ee859cdadbc7bc9020c3f751b3446c700deacd1ce8", + "Name": "~internal~ecs~pause", + "DockerName": "ecs-ecs-exporter-fixtures-ec2-4-internalecspause-d0f6aaab84b9e2e8ed01", + "Image": "amazon/amazon-ecs-pause:0.1.0", + "ImageID": "", + "Labels": { + "com.amazonaws.ecs.cluster": "prom-ecs-exporter-fixtures", + "com.amazonaws.ecs.container-name": "~internal~ecs~pause", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-fixtures/1e76d951e76c4ea5ad410966ffde3bdb", + "com.amazonaws.ecs.task-definition-family": "ecs-exporter-fixtures-ec2", + "com.amazonaws.ecs.task-definition-version": "4" + }, + "DesiredStatus": "RESOURCES_PROVISIONED", + "KnownStatus": "RESOURCES_PROVISIONED", + "Limits": { + "CPU": 2, + "Memory": 0 + }, + "CreatedAt": "2025-04-28T02:04:55.307033971Z", + "StartedAt": "2025-04-28T02:04:55.775480003Z", + "Type": "CNI_PAUSE", "Networks": [ { - "NetworkMode": "bridge", + "NetworkMode": "awsvpc", "IPv4Addresses": [ - "172.17.0.3" - ] + "10.0.178.177" + ], + "AttachmentIndex": 0, + "MACAddress": "0a:ff:c0:bd:cb:53", + "IPv4SubnetCIDRBlock": "10.0.128.0/17", + "PrivateDNSName": "ip-10-0-178-177.ec2.internal", + "SubnetGatewayIpv4Address": "10.0.128.1/17" } ] } ], - "VPCID": "vpc-0839c743edb0c009e", - "ServiceName": "prom-ecs-exporter-sandbox-main-ec2" + "VPCID": "vpc-033f2f6b3186233ca", + "ServiceName": "prom-ecs-exporter-fixtures-ec2", + "FaultInjectionEnabled": false } diff --git a/ecscollector/testdata/fixtures/ec2_task_stats.json b/ecscollector/testdata/fixtures/ec2_task_stats.json index 4d61c40..0a5b0c8 100644 --- a/ecscollector/testdata/fixtures/ec2_task_stats.json +++ b/ecscollector/testdata/fixtures/ec2_task_stats.json @@ -1,9 +1,10 @@ { - "01cf1f3208005cda71d5ac936ded65d2ecc0a8cc8ff8a82d2e00410bf4fbbd6d": { - "read": "2025-02-27T05:18:07.856950259Z", - "preread": "2025-02-27T05:18:06.853724878Z", + "74d72daf3420705c7038b9f11295b4d951ca32c4f71f1ff6e3abe58202abc093": {}, + "559f4af51a2f85286138de04fbe2892348128ed55dbf24033bc6a1a3eb6f1d7f": { + "read": "2025-04-28T03:30:42.768147457Z", + "preread": "2025-04-28T03:30:41.760208757Z", "pids_stats": { - "current": 33, + "current": 38, "limit": 404 }, "blkio_stats": { @@ -12,13 +13,13 @@ "major": 259, "minor": 0, "op": "read", - "value": 60960768 + "value": 40013824 }, { "major": 259, "minor": 0, "op": "write", - "value": 57344 + "value": 172032 } ], "io_serviced_recursive": null, @@ -33,11 +34,11 @@ "storage_stats": {}, "cpu_stats": { "cpu_usage": { - "total_usage": 331125000, - "usage_in_kernelmode": 66278000, - "usage_in_usermode": 264846000 + "total_usage": 1075472000, + "usage_in_kernelmode": 449300000, + "usage_in_usermode": 626172000 }, - "system_cpu_usage": 1045600000000, + "system_cpu_usage": 10724370000000, "online_cpus": 2, "throttling_data": { "periods": 0, @@ -47,11 +48,11 @@ }, "precpu_stats": { "cpu_usage": { - "total_usage": 325963000, - "usage_in_kernelmode": 65245000, - "usage_in_usermode": 260717000 + "total_usage": 1052847000, + "usage_in_kernelmode": 433699000, + "usage_in_usermode": 619147000 }, - "system_cpu_usage": 1043620000000, + "system_cpu_usage": 10722330000000, "online_cpus": 2, "throttling_data": { "periods": 0, @@ -60,32 +61,32 @@ } }, "memory_stats": { - "usage": 65249280, + "usage": 62619648, "stats": { - "active_anon": 9170944, - "active_file": 7655424, - "anon": 37691392, + "active_anon": 10895360, + "active_file": 13266944, + "anon": 39903232, "anon_thp": 0, - "file": 25296896, - "file_dirty": 4096, - "file_mapped": 19968000, + "file": 20271104, + "file_dirty": 20480, + "file_mapped": 14790656, "file_writeback": 0, - "inactive_anon": 28520448, - "inactive_file": 17641472, - "kernel_stack": 524288, - "pgactivate": 6895, - "pgdeactivate": 4638, - "pgfault": 17631, + "inactive_anon": 29007872, + "inactive_file": 7004160, + "kernel_stack": 606208, + "pgactivate": 6594, + "pgdeactivate": 5012, + "pgfault": 32886, "pglazyfree": 0, "pglazyfreed": 0, - "pgmajfault": 1120, - "pgrefill": 6128, - "pgscan": 24707, - "pgsteal": 10033, + "pgmajfault": 263, + "pgrefill": 6255, + "pgscan": 16825, + "pgsteal": 6574, "shmem": 0, - "slab": 908520, - "slab_reclaimable": 383648, - "slab_unreclaimable": 524872, + "slab": 866488, + "slab_reclaimable": 367352, + "slab_unreclaimable": 499136, "sock": 0, "thp_collapse_alloc": 0, "thp_fault_alloc": 0, @@ -94,33 +95,32 @@ "workingset_nodereclaim": 0, "workingset_refault": 0 }, - "limit": 268435456 + "limit": 134217728 }, - "name": "/ecs-prom-ecs-exporter-sandbox-main-ec2-13-ecs-exporter-e2aeb1e6be8998c72300", - "id": "01cf1f3208005cda71d5ac936ded65d2ecc0a8cc8ff8a82d2e00410bf4fbbd6d", + "name": "/ecs-ecs-exporter-fixtures-ec2-4-ecs-exporter-f8a886e3c3d191f72100", + "id": "559f4af51a2f85286138de04fbe2892348128ed55dbf24033bc6a1a3eb6f1d7f", "networks": { "eth0": { - "rx_bytes": 101869, - "rx_packets": 284, + "rx_bytes": 44555, + "rx_packets": 397, "rx_errors": 0, "rx_dropped": 0, - "tx_bytes": 43958, - "tx_packets": 278, + "tx_bytes": 45918, + "tx_packets": 444, "tx_errors": 0, "tx_dropped": 0 } }, "network_rate_stats": { - "rx_bytes_per_sec": 2764.084716796875, - "tx_bytes_per_sec": 3390.065673828125 + "rx_bytes_per_sec": 4.900143623352051, + "tx_bytes_per_sec": 9.600282669067383 } }, - "213e1203f4bb72af185724d937e698d2724acf35b57ec2dd5f3c963adbd2d38c": {}, - "6b80adab0733f579594eccae31e5b0056b9544b805450ad6e278fed7f5e1c5ba": { - "read": "2025-02-27T05:18:07.855390957Z", - "preread": "2025-02-27T05:18:06.852213453Z", + "b14a1fde2922565d8820e6ee859cdadbc7bc9020c3f751b3446c700deacd1ce8": { + "read": "2025-04-28T03:30:42.765214131Z", + "preread": "2025-04-28T03:30:41.761511112Z", "pids_stats": { - "current": 25, + "current": 1, "limit": 404 }, "blkio_stats": { @@ -129,13 +129,13 @@ "major": 259, "minor": 0, "op": "read", - "value": 99926016 + "value": 770048 }, { "major": 259, "minor": 0, "op": "write", - "value": 274432 + "value": 0 } ], "io_serviced_recursive": null, @@ -150,11 +150,11 @@ "storage_stats": {}, "cpu_stats": { "cpu_usage": { - "total_usage": 566060000, - "usage_in_kernelmode": 164664000, - "usage_in_usermode": 401395000 + "total_usage": 18843000, + "usage_in_kernelmode": 9421000, + "usage_in_usermode": 9421000 }, - "system_cpu_usage": 1045600000000, + "system_cpu_usage": 10724370000000, "online_cpus": 2, "throttling_data": { "periods": 0, @@ -164,11 +164,11 @@ }, "precpu_stats": { "cpu_usage": { - "total_usage": 566060000, - "usage_in_kernelmode": 164664000, - "usage_in_usermode": 401395000 + "total_usage": 18843000, + "usage_in_kernelmode": 9421000, + "usage_in_usermode": 9421000 }, - "system_cpu_usage": 1043620000000, + "system_cpu_usage": 10722330000000, "online_cpus": 2, "throttling_data": { "periods": 0, @@ -177,32 +177,32 @@ } }, "memory_stats": { - "usage": 60981248, + "usage": 655360, "stats": { - "active_anon": 14704640, - "active_file": 8572928, - "anon": 39268352, + "active_anon": 4096, + "active_file": 110592, + "anon": 36864, "anon_thp": 0, - "file": 19619840, + "file": 348160, "file_dirty": 0, - "file_mapped": 17047552, + "file_mapped": 299008, "file_writeback": 0, - "inactive_anon": 24563712, - "inactive_file": 11046912, - "kernel_stack": 393216, - "pgactivate": 13496, - "pgdeactivate": 11069, - "pgfault": 18768, + "inactive_anon": 32768, + "inactive_file": 237568, + "kernel_stack": 16384, + "pgactivate": 3, + "pgdeactivate": 93, + "pgfault": 1086, "pglazyfree": 0, "pglazyfreed": 0, - "pgmajfault": 1133, - "pgrefill": 13249, - "pgscan": 48430, - "pgsteal": 20303, + "pgmajfault": 8, + "pgrefill": 153, + "pgscan": 211, + "pgsteal": 103, "shmem": 0, - "slab": 929280, - "slab_reclaimable": 519208, - "slab_unreclaimable": 410072, + "slab": 201000, + "slab_reclaimable": 72112, + "slab_unreclaimable": 128888, "sock": 0, "thp_collapse_alloc": 0, "thp_fault_alloc": 0, @@ -211,25 +211,141 @@ "workingset_nodereclaim": 0, "workingset_refault": 0 }, - "limit": 268435456 + "limit": 439066624 }, - "name": "/ecs-prom-ecs-exporter-sandbox-main-ec2-13-prometheus-86f1e9bab7a8e9a65400", - "id": "6b80adab0733f579594eccae31e5b0056b9544b805450ad6e278fed7f5e1c5ba", + "name": "/ecs-ecs-exporter-fixtures-ec2-4-internalecspause-d0f6aaab84b9e2e8ed01", + "id": "b14a1fde2922565d8820e6ee859cdadbc7bc9020c3f751b3446c700deacd1ce8", "networks": { "eth0": { - "rx_bytes": 45368, - "rx_packets": 132, + "rx_bytes": 44555, + "rx_packets": 397, "rx_errors": 0, "rx_dropped": 0, - "tx_bytes": 13532, - "tx_packets": 118, + "tx_bytes": 45918, + "tx_packets": 444, "tx_errors": 0, "tx_dropped": 0 } }, "network_rate_stats": { - "rx_bytes_per_sec": 41.86697006225586, - "tx_bytes_per_sec": 41.86697006225586 + "rx_bytes_per_sec": 4.900143623352051, + "tx_bytes_per_sec": 9.600282669067383 + } + }, + "d3b4c06f3fe8614d958ed27f7f3e40adc3b252793399741a92f0935fb60fb5a8": { + "read": "2025-04-28T03:30:42.766822637Z", + "preread": "2025-04-28T03:30:41.76263231Z", + "pids_stats": { + "current": 20, + "limit": 404 + }, + "blkio_stats": { + "io_service_bytes_recursive": [ + { + "major": 259, + "minor": 0, + "op": "read", + "value": 40865792 + }, + { + "major": 259, + "minor": 0, + "op": "write", + "value": 61440 + } + ], + "io_serviced_recursive": null, + "io_queue_recursive": null, + "io_service_time_recursive": null, + "io_wait_time_recursive": null, + "io_merged_recursive": null, + "io_time_recursive": null, + "sectors_recursive": null + }, + "num_procs": 0, + "storage_stats": {}, + "cpu_stats": { + "cpu_usage": { + "total_usage": 639180000, + "usage_in_kernelmode": 192020000, + "usage_in_usermode": 447159000 + }, + "system_cpu_usage": 10724370000000, + "online_cpus": 2, + "throttling_data": { + "periods": 0, + "throttled_periods": 0, + "throttled_time": 0 + } + }, + "precpu_stats": { + "cpu_usage": { + "total_usage": 639180000, + "usage_in_kernelmode": 192020000, + "usage_in_usermode": 447159000 + }, + "system_cpu_usage": 10722330000000, + "online_cpus": 2, + "throttling_data": { + "periods": 0, + "throttled_periods": 0, + "throttled_time": 0 + } + }, + "memory_stats": { + "usage": 26918912, + "stats": { + "active_anon": 7688192, + "active_file": 6758400, + "anon": 15392768, + "anon_thp": 0, + "file": 10203136, + "file_dirty": 0, + "file_mapped": 8835072, + "file_writeback": 0, + "inactive_anon": 7704576, + "inactive_file": 3444736, + "kernel_stack": 311296, + "pgactivate": 5608, + "pgdeactivate": 8637, + "pgfault": 12909, + "pglazyfree": 0, + "pglazyfreed": 0, + "pgmajfault": 1287, + "pgrefill": 17877, + "pgscan": 20826, + "pgsteal": 9626, + "shmem": 0, + "slab": 508584, + "slab_reclaimable": 232736, + "slab_unreclaimable": 275848, + "sock": 0, + "thp_collapse_alloc": 0, + "thp_fault_alloc": 0, + "unevictable": 0, + "workingset_activate": 0, + "workingset_nodereclaim": 0, + "workingset_refault": 0 + }, + "limit": 439066624 + }, + "name": "/ecs-ecs-exporter-fixtures-ec2-4-main-c0d28ea4b8e4b68e2500", + "id": "d3b4c06f3fe8614d958ed27f7f3e40adc3b252793399741a92f0935fb60fb5a8", + "networks": { + "eth0": { + "rx_bytes": 44555, + "rx_packets": 397, + "rx_errors": 0, + "rx_dropped": 0, + "tx_bytes": 45918, + "tx_packets": 444, + "tx_errors": 0, + "tx_dropped": 0 + } + }, + "network_rate_stats": { + "rx_bytes_per_sec": 4.900143623352051, + "tx_bytes_per_sec": 9.600282669067383 } } } diff --git a/ecscollector/testdata/fixtures/fargate_task_metadata.json b/ecscollector/testdata/fixtures/fargate_task_metadata.json index f22c715..766322d 100644 --- a/ecscollector/testdata/fixtures/fargate_task_metadata.json +++ b/ecscollector/testdata/fixtures/fargate_task_metadata.json @@ -1,176 +1,161 @@ { - "Cluster": "arn:aws:ecs:us-east-1:829490980523:cluster/prom-ecs-exporter-sandbox", - "TaskARN": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-sandbox/bae32def0ab64f06818e8862e58f8d6d", - "Family": "prom-ecs-exporter-sandbox-main-fargate", - "Revision": "9", + "Cluster": "arn:aws:ecs:us-east-1:829490980523:cluster/prom-ecs-exporter-fixtures", + "TaskARN": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-fixtures/04d558ed038d41bb9de115aab248e4f9", + "Family": "ecs-exporter-fixtures-fargate", + "Revision": "4", "DesiredStatus": "RUNNING", "KnownStatus": "RUNNING", "Limits": { "CPU": 0.25, "Memory": 512 }, - "PullStartedAt": "2025-02-27T05:06:03.714437592Z", - "PullStoppedAt": "2025-02-27T05:06:18.599126545Z", + "PullStartedAt": "2025-04-28T02:04:12.179992648Z", + "PullStoppedAt": "2025-04-28T02:04:21.603777413Z", "AvailabilityZone": "us-east-1a", "LaunchType": "FARGATE", "Containers": [ { - "DockerId": "bae32def0ab64f06818e8862e58f8d6d-1585788040", - "Name": "nonessential", - "DockerName": "nonessential", - "Image": "alpine", - "ImageID": "sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c", + "DockerId": "04d558ed038d41bb9de115aab248e4f9-4159844948", + "Name": "ecs-exporter", + "DockerName": "ecs-exporter", + "Image": "quay.io/prometheuscommunity/ecs-exporter:v0.4.0", + "ImageID": "sha256:e9520794c877d81fec970f2de4558dc0c6e3ac3fd9edf9e4418f326f52236bfb", "Labels": { - "com.amazonaws.ecs.cluster": "arn:aws:ecs:us-east-1:829490980523:cluster/prom-ecs-exporter-sandbox", - "com.amazonaws.ecs.container-name": "nonessential", - "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-sandbox/bae32def0ab64f06818e8862e58f8d6d", - "com.amazonaws.ecs.task-definition-family": "prom-ecs-exporter-sandbox-main-fargate", - "com.amazonaws.ecs.task-definition-version": "9" + "com.amazonaws.ecs.cluster": "arn:aws:ecs:us-east-1:829490980523:cluster/prom-ecs-exporter-fixtures", + "com.amazonaws.ecs.container-name": "ecs-exporter", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-fixtures/04d558ed038d41bb9de115aab248e4f9", + "com.amazonaws.ecs.task-definition-family": "ecs-exporter-fixtures-fargate", + "com.amazonaws.ecs.task-definition-version": "4" }, "DesiredStatus": "RUNNING", - "KnownStatus": "STOPPED", - "ExitCode": 0, + "KnownStatus": "RUNNING", "Limits": { - "CPU": 2 + "CPU": 128, + "Memory": 128 }, - "CreatedAt": "2025-02-27T05:06:19.200809191Z", - "StartedAt": "2025-02-27T05:06:19.200809191Z", - "FinishedAt": "2025-02-27T05:06:19.219711004Z", + "CreatedAt": "2025-04-28T02:04:22.237215942Z", + "StartedAt": "2025-04-28T02:04:22.237215942Z", "Type": "NORMAL", - "ContainerARN": "arn:aws:ecs:us-east-1:829490980523:container/prom-ecs-exporter-sandbox/bae32def0ab64f06818e8862e58f8d6d/cafd106c-dc95-4396-a466-a894961efa50", + "ContainerARN": "arn:aws:ecs:us-east-1:829490980523:container/prom-ecs-exporter-fixtures/04d558ed038d41bb9de115aab248e4f9/9b57fc5b-593c-4e68-ab02-04ae2748e68c", "Networks": [ { "NetworkMode": "awsvpc", "IPv4Addresses": [ - "10.0.117.145" - ], - "IPv6Addresses": [ - "2600:1f18:4ae8:400:7ca9:f2:a4c:8285" + "10.0.170.149" ], "AttachmentIndex": 0, - "MACAddress": "0a:ff:e5:34:fa:c9", - "IPv4SubnetCIDRBlock": "10.0.0.0/17", - "IPv6SubnetCIDRBlock": "2600:1f18:4ae8:400::/64", + "MACAddress": "0a:ff:dd:53:8c:35", + "IPv4SubnetCIDRBlock": "10.0.128.0/17", "DomainNameServers": [ "10.0.0.2" ], "DomainNameSearchList": [ "ec2.internal" ], - "PrivateDNSName": "ip-10-0-117-145.ec2.internal", - "SubnetGatewayIpv4Address": "10.0.0.1/17" + "PrivateDNSName": "ip-10-0-170-149.ec2.internal", + "SubnetGatewayIpv4Address": "10.0.128.1/17" } ], "Snapshotter": "overlayfs" }, { - "DockerId": "bae32def0ab64f06818e8862e58f8d6d-1819985369", - "Name": "prometheus", - "DockerName": "prometheus", - "Image": "prom/prometheus:v3.1.0", - "ImageID": "sha256:6559acbd5d770b15bb3c954629ce190ac3cbbdb2b7f1c30f0385c4e05104e218", + "DockerId": "04d558ed038d41bb9de115aab248e4f9-3935363592", + "Name": "main", + "DockerName": "main", + "Image": "alpine", + "ImageID": "sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c", "Labels": { - "com.amazonaws.ecs.cluster": "arn:aws:ecs:us-east-1:829490980523:cluster/prom-ecs-exporter-sandbox", - "com.amazonaws.ecs.container-name": "prometheus", - "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-sandbox/bae32def0ab64f06818e8862e58f8d6d", - "com.amazonaws.ecs.task-definition-family": "prom-ecs-exporter-sandbox-main-fargate", - "com.amazonaws.ecs.task-definition-version": "9" + "com.amazonaws.ecs.cluster": "arn:aws:ecs:us-east-1:829490980523:cluster/prom-ecs-exporter-fixtures", + "com.amazonaws.ecs.container-name": "main", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-fixtures/04d558ed038d41bb9de115aab248e4f9", + "com.amazonaws.ecs.task-definition-family": "ecs-exporter-fixtures-fargate", + "com.amazonaws.ecs.task-definition-version": "4" }, "DesiredStatus": "RUNNING", "KnownStatus": "RUNNING", "Limits": { "CPU": 2 }, - "CreatedAt": "2025-02-27T05:06:19.179996393Z", - "StartedAt": "2025-02-27T05:06:19.179996393Z", + "CreatedAt": "2025-04-28T02:04:22.279743113Z", + "StartedAt": "2025-04-28T02:04:22.279743113Z", "Type": "NORMAL", - "ContainerARN": "arn:aws:ecs:us-east-1:829490980523:container/prom-ecs-exporter-sandbox/bae32def0ab64f06818e8862e58f8d6d/50e269e1-4232-4aed-8bf4-29c4909858f9", + "ContainerARN": "arn:aws:ecs:us-east-1:829490980523:container/prom-ecs-exporter-fixtures/04d558ed038d41bb9de115aab248e4f9/ec4f2206-b03b-49e8-bcd7-dcf6b962d021", "Networks": [ { "NetworkMode": "awsvpc", "IPv4Addresses": [ - "10.0.117.145" - ], - "IPv6Addresses": [ - "2600:1f18:4ae8:400:7ca9:f2:a4c:8285" + "10.0.170.149" ], "AttachmentIndex": 0, - "MACAddress": "0a:ff:e5:34:fa:c9", - "IPv4SubnetCIDRBlock": "10.0.0.0/17", - "IPv6SubnetCIDRBlock": "2600:1f18:4ae8:400::/64", + "MACAddress": "0a:ff:dd:53:8c:35", + "IPv4SubnetCIDRBlock": "10.0.128.0/17", "DomainNameServers": [ "10.0.0.2" ], "DomainNameSearchList": [ "ec2.internal" ], - "PrivateDNSName": "ip-10-0-117-145.ec2.internal", - "SubnetGatewayIpv4Address": "10.0.0.1/17" + "PrivateDNSName": "ip-10-0-170-149.ec2.internal", + "SubnetGatewayIpv4Address": "10.0.128.1/17" } ], "Snapshotter": "overlayfs" }, { - "DockerId": "bae32def0ab64f06818e8862e58f8d6d-4159844948", - "Name": "ecs-exporter", - "DockerName": "ecs-exporter", - "Image": "quay.io/prometheuscommunity/ecs-exporter:main", - "ImageID": "sha256:d1802fb18cb208eda88d4b23aeff903e72c091c20fcdf02596d6bec4679f676d", + "DockerId": "04d558ed038d41bb9de115aab248e4f9-1585788040", + "Name": "nonessential", + "DockerName": "nonessential", + "Image": "alpine", + "ImageID": "sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c", "Labels": { - "com.amazonaws.ecs.cluster": "arn:aws:ecs:us-east-1:829490980523:cluster/prom-ecs-exporter-sandbox", - "com.amazonaws.ecs.container-name": "ecs-exporter", - "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-sandbox/bae32def0ab64f06818e8862e58f8d6d", - "com.amazonaws.ecs.task-definition-family": "prom-ecs-exporter-sandbox-main-fargate", - "com.amazonaws.ecs.task-definition-version": "9" + "com.amazonaws.ecs.cluster": "arn:aws:ecs:us-east-1:829490980523:cluster/prom-ecs-exporter-fixtures", + "com.amazonaws.ecs.container-name": "nonessential", + "com.amazonaws.ecs.task-arn": "arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-fixtures/04d558ed038d41bb9de115aab248e4f9", + "com.amazonaws.ecs.task-definition-family": "ecs-exporter-fixtures-fargate", + "com.amazonaws.ecs.task-definition-version": "4" }, "DesiredStatus": "RUNNING", - "KnownStatus": "RUNNING", + "KnownStatus": "STOPPED", + "ExitCode": 0, "Limits": { - "CPU": 2 + "CPU": 128, + "Memory": 128 }, - "CreatedAt": "2025-02-27T05:06:19.394790335Z", - "StartedAt": "2025-02-27T05:06:19.394790335Z", + "CreatedAt": "2025-04-28T02:04:22.240922754Z", + "StartedAt": "2025-04-28T02:04:22.240922754Z", + "FinishedAt": "2025-04-28T02:04:22.270452337Z", "Type": "NORMAL", - "LogDriver": "awslogs", - "LogOptions": { - "awslogs-group": "EcsExporterCdkStack-promecsexportersandboxmainfargatetaskdefinitionpromecsexportersandboxmainfargateecsexporterLogGroup44D32D35-DcG8HDbOu1Sl", - "awslogs-region": "us-east-1", - "awslogs-stream": "ecs-exporter/ecs-exporter/bae32def0ab64f06818e8862e58f8d6d" - }, - "ContainerARN": "arn:aws:ecs:us-east-1:829490980523:container/prom-ecs-exporter-sandbox/bae32def0ab64f06818e8862e58f8d6d/a9b9d903-4ca1-4ce2-8138-93094e438c6b", + "ContainerARN": "arn:aws:ecs:us-east-1:829490980523:container/prom-ecs-exporter-fixtures/04d558ed038d41bb9de115aab248e4f9/5c195179-a14d-422e-9c85-bbee7bbbfc44", "Networks": [ { "NetworkMode": "awsvpc", "IPv4Addresses": [ - "10.0.117.145" - ], - "IPv6Addresses": [ - "2600:1f18:4ae8:400:7ca9:f2:a4c:8285" + "10.0.170.149" ], "AttachmentIndex": 0, - "MACAddress": "0a:ff:e5:34:fa:c9", - "IPv4SubnetCIDRBlock": "10.0.0.0/17", - "IPv6SubnetCIDRBlock": "2600:1f18:4ae8:400::/64", + "MACAddress": "0a:ff:dd:53:8c:35", + "IPv4SubnetCIDRBlock": "10.0.128.0/17", "DomainNameServers": [ "10.0.0.2" ], "DomainNameSearchList": [ "ec2.internal" ], - "PrivateDNSName": "ip-10-0-117-145.ec2.internal", - "SubnetGatewayIpv4Address": "10.0.0.1/17" + "PrivateDNSName": "ip-10-0-170-149.ec2.internal", + "SubnetGatewayIpv4Address": "10.0.128.1/17" } ], "Snapshotter": "overlayfs" } ], "ClockDrift": { - "ClockErrorBound": 0.33292849999999996, - "ReferenceTimestamp": "2025-02-27T05:22:43Z", + "ClockErrorBound": 0.6756489999999999, + "ReferenceTimestamp": "2025-04-28T03:30:17Z", "ClockSynchronizationStatus": "SYNCHRONIZED" }, "EphemeralStorageMetrics": { - "Utilized": 427, + "Utilized": 40, "Reserved": 20496 - } + }, + "FaultInjectionEnabled": false } diff --git a/ecscollector/testdata/fixtures/fargate_task_stats.json b/ecscollector/testdata/fixtures/fargate_task_stats.json index 8892403..6761192 100644 --- a/ecscollector/testdata/fixtures/fargate_task_stats.json +++ b/ecscollector/testdata/fixtures/fargate_task_stats.json @@ -1,8 +1,8 @@ { - "bae32def0ab64f06818e8862e58f8d6d-1585788040": null, - "bae32def0ab64f06818e8862e58f8d6d-1819985369": { - "read": "2025-02-27T05:22:49.186680233Z", - "preread": "2025-02-27T05:22:39.185738849Z", + "04d558ed038d41bb9de115aab248e4f9-1585788040": null, + "04d558ed038d41bb9de115aab248e4f9-4159844948": { + "read": "2025-04-28T03:30:22.254837493Z", + "preread": "2025-04-28T03:30:12.255515507Z", "pids_stats": {}, "blkio_stats": { "io_service_bytes_recursive": [ @@ -10,25 +10,25 @@ "major": 259, "minor": 1, "op": "Read", - "value": 23793664 + "value": 12288 }, { "major": 259, "minor": 1, "op": "Write", - "value": 0 + "value": 172032 }, { "major": 259, "minor": 1, "op": "Sync", - "value": 23793664 + "value": 12288 }, { "major": 259, "minor": 1, "op": "Async", - "value": 0 + "value": 172032 }, { "major": 259, @@ -40,13 +40,13 @@ "major": 259, "minor": 1, "op": "Total", - "value": 23793664 + "value": 184320 }, { "major": 259, "minor": 0, "op": "Read", - "value": 65409024 + "value": 10608640 }, { "major": 259, @@ -58,7 +58,7 @@ "major": 259, "minor": 0, "op": "Sync", - "value": 65409024 + "value": 10608640 }, { "major": 259, @@ -76,7 +76,7 @@ "major": 259, "minor": 0, "op": "Total", - "value": 65409024 + "value": 10608640 } ], "io_serviced_recursive": [ @@ -84,25 +84,25 @@ "major": 259, "minor": 1, "op": "Read", - "value": 295 + "value": 3 }, { "major": 259, "minor": 1, "op": "Write", - "value": 0 + "value": 42 }, { "major": 259, "minor": 1, "op": "Sync", - "value": 295 + "value": 3 }, { "major": 259, "minor": 1, "op": "Async", - "value": 0 + "value": 42 }, { "major": 259, @@ -114,13 +114,13 @@ "major": 259, "minor": 1, "op": "Total", - "value": 295 + "value": 45 }, { "major": 259, "minor": 0, "op": "Read", - "value": 682 + "value": 118 }, { "major": 259, @@ -132,7 +132,7 @@ "major": 259, "minor": 0, "op": "Sync", - "value": 682 + "value": 118 }, { "major": 259, @@ -150,7 +150,7 @@ "major": 259, "minor": 0, "op": "Total", - "value": 682 + "value": 118 } ], "io_queue_recursive": [], @@ -164,15 +164,15 @@ "storage_stats": {}, "cpu_stats": { "cpu_usage": { - "total_usage": 932439492, + "total_usage": 2445096927, "percpu_usage": [ - 484165457, - 448274035 + 1217444718, + 1227652209 ], - "usage_in_kernelmode": 120000000, - "usage_in_usermode": 880000000 + "usage_in_kernelmode": 750000000, + "usage_in_usermode": 1400000000 }, - "system_cpu_usage": 2121200000000, + "system_cpu_usage": 10690100000000, "online_cpus": 2, "throttling_data": { "periods": 0, @@ -182,15 +182,15 @@ }, "precpu_stats": { "cpu_usage": { - "total_usage": 925246189, + "total_usage": 2405275582, "percpu_usage": [ - 479268399, - 445977790 + 1199980331, + 1205295251 ], - "usage_in_kernelmode": 120000000, - "usage_in_usermode": 870000000 + "usage_in_kernelmode": 720000000, + "usage_in_usermode": 1390000000 }, - "system_cpu_usage": 2101320000000, + "system_cpu_usage": 10670160000000, "online_cpus": 2, "throttling_data": { "periods": 0, @@ -199,66 +199,66 @@ } }, "memory_stats": { - "usage": 127934464, - "max_usage": 128557056, + "usage": 40611840, + "max_usage": 69406720, "stats": { "active_anon": 0, - "active_file": 32952320, - "cache": 85426176, - "dirty": 0, - "hierarchical_memory_limit": 536870912, + "active_file": 10346496, + "cache": 11218944, + "dirty": 135168, + "hierarchical_memory_limit": 134217728, "hierarchical_memsw_limit": 9223372036854771712, - "inactive_anon": 40820736, - "inactive_file": 52383744, - "mapped_file": 72179712, - "pgfault": 18975, - "pgmajfault": 693, - "pgpgin": 34749, - "pgpgout": 3936, - "rss": 40820736, + "inactive_anon": 27844608, + "inactive_file": 946176, + "mapped_file": 8110080, + "pgfault": 108042, + "pgmajfault": 33, + "pgpgin": 88473, + "pgpgout": 78973, + "rss": 27844608, "rss_huge": 0, "total_active_anon": 0, - "total_active_file": 32952320, - "total_cache": 85426176, - "total_dirty": 0, - "total_inactive_anon": 40820736, - "total_inactive_file": 52383744, - "total_mapped_file": 72179712, - "total_pgfault": 18975, - "total_pgmajfault": 693, - "total_pgpgin": 34749, - "total_pgpgout": 3936, - "total_rss": 40820736, + "total_active_file": 10346496, + "total_cache": 11218944, + "total_dirty": 135168, + "total_inactive_anon": 27844608, + "total_inactive_file": 946176, + "total_mapped_file": 8110080, + "total_pgfault": 108042, + "total_pgmajfault": 33, + "total_pgpgin": 88473, + "total_pgpgout": 78973, + "total_rss": 27844608, "total_rss_huge": 0, "total_unevictable": 0, "total_writeback": 0, "unevictable": 0, "writeback": 0 }, - "limit": 9223372036854771712 + "limit": 134217728 }, - "name": "prometheus", - "id": "bae32def0ab64f06818e8862e58f8d6d-1819985369", + "name": "ecs-exporter", + "id": "04d558ed038d41bb9de115aab248e4f9-4159844948", "networks": { "eth1": { - "rx_bytes": 129045374, - "rx_packets": 88933, + "rx_bytes": 12906990, + "rx_packets": 10768, "rx_errors": 0, "rx_dropped": 0, - "tx_bytes": 347839, - "tx_packets": 3501, + "tx_bytes": 462136, + "tx_packets": 2956, "tx_errors": 0, "tx_dropped": 0 } }, "network_rate_stats": { - "rx_bytes_per_sec": 2464.6679803462657, - "tx_bytes_per_sec": 1173.289548516495 + "rx_bytes_per_sec": 1239.9840756322674, + "tx_bytes_per_sec": 1673.6134773534957 } }, - "bae32def0ab64f06818e8862e58f8d6d-4159844948": { - "read": "2025-02-27T05:22:49.406170373Z", - "preread": "2025-02-27T05:22:39.406479661Z", + "04d558ed038d41bb9de115aab248e4f9-3935363592": { + "read": "2025-04-28T03:30:22.287279291Z", + "preread": "2025-04-28T03:30:12.286947751Z", "pids_stats": {}, "blkio_stats": { "io_service_bytes_recursive": [ @@ -266,7 +266,7 @@ "major": 259, "minor": 1, "op": "Read", - "value": 28639232 + "value": 1576960 }, { "major": 259, @@ -278,7 +278,7 @@ "major": 259, "minor": 1, "op": "Sync", - "value": 28639232 + "value": 1576960 }, { "major": 259, @@ -296,31 +296,31 @@ "major": 259, "minor": 1, "op": "Total", - "value": 28639232 + "value": 1576960 }, { "major": 259, "minor": 0, "op": "Read", - "value": 14655488 + "value": 2088960 }, { "major": 259, "minor": 0, "op": "Write", - "value": 4096 + "value": 0 }, { "major": 259, "minor": 0, "op": "Sync", - "value": 14655488 + "value": 2088960 }, { "major": 259, "minor": 0, "op": "Async", - "value": 4096 + "value": 0 }, { "major": 259, @@ -332,7 +332,7 @@ "major": 259, "minor": 0, "op": "Total", - "value": 14659584 + "value": 2088960 } ], "io_serviced_recursive": [ @@ -340,7 +340,7 @@ "major": 259, "minor": 1, "op": "Read", - "value": 327 + "value": 37 }, { "major": 259, @@ -352,7 +352,7 @@ "major": 259, "minor": 1, "op": "Sync", - "value": 327 + "value": 37 }, { "major": 259, @@ -370,31 +370,31 @@ "major": 259, "minor": 1, "op": "Total", - "value": 327 + "value": 37 }, { "major": 259, "minor": 0, "op": "Read", - "value": 157 + "value": 31 }, { "major": 259, "minor": 0, "op": "Write", - "value": 1 + "value": 0 }, { "major": 259, "minor": 0, "op": "Sync", - "value": 157 + "value": 31 }, { "major": 259, "minor": 0, "op": "Async", - "value": 1 + "value": 0 }, { "major": 259, @@ -406,7 +406,7 @@ "major": 259, "minor": 0, "op": "Total", - "value": 158 + "value": 31 } ], "io_queue_recursive": [], @@ -420,15 +420,15 @@ "storage_stats": {}, "cpu_stats": { "cpu_usage": { - "total_usage": 322633383, + "total_usage": 609984441, "percpu_usage": [ - 138347736, - 184285647 + 334299398, + 275685043 ], - "usage_in_kernelmode": 50000000, - "usage_in_usermode": 180000000 + "usage_in_kernelmode": 80000000, + "usage_in_usermode": 370000000 }, - "system_cpu_usage": 2121630000000, + "system_cpu_usage": 10690160000000, "online_cpus": 2, "throttling_data": { "periods": 0, @@ -438,15 +438,15 @@ }, "precpu_stats": { "cpu_usage": { - "total_usage": 242770940, + "total_usage": 609984441, "percpu_usage": [ - 104627034, - 138143906 + 334299398, + 275685043 ], - "usage_in_kernelmode": 30000000, - "usage_in_usermode": 140000000 + "usage_in_kernelmode": 80000000, + "usage_in_usermode": 370000000 }, - "system_cpu_usage": 2101780000000, + "system_cpu_usage": 10670220000000, "online_cpus": 2, "throttling_data": { "periods": 0, @@ -455,36 +455,36 @@ } }, "memory_stats": { - "usage": 84111360, - "max_usage": 84238336, + "usage": 24264704, + "max_usage": 27025408, "stats": { "active_anon": 0, - "active_file": 3379200, - "cache": 42442752, + "active_file": 3649536, + "cache": 3649536, "dirty": 0, "hierarchical_memory_limit": 536870912, "hierarchical_memsw_limit": 9223372036854771712, - "inactive_anon": 39469056, - "inactive_file": 39100416, - "mapped_file": 33927168, - "pgfault": 17358, - "pgmajfault": 297, - "pgpgin": 23430, - "pgpgout": 3367, - "rss": 39469056, + "inactive_anon": 19193856, + "inactive_file": 270336, + "mapped_file": 1757184, + "pgfault": 12078, + "pgmajfault": 0, + "pgpgin": 9306, + "pgpgout": 3671, + "rss": 19329024, "rss_huge": 0, "total_active_anon": 0, - "total_active_file": 3379200, - "total_cache": 42442752, + "total_active_file": 3649536, + "total_cache": 3649536, "total_dirty": 0, - "total_inactive_anon": 39469056, - "total_inactive_file": 39100416, - "total_mapped_file": 33927168, - "total_pgfault": 17358, - "total_pgmajfault": 297, - "total_pgpgin": 23430, - "total_pgpgout": 3367, - "total_rss": 39469056, + "total_inactive_anon": 19193856, + "total_inactive_file": 270336, + "total_mapped_file": 1757184, + "total_pgfault": 12078, + "total_pgmajfault": 0, + "total_pgpgin": 9306, + "total_pgpgout": 3671, + "total_rss": 19329024, "total_rss_huge": 0, "total_unevictable": 0, "total_writeback": 0, @@ -493,23 +493,23 @@ }, "limit": 9223372036854771712 }, - "name": "ecs-exporter", - "id": "bae32def0ab64f06818e8862e58f8d6d-4159844948", + "name": "main", + "id": "04d558ed038d41bb9de115aab248e4f9-3935363592", "networks": { "eth1": { - "rx_bytes": 129046293, - "rx_packets": 88938, + "rx_bytes": 12906990, + "rx_packets": 10768, "rx_errors": 0, "rx_dropped": 0, - "tx_bytes": 348223, - "tx_packets": 3507, + "tx_bytes": 462136, + "tx_packets": 2956, "tx_errors": 0, "tx_dropped": 0 } }, "network_rate_stats": { - "rx_bytes_per_sec": 2556.879064581499, - "tx_bytes_per_sec": 1211.8374728018853 + "rx_bytes_per_sec": 1187.660623349565, + "tx_bytes_per_sec": 1666.8447360961436 } } } diff --git a/ecscollector/testdata/snapshots/ec2_metrics.txt b/ecscollector/testdata/snapshots/ec2_metrics.txt index 7674fff..79f5062 100644 --- a/ecscollector/testdata/snapshots/ec2_metrics.txt +++ b/ecscollector/testdata/snapshots/ec2_metrics.txt @@ -1,22 +1,26 @@ # HELP ecs_container_cpu_usage_seconds_total Cumulative total container CPU usage in seconds. # TYPE ecs_container_cpu_usage_seconds_total counter -ecs_container_cpu_usage_seconds_total{container_name="ecs-exporter"} 0.331125 -ecs_container_cpu_usage_seconds_total{container_name="prometheus"} 0.56606 +ecs_container_cpu_usage_seconds_total{container_name="ecs-exporter"} 1.075472 +ecs_container_cpu_usage_seconds_total{container_name="main"} 0.6391800000000001 +ecs_container_cpu_usage_seconds_total{container_name="~internal~ecs~pause"} 0.018843000000000002 # HELP ecs_container_memory_limit_bytes Configured container memory limit in bytes, set from the container-level limit in the task definition if any, otherwise the task-level limit. # TYPE ecs_container_memory_limit_bytes gauge -ecs_container_memory_limit_bytes{container_name="ecs-exporter"} 2.68435456e+08 -ecs_container_memory_limit_bytes{container_name="prometheus"} 2.68435456e+08 +ecs_container_memory_limit_bytes{container_name="ecs-exporter"} 1.34217728e+08 +ecs_container_memory_limit_bytes{container_name="main"} 0 +ecs_container_memory_limit_bytes{container_name="~internal~ecs~pause"} 0 # HELP ecs_container_memory_page_cache_size_bytes Current container memory page cache size in bytes. This is not a subset of used bytes. # TYPE ecs_container_memory_page_cache_size_bytes gauge ecs_container_memory_page_cache_size_bytes{container_name="ecs-exporter"} 0 -ecs_container_memory_page_cache_size_bytes{container_name="prometheus"} 0 +ecs_container_memory_page_cache_size_bytes{container_name="main"} 0 +ecs_container_memory_page_cache_size_bytes{container_name="~internal~ecs~pause"} 0 # HELP ecs_container_memory_usage_bytes Current container memory usage in bytes. # TYPE ecs_container_memory_usage_bytes gauge -ecs_container_memory_usage_bytes{container_name="ecs-exporter"} 6.524928e+07 -ecs_container_memory_usage_bytes{container_name="prometheus"} 6.0981248e+07 +ecs_container_memory_usage_bytes{container_name="ecs-exporter"} 6.2619648e+07 +ecs_container_memory_usage_bytes{container_name="main"} 2.6918912e+07 +ecs_container_memory_usage_bytes{container_name="~internal~ecs~pause"} 655360 # HELP ecs_network_receive_bytes_total Cumulative total size of network packets received in bytes. # TYPE ecs_network_receive_bytes_total counter -ecs_network_receive_bytes_total{interface="eth0"} 45368 +ecs_network_receive_bytes_total{interface="eth0"} 44555 # HELP ecs_network_receive_errors_total Cumulative total count of network errors in receiving. # TYPE ecs_network_receive_errors_total counter ecs_network_receive_errors_total{interface="eth0"} 0 @@ -25,10 +29,10 @@ ecs_network_receive_errors_total{interface="eth0"} 0 ecs_network_receive_packets_dropped_total{interface="eth0"} 0 # HELP ecs_network_receive_packets_total Cumulative total count of network packets received. # TYPE ecs_network_receive_packets_total counter -ecs_network_receive_packets_total{interface="eth0"} 132 +ecs_network_receive_packets_total{interface="eth0"} 397 # HELP ecs_network_transmit_bytes_total Cumulative total size of network packets transmitted in bytes. # TYPE ecs_network_transmit_bytes_total counter -ecs_network_transmit_bytes_total{interface="eth0"} 13532 +ecs_network_transmit_bytes_total{interface="eth0"} 45918 # HELP ecs_network_transmit_errors_total Cumulative total count of network errors in transmit. # TYPE ecs_network_transmit_errors_total counter ecs_network_transmit_errors_total{interface="eth0"} 0 @@ -37,13 +41,16 @@ ecs_network_transmit_errors_total{interface="eth0"} 0 ecs_network_transmit_packets_dropped_total{interface="eth0"} 0 # HELP ecs_network_transmit_packets_total Cumulative total count of network packets transmitted. # TYPE ecs_network_transmit_packets_total counter -ecs_network_transmit_packets_total{interface="eth0"} 118 +ecs_network_transmit_packets_total{interface="eth0"} 444 # HELP ecs_task_image_pull_start_timestamp_seconds The time at which the task started pulling docker images for its containers. # TYPE ecs_task_image_pull_start_timestamp_seconds gauge -ecs_task_image_pull_start_timestamp_seconds 1.7406329923325953e+09 +ecs_task_image_pull_start_timestamp_seconds 1.7458058962032692e+09 # HELP ecs_task_image_pull_stop_timestamp_seconds The time at which the task stopped (i.e. completed) pulling docker images for its containers. # TYPE ecs_task_image_pull_stop_timestamp_seconds gauge -ecs_task_image_pull_stop_timestamp_seconds 1.7406330012060723e+09 +ecs_task_image_pull_stop_timestamp_seconds 1.7458059035167944e+09 +# HELP ecs_task_memory_limit_bytes Configured task memory limit in bytes. This is optional when running on EC2; if no limit is set, this metric has no value. +# TYPE ecs_task_memory_limit_bytes gauge +ecs_task_memory_limit_bytes 2.68435456e+08 # HELP ecs_task_metadata_info ECS task metadata, sourced from the task metadata endpoint version 4. # TYPE ecs_task_metadata_info gauge -ecs_task_metadata_info{availability_zone="us-east-1a",cluster="prom-ecs-exporter-sandbox",desired_status="RUNNING",family="prom-ecs-exporter-sandbox-main-ec2",known_status="RUNNING",launch_type="EC2",revision="13",task_arn="arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-sandbox/506f22fab0414cde856201584703fed9"} 1 +ecs_task_metadata_info{availability_zone="us-east-1a",cluster="prom-ecs-exporter-fixtures",desired_status="RUNNING",family="ecs-exporter-fixtures-ec2",known_status="RUNNING",launch_type="EC2",revision="4",task_arn="arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-fixtures/1e76d951e76c4ea5ad410966ffde3bdb"} 1 diff --git a/ecscollector/testdata/snapshots/fargate_metrics.txt b/ecscollector/testdata/snapshots/fargate_metrics.txt index 83cf0f0..168a8ad 100644 --- a/ecscollector/testdata/snapshots/fargate_metrics.txt +++ b/ecscollector/testdata/snapshots/fargate_metrics.txt @@ -1,22 +1,22 @@ # HELP ecs_container_cpu_usage_seconds_total Cumulative total container CPU usage in seconds. # TYPE ecs_container_cpu_usage_seconds_total counter -ecs_container_cpu_usage_seconds_total{container_name="ecs-exporter"} 0.322633383 -ecs_container_cpu_usage_seconds_total{container_name="prometheus"} 0.9324394920000001 +ecs_container_cpu_usage_seconds_total{container_name="ecs-exporter"} 2.4450969270000003 +ecs_container_cpu_usage_seconds_total{container_name="main"} 0.609984441 # HELP ecs_container_memory_limit_bytes Configured container memory limit in bytes, set from the container-level limit in the task definition if any, otherwise the task-level limit. # TYPE ecs_container_memory_limit_bytes gauge -ecs_container_memory_limit_bytes{container_name="ecs-exporter"} 5.36870912e+08 -ecs_container_memory_limit_bytes{container_name="prometheus"} 5.36870912e+08 +ecs_container_memory_limit_bytes{container_name="ecs-exporter"} 1.34217728e+08 +ecs_container_memory_limit_bytes{container_name="main"} 5.36870912e+08 # HELP ecs_container_memory_page_cache_size_bytes Current container memory page cache size in bytes. This is not a subset of used bytes. # TYPE ecs_container_memory_page_cache_size_bytes gauge -ecs_container_memory_page_cache_size_bytes{container_name="ecs-exporter"} 4.2442752e+07 -ecs_container_memory_page_cache_size_bytes{container_name="prometheus"} 8.5426176e+07 +ecs_container_memory_page_cache_size_bytes{container_name="ecs-exporter"} 1.1218944e+07 +ecs_container_memory_page_cache_size_bytes{container_name="main"} 3.649536e+06 # HELP ecs_container_memory_usage_bytes Current container memory usage in bytes. # TYPE ecs_container_memory_usage_bytes gauge -ecs_container_memory_usage_bytes{container_name="ecs-exporter"} 8.411136e+07 -ecs_container_memory_usage_bytes{container_name="prometheus"} 1.27934464e+08 +ecs_container_memory_usage_bytes{container_name="ecs-exporter"} 4.061184e+07 +ecs_container_memory_usage_bytes{container_name="main"} 2.4264704e+07 # HELP ecs_network_receive_bytes_total Cumulative total size of network packets received in bytes. # TYPE ecs_network_receive_bytes_total counter -ecs_network_receive_bytes_total{interface="eth1"} 1.29046293e+08 +ecs_network_receive_bytes_total{interface="eth1"} 1.290699e+07 # HELP ecs_network_receive_errors_total Cumulative total count of network errors in receiving. # TYPE ecs_network_receive_errors_total counter ecs_network_receive_errors_total{interface="eth1"} 0 @@ -25,10 +25,10 @@ ecs_network_receive_errors_total{interface="eth1"} 0 ecs_network_receive_packets_dropped_total{interface="eth1"} 0 # HELP ecs_network_receive_packets_total Cumulative total count of network packets received. # TYPE ecs_network_receive_packets_total counter -ecs_network_receive_packets_total{interface="eth1"} 88938 +ecs_network_receive_packets_total{interface="eth1"} 10768 # HELP ecs_network_transmit_bytes_total Cumulative total size of network packets transmitted in bytes. # TYPE ecs_network_transmit_bytes_total counter -ecs_network_transmit_bytes_total{interface="eth1"} 348223 +ecs_network_transmit_bytes_total{interface="eth1"} 462136 # HELP ecs_network_transmit_errors_total Cumulative total count of network errors in transmit. # TYPE ecs_network_transmit_errors_total counter ecs_network_transmit_errors_total{interface="eth1"} 0 @@ -37,7 +37,7 @@ ecs_network_transmit_errors_total{interface="eth1"} 0 ecs_network_transmit_packets_dropped_total{interface="eth1"} 0 # HELP ecs_network_transmit_packets_total Cumulative total count of network packets transmitted. # TYPE ecs_network_transmit_packets_total counter -ecs_network_transmit_packets_total{interface="eth1"} 3507 +ecs_network_transmit_packets_total{interface="eth1"} 2956 # HELP ecs_task_cpu_limit_vcpus Configured task CPU limit in vCPUs (1 vCPU = 1024 CPU units). This is optional when running on EC2; if no limit is set, this metric has no value. # TYPE ecs_task_cpu_limit_vcpus gauge ecs_task_cpu_limit_vcpus 0.25 @@ -46,16 +46,16 @@ ecs_task_cpu_limit_vcpus 0.25 ecs_task_ephemeral_storage_allocated_bytes 2.1491613696e+10 # HELP ecs_task_ephemeral_storage_used_bytes Current Fargate task ephemeral storage usage in bytes. # TYPE ecs_task_ephemeral_storage_used_bytes gauge -ecs_task_ephemeral_storage_used_bytes 4.47741952e+08 +ecs_task_ephemeral_storage_used_bytes 4.194304e+07 # HELP ecs_task_image_pull_start_timestamp_seconds The time at which the task started pulling docker images for its containers. # TYPE ecs_task_image_pull_start_timestamp_seconds gauge -ecs_task_image_pull_start_timestamp_seconds 1.7406327637144377e+09 +ecs_task_image_pull_start_timestamp_seconds 1.7458058521799927e+09 # HELP ecs_task_image_pull_stop_timestamp_seconds The time at which the task stopped (i.e. completed) pulling docker images for its containers. # TYPE ecs_task_image_pull_stop_timestamp_seconds gauge -ecs_task_image_pull_stop_timestamp_seconds 1.7406327785991266e+09 +ecs_task_image_pull_stop_timestamp_seconds 1.7458058616037776e+09 # HELP ecs_task_memory_limit_bytes Configured task memory limit in bytes. This is optional when running on EC2; if no limit is set, this metric has no value. # TYPE ecs_task_memory_limit_bytes gauge ecs_task_memory_limit_bytes 5.36870912e+08 # HELP ecs_task_metadata_info ECS task metadata, sourced from the task metadata endpoint version 4. # TYPE ecs_task_metadata_info gauge -ecs_task_metadata_info{availability_zone="us-east-1a",cluster="arn:aws:ecs:us-east-1:829490980523:cluster/prom-ecs-exporter-sandbox",desired_status="RUNNING",family="prom-ecs-exporter-sandbox-main-fargate",known_status="RUNNING",launch_type="FARGATE",revision="9",task_arn="arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-sandbox/bae32def0ab64f06818e8862e58f8d6d"} 1 +ecs_task_metadata_info{availability_zone="us-east-1a",cluster="arn:aws:ecs:us-east-1:829490980523:cluster/prom-ecs-exporter-fixtures",desired_status="RUNNING",family="ecs-exporter-fixtures-fargate",known_status="RUNNING",launch_type="FARGATE",revision="4",task_arn="arn:aws:ecs:us-east-1:829490980523:task/prom-ecs-exporter-fixtures/04d558ed038d41bb9de115aab248e4f9"} 1 diff --git a/go.mod b/go.mod index 5d91fcc..77f5139 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,9 @@ go 1.23.0 require ( github.com/alecthomas/kingpin/v2 v2.4.0 github.com/aws/amazon-ecs-agent/ecs-agent v0.0.0-20250311191058-43b89f06b96f + github.com/aws/aws-cdk-go/awscdk/v2 v2.192.0 + github.com/aws/constructs-go/constructs/v10 v10.4.2 + github.com/aws/jsii-runtime-go v1.111.0 github.com/docker/docker v27.3.1+incompatible github.com/prometheus/client_golang v1.21.1 github.com/prometheus/common v0.62.0 @@ -12,20 +15,27 @@ require ( ) require ( + github.com/Masterminds/semver/v3 v3.3.1 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/aws/aws-sdk-go v1.51.3 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/cdklabs/awscdk-asset-awscli-go/awscliv1/v2 v2.2.229 // indirect + github.com/cdklabs/awscdk-asset-node-proxy-agent-go/nodeproxyagentv6/v2 v2.1.0 // indirect + github.com/cdklabs/cloud-assembly-schema-go/awscdkcloudassemblyschema/v41 v41.0.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/klauspost/compress v1.17.11 // indirect github.com/kylelemons/godebug v1.1.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mdlayher/socket v0.4.1 // indirect github.com/mdlayher/vsock v1.2.1 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect @@ -39,13 +49,17 @@ require ( github.com/vishvananda/netlink v1.2.1-beta.2 // indirect github.com/vishvananda/netns v0.0.4 // indirect github.com/xhit/go-str2duration/v2 v2.1.0 // indirect - golang.org/x/crypto v0.31.0 // indirect + github.com/yuin/goldmark v1.4.13 // indirect + golang.org/x/crypto v0.36.0 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/net v0.33.0 // indirect + golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect + golang.org/x/mod v0.24.0 // indirect + golang.org/x/net v0.37.0 // indirect golang.org/x/oauth2 v0.24.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/sync v0.12.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.23.0 // indirect + golang.org/x/tools v0.31.0 // indirect google.golang.org/protobuf v1.36.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 3001c0f..30efefd 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,27 @@ +github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= +github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/aws/amazon-ecs-agent/ecs-agent v0.0.0-20250311191058-43b89f06b96f h1:DJrZ85TxEVYi6K2Ao1UCzI98oyFzu2XpmpSjiHtmV8Q= github.com/aws/amazon-ecs-agent/ecs-agent v0.0.0-20250311191058-43b89f06b96f/go.mod h1:Myn1TSfJvFHEftmqtT3aw4CYktyuLijgKw8LOteQLno= +github.com/aws/aws-cdk-go/awscdk/v2 v2.192.0 h1:HYswn2veBK2NdL5NrH6rbCaBKLZKwj1q0SVsGcOziYk= +github.com/aws/aws-cdk-go/awscdk/v2 v2.192.0/go.mod h1:9ENCp/SkuTkIrAxG0cEdAD1QCC+QfpN82ukwrbwzwGE= github.com/aws/aws-sdk-go v1.51.3 h1:OqSyEXcJwf/XhZNVpMRgKlLA9nmbo5X8dwbll4RWxq8= github.com/aws/aws-sdk-go v1.51.3/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/constructs-go/constructs/v10 v10.4.2 h1:+hDLTsFGLJmKIn0Dg20vWpKBrVnFrEWYgTEY5UiTEG8= +github.com/aws/constructs-go/constructs/v10 v10.4.2/go.mod h1:cXsNCKDV+9eR9zYYfwy6QuE4uPFp6jsq6TtH1MwBx9w= +github.com/aws/jsii-runtime-go v1.111.0 h1:KR0URQxaw6FRTtNSKQ/weqVP2QEaAOssBcKD/uBlnh4= +github.com/aws/jsii-runtime-go v1.111.0/go.mod h1:eLDUEd0lRYsu2WoR+EoApYPz6ibG7JOaJgbL0IlD/m8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cdklabs/awscdk-asset-awscli-go/awscliv1/v2 v2.2.229 h1:pwQ0ejIdyj0HHdUomZzEGpzi8zTE8NMr55gwBGom8Y4= +github.com/cdklabs/awscdk-asset-awscli-go/awscliv1/v2 v2.2.229/go.mod h1:oquOkMHjv3uVsjt8ToBdJ3/i0HLD3RPEzuQlTzaieek= +github.com/cdklabs/awscdk-asset-node-proxy-agent-go/nodeproxyagentv6/v2 v2.1.0 h1:kElXjprC8wkpJu58vp+WFH6z0AJw4zitg5iSKJPKe3c= +github.com/cdklabs/awscdk-asset-node-proxy-agent-go/nodeproxyagentv6/v2 v2.1.0/go.mod h1:JY4UnvNa1YDGQ4H5wohXTHl6YVY3uCDUWl4JYUrQfb8= +github.com/cdklabs/cloud-assembly-schema-go/awscdkcloudassemblyschema/v41 v41.0.0 h1:vUMERjQ8BFG4wW6DNW+sxF5fDCnAYOukvZEiRX4kRkw= +github.com/cdklabs/cloud-assembly-schema-go/awscdkcloudassemblyschema/v41 v41.0.0/go.mod h1:JNDQuA9sW21qkalkNLfhtii9NztdzL/lscAjDIKhbV0= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 h1:kHaBemcxl8o/pQ5VM1c8PVE1PubbNx3mjUr09OqWGCs= @@ -23,6 +37,8 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -48,6 +64,11 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ= @@ -91,43 +112,55 @@ github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8 github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= +golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/tools/cdk/README.md b/tools/cdk/README.md new file mode 100644 index 0000000..4148008 --- /dev/null +++ b/tools/cdk/README.md @@ -0,0 +1,71 @@ +# Fixture collector + +This is an [AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/home.html) app +that deploys ECS resources to AWS to enable real [task metadata +API](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-metadata-endpoint.html) +responses to be collected and versioned in this repository as test fixtures. +It's important to power our tests using real fixtures, as the documentation of +the task metadata API is not comprehensive or even perfectly accurate, and the +API is subject to change at any time. + +The expectation is that we collect sufficient fixtures to exercise all the +features of the exporter and all the hidden edge cases of the task metadata API +with respect to task configuration. So, for example, we know that ECS on EC2 and +on Fargate use completely different implementations of the API, so we should +deploy all tasks to both in order to collect fixtures from both. + +## How to update fixtures + +### Prerequisites + +You need to follow the [AWS CDK setup +guide](https://docs.aws.amazon.com/cdk/v2/guide/prerequisites.html). The full +details are there, but in short, you will need: +- NodeJS installed, with the `aws-cdk` NPM package globally installed. CDK is + written in Node. Even though our CDK app is written in Go, any non-NodeJS CDK + app is ultimately doing RPC to a NodeJS process using code generated from the + CDK NodeJS codebase. +- An AWS account, + [bootstrapped](https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping-env.html) + to receive CDK deployments. +- The AWS CLI installed, with proper credentials for that account configured. + You also need the extra [Session Manager + plugin](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html) + for the CLI, to enable running commands inside task containers to actually + download the fixtures, using the CLI. + +Additionally, the update steps below use `jq` to query and pretty print JSON +output. + +### Update steps + +With all that done, the process works as follows: +1. Deploy our CDK app's stack, which will result in various ECS tasks being + launched. +2. Run commands in said tasks to produce the fixtures. +3. Destroy the stack, such that you are no longer paying money to AWS. + +In other words: + +```sh +# Prerequisite: you are authenticated to your AWS account. This can be done in +# multiple ways; one common way involves having an AWS_ACCESS_KEY_ID and +# AWS_SECRET_ACCESS_KEY set in the environment. + +# Deploy the stack. You will have to confirm the changes interactively. +cdk deploy + +# Update fixtures. We have to use `tail`/`head` to chop off non-JSON output +# printed by `aws ecs execute-command` to stdout. See: +# https://github.com/aws/session-manager-plugin/issues/85 +# +# We also use `jq` to sort parts of the output data to keep fixture diffs more +# readable - some things are not consistently ordered. +aws ecs execute-command --interactive --cluster prom-ecs-exporter-fixtures --task "$(aws ecs list-tasks --cluster prom-ecs-exporter-fixtures --service prom-ecs-exporter-fixtures-fargate | jq -r .taskArns[0])" --container ecs-exporter --command 'sh -c "wget -q -O- ${ECS_CONTAINER_METADATA_URI_V4}/task"' | tail -n4 | head -n1 | jq '.Containers |= sort_by(.Name)' > ../../ecscollector/testdata/fixtures/fargate_task_metadata.json +aws ecs execute-command --interactive --cluster prom-ecs-exporter-fixtures --task "$(aws ecs list-tasks --cluster prom-ecs-exporter-fixtures --service prom-ecs-exporter-fixtures-fargate | jq -r .taskArns[0])" --container ecs-exporter --command 'sh -c "wget -q -O- ${ECS_CONTAINER_METADATA_URI_V4}/task/stats"' | tail -n4 | head -n1 | jq 'to_entries | sort_by(.value.name) | from_entries' > ../../ecscollector/testdata/fixtures/fargate_task_stats.json +aws ecs execute-command --interactive --cluster prom-ecs-exporter-fixtures --task "$(aws ecs list-tasks --cluster prom-ecs-exporter-fixtures --service prom-ecs-exporter-fixtures-ec2 | jq -r .taskArns[0])" --container ecs-exporter --command 'sh -c "wget -q -O- ${ECS_CONTAINER_METADATA_URI_V4}/task"' | tail -n4 | head -n1 | jq '.Containers |= sort_by(.Name)' > ../../ecscollector/testdata/fixtures/ec2_task_metadata.json +aws ecs execute-command --interactive --cluster prom-ecs-exporter-fixtures --task "$(aws ecs list-tasks --cluster prom-ecs-exporter-fixtures --service prom-ecs-exporter-fixtures-ec2 | jq -r .taskArns[0])" --container ecs-exporter --command 'sh -c "wget -q -O- ${ECS_CONTAINER_METADATA_URI_V4}/task/stats"' | tail -n4 | head -n1 | jq 'to_entries | sort_by(.value.name) | from_entries' > ../../ecscollector/testdata/fixtures/ec2_task_stats.json + +# Destroy the stack. You will have to confirm the changes interactively. +cdk destroy +``` diff --git a/tools/cdk/cdk.json b/tools/cdk/cdk.json new file mode 100644 index 0000000..bb1b5d2 --- /dev/null +++ b/tools/cdk/cdk.json @@ -0,0 +1,72 @@ +{ + "app": "go run main.go", + "context": { + "@aws-cdk/aws-lambda:recognizeLayerVersion": true, + "@aws-cdk/core:checkSecretUsage": true, + "@aws-cdk/core:target-partitions": [ + "aws", + "aws-cn" + ], + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true, + "@aws-cdk/aws-iam:minimizePolicies": true, + "@aws-cdk/core:validateSnapshotRemovalPolicy": true, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, + "@aws-cdk/core:enablePartitionLiterals": true, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true, + "@aws-cdk/aws-route53-patters:useCertificate": true, + "@aws-cdk/customresources:installLatestAwsSdkDefault": false, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true, + "@aws-cdk/aws-redshift:columnId": true, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true, + "@aws-cdk/aws-kms:aliasNameRef": true, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": true, + "@aws-cdk/aws-efs:denyAnonymousAccess": true, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true, + "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true, + "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true, + "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true, + "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true, + "@aws-cdk/aws-eks:nodegroupNameAttribute": true, + "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true, + "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true, + "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false, + "@aws-cdk/aws-s3:keepNotificationInImportedBucket": false, + "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": false, + "@aws-cdk/aws-ecs:disableEcsImdsBlocking": true, + "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": true, + "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": true, + "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": true, + "@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": true, + "@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": true, + "@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": true, + "@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": true, + "@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": true, + "@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": true, + "@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": true, + "@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": true, + "@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": true, + "@aws-cdk/core:enableAdditionalMetadataCollection": true, + "@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": true + } +} diff --git a/tools/cdk/main.go b/tools/cdk/main.go new file mode 100644 index 0000000..80d12c4 --- /dev/null +++ b/tools/cdk/main.go @@ -0,0 +1,206 @@ +// Copyright 2025 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License 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 main + +import ( + "github.com/aws/aws-cdk-go/awscdk/v2" + "github.com/aws/aws-cdk-go/awscdk/v2/awsautoscaling" + "github.com/aws/aws-cdk-go/awscdk/v2/awsec2" + "github.com/aws/aws-cdk-go/awscdk/v2/awsecs" + "github.com/aws/aws-cdk-go/awscdk/v2/customresources" + "github.com/aws/constructs-go/constructs/v10" + "github.com/aws/jsii-runtime-go" +) + +type TetStackProps struct { + awscdk.StackProps +} + +func main() { + defer jsii.Close() + app := awscdk.NewApp(nil) + _ = NewFixtureCollectorStack(app, "FixtureCollectorStack") + app.Synth(nil) +} + +func NewFixtureCollectorStack(scope constructs.Construct, id string) awscdk.Stack { + stack := awscdk.NewStack(scope, &id, &awscdk.StackProps{}) + + // The human-readable name for many resources we create here. + resourceName := "prom-ecs-exporter-fixtures" + + vpc := awsec2.NewVpc(stack, jsii.String("Vpc"), &awsec2.VpcProps{MaxAzs: jsii.Number(1)}) + cluster := awsecs.NewCluster(stack, jsii.String("Cluster"), &awsecs.ClusterProps{ + ClusterName: &resourceName, + Vpc: vpc, + EnableFargateCapacityProviders: jsii.Bool(true), + }) + + // ASG capacity provider used for tasks on EC2 instances. + autoScalingGroup := awsautoscaling.NewAutoScalingGroup(stack, jsii.String("ASG"), &awsautoscaling.AutoScalingGroupProps{ + Vpc: vpc, + AutoScalingGroupName: &resourceName, + InstanceType: awsec2.NewInstanceType(jsii.String("t4g.nano")), + MachineImage: awsecs.EcsOptimizedImage_AmazonLinux2023(awsecs.AmiHardwareType_ARM, nil), + MinCapacity: jsii.Number(0), + MaxCapacity: jsii.Number(2), + BlockDevices: &[]*awsautoscaling.BlockDevice{ + {DeviceName: jsii.String("/dev/xvda"), Volume: awsautoscaling.BlockDeviceVolume_Ebs(jsii.Number(40), nil)}, + }, + NewInstancesProtectedFromScaleIn: jsii.Bool(true), + }) + // https://github.com/aws/aws-cdk/issues/18179#issuecomment-1150981559 + customresources.NewAwsCustomResource(stack, jsii.String("AsgForceDelete"), &customresources.AwsCustomResourceProps{ + OnDelete: &customresources.AwsSdkCall{ + Service: jsii.String("AutoScaling"), + Action: jsii.String("deleteAutoScalingGroup"), + Parameters: map[string]any{ + "AutoScalingGroupName": autoScalingGroup.AutoScalingGroupName(), + "ForceDelete": jsii.Bool(true), + }, + }, + Policy: customresources.AwsCustomResourcePolicy_FromSdkCalls(&customresources.SdkCallsPolicyOptions{ + Resources: customresources.AwsCustomResourcePolicy_ANY_RESOURCE(), + }), + }).Node().AddDependency(autoScalingGroup) + + capacityProvider := awsecs.NewAsgCapacityProvider(stack, jsii.String("Capacity"), &awsecs.AsgCapacityProviderProps{ + CapacityProviderName: &resourceName, + InstanceWarmupPeriod: jsii.Number(0), + EnableManagedTerminationProtection: jsii.Bool(true), + AutoScalingGroup: autoScalingGroup, + }) + cluster.AddAsgCapacityProvider(capacityProvider, nil) + + // We do not strictly need such an image to capture the fixtures we need, + // but given that there should always be an ecs-exporter sidecar in every + // real Task, it would be strange not to include in the fixture data here. + ecsExporterImage := awsecs.ContainerImage_FromRegistry(jsii.String("quay.io/prometheuscommunity/ecs-exporter:v0.4.0"), nil) + + { + // Create an EC2 task. + taskDefinition := awsecs.NewTaskDefinition(stack, jsii.String("Ec2TaskDefinition"), &awsecs.TaskDefinitionProps{ + Family: jsii.String("ecs-exporter-fixtures-ec2"), + NetworkMode: awsecs.NetworkMode_AWS_VPC, + Compatibility: awsecs.Compatibility_EC2, + MemoryMiB: jsii.String("256"), + }) + taskDefinition.AddContainer(jsii.String("EcsExporter"), &awsecs.ContainerDefinitionOptions{ + ContainerName: jsii.String("ecs-exporter"), + Image: ecsExporterImage, + MemoryReservationMiB: jsii.Number(128), + MemoryLimitMiB: jsii.Number(128), + Cpu: jsii.Number(128), + }) + taskDefinition.AddContainer(jsii.String("AlpineShell"), &awsecs.ContainerDefinitionOptions{ + ContainerName: jsii.String("main"), + Image: awsecs.ContainerImage_FromRegistry(jsii.String("alpine"), nil), + // Hang on forever. + Command: &[]*string{jsii.String("sh"), jsii.String("-c"), jsii.String("sleep infinity")}, + }) + taskDefinition.AddContainer(jsii.String("Nonessential"), &awsecs.ContainerDefinitionOptions{ + ContainerName: jsii.String("nonessential"), + Image: awsecs.ContainerImage_FromRegistry(jsii.String("alpine"), nil), + Command: &[]*string{jsii.String("sh"), jsii.String("-c"), jsii.String("echo goodbye")}, + MemoryReservationMiB: jsii.Number(128), + MemoryLimitMiB: jsii.Number(128), + Cpu: jsii.Number(128), + Essential: jsii.Bool(false), + }) + + service := awsecs.NewEc2Service(stack, jsii.String("Ec2Service"), &awsecs.Ec2ServiceProps{ + ServiceName: jsii.String(resourceName + "-ec2"), + Cluster: cluster, + TaskDefinition: taskDefinition, + DesiredCount: jsii.Number(1), + MinHealthyPercent: jsii.Number(0), + CapacityProviderStrategies: &[]*awsecs.CapacityProviderStrategy{ + {CapacityProvider: capacityProvider.CapacityProviderName(), Weight: jsii.Number(1)}, + }, + EnableExecuteCommand: jsii.Bool(true), + }) + // Deletion does not work if we don't do this - the VPC will tear down + // route tables etc before we can delete the cluster/capacity provider, + // leaving instances and their tasks in limbo. + vpcConstructs := *vpc.Node().FindAll(constructs.ConstructOrder_PREORDER) + vpcDependables := make([]constructs.IDependable, len(vpcConstructs)) + for i, c := range vpcConstructs { + vpcDependables[i] = c + } + service.Node().AddDependency(vpcDependables...) + } + + { + // Create a Fargate task. + taskDefinition := awsecs.NewFargateTaskDefinition(stack, jsii.String("FargateTaskDefinition"), &awsecs.FargateTaskDefinitionProps{ + Family: jsii.String("ecs-exporter-fixtures-fargate"), + RuntimePlatform: &awsecs.RuntimePlatform{ + CpuArchitecture: awsecs.CpuArchitecture_ARM64(), + OperatingSystemFamily: awsecs.OperatingSystemFamily_LINUX(), + }, + }) + taskDefinition.AddContainer(jsii.String("EcsExporter"), &awsecs.ContainerDefinitionOptions{ + ContainerName: jsii.String("ecs-exporter"), + Image: ecsExporterImage, + MemoryReservationMiB: jsii.Number(128), + MemoryLimitMiB: jsii.Number(128), + Cpu: jsii.Number(128), + }) + taskDefinition.AddContainer(jsii.String("AlpineShell"), &awsecs.ContainerDefinitionOptions{ + ContainerName: jsii.String("main"), + Image: awsecs.ContainerImage_FromRegistry(jsii.String("alpine"), nil), + // Hang on forever. + Command: &[]*string{jsii.String("sh"), jsii.String("-c"), jsii.String("sleep infinity")}, + }) + taskDefinition.AddContainer(jsii.String("Nonessential"), &awsecs.ContainerDefinitionOptions{ + ContainerName: jsii.String("nonessential"), + Image: awsecs.ContainerImage_FromRegistry(jsii.String("alpine"), nil), + Command: &[]*string{jsii.String("sh"), jsii.String("-c"), jsii.String("echo goodbye")}, + MemoryReservationMiB: jsii.Number(128), + MemoryLimitMiB: jsii.Number(128), + Cpu: jsii.Number(128), + Essential: jsii.Bool(false), + }) + + awsecs.NewFargateService(stack, jsii.String("FargateService"), &awsecs.FargateServiceProps{ + ServiceName: jsii.String(resourceName + "-fargate"), + Cluster: cluster, + TaskDefinition: taskDefinition, + DesiredCount: jsii.Number(1), + MinHealthyPercent: jsii.Number(0), + EnableExecuteCommand: jsii.Bool(true), + }) + } + + awscdk.Aspects_Of(stack).Add(&CapacityProviderDependencyAspect{}, nil) + + return stack +} + +type CapacityProviderDependencyAspect struct{} + +// Add a dependency from capacity provider association to the cluster +// and from each service to the capacity provider association. +// +// https://github.com/aws/aws-cdk/issues/19275#issuecomment-1152860147 +func (CapacityProviderDependencyAspect) Visit(node constructs.IConstruct) { + if service, ok := node.(awsecs.Ec2Service); ok { + for _, child := range *service.Cluster().Node().FindAll(constructs.ConstructOrder_PREORDER) { + if assoc, ok := child.(awsecs.CfnClusterCapacityProviderAssociations); ok { + assoc.Node().AddDependency(service.Cluster()) + service.Node().AddDependency(assoc) + } + } + } +}