Skip to content

Commit c00824d

Browse files
committed
Add script to clean-up unused AWS EC2 Instances and VPCs
Signed-off-by: shiva kumar <[email protected]>
1 parent 860b91d commit c00824d

2 files changed

Lines changed: 193 additions & 0 deletions

File tree

.github/workflows/awscleanup.yaml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: AWS Periodic Cleanup
2+
3+
on:
4+
schedule:
5+
- cron: '0 0,12 * * *' # Runs daily at 12AM and 12PM
6+
7+
jobs:
8+
cleanup:
9+
runs-on: linux-amd64-cpu4
10+
11+
steps:
12+
- name: Checkout repository
13+
uses: actions/checkout@v4
14+
15+
- name: Set up AWS CLI
16+
uses: aws-actions/configure-aws-credentials@v4
17+
with:
18+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
19+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
20+
aws-region: us-west-1
21+
22+
- name: Identify resources for deletion
23+
id: identify-resources
24+
run: |
25+
# Find vpcs with Project holodeck and cicd Environment
26+
vpcs=$(aws ec2 describe-vpcs \
27+
--filters "Name=tag:Project,Values=holodeck" "Name=tag:Environment,Values=cicd" \
28+
--query "Vpcs[].VpcId" \
29+
--output text | tr -d '\r' | tr '\n' ' ')
30+
echo "Found VPCs: $vpcs"
31+
echo "AWS_VPC_IDS=$vpcs" >> $GITHUB_ENV
32+
33+
- name: Clean up VPCs
34+
if: env.AWS_VPC_IDS != ''
35+
env:
36+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37+
run: |
38+
for vpcid in $AWS_VPC_IDS; do
39+
scripts/awscleanup.sh $vpcid
40+
done
41+
42+
- name: Post cleanup
43+
run: |
44+
echo "Cleanup completed."

scripts/awscleanup.sh

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#!/bin/bash
2+
3+
if [[ $# -ne 1 ]]; then
4+
echo " vpcid required for deletion"
5+
exit 1
6+
fi
7+
8+
export vpcid=$1
9+
10+
get_tag_value(){
11+
if [[ $# -ne 2 ]]; then
12+
echo " vpcid and key required to get tag value"
13+
exit 1
14+
fi
15+
local vpc=$1
16+
local key=$2
17+
aws ec2 describe-tags --filters "Name=resource-id,Values=$vpcid" "Name=key,Values=$key" \
18+
--query "Tags[0].Value" --output text
19+
}
20+
21+
delete_vpc_resources() {
22+
if [[ $# -ne 1 ]]; then
23+
echo " vpcid required for deletion"
24+
exit 1
25+
fi
26+
local vpcid=$1
27+
28+
echo "Start cleanup of resources in VPC: $vpcid"
29+
30+
# Delete Instance
31+
instances=$(aws ec2 describe-instances \
32+
--filters "Name=vpc-id,Values=$vpcid" \
33+
--query "Reservations[].Instances[].InstanceId" \
34+
--output text | tr -d '\r' | tr '\n' ' ')
35+
for instance in $instances; do
36+
aws ec2 terminate-instances --instance-ids "$instance"
37+
done
38+
39+
# Detach and Delete Security Groups
40+
security_groups=$(aws ec2 describe-security-groups \
41+
--filters Name=vpc-id,Values=$vpcid \
42+
--query "SecurityGroups[?GroupName!='default'].GroupId" \
43+
--output text | tr -d '\r' | tr '\n' ' ')
44+
for sg in $security_groups; do
45+
enis=$(aws ec2 describe-network-interfaces \
46+
--filters Name=group-id,Values=$sg \
47+
--query "NetworkInterfaces[].NetworkInterfaceId" \
48+
--output text | tr -d '\r' | tr '\n' ' ')
49+
for eni in $enis; do
50+
aws ec2 modify-network-interface-attribute \
51+
--network-interface-id "$eni" \
52+
--groups "$(aws ec2 describe-security-groups \
53+
--query 'SecurityGroups[?GroupName==`default`].GroupId' \
54+
--output text)"
55+
done
56+
aws ec2 delete-security-group --group-id "$sg"
57+
done
58+
59+
# Delete Subnets
60+
subnets=$(aws ec2 describe-subnets \
61+
--filters Name=vpc-id,Values=$vpcid \
62+
--query "Subnets[].SubnetId" \
63+
--output text | tr -d '\r' | tr '\n' ' ')
64+
for subnet in $subnets; do
65+
aws ec2 delete-subnet --subnet-id "$subnet"
66+
done
67+
68+
# Delete Route Tables
69+
# 1. Make first rt as Main , as we cannot delete vpcs attached with main
70+
# 2. replace all rt with first rt
71+
# 3. delete rt
72+
# 4. Main table(first_rt) will be deleted once vpc deleted
73+
first_rt=""
74+
route_tables=$(aws ec2 describe-route-tables \
75+
--filters Name=vpc-id,Values=$vpcid \
76+
--query "RouteTables[].RouteTableId" \
77+
--output text | tr -d '\r' | tr '\n' ' ')
78+
for rt in $route_tables; do
79+
associations=$(aws ec2 describe-route-tables \
80+
--route-table-ids "$rt" \
81+
--query "RouteTables[].Associations[].RouteTableAssociationId" \
82+
--output text | tr -d '\r' | tr '\n' ' ')
83+
for assoc_id in $associations; do
84+
if [ -z "$first_rt" ]; then
85+
aws ec2 replace-route-table-association --association-id $assoc_id --route-table-id $rt
86+
first_rt=$rt
87+
else
88+
aws ec2 replace-route-table-association --association-id $assoc_id --route-table-id $first_rt
89+
fi
90+
done
91+
aws ec2 delete-route-table --route-table-id "$rt" 2>>/dev/null
92+
done
93+
94+
# Delete Internet Gateway
95+
internet_gateways=$(aws ec2 describe-internet-gateways \
96+
--filters Name=attachment.vpc-id,Values=$vpcid \
97+
--query "InternetGateways[].InternetGatewayId" \
98+
--output text | tr -d '\r' | tr '\n' ' ')
99+
for igw in $internet_gateways; do
100+
aws ec2 detach-internet-gateway --internet-gateway-id "$igw" --vpc-id "$vpcid"
101+
aws ec2 delete-internet-gateway --internet-gateway-id "$igw"
102+
done
103+
104+
# Delete vpc
105+
# try 3 times with 30 seconds interval
106+
attempts=0
107+
echo "All resource Deleted for VPC: $vpcid , now delete vpc"
108+
while [ $attempts -lt 3 ]; do
109+
if aws ec2 delete-vpc --vpc-id $vpcid; then
110+
echo "Successfully deleted VPC: $vpcid"
111+
break
112+
else
113+
attempts=$((attempts + 1))
114+
if [ $attempts -lt 3 ]; then
115+
echo "Failed to delete VPC: $vpcid. Retrying in 30 seconds..."
116+
sleep 30
117+
fi
118+
fi
119+
done
120+
if [ $attempts -eq 3 ]; then
121+
echo "Failed to delete VPC: $vpcid after 3 attempts. Continue the loop to delete other vpc"
122+
fi
123+
}
124+
125+
github_repository=$(get_tag_value $vpcid "GitHubRepository")
126+
run_id=$(get_tag_value $vpcid "GitHubRunId")
127+
job_name=$(get_tag_value $vpcid "GitHubJob")
128+
response=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" \
129+
"https://api.github.com/repos/${github_repository}/actions/runs/${run_id}/jobs")
130+
if [[ -z "$response" || "$response" == "null" ]]; then
131+
exit 0
132+
fi
133+
134+
# 1. make sure .jobs exist in response
135+
# e.g. { "message": "Not Found", "documentation_url": "https://docs.github.com/rest", "status": "404" }
136+
# 2. check if all jobs completed
137+
138+
if ! echo "$response" | jq -e '.jobs != null' >/dev/null 2>&1; then
139+
exit 0
140+
fi
141+
142+
is_jobs_not_completed=$(echo "$response" | jq -r ".jobs? // [] |
143+
map(select(.status != \"completed\")) |
144+
length")
145+
146+
if [[ "$is_jobs_not_completed" -eq 0 ]]; then
147+
echo "Holodeck e2e Job status is not in running stage , Delete the vpc $vpcid and dependent resources"
148+
delete_vpc_resources $vpcid
149+
fi

0 commit comments

Comments
 (0)