2014-02-24 20:37:23 +01:00
|
|
|
'''
|
|
|
|
Find and delete AWS resources matching the provided --match string. Unless
|
|
|
|
--yes|-y is provided, the prompt for confirmation prior to deleting resources.
|
|
|
|
Please use caution, you can easily delete you're *ENTIRE* EC2 infrastructure.
|
|
|
|
'''
|
|
|
|
|
2019-10-30 17:48:59 +01:00
|
|
|
from __future__ import (absolute_import, division, print_function)
|
|
|
|
__metaclass__ = type
|
|
|
|
|
2014-02-24 20:37:23 +01:00
|
|
|
import boto
|
2017-05-30 19:05:19 +02:00
|
|
|
import boto.ec2.elb
|
2014-02-24 20:37:23 +01:00
|
|
|
import optparse
|
2017-05-30 19:05:19 +02:00
|
|
|
import os
|
2014-04-17 20:32:02 +02:00
|
|
|
import os.path
|
2017-05-30 19:05:19 +02:00
|
|
|
import re
|
|
|
|
import sys
|
2015-01-27 18:46:22 +01:00
|
|
|
import time
|
2017-05-30 19:05:19 +02:00
|
|
|
import yaml
|
|
|
|
|
2017-07-23 03:15:46 +02:00
|
|
|
from ansible.module_utils.six.moves import input
|
|
|
|
|
2014-02-24 20:37:23 +01:00
|
|
|
|
|
|
|
def delete_aws_resources(get_func, attr, opts):
|
|
|
|
for item in get_func():
|
|
|
|
val = getattr(item, attr)
|
|
|
|
if re.search(opts.match_re, val):
|
2014-03-13 14:52:36 +01:00
|
|
|
prompt_and_delete(item, "Delete matching %s? [y/n]: " % (item,), opts.assumeyes)
|
2014-02-24 20:37:23 +01:00
|
|
|
|
2017-05-30 19:05:19 +02:00
|
|
|
|
2015-01-27 18:46:22 +01:00
|
|
|
def delete_autoscaling_group(get_func, attr, opts):
|
|
|
|
assumeyes = opts.assumeyes
|
|
|
|
group_name = None
|
|
|
|
for item in get_func():
|
|
|
|
group_name = getattr(item, attr)
|
|
|
|
if re.search(opts.match_re, group_name):
|
|
|
|
if not opts.assumeyes:
|
2017-07-23 03:15:46 +02:00
|
|
|
assumeyes = input("Delete matching %s? [y/n]: " % (item).lower()) == 'y'
|
2015-01-27 18:46:22 +01:00
|
|
|
break
|
|
|
|
if assumeyes and group_name:
|
|
|
|
groups = asg.get_all_groups(names=[group_name])
|
|
|
|
if groups:
|
|
|
|
group = groups[0]
|
|
|
|
group.max_size = 0
|
|
|
|
group.min_size = 0
|
|
|
|
group.desired_capacity = 0
|
|
|
|
group.update()
|
|
|
|
instances = True
|
|
|
|
while instances:
|
|
|
|
tmp_groups = asg.get_all_groups(names=[group_name])
|
|
|
|
if tmp_groups:
|
|
|
|
tmp_group = tmp_groups[0]
|
|
|
|
if not tmp_group.instances:
|
2017-01-31 00:01:47 +01:00
|
|
|
instances = False
|
2015-01-27 18:46:22 +01:00
|
|
|
time.sleep(10)
|
|
|
|
|
|
|
|
group.delete()
|
|
|
|
while len(asg.get_all_groups(names=[group_name])):
|
|
|
|
time.sleep(5)
|
2017-05-30 19:05:19 +02:00
|
|
|
print("Terminated ASG: %s" % group_name)
|
|
|
|
|
2015-01-27 18:46:22 +01:00
|
|
|
|
2014-04-17 20:32:02 +02:00
|
|
|
def delete_aws_eips(get_func, attr, opts):
|
|
|
|
|
|
|
|
# the file might not be there if the integration test wasn't run
|
|
|
|
try:
|
2019-12-21 13:01:38 +01:00
|
|
|
with open(opts.eip_log, 'r') as f:
|
|
|
|
eip_log = f.read().splitlines()
|
2014-04-17 20:32:02 +02:00
|
|
|
except IOError:
|
2017-01-31 00:01:47 +01:00
|
|
|
print('%s not found.' % opts.eip_log)
|
|
|
|
return
|
2014-04-17 20:32:02 +02:00
|
|
|
|
|
|
|
for item in get_func():
|
|
|
|
val = getattr(item, attr)
|
|
|
|
if val in eip_log:
|
2017-01-31 00:01:47 +01:00
|
|
|
prompt_and_delete(item, "Delete matching %s? [y/n]: " % (item,), opts.assumeyes)
|
2014-04-17 20:32:02 +02:00
|
|
|
|
2017-05-30 19:05:19 +02:00
|
|
|
|
2014-04-17 20:32:02 +02:00
|
|
|
def delete_aws_instances(reservation, opts):
|
|
|
|
for list in reservation:
|
|
|
|
for item in list.instances:
|
|
|
|
prompt_and_delete(item, "Delete matching %s? [y/n]: " % (item,), opts.assumeyes)
|
|
|
|
|
2017-05-30 19:05:19 +02:00
|
|
|
|
2014-03-13 00:28:57 +01:00
|
|
|
def prompt_and_delete(item, prompt, assumeyes):
|
|
|
|
if not assumeyes:
|
2017-07-23 03:15:46 +02:00
|
|
|
assumeyes = input(prompt).lower() == 'y'
|
2017-05-30 19:05:19 +02:00
|
|
|
assert hasattr(item, 'delete') or hasattr(item, 'terminate'), "Class <%s> has no delete or terminate attribute" % item.__class__
|
2014-03-13 00:28:57 +01:00
|
|
|
if assumeyes:
|
2017-01-28 00:45:23 +01:00
|
|
|
if hasattr(item, 'delete'):
|
2014-04-17 20:32:02 +02:00
|
|
|
item.delete()
|
2017-05-30 19:05:19 +02:00
|
|
|
print("Deleted %s" % item)
|
2017-01-28 00:45:23 +01:00
|
|
|
if hasattr(item, 'terminate'):
|
2014-04-17 20:32:02 +02:00
|
|
|
item.terminate()
|
2017-05-30 19:05:19 +02:00
|
|
|
print("Terminated %s" % item)
|
|
|
|
|
2014-02-24 20:37:23 +01:00
|
|
|
|
|
|
|
def parse_args():
|
|
|
|
# Load details from credentials.yml
|
|
|
|
default_aws_access_key = os.environ.get('AWS_ACCESS_KEY', None)
|
|
|
|
default_aws_secret_key = os.environ.get('AWS_SECRET_KEY', None)
|
|
|
|
if os.path.isfile('credentials.yml'):
|
|
|
|
credentials = yaml.load(open('credentials.yml', 'r'))
|
|
|
|
|
|
|
|
if default_aws_access_key is None:
|
|
|
|
default_aws_access_key = credentials['ec2_access_key']
|
|
|
|
if default_aws_secret_key is None:
|
|
|
|
default_aws_secret_key = credentials['ec2_secret_key']
|
|
|
|
|
2017-05-30 19:05:19 +02:00
|
|
|
parser = optparse.OptionParser(
|
|
|
|
usage="%s [options]" % (sys.argv[0], ),
|
|
|
|
description=__doc__
|
|
|
|
)
|
|
|
|
parser.add_option(
|
|
|
|
"--access",
|
2014-02-24 20:37:23 +01:00
|
|
|
action="store", dest="ec2_access_key",
|
|
|
|
default=default_aws_access_key,
|
2017-05-30 19:05:19 +02:00
|
|
|
help="Amazon ec2 access id. Can use EC2_ACCESS_KEY environment variable, or a values from credentials.yml."
|
|
|
|
)
|
|
|
|
parser.add_option(
|
|
|
|
"--secret",
|
2014-02-24 20:37:23 +01:00
|
|
|
action="store", dest="ec2_secret_key",
|
|
|
|
default=default_aws_secret_key,
|
2017-05-30 19:05:19 +02:00
|
|
|
help="Amazon ec2 secret key. Can use EC2_SECRET_KEY environment variable, or a values from credentials.yml."
|
|
|
|
)
|
|
|
|
parser.add_option(
|
|
|
|
"--eip-log",
|
2014-04-17 20:32:02 +02:00
|
|
|
action="store", dest="eip_log",
|
2017-05-30 19:05:19 +02:00
|
|
|
default=None,
|
|
|
|
help="Path to log of EIPs created during test."
|
|
|
|
)
|
|
|
|
parser.add_option(
|
|
|
|
"--integration-config",
|
2014-04-17 20:32:02 +02:00
|
|
|
action="store", dest="int_config",
|
2017-05-30 19:05:19 +02:00
|
|
|
default="integration_config.yml",
|
|
|
|
help="path to integration config"
|
|
|
|
)
|
|
|
|
parser.add_option(
|
|
|
|
"--credentials", "-c",
|
2014-02-24 20:37:23 +01:00
|
|
|
action="store", dest="credential_file",
|
|
|
|
default="credentials.yml",
|
2017-05-30 19:05:19 +02:00
|
|
|
help="YAML file to read cloud credentials (default: %default)"
|
|
|
|
)
|
|
|
|
parser.add_option(
|
|
|
|
"--yes", "-y",
|
2014-02-24 20:37:23 +01:00
|
|
|
action="store_true", dest="assumeyes",
|
|
|
|
default=False,
|
2017-05-30 19:05:19 +02:00
|
|
|
help="Don't prompt for confirmation"
|
|
|
|
)
|
|
|
|
parser.add_option(
|
|
|
|
"--match",
|
2014-02-24 20:37:23 +01:00
|
|
|
action="store", dest="match_re",
|
|
|
|
default="^ansible-testing-",
|
2017-05-30 19:05:19 +02:00
|
|
|
help="Regular expression used to find AWS resources (default: %default)"
|
|
|
|
)
|
2014-02-24 20:37:23 +01:00
|
|
|
|
|
|
|
(opts, args) = parser.parse_args()
|
|
|
|
for required in ['ec2_access_key', 'ec2_secret_key']:
|
|
|
|
if getattr(opts, required) is None:
|
|
|
|
parser.error("Missing required parameter: --%s" % required)
|
|
|
|
|
|
|
|
return (opts, args)
|
|
|
|
|
2017-05-30 19:05:19 +02:00
|
|
|
|
2014-02-24 20:37:23 +01:00
|
|
|
if __name__ == '__main__':
|
|
|
|
|
|
|
|
(opts, args) = parse_args()
|
|
|
|
|
2014-04-17 20:32:02 +02:00
|
|
|
int_config = yaml.load(open(opts.int_config).read())
|
|
|
|
if not opts.eip_log:
|
|
|
|
output_dir = os.path.expanduser(int_config["output_dir"])
|
2017-05-30 19:05:19 +02:00
|
|
|
opts.eip_log = output_dir + '/' + opts.match_re.replace('^', '') + '-eip_integration_tests.log'
|
2014-04-17 20:32:02 +02:00
|
|
|
|
2014-02-24 20:37:23 +01:00
|
|
|
# Connect to AWS
|
|
|
|
aws = boto.connect_ec2(aws_access_key_id=opts.ec2_access_key,
|
2017-05-30 19:05:19 +02:00
|
|
|
aws_secret_access_key=opts.ec2_secret_key)
|
2014-02-24 20:37:23 +01:00
|
|
|
|
2014-04-24 22:53:40 +02:00
|
|
|
elb = boto.connect_elb(aws_access_key_id=opts.ec2_access_key,
|
2017-05-30 19:05:19 +02:00
|
|
|
aws_secret_access_key=opts.ec2_secret_key)
|
2014-04-24 22:53:40 +02:00
|
|
|
|
2014-05-28 06:36:42 +02:00
|
|
|
asg = boto.connect_autoscale(aws_access_key_id=opts.ec2_access_key,
|
2017-05-30 19:05:19 +02:00
|
|
|
aws_secret_access_key=opts.ec2_secret_key)
|
2014-05-28 06:36:42 +02:00
|
|
|
|
2014-03-13 14:52:36 +01:00
|
|
|
try:
|
|
|
|
# Delete matching keys
|
|
|
|
delete_aws_resources(aws.get_all_key_pairs, 'name', opts)
|
2014-02-24 20:37:23 +01:00
|
|
|
|
2014-05-28 06:36:42 +02:00
|
|
|
# Delete matching security groups
|
2014-03-13 14:52:36 +01:00
|
|
|
delete_aws_resources(aws.get_all_security_groups, 'name', opts)
|
2014-04-17 20:32:02 +02:00
|
|
|
|
2014-05-28 06:36:42 +02:00
|
|
|
# Delete matching ASGs
|
2015-01-27 18:46:22 +01:00
|
|
|
delete_autoscaling_group(asg.get_all_groups, 'name', opts)
|
2014-05-28 06:36:42 +02:00
|
|
|
|
|
|
|
# Delete matching launch configs
|
|
|
|
delete_aws_resources(asg.get_all_launch_configurations, 'name', opts)
|
|
|
|
|
2014-04-24 22:53:40 +02:00
|
|
|
# Delete ELBs
|
|
|
|
delete_aws_resources(elb.get_all_load_balancers, 'name', opts)
|
|
|
|
|
2014-04-17 20:32:02 +02:00
|
|
|
# Delete recorded EIPs
|
|
|
|
delete_aws_eips(aws.get_all_addresses, 'public_ip', opts)
|
|
|
|
|
|
|
|
# Delete temporary instances
|
2017-05-30 19:05:19 +02:00
|
|
|
filters = {"tag:Name": opts.match_re.replace('^', ''), "instance-state-name": ['running', 'pending', 'stopped']}
|
2014-04-17 20:32:02 +02:00
|
|
|
delete_aws_instances(aws.get_all_instances(filters=filters), opts)
|
|
|
|
|
2015-08-27 20:58:51 +02:00
|
|
|
except KeyboardInterrupt as e:
|
2015-08-27 21:02:35 +02:00
|
|
|
print("\nExiting on user command.")
|