Skip to content

Instantly share code, notes, and snippets.

@brianredbeard
Created August 28, 2017 18:03
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save brianredbeard/bf97cc90236821b2052cc505b07be7ea to your computer and use it in GitHub Desktop.
Save brianredbeard/bf97cc90236821b2052cc505b07be7ea to your computer and use it in GitHub Desktop.
Trying out something to delete annoying VPCs
#!/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