|
| 1 | +import boto3 |
| 2 | +import logging |
| 3 | +from common import get_all_regions |
| 4 | + |
| 5 | +DELETEABLE_STATUS = ["CREATE_FAILED", "DELETE_FAILED"] |
| 6 | + |
| 7 | +AWS_RESOURCE_TYPE_EC2_INSTANCE = "AWS::EC2::Instance" |
| 8 | + |
| 9 | +AWS_EKS_MANAGED_TAGS = ["alpha.eksctl.io/cluster-name"] |
| 10 | + |
| 11 | +logger = logging.getLogger(__name__) |
| 12 | + |
| 13 | +def get_deleteable_cf_templates(client): |
| 14 | + deleteable_stacks = [] |
| 15 | + response = client.describe_stacks() |
| 16 | + for stack in response.get('Stacks', []): |
| 17 | + stackName = stack.get("StackName", "") |
| 18 | + if stackName != "": |
| 19 | + is_eks_managed = False |
| 20 | + for tag in stack.get('Tags', []): |
| 21 | + if tag.get('Key', '') in AWS_EKS_MANAGED_TAGS: |
| 22 | + is_eks_managed = True |
| 23 | + logger.info("{} Found EKS managed stack {}".format(client.meta.region_name, stackName)) |
| 24 | + if not is_eks_managed: |
| 25 | + if stack.get('StackStatus', '') in DELETEABLE_STATUS: |
| 26 | + deleteable_stacks.append(stack) |
| 27 | + logger.info("{} Found stack with deleteable status {}".format(client.meta.region_name, stackName)) |
| 28 | + elif not does_cf_template_have_ec2_instances(client, stackName): |
| 29 | + deleteable_stacks.append(stack) |
| 30 | + logger.info("{} Found stack without instances {}".format(client.meta.region_name, stackName)) |
| 31 | + return deleteable_stacks |
| 32 | + |
| 33 | +def does_cf_template_have_ec2_instances(client, stack_name: str): |
| 34 | + for resource in client.describe_stack_resources(StackName=stack_name)['StackResources']: |
| 35 | + if resource.get('ResourceType', '') == AWS_RESOURCE_TYPE_EC2_INSTANCE: |
| 36 | + return True |
| 37 | + return False |
| 38 | + |
| 39 | +def delete_stacks(dry_run = False): |
| 40 | + for region in get_all_regions(): |
| 41 | + client = boto3.client('cloudformation', region_name=region) |
| 42 | + stacks = get_deleteable_cf_templates(client) |
| 43 | + for stack in stacks: |
| 44 | + stackName = stack.get("StackName", "") |
| 45 | + if stackName != "": |
| 46 | + try: |
| 47 | + logger.info("{} Attempting to delete stack {}".format(region, stackName)) |
| 48 | + if not dry_run: |
| 49 | + client.delete_stack(StackName=stackName) |
| 50 | + logger.info("{} Deleted stack {}".format(region, stackName)) |
| 51 | + except: |
| 52 | + logger.info("{} Failed deleting stack {}".format(region, stackName)) |
0 commit comments