Created
October 11, 2025 17:36
-
-
Save lucydjo/3b0c5ce1b269978b903eed3ba92d57f0 to your computer and use it in GitHub Desktop.
AWS cleanup region v1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| # Script to list and cleanup ALL AWS resources in the current region | |
| : "${AWS_REGION:?Set AWS_REGION}" | |
| echo "======================================================" | |
| echo "π AWS Resources Inventory - Region: $AWS_REGION" | |
| echo "======================================================" | |
| echo "" | |
| # Function to check if a command returns non-empty results | |
| has_resources() { | |
| local result="$1" | |
| [[ -n "$result" && "$result" != "[]" && "$result" != "null" ]] | |
| } | |
| # ============================================ | |
| # 1. ECS Resources | |
| # ============================================ | |
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββ" | |
| echo "π¦ ECS (Elastic Container Service)" | |
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββ" | |
| # ECS Clusters | |
| CLUSTERS=$(aws ecs list-clusters --region "$AWS_REGION" --query 'clusterArns' --output text) | |
| if has_resources "$CLUSTERS"; then | |
| echo "πΉ ECS Clusters:" | |
| for CLUSTER_ARN in $CLUSTERS; do | |
| CLUSTER_NAME=$(echo "$CLUSTER_ARN" | awk -F'/' '{print $NF}') | |
| echo " - $CLUSTER_NAME" | |
| # Services in cluster | |
| SERVICES=$(aws ecs list-services --cluster "$CLUSTER_NAME" --region "$AWS_REGION" --query 'serviceArns' --output text) | |
| if has_resources "$SERVICES"; then | |
| echo " Services:" | |
| for SERVICE_ARN in $SERVICES; do | |
| SERVICE_NAME=$(echo "$SERVICE_ARN" | awk -F'/' '{print $NF}') | |
| SERVICE_INFO=$(aws ecs describe-services --cluster "$CLUSTER_NAME" --services "$SERVICE_NAME" --region "$AWS_REGION" --query 'services[0].[desiredCount,runningCount,status]' --output text) | |
| echo " β’ $SERVICE_NAME: $SERVICE_INFO" | |
| done | |
| fi | |
| # Tasks in cluster | |
| TASKS=$(aws ecs list-tasks --cluster "$CLUSTER_NAME" --region "$AWS_REGION" --query 'taskArns' --output text) | |
| if has_resources "$TASKS"; then | |
| TASK_COUNT=$(echo "$TASKS" | wc -w | tr -d ' ') | |
| echo " Running Tasks: $TASK_COUNT" | |
| fi | |
| # Container Instances | |
| CONTAINER_INSTANCES=$(aws ecs list-container-instances --cluster "$CLUSTER_NAME" --region "$AWS_REGION" --query 'containerInstanceArns' --output text) | |
| if has_resources "$CONTAINER_INSTANCES"; then | |
| INSTANCE_COUNT=$(echo "$CONTAINER_INSTANCES" | wc -w | tr -d ' ') | |
| echo " Container Instances: $INSTANCE_COUNT" | |
| for INSTANCE_ARN in $CONTAINER_INSTANCES; do | |
| EC2_ID=$(aws ecs describe-container-instances --cluster "$CLUSTER_NAME" --container-instances "$INSTANCE_ARN" --region "$AWS_REGION" --query 'containerInstances[0].ec2InstanceId' --output text) | |
| echo " β’ $EC2_ID" | |
| done | |
| fi | |
| # Capacity Providers | |
| CAPACITY_PROVIDERS=$(aws ecs describe-clusters --clusters "$CLUSTER_NAME" --region "$AWS_REGION" --query 'clusters[0].capacityProviders' --output text) | |
| if has_resources "$CAPACITY_PROVIDERS"; then | |
| echo " Capacity Providers:" | |
| for CP in $CAPACITY_PROVIDERS; do | |
| echo " β’ $CP" | |
| done | |
| fi | |
| done | |
| else | |
| echo " β No ECS clusters" | |
| fi | |
| echo "" | |
| # ECS Task Definitions | |
| TASK_DEFS=$(aws ecs list-task-definitions --region "$AWS_REGION" --query 'taskDefinitionArns' --output text | head -20) | |
| if has_resources "$TASK_DEFS"; then | |
| TASK_COUNT=$(aws ecs list-task-definitions --region "$AWS_REGION" --query 'length(taskDefinitionArns)' --output text) | |
| echo "πΉ ECS Task Definitions: $TASK_COUNT registered" | |
| echo " (showing first 20)" | |
| for TASK_ARN in $TASK_DEFS; do | |
| TASK_NAME=$(echo "$TASK_ARN" | awk -F'/' '{print $NF}') | |
| echo " - $TASK_NAME" | |
| done | |
| else | |
| echo "πΉ Task Definitions: β None" | |
| fi | |
| echo "" | |
| # ============================================ | |
| # 2. EC2 Resources | |
| # ============================================ | |
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββ" | |
| echo "π₯οΈ EC2 (Elastic Compute Cloud)" | |
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββ" | |
| # EC2 Instances | |
| INSTANCES=$(aws ec2 describe-instances \ | |
| --region "$AWS_REGION" \ | |
| --filters "Name=instance-state-name,Values=running,pending,stopping,stopped" \ | |
| --query 'Reservations[*].Instances[*].[InstanceId,InstanceType,State.Name,Tags[?Key==`Name`].Value|[0]]' \ | |
| --output text) | |
| if has_resources "$INSTANCES"; then | |
| echo "πΉ EC2 Instances:" | |
| echo "$INSTANCES" | while read -r INSTANCE_ID INSTANCE_TYPE STATE NAME; do | |
| NAME_DISPLAY="${NAME:-<no-name>}" | |
| echo " - $INSTANCE_ID ($INSTANCE_TYPE) - $STATE - $NAME_DISPLAY" | |
| done | |
| else | |
| echo "πΉ EC2 Instances: β None" | |
| fi | |
| echo "" | |
| # Auto Scaling Groups | |
| ASGS=$(aws autoscaling describe-auto-scaling-groups --region "$AWS_REGION" --query 'AutoScalingGroups[*].[AutoScalingGroupName,MinSize,MaxSize,DesiredCapacity,length(Instances)]' --output text) | |
| if has_resources "$ASGS"; then | |
| echo "πΉ Auto Scaling Groups:" | |
| echo "$ASGS" | while read -r ASG_NAME MIN MAX DESIRED INSTANCES; do | |
| echo " - $ASG_NAME: Min=$MIN, Max=$MAX, Desired=$DESIRED, Current=$INSTANCES" | |
| done | |
| else | |
| echo "πΉ Auto Scaling Groups: β None" | |
| fi | |
| echo "" | |
| # Launch Templates | |
| LAUNCH_TEMPLATES=$(aws ec2 describe-launch-templates --region "$AWS_REGION" --query 'LaunchTemplates[*].[LaunchTemplateName,LaunchTemplateId,LatestVersionNumber]' --output text) | |
| if has_resources "$LAUNCH_TEMPLATES"; then | |
| echo "πΉ Launch Templates:" | |
| echo "$LAUNCH_TEMPLATES" | while read -r LT_NAME LT_ID VERSION; do | |
| echo " - $LT_NAME (ID: $LT_ID, Version: $VERSION)" | |
| done | |
| else | |
| echo "πΉ Launch Templates: β None" | |
| fi | |
| echo "" | |
| # Security Groups (non-default only) | |
| SECURITY_GROUPS=$(aws ec2 describe-security-groups \ | |
| --region "$AWS_REGION" \ | |
| --filters "Name=group-name,Values=*" \ | |
| --query 'SecurityGroups[?GroupName!=`default`].[GroupId,GroupName,Description]' \ | |
| --output text) | |
| if has_resources "$SECURITY_GROUPS"; then | |
| echo "πΉ Security Groups (non-default):" | |
| echo "$SECURITY_GROUPS" | while read -r SG_ID SG_NAME SG_DESC; do | |
| echo " - $SG_ID: $SG_NAME - $SG_DESC" | |
| done | |
| else | |
| echo "πΉ Custom Security Groups: β None" | |
| fi | |
| echo "" | |
| # ============================================ | |
| # 3. ECR (Container Registry) | |
| # ============================================ | |
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββ" | |
| echo "π³ ECR (Elastic Container Registry)" | |
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββ" | |
| REPOS=$(aws ecr describe-repositories --region "$AWS_REGION" --query 'repositories[*].[repositoryName,repositoryUri]' --output text 2>/dev/null || echo "") | |
| if has_resources "$REPOS"; then | |
| echo "πΉ ECR Repositories:" | |
| echo "$REPOS" | while read -r REPO_NAME REPO_URI; do | |
| IMAGE_COUNT=$(aws ecr list-images --repository-name "$REPO_NAME" --region "$AWS_REGION" --query 'length(imageIds)' --output text) | |
| echo " - $REPO_NAME ($IMAGE_COUNT images)" | |
| echo " URI: $REPO_URI" | |
| done | |
| else | |
| echo "πΉ ECR Repositories: β None" | |
| fi | |
| echo "" | |
| # ============================================ | |
| # 4. CloudWatch Logs | |
| # ============================================ | |
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββ" | |
| echo "π CloudWatch Logs" | |
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββ" | |
| LOG_GROUPS=$(aws logs describe-log-groups --region "$AWS_REGION" --query 'logGroups[*].[logGroupName,storedBytes]' --output text 2>/dev/null || echo "") | |
| if has_resources "$LOG_GROUPS"; then | |
| echo "πΉ Log Groups:" | |
| echo "$LOG_GROUPS" | while read -r LOG_GROUP SIZE_BYTES; do | |
| SIZE_MB=$(echo "scale=2; $SIZE_BYTES / 1024 / 1024" | bc) | |
| echo " - $LOG_GROUP (${SIZE_MB} MB)" | |
| done | |
| else | |
| echo "πΉ Log Groups: β None" | |
| fi | |
| echo "" | |
| # ============================================ | |
| # 5. IAM Roles (relevant to ECS) | |
| # ============================================ | |
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββ" | |
| echo "π IAM Roles (ECS-related)" | |
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββ" | |
| ECS_ROLES=$(aws iam list-roles --query 'Roles[?contains(RoleName, `ecs`) || contains(RoleName, `ECS`)].[RoleName,CreateDate]' --output text 2>/dev/null || echo "") | |
| if has_resources "$ECS_ROLES"; then | |
| echo "πΉ ECS-related IAM Roles:" | |
| echo "$ECS_ROLES" | while read -r ROLE_NAME CREATE_DATE; do | |
| echo " - $ROLE_NAME (Created: $CREATE_DATE)" | |
| done | |
| else | |
| echo "πΉ ECS IAM Roles: β None" | |
| fi | |
| echo "" | |
| # ============================================ | |
| # SUMMARY & CLEANUP OPTIONS | |
| # ============================================ | |
| echo "======================================================" | |
| echo "π§Ή CLEANUP OPTIONS" | |
| echo "======================================================" | |
| echo "" | |
| echo "To clean up resources, run these commands:" | |
| echo "" | |
| if has_resources "$CLUSTERS"; then | |
| for CLUSTER_ARN in $CLUSTERS; do | |
| CLUSTER_NAME=$(echo "$CLUSTER_ARN" | awk -F'/' '{print $NF}') | |
| echo "# Delete ECS cluster and all services: $CLUSTER_NAME" | |
| SERVICES=$(aws ecs list-services --cluster "$CLUSTER_NAME" --region "$AWS_REGION" --query 'serviceArns' --output text) | |
| if has_resources "$SERVICES"; then | |
| for SERVICE_ARN in $SERVICES; do | |
| SERVICE_NAME=$(echo "$SERVICE_ARN" | awk -F'/' '{print $NF}') | |
| echo "aws ecs update-service --cluster $CLUSTER_NAME --service $SERVICE_NAME --desired-count 0 --region $AWS_REGION" | |
| echo "aws ecs delete-service --cluster $CLUSTER_NAME --service $SERVICE_NAME --force --region $AWS_REGION" | |
| done | |
| fi | |
| echo "aws ecs delete-cluster --cluster $CLUSTER_NAME --region $AWS_REGION" | |
| echo "" | |
| done | |
| fi | |
| if has_resources "$ASGS"; then | |
| echo "# Delete Auto Scaling Groups:" | |
| echo "$ASGS" | while read -r ASG_NAME _; do | |
| echo "aws autoscaling delete-auto-scaling-group --auto-scaling-group-name $ASG_NAME --force-delete --region $AWS_REGION" | |
| done | |
| echo "" | |
| fi | |
| if has_resources "$INSTANCES"; then | |
| INSTANCE_IDS=$(echo "$INSTANCES" | awk '{print $1}' | tr '\n' ' ') | |
| echo "# Terminate EC2 Instances:" | |
| echo "aws ec2 terminate-instances --instance-ids $INSTANCE_IDS --region $AWS_REGION" | |
| echo "" | |
| fi | |
| if has_resources "$REPOS"; then | |
| echo "# Delete ECR Repositories:" | |
| echo "$REPOS" | while read -r REPO_NAME _; do | |
| echo "aws ecr delete-repository --repository-name $REPO_NAME --force --region $AWS_REGION" | |
| done | |
| echo "" | |
| fi | |
| if has_resources "$LOG_GROUPS"; then | |
| echo "# Delete CloudWatch Log Groups:" | |
| echo "$LOG_GROUPS" | while read -r LOG_GROUP _; do | |
| echo "aws logs delete-log-group --log-group-name $LOG_GROUP --region $AWS_REGION" | |
| done | |
| echo "" | |
| fi | |
| echo "======================================================" | |
| echo "β οΈ WARNING: Review commands carefully before running!" | |
| echo "======================================================" | |
| echo "" | |
| echo "π‘ Quick cleanup script:" | |
| echo " ./scripts/99_cleanup_all.sh | grep -E '^aws ' > /tmp/cleanup.sh" | |
| echo " # Review /tmp/cleanup.sh" | |
| echo " bash /tmp/cleanup.sh" | |
| echo "" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment