@@ -4,11 +4,168 @@ echo ---------------------------------------------------------------------------
44echo This script destroys the resources created in the workshop
55echo ---------------------------------------------------------------------------------------------
66
7+ # Parse command line arguments
8+ FORCE_CLEANUP=false
9+ while [[ $# -gt 0 ]]; do
10+ case $1 in
11+ -f|--force)
12+ FORCE_CLEANUP=true
13+ echo " 🚨 Force cleanup mode enabled - will delete dangling resources tagged with Workshop=true"
14+ shift
15+ ;;
16+ -h|--help)
17+ echo " Usage: $0 [-f|--force] [-h|--help]"
18+ echo " -f, --force Enable force cleanup of dangling resources (use with caution)"
19+ echo " -h, --help Show this help message"
20+ exit 0
21+ ;;
22+ * )
23+ echo " Unknown option $1 "
24+ echo " Use -h or --help for usage information"
25+ exit 1
26+ ;;
27+ esac
28+ done
29+
730if [ -z " $AWS_REGION " ]; then
831 echo " Fatal: environment variable AWS_REGION not set. Aborting."
932 exit 1
1033fi
1134
35+ # Function to check if stack deletion failed
36+ check_stack_deletion_status () {
37+ local stack_name=$1
38+ local status=$( aws cloudformation describe-stacks --stack-name " $stack_name " --query ' Stacks[0].StackStatus' --output text 2> /dev/null)
39+
40+ if [[ " $status " == " DELETE_FAILED" ]]; then
41+ echo " ⚠️ Stack $stack_name deletion failed. Status: $status "
42+ return 1
43+ elif [[ " $status " == " DELETE_COMPLETE" ]] || [[ -z " $status " ]]; then
44+ echo " ✅ Stack $stack_name deleted successfully or doesn't exist"
45+ return 0
46+ else
47+ echo " ℹ️ Stack $stack_name status: $status "
48+ return 0
49+ fi
50+ }
51+
52+ # Function to force delete EKS cluster
53+ force_delete_eks_cluster () {
54+ echo " 🔍 Checking for EKS clusters tagged with Workshop=true..."
55+
56+ local clusters=$( aws eks list-clusters --query ' clusters[]' --output text)
57+
58+ for cluster in $clusters ; do
59+ local tags=$( aws eks list-tags-for-resource --resource-arn " arn:aws:eks:$AWS_REGION :$( aws sts get-caller-identity --query Account --output text) :cluster/$cluster " --query ' tags.Workshop' --output text 2> /dev/null)
60+
61+ if [[ " $tags " == " true" ]]; then
62+ echo " 🗑️ Force deleting EKS cluster: $cluster "
63+
64+ # Delete node groups first
65+ local nodegroups=$( aws eks list-nodegroups --cluster-name " $cluster " --query ' nodegroups[]' --output text 2> /dev/null)
66+ for ng in $nodegroups ; do
67+ echo " Deleting node group: $ng "
68+ aws eks delete-nodegroup --cluster-name " $cluster " --nodegroup-name " $ng " 2> /dev/null
69+ done
70+
71+ # Wait for node groups to be deleted
72+ for ng in $nodegroups ; do
73+ echo " Waiting for node group $ng to be deleted..."
74+ aws eks wait nodegroup-deleted --cluster-name " $cluster " --nodegroup-name " $ng " 2> /dev/null
75+ done
76+
77+ # Delete the cluster
78+ aws eks delete-cluster --name " $cluster "
79+ echo " Waiting for cluster $cluster to be deleted..."
80+ aws eks wait cluster-deleted --name " $cluster "
81+ echo " ✅ EKS cluster $cluster deleted"
82+ fi
83+ done
84+ }
85+
86+ # Function to force delete VPC and related resources
87+ force_delete_vpc_resources () {
88+ echo " 🔍 Checking for VPCs tagged with Workshop=true..."
89+
90+ local vpcs=$( aws ec2 describe-vpcs --filters " Name=tag:Workshop,Values=true" --query ' Vpcs[].VpcId' --output text)
91+
92+ for vpc in $vpcs ; do
93+ echo " 🗑️ Force deleting VPC and related resources: $vpc "
94+
95+ # Delete NAT Gateways
96+ local nat_gateways=$( aws ec2 describe-nat-gateways --filter " Name=vpc-id,Values=$vpc " --query ' NatGateways[?State==`available`].NatGatewayId' --output text)
97+ for nat in $nat_gateways ; do
98+ echo " Deleting NAT Gateway: $nat "
99+ aws ec2 delete-nat-gateway --nat-gateway-id " $nat "
100+ done
101+
102+ # Wait for NAT Gateways to be deleted
103+ for nat in $nat_gateways ; do
104+ echo " Waiting for NAT Gateway $nat to be deleted..."
105+ aws ec2 wait nat-gateway-deleted --nat-gateway-ids " $nat " 2> /dev/null || true
106+ done
107+
108+ # Delete Internet Gateway
109+ local igws=$( aws ec2 describe-internet-gateways --filters " Name=attachment.vpc-id,Values=$vpc " --query ' InternetGateways[].InternetGatewayId' --output text)
110+ for igw in $igws ; do
111+ echo " Detaching and deleting Internet Gateway: $igw "
112+ aws ec2 detach-internet-gateway --internet-gateway-id " $igw " --vpc-id " $vpc " 2> /dev/null
113+ aws ec2 delete-internet-gateway --internet-gateway-id " $igw " 2> /dev/null
114+ done
115+
116+ # Delete subnets
117+ local subnets=$( aws ec2 describe-subnets --filters " Name=vpc-id,Values=$vpc " --query ' Subnets[].SubnetId' --output text)
118+ for subnet in $subnets ; do
119+ echo " Deleting subnet: $subnet "
120+ aws ec2 delete-subnet --subnet-id " $subnet " 2> /dev/null
121+ done
122+
123+ # Delete route tables (except main)
124+ local route_tables=$( aws ec2 describe-route-tables --filters " Name=vpc-id,Values=$vpc " --query ' RouteTables[?Associations[0].Main!=`true`].RouteTableId' --output text)
125+ for rt in $route_tables ; do
126+ echo " Deleting route table: $rt "
127+ aws ec2 delete-route-table --route-table-id " $rt " 2> /dev/null
128+ done
129+
130+ # Delete security groups (except default)
131+ local security_groups=$( aws ec2 describe-security-groups --filters " Name=vpc-id,Values=$vpc " --query ' SecurityGroups[?GroupName!=`default`].GroupId' --output text)
132+ for sg in $security_groups ; do
133+ echo " Deleting security group: $sg "
134+ aws ec2 delete-security-group --group-id " $sg " 2> /dev/null
135+ done
136+
137+ # Delete VPC
138+ echo " Deleting VPC: $vpc "
139+ aws ec2 delete-vpc --vpc-id " $vpc " 2> /dev/null
140+ echo " ✅ VPC $vpc and related resources deleted"
141+ done
142+ }
143+
144+ # Function to delete other tagged resources
145+ force_delete_other_resources () {
146+ echo " 🔍 Checking for other resources tagged with Workshop=true..."
147+
148+ # Delete Load Balancers
149+ local elbs=$( aws elbv2 describe-load-balancers --query ' LoadBalancers[].LoadBalancerArn' --output text)
150+ for elb_arn in $elbs ; do
151+ local tags=$( aws elbv2 describe-tags --resource-arns " $elb_arn " --query ' TagDescriptions[0].Tags[?Key==`Workshop`].Value' --output text 2> /dev/null)
152+ if [[ " $tags " == " true" ]]; then
153+ echo " 🗑️ Deleting Load Balancer: $elb_arn "
154+ aws elbv2 delete-load-balancer --load-balancer-arn " $elb_arn "
155+ fi
156+ done
157+
158+ # Delete RDS instances
159+ local rds_instances=$( aws rds describe-db-instances --query ' DBInstances[].DBInstanceIdentifier' --output text)
160+ for db in $rds_instances ; do
161+ local tags=$( aws rds list-tags-for-resource --resource-name " arn:aws:rds:$AWS_REGION :$( aws sts get-caller-identity --query Account --output text) :db:$db " --query ' TagList[?Key==`Workshop`].Value' --output text 2> /dev/null)
162+ if [[ " $tags " == " true" ]]; then
163+ echo " 🗑️ Deleting RDS instance: $db "
164+ aws rds delete-db-instance --db-instance-identifier " $db " --skip-final-snapshot --delete-automated-backups
165+ fi
166+ done
167+ }
168+
12169# Disable Contributor Insights
13170DDB_CONTRIB=$( aws ssm get-parameter --name ' /petstore/dynamodbtablename' | jq .Parameter.Value -r)
14171aws dynamodb update-contributor-insights --table-name $DDB_CONTRIB --contributor-insights-action DISABLE
@@ -43,15 +200,49 @@ kubectl delete namespace keycloak --force
43200# Sometimes the SqlSeeder doesn't get deleted cleanly. This helps clean up the environment completely including Sqlseeder
44201aws cloudformation delete-stack --stack-name $STACK_NAME_APP
45202aws cloudformation wait stack-delete-complete --stack-name $STACK_NAME_APP
203+
204+ # Check if Applications stack deletion failed and force cleanup if needed
205+ if ! check_stack_deletion_status " $STACK_NAME_APP " ; then
206+ if [ " $FORCE_CLEANUP " = true ]; then
207+ echo " 🚨 Applications stack deletion failed. Starting force cleanup..."
208+ force_delete_eks_cluster
209+ force_delete_vpc_resources
210+ force_delete_other_resources
211+ else
212+ echo " ⚠️ Applications stack deletion failed. Use -f flag to enable force cleanup of dangling resources."
213+ fi
214+ fi
215+
46216aws cloudformation delete-stack --stack-name $STACK_NAME
47217aws cloudformation wait stack-delete-complete --stack-name $STACK_NAME
48218
219+ # Check if Services stack deletion failed and force cleanup if needed
220+ if ! check_stack_deletion_status " $STACK_NAME " ; then
221+ if [ " $FORCE_CLEANUP " = true ]; then
222+ echo " 🚨 Services stack deletion failed. Starting force cleanup..."
223+ force_delete_vpc_resources
224+ force_delete_other_resources
225+ else
226+ echo " ⚠️ Services stack deletion failed. Use -f flag to enable force cleanup of dangling resources."
227+ fi
228+ fi
229+
49230aws cloudwatch delete-dashboards --dashboard-names " EKS_FluentBit_Dashboard"
50231
51232# delete the code pipeline stack
52233aws cloudformation delete-stack --stack-name $STACK_NAME_CODEPIPELINE
53234aws cloudformation wait stack-delete-complete --stack-name $STACK_NAME_CODEPIPELINE
54235
236+ # Check if CodePipeline stack deletion failed and force cleanup if needed
237+ if ! check_stack_deletion_status " $STACK_NAME_CODEPIPELINE " ; then
238+ if [ " $FORCE_CLEANUP " = true ]; then
239+ echo " 🚨 CodePipeline stack deletion failed. Starting force cleanup..."
240+ force_delete_other_resources
241+ else
242+ echo " ⚠️ CodePipeline stack deletion failed. Use -f flag to enable force cleanup of dangling resources."
243+ fi
244+ fi
245+
55246echo CDK BOOTSTRAP WAS NOT DELETED
56247
57248echo ----- ✅ DONE --------
0 commit comments