Created
August 28, 2017 18:03
-
-
Save brianredbeard/bf97cc90236821b2052cc505b07be7ea to your computer and use it in GitHub Desktop.
Trying out something to delete annoying VPCs
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 python | |
import boto3 | |
import logging | |
import sys | |
from pprint import pprint | |
from time import sleep | |
import botocore.exceptions | |
# In order to do this right we have to track all of the dependencies in the | |
# right order. This sucks, but it's better than waiting for Amazon to get | |
# things done. | |
# | |
# We need to delete (in this order): | |
# EC2 Route Table Subnet Associations | |
# Public EC2 Routes | |
# EC2 Route Tables | |
# EC2 Subnets | |
# EC2 VPC DHCP Associations | |
# ENIs in the VPC | |
# VPC Gateway Attachments | |
# - NAT Gateways | |
# - Internet Gateways | |
# DHCP Options | |
# The VPC | |
def main(): | |
vpc = sys.argv[1] | |
#boto3.set_stream_logger('boto3.resources', logging.INFO) | |
try: | |
c = boto3.client('ec2') | |
except (botocore.exceptions.NoRegionError): | |
print("You must supply the environment variable AWS_DEFAULT_REGION") | |
exit(1) | |
ec2 = boto3.resource('ec2') | |
ec2c = boto3.client('ec2') | |
rds = boto3.client('rds') | |
elb = boto3.client('elb') | |
v = ec2.Vpc(vpc) | |
filters = [{'VPC ID': vpc}] | |
try: | |
db = rds.describe_db_instances() | |
except (botocore.exceptions.NoCredentialsError): | |
print("You must supply environment variables to authenticate against " + | |
"the AWS API, these could include:") | |
print(" - AWS_PROFILE") | |
print(" - AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY") | |
print(" - AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY" + | |
" + AWS_SESSION_TOKEN") | |
exit(1) | |
for r in db['DBInstances']: | |
if r['DBSubnetGroup']['VpcId'] == vpc: | |
dbid = r['DBInstanceIdentifier'] | |
try: | |
rds.delete_db_instance( | |
DBInstanceIdentifier=dbid, SkipFinalSnapshot=True) | |
except: | |
pass | |
print("Waiting for database {} to complete deletion".format(dbid)) | |
waiter = rds.get_waiter('db_instance_deleted') | |
waiter.wait(DBInstanceIdentifier=dbid) | |
p = elb.get_paginator('describe_load_balancers') | |
query = "LoadBalancerDescriptions[?VPCId == `" + vpc + "`]" | |
p_iter = p.paginate().search(query) | |
for e in p_iter: | |
print("Deleting ELB {} - {}".format(e['VPCId'], e['LoadBalancerName'])) | |
elb.delete_load_balancer(LoadBalancerName=e['LoadBalancerName']) | |
for i in v.instances.all(): | |
i.terminate() | |
for acl in v.network_acls.all(): | |
if not acl.is_default: | |
acl.delete() | |
sgl = v.security_groups.all() | |
count = sum(1 for _ in sgl) | |
crashcount = 0 | |
while count > 1: | |
# Create a backoff loop to minimize hitting API limits | |
sleep(crashcount * 2) | |
print("Crash looping to delete security groups. Total remaining: {}".format(count)) | |
for sg in sgl: | |
# .SecurityGroups[].IpPermissions[]?.UserIdGroupPairs[]?.GroupId | |
if len(sg.ip_permissions) > 0: | |
for permission in sg.ip_permissions: | |
response = ec2c.revoke_security_group_ingress(GroupId=sg.group_id, | |
IpPermissions=[permission]) | |
try: | |
if sg.group_name != 'default': | |
print("Attempting delete of {}".format(sg.group_name)) | |
sg.delete() | |
except Exception as e: | |
print(e) | |
pass | |
sgl = v.security_groups.all() | |
count = sum(1 for _ in sgl) | |
crashcount += 1 | |
filter=[{"Name": "vpc-id", "Values": [ vpc ]}] | |
natg = ec2c.describe_nat_gateways(Filter=filter)['NatGateways'] | |
count = sum(1 for _ in natg) | |
print("Total Nat Gateways: {}".format(count)) | |
for nat in natg: | |
print("Next NAT loop") | |
if not (nat['State'] in ["deleted","deleting"]): | |
print("Deleting NAT gateway {}".format(nat['NatGatewayId'])) | |
try: | |
ec2c.delete_nat_gateway(NatGatewayId=nat['NatGatewayId']) | |
waiter = ec2c.get_waiter('nat_gateway_available') | |
waiter.wait(Filters=[ | |
{ | |
'Name': 'state', | |
'Values': [ | |
'deleted', | |
] | |
},{ | |
'Name': 'nat-gateway-id', | |
'Values': [ | |
nat['NatGatewayId'], | |
] | |
}, | |
]) | |
except: | |
pass | |
for eni in v.network_interfaces.all(): | |
print(eni.association) | |
eni.association.delete() | |
#eni.detach(Force=True) | |
#eni.delete() | |
for ig in v.internet_gateways.all(): | |
ig.detach_from_vpc(VpcId=vpc) | |
try: | |
dhcp = v.dhcp_options | |
v.associate_dhcp_options(DhcpOptionsId='default') | |
dhcp.delete() | |
print("Deleted DHCP") | |
except: | |
pass | |
rtl = v.route_tables.all() | |
count = sum(1 for _ in rtl) | |
while count > 1: | |
print("Crash looping to delete routing tables. Total remaining: {}".format(count)) | |
for rt in rtl: | |
for ra in rt.associations: | |
if not ra.main: | |
print("Deleting route table associations") | |
ra.delete() | |
for r in rt.routes: | |
try: | |
x = r.delete() | |
print(x) | |
except: | |
pass | |
try: | |
rt.delete() | |
except: | |
pass | |
rtl = v.route_tables.all() | |
count = sum(1 for _ in rtl) | |
for sub in v.subnets.all(): | |
sub.delete() | |
v.delete() | |
if __name__ == "__main__": | |
try: | |
main() | |
except KeyboardInterrupt: | |
exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment