{"id":18489699,"url":"https://github.com/abicky/ecsmec","last_synced_at":"2025-04-08T21:30:45.240Z","repository":{"id":39375454,"uuid":"248944351","full_name":"abicky/ecsmec","owner":"abicky","description":"A CLI tool for Amazon ECS that provides some commands to execute bothersome operations","archived":false,"fork":false,"pushed_at":"2024-11-13T15:48:12.000Z","size":310,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-23T18:11:14.015Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/abicky.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-21T09:30:35.000Z","updated_at":"2025-01-03T08:03:33.000Z","dependencies_parsed_at":"2024-10-28T04:28:38.162Z","dependency_job_id":"36b568b9-fba3-4cc8-89e8-b30833949ac7","html_url":"https://github.com/abicky/ecsmec","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abicky%2Fecsmec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abicky%2Fecsmec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abicky%2Fecsmec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abicky%2Fecsmec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/abicky","download_url":"https://codeload.github.com/abicky/ecsmec/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247931047,"owners_count":21020156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T12:57:37.049Z","updated_at":"2025-04-08T21:30:45.235Z","avatar_url":"https://github.com/abicky.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ecsmec\n\n[![main](https://github.com/abicky/ecsmec/actions/workflows/main.yml/badge.svg)](https://github.com/abicky/ecsmec/actions/workflows/main.yml)\n\n`ecsmec` is a CLI tool for Amazon ECS that provides some commands to execute bothersome operations.\nFor example, if you manage your ECS clusters with a auto scaling group and want to replace all the container instances with new ones, you have to launch new instances, drain old instances, and so on. What a pain!\nThis tool enables you to do such operations easily.\n\n## Installation\n\n### Install pre-compiled binary\n\nDownload the binary archive from the [releases page](https://github.com/abicky/ecsmec/releases), unpack it, and move the executable \"ecsmec\" to a directory in your path (e.g. `/usr/local/bin`).\n\nFor example, you can install the latest binary on a Mac with Apple silicon by the following commands:\n\n```sh\ncurl -LO https://github.com/abicky/ecsmec/releases/latest/download/ecsmec_darwin_arm64.tar.gz\ntar xvf ecsmec_darwin_arm64.tar.gz\nmv ecsmec_darwin_arm64/ecsmec /usr/local/bin/\n```\n\nIf you download the archive via a browser on macOS Catalina or later, you may receive the message \"“ecsmec” cannot be opened because the developer cannot be verified.\"\nIn such a case, you need to delete the attribute \"com.apple.quarantine\" like below:\n\n```sh\nxattr -d com.apple.quarantine /path/to/ecsmec\n```\n\n### Install with Homebrew (macOS or Linux)\n\n```sh\nbrew install abicky/tools/ecsmec\n```\n\n### Install from source\n\n```sh\ngo get -u github.com:abicky/ecsmec\n```\n\nor\n\n```sh\ngit clone https://github.com:abicky/ecsmec\ncd ecsmec\nmake install\n```\n\n### Enable completions\n\nThe `completion` subcommand generates an autocompletion script. For example, you can generate the autocompletion script for zsh as follows:\n\n```sh\necsmec completion zsh \u003e/usr/local/share/zsh/site-functions/_ecsmec\n```\n\n## Usage\n\n### recreate-service\n\n```console\n$ ecsmec recreate-service --help\nThis command creates a new service from the specified service with overrides,\nand after the new service becomes stable, it deletes the old one.\nTherefore, as necessary, you have to increase the capacity of the cluster the\nservice belongs to manually so that it has enough capacity for the new service\nto place its tasks.\n\nUsage:\n  ecsmec recreate-service [flags]\n\nExamples:\n  You can change the placement strategy of the service \"test\" in the default cluster\n  by the following command:\n\n    ecsmec recreate-service --service test --overrides '{\n      \"PlacementStrategy\": [\n        { \"Field\": \"attribute:ecs.availability-zone\", \"Type\": \"spread\" },\n        { \"Field\": \"CPU\", \"Type\": \"binpack\" }\n      ]\n    }'\n\n  In the same way, you can change the name of the service \"test\" in the default\n  cluster like below:\n\n    ecsmec recreate-service --service test --overrides '{\n      \"ServiceName\": \"new-name\"\n    }'\n\n\nFlags:\n      --cluster CLUSTER   The name of the target CLUSTER (default \"default\")\n  -h, --help              help for recreate-service\n      --overrides JSON    An JSON to override some fields of the new service (default \"{}\")\n      --service SERVICE   The name of the target SERVICE (required)\n\nGlobal Flags:\n      --profile string   An AWS profile name in your credential file\n      --region string    The AWS region\n```\n\nThe option \"overrides\" is in the same format as the [CreateService API](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_CreateService.html) parameter, except that the first letter of each field is uppercase.\n\nThis command does the following operations to recreate the specified service:\n\n1. Create a temporal service from the service with overrides\n1. Delete the old service\n1. Create a new service from the temporal service\n1. Delete the temporal service\n\nIf the service name is overridden, the operations change as follow:\n\n1. Create a new service from the service with overrides\n1. Delete the old service\n\n\nYou need the following permissions to execute the command:\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:ListTasks\"\n      ],\n      \"Resource\": \"*\"\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:DescribeTasks\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount-id\u003e:task/\u003ccluster\u003e/*\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:CreateService\",\n        \"ecs:DeleteService\",\n        \"ecs:DescribeServices\",\n        \"ecs:UpdateService\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount-id\u003e:service/\u003ccluster\u003e/*\"\n      ],\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"iam:PassRole\"\n      ],\n      \"Resource\": [\n        \"arn:aws:iam::\u003caccount-id\u003e:role/\u003crole_for_volume_configurations\u003e\"\n      ]\n    }\n  ]\n}\n```\n\n### reduce-cluster-capacity\n\n```console\n$ ecsmec reduce-cluster-capacity --help\nThis command reduces the capacity of the specified cluster safely\nthat belong to the auto scaling group or spot fleet request.\n\nUsage:\n  ecsmec reduce-cluster-capacity [flags]\n\nFlags:\n      --amount int                      The amount of the capacity to reduce (required)\n      --auto-scaling-group-name GROUP   The name of the target GROUP\n      --cluster CLUSTER                 The name of the target CLUSTER (default \"default\")\n  -h, --help                            help for reduce-cluster-capacity\n      --spot-fleet-request-id REQUEST   The ID of the target REQUEST\n\nGlobal Flags:\n      --profile string   An AWS profile name in your credential file\n      --region string    The AWS region\n```\n\nThis command does the following operations if `--auto-scaling-group-name` is specified:\n\n1. Drain container instances and stop tasks that are running on the instances and don't belong to a service\n    - See the [AWS document](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/container-instance-draining.html) for more details on container instance draining\n1. Detach the instances from the auto scaling group\n1. Terminate the instances\n\nand does the following operations if `--spot-fleet-request-id` is specified:\n\n1. Create a SQS queue to receive interruption warnings\n1. Reduce the capacity of the spot fleet request\n1. Poll the SQS queue, and then drain container instances and stop tasks that are running on the instances and don't belong to a service\n    - You might think this operation is not necessary if [ECS_ENABLE_SPOT_INSTANCE_DRAINING](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/container-instance-spot.html#spot-instance-draining) is set to true, but draining doesn't stop tasks that don't belong to a service.\n1. Delete the SQS queue\n\nYou need the following permissions to execute the command:\n\nFor a auto scaling group:\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"autoscaling:DetachInstances\"\n      ],\n      \"Resource\": \"arn:aws:autoscaling:\u003cregion\u003e:\u003caccount\u003e:autoScalingGroup:*:autoScalingGroupName/\u003cgroup\u003e\"\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"autoscaling:DescribeAutoScalingGroups\",\n        \"ec2:DescribeInstances\",\n        \"ec2:TerminateInstances\"\n      ],\n      \"Resource\": \"*\"\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:ListContainerInstances\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount\u003e:cluster/\u003ccluster\u003e\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:DescribeContainerInstances\",\n        \"ecs:ListTasks\",\n        \"ecs:UpdateContainerInstancesState\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount\u003e:container-instance/\u003ccluster\u003e/*\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:DescribeTasks\",\n        \"ecs:StopTask\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount\u003e:task/\u003ccluster\u003e/*\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:DescribeServices\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount\u003e:service/\u003ccluster\u003e/*\"\n      ]\n    }\n  ]\n}\n```\n\nFor a spot fleet request:\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ec2:DescribeSpotFleetRequests\",\n        \"ec2:ModifySpotFleetRequest\"\n      ],\n      \"Resource\": \"*\"\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:ListContainerInstances\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount\u003e:cluster/\u003ccluster\u003e\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:DescribeContainerInstances\",\n        \"ecs:ListTasks\",\n        \"ecs:UpdateContainerInstancesState\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount\u003e:container-instance/\u003ccluster\u003e/*\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:DescribeTasks\",\n        \"ecs:StopTask\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount\u003e:task/\u003ccluster\u003e/*\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"events:DeleteRule\",\n        \"events:PutRule\",\n        \"events:PutTargets\",\n        \"events:RemoveTargets\"\n      ],\n      \"Resource\": [\n        \"arn:aws:events:\u003cregion\u003e:\u003caccount\u003e:rule/ecsmec-forward-ec2-spot-instance-interruption-warnings\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"sqs:CreateQueue\",\n        \"sqs:DeleteMessage\",\n        \"sqs:DeleteMessageBatch\",\n        \"sqs:DeleteQueue\",\n        \"sqs:GetQueueAttributes\",\n        \"sqs:ReceiveMessage\",\n        \"sqs:SetQueueAttributes\"\n      ],\n      \"Resource\": [\n        \"arn:aws:sqs:\u003cregion\u003e:\u003caccount\u003e:ecsmec-ec2-spot-instance-interruption-warnings\"\n      ]\n    }\n  ]\n}\n```\n\n### replace-auto-scaling-group-instances\n\n```console\n$ ecsmec replace-auto-scaling-group-instances --help\nThis command replaces container instances that belong to the specified\nauto scaling group and are launched before the time when this command\nlaunches new ones.\n\nUsage:\n  ecsmec replace-auto-scaling-group-instances [flags]\n\nFlags:\n      --auto-scaling-group-name GROUP   The name of the target GROUP (required)\n      --batch-size int                  The number of instances drained at a once (default 100)\n      --cluster CLUSTER                 The name of the target CLUSTER (default \"default\")\n  -h, --help                            help for replace-auto-scaling-group-instances\n\nGlobal Flags:\n      --profile string   An AWS profile name in your credential file\n      --region string    The AWS region\n```\n\nYou can resume the operations by executing the same command until the replacement is complete. `ecsmec` temporarily adds some tags starting with the prefix \"ecsmec:\" to the auto scaling group so that the command resumes the operations.\n\nThis command does the following operations to replace container instances:\n\n1. Launch new instances\n1. Drain the old container instances and stop tasks that are running on the instances and don't belong to a service\n    - See the [AWS document](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/container-instance-draining.html) for more details on container instance draining\n1. Detach the old instances from the auto scaling group\n1. Terminate the old instances\n\nYou need the following permissions to execute the command:\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"autoscaling:CreateOrUpdateTags\",\n        \"autoscaling:DeleteTags\",\n        \"autoscaling:DetachInstances\",\n        \"autoscaling:UpdateAutoScalingGroup\"\n      ],\n      \"Resource\": \"arn:aws:autoscaling:\u003cregion\u003e:\u003caccount-id\u003e:autoScalingGroup:*:autoScalingGroupName/\u003cgroup\u003e\"\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"autoscaling:DescribeAutoScalingGroups\",\n        \"ec2:DescribeInstances\",\n        \"ec2:TerminateInstances\"\n      ],\n      \"Resource\": \"*\"\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:ListContainerInstances\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount-id\u003e:cluster/\u003ccluster\u003e\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:DescribeContainerInstances\",\n        \"ecs:ListTasks\",\n        \"ecs:UpdateContainerInstancesState\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount-id\u003e:container-instance/\u003ccluster\u003e/*\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:DescribeTasks\",\n        \"ecs:StopTask\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount-id\u003e:task/\u003ccluster\u003e/*\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:DescribeServices\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount-id\u003e:service/\u003ccluster\u003e/*\"\n      ]\n    }\n  ]\n}\n```\n\n### terminate-spot-fleet-instances\n\n```console\n$ ecsmec terminate-spot-fleet-instances --help\nThis command terminates all the container instances safely that belong\nto the specified spot fleet request with state \"cancelled\".\n\nUsage:\n  ecsmec terminate-spot-fleet-instances [flags]\n\nFlags:\n      --batch-size int                  The number of instances drained at a once (default 100)\n      --cluster CLUSTER                 The name of the target CLUSTER (default \"default\")\n  -h, --help                            help for terminate-spot-fleet-instances\n      --spot-fleet-request-id REQUEST   The ID of the target REQUEST (required)\n\nGlobal Flags:\n      --profile string   An AWS profile name in your credential file\n      --region string    The AWS region\n```\n\nThis command does the following operations to terminate container instances:\n\n1. Drain container instances and stop tasks that are running on the instances and don't belong to a service\n    - See the [AWS document](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/container-instance-draining.html) for more details on container instance draining\n1. Terminate the instances\n\nYou need the following permissions to execute the command:\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ec2:DescribeInstances\",\n        \"ec2:DescribeSpotFleetInstances\",\n        \"ec2:DescribeSpotFleetRequests\",\n        \"ec2:TerminateInstances\"\n      ],\n      \"Resource\": \"*\"\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:ListContainerInstances\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount-id\u003e:cluster/\u003ccluster\u003e\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:DescribeContainerInstances\",\n        \"ecs:ListTasks\",\n        \"ecs:UpdateContainerInstancesState\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount-id\u003e:container-instance/\u003ccluster\u003e/*\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:DescribeTasks\",\n        \"ecs:StopTask\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount-id\u003e:task/\u003ccluster\u003e/*\"\n      ]\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecs:DescribeServices\"\n      ],\n      \"Resource\": [\n        \"arn:aws:ecs:\u003cregion\u003e:\u003caccount-id\u003e:service/\u003ccluster\u003e/*\"\n      ]\n    }\n  ]\n}\n```\n\n## Author\n\nTakeshi Arabiki ([@abicky](http://github.com/abicky))\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabicky%2Fecsmec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabicky%2Fecsmec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabicky%2Fecsmec/lists"}