Permalink
Browse files

Added resource exclusion filter handling.

[Issue(s) #24]
  • Loading branch information...
1 parent 7ddbbdf commit c0c1e322973842db429443a8a0cc3b685473eb75 @sopel committed Dec 11, 2012
View
@@ -47,6 +47,9 @@ def create_arn(iam, service, region, resource):
return 'arn:aws:' + service + ':' + region + ':' + account.id + ':' + resource
# TODO: refactor to argparse custom action for inline usage!
+def build_filter(filter_args, exclude_args):
+ return {'filters': build_filter_params(filter_args), 'excludes': build_filter_params(exclude_args)}
+
def build_filter_params(filter_args):
from collections import defaultdict
@@ -76,10 +79,12 @@ def build_region_parser():
parser.add_argument("-r", "--region", help="A region substring selector (e.g. 'us-west')")
return parser
-def build_filter_parser(resource_name):
+def build_filter_parser(resource_name, add_ids=True):
parser = argparse.ArgumentParser(add_help=False)
- parser.add_argument("-f", "--filter", action="append", help="An EC2 instance filter. [can be used multiple times]")
- parser.add_argument("-i", "--id", dest="resource_ids", action="append", help="An EC2 instance id. [can be used multiple times]")
+ parser.add_argument("-f", "--filter", action="append", help="A {0} filter. [can be used multiple times]".format(resource_name))
+ parser.add_argument("-x", "--exclude", action="append", help="A {0} filter (matching ones are excluded). [can be used multiple times]".format(resource_name))
+ if add_ids:
+ parser.add_argument("-i", "--id", dest="resource_ids", action="append", help="A {0} id. [can be used multiple times]".format(resource_name))
return parser
def parse_credentials(args):
@@ -88,6 +93,10 @@ def parse_credentials(args):
def is_region_selected(region, name):
return True if region.name.find(name) != -1 else False
+def filter_list_by_attribute(includes, excludes, attribute):
+ excluded_ids = set([getattr(exclude, attribute) for exclude in excludes])
+ return [include for include in includes if getattr(include, attribute) not in excluded_ids]
+
def filter_regions(regions, region):
if region:
botocross_log.info("... (filtered by region '" + region + "')")
@@ -30,9 +30,7 @@
# configure command line argument parsing
parser = argparse.ArgumentParser(description='Backup EC2 instances in all/some available EC2 regions',
- parents=[bc.build_region_parser(), bc.build_common_parser()])
-parser.add_argument("-f", "--filter", action="append", help="An EC2 instance filter. [can be used multiple times]")
-parser.add_argument("-i", "--id", dest="resource_ids", action="append", help="An EC2 instance id. [can be used multiple times]")
+ parents=[bc.build_region_parser(), bc.build_filter_parser('EC2 instance'), bc.build_common_parser()])
parser.add_argument("-d", "--description", help="A description for the EC2 image [default: <provided>]")
parser.add_argument("-br", "--backup_retention", type=int, default=1, help="The number of backups to retain (correlated via backup_set). [default: 1]")
parser.add_argument("-bs", "--backup_set", default=DEFAULT_BACKUP_SET, help="A backup set name (determines retention correlation). [default: 'default]'")
@@ -45,7 +43,7 @@
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
-filters = bc.build_filter_params(args.filter)
+filter = bc.build_filter(args.filter, args.exclude)
log.info(args.resource_ids)
# execute business logic
@@ -57,7 +55,10 @@
for region in regions:
try:
ec2 = boto.connect_ec2(region=region, **credentials)
- reservations = ec2.get_all_instances(instance_ids=args.resource_ids, filters=filters)
+ reservations = ec2.get_all_instances(instance_ids=args.resource_ids, filters=filter['filters'])
+ if filter['excludes']:
+ exclusions = ec2.get_all_instances(filters=filter['excludes'])
+ reservations = bc.filter_list_by_attribute(reservations, exclusions, 'id')
instances = [instance for reservation in reservations for instance in reservation.instances]
print region.name + ": " + str(len(instances)) + " instances"
images = create_images(ec2, instances, backup_set, args.description, no_reboot=args.no_reboot)
@@ -30,9 +30,7 @@
# configure command line argument parsing
parser = argparse.ArgumentParser(description='Backup EBS volumes in all/some available EC2 regions',
- parents=[bc.build_region_parser(), bc.build_common_parser()])
-parser.add_argument("-f", "--filter", action="append", help="An EBS volume filter. [can be used multiple times]")
-parser.add_argument("-i", "--id", dest="resource_ids", action="append", help="An EBS volume id. [can be used multiple times]")
+ parents=[bc.build_region_parser(), bc.build_filter_parser('EBS volume'), bc.build_common_parser()])
parser.add_argument("-d", "--description", help="A description for the EBS snapshot [default: <provided>]")
parser.add_argument("-br", "--backup_retention", type=int, default=1, help="The number of backups to retain (correlated via backup_set). [default: 1]")
parser.add_argument("-bs", "--backup_set", default=DEFAULT_BACKUP_SET, help="A backup set name (determines retention correlation). [default: 'default']")
@@ -44,7 +42,7 @@
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
-filters = bc.build_filter_params(args.filter)
+filter = bc.build_filter(args.filter, args.exclude)
log.info(args.resource_ids)
# execute business logic
@@ -56,7 +54,10 @@
for region in regions:
try:
ec2 = boto.connect_ec2(region=region, **credentials)
- volumes = ec2.get_all_volumes(volume_ids=args.resource_ids, filters=filters)
+ volumes = ec2.get_all_volumes(volume_ids=args.resource_ids, filters=filter['filters'])
+ if filter['excludes']:
+ exclusions = ec2.get_all_volumes(filters=filter['excludes'])
+ volumes = bc.filter_list_by_attribute(volumes, exclusions, 'id')
print region.name + ": " + str(len(volumes)) + " volumes"
snapshots = create_snapshots(ec2, volumes, backup_set, args.description)
# TODO: add support for 'awaiting' the smapshot creation result, once available.
@@ -30,9 +30,7 @@
# configure command line argument parsing
parser = argparse.ArgumentParser(description='Create images of EC2 instances in all/some available EC2 regions',
- parents=[bc.build_region_parser(), bc.build_common_parser()])
-parser.add_argument("-f", "--filter", action="append", help="An EC2 instance filter. [can be used multiple times]")
-parser.add_argument("-i", "--id", dest="resource_ids", action="append", help="An EC2 instance id. [can be used multiple times]")
+ parents=[bc.build_region_parser(), bc.build_filter_parser('EC2 instance'), bc.build_common_parser()])
parser.add_argument("-d", "--description", help="A description for the EC2 image [default: <provided>]")
parser.add_argument("-nr", "--no_reboot", action="store_true", help="Prevent shut down of instance before creating the image. [default: False]")
parser.add_argument("-bs", "--backup_set", default=DEFAULT_BACKUP_SET, help="A backup set name (determines retention correlation). [default: 'default'")
@@ -43,7 +41,7 @@
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
-filters = bc.build_filter_params(args.filter)
+filter = bc.build_filter(args.filter, args.exclude)
log.info(args.resource_ids)
# execute business logic
@@ -55,7 +53,10 @@
for region in regions:
try:
ec2 = boto.connect_ec2(region=region, **credentials)
- reservations = ec2.get_all_instances(instance_ids=args.resource_ids, filters=filters)
+ reservations = ec2.get_all_instances(instance_ids=args.resource_ids, filters=filter['filters'])
+ if filter['excludes']:
+ exclusions = ec2.get_all_instances(filters=filter['excludes'])
+ reservations = bc.filter_list_by_attribute(reservations, exclusions, 'id')
instances = [instance for reservation in reservations for instance in reservation.instances]
print region.name + ": " + str(len(instances)) + " instances"
create_images(ec2, instances, backup_set, args.description, no_reboot=args.no_reboot)
@@ -30,9 +30,7 @@
# configure command line argument parsing
parser = argparse.ArgumentParser(description='Create snapshots of EBS volumes in all/some available EC2 regions',
- parents=[bc.build_region_parser(), bc.build_common_parser()])
-parser.add_argument("-f", "--filter", action="append", help="An EBS volume filter. [can be used multiple times]")
-parser.add_argument("-i", "--id", dest="resource_ids", action="append", help="An EBS volume id. [can be used multiple times]")
+ parents=[bc.build_region_parser(), bc.build_filter_parser('EBS volume'), bc.build_common_parser()])
parser.add_argument("-d", "--description", help="A description for the EBS snapshot [default: <provided>]")
parser.add_argument("-bs", "--backup_set", default=DEFAULT_BACKUP_SET, help="A backup set name (determines retention correlation). [default: 'default'")
args = parser.parse_args()
@@ -42,7 +40,7 @@
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
-filters = bc.build_filter_params(args.filter)
+filter = bc.build_filter(args.filter, args.exclude)
log.info(args.resource_ids)
# execute business logic
@@ -54,7 +52,10 @@
for region in regions:
try:
ec2 = boto.connect_ec2(region=region, **credentials)
- volumes = ec2.get_all_volumes(volume_ids=args.resource_ids, filters=filters)
+ volumes = ec2.get_all_volumes(volume_ids=args.resource_ids, filters=filter['filters'])
+ if filter['excludes']:
+ exclusions = ec2.get_all_volumes(filters=filter['excludes'])
+ volumes = bc.filter_list_by_attribute(volumes, exclusions, 'id')
print region.name + ": " + str(len(volumes)) + " volumes"
create_snapshots(ec2, volumes, backup_set, args.description)
except boto.exception.BotoServerError, e:
@@ -29,17 +29,15 @@
# configure command line argument parsing
parser = argparse.ArgumentParser(description='Delete EBS snapshots in all/some available EC2 regions',
- parents=[bc.build_region_parser(), bc.build_common_parser()])
-parser.add_argument("-f", "--filter", action="append", help="An EBS snapshot filter. [can be used multiple times]")
-parser.add_argument("-i", "--id", dest="resource_ids", action="append", help="An EBS snapshot id. [can be used multiple times]")
+ parents=[bc.build_region_parser(), bc.build_filter_parser('EBS snapshot'), bc.build_common_parser()])
args = parser.parse_args()
# process common command line arguments
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
-filters = bc.build_filter_params(args.filter)
+filter = bc.build_filter(args.filter, args.exclude)
log.info(args.resource_ids)
# execute business logic
@@ -48,12 +46,15 @@
for region in regions:
try:
ec2 = boto.connect_ec2(region=region, **credentials)
- resources = ec2.get_all_snapshots(snapshot_ids=args.resource_ids, owner='self', filters=filters)
- print region.name + ": " + str(len(resources)) + " EBS snapshots"
- for resource in resources:
+ snapshots = ec2.get_all_snapshots(snapshot_ids=args.resource_ids, owner='self', filters=filter['filters'])
+ if filter['excludes']:
+ exclusions = ec2.get_all_snapshots(owner='self', filters=filter['excludes'])
+ snapshots = bc.filter_list_by_attribute(snapshots, exclusions, 'id')
+ print region.name + ": " + str(len(snapshots)) + " EBS snapshots"
+ for snapshot in snapshots:
if args.verbose:
- print resource.id
+ print snapshot.id
else:
- ec2.delete_snapshot(resource.id)
+ ec2.delete_snapshot(snapshot.id)
except boto.exception.BotoServerError, e:
log.error(e.error_message)
@@ -29,17 +29,15 @@
# configure command line argument parsing
parser = argparse.ArgumentParser(description='Deregister EC2 images in all/some available EC2 regions',
- parents=[bc.build_region_parser(), bc.build_common_parser()])
-parser.add_argument("-f", "--filter", action="append", help="An EC2 image filter. [can be used multiple times]")
-parser.add_argument("-i", "--id", dest="resource_ids", action="append", help="An EC2 image id. [can be used multiple times]")
+ parents=[bc.build_region_parser(), bc.build_filter_parser('EC2 image'), bc.build_common_parser()])
args = parser.parse_args()
# process common command line arguments
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
-filters = bc.build_filter_params(args.filter)
+filter = bc.build_filter(args.filter, args.exclude)
log.info(args.resource_ids)
# execute business logic
@@ -48,12 +46,15 @@
for region in regions:
try:
ec2 = boto.connect_ec2(region=region, **credentials)
- resources = ec2.get_all_images(image_ids=args.resource_ids, owners=['self'], filters=filters)
- print region.name + ": " + str(len(resources)) + " EC2 images"
- for resource in resources:
+ images = ec2.get_all_images(image_ids=args.resource_ids, owners=['self'], filters=filter['filters'])
+ if filter['excludes']:
+ exclusions = ec2.get_all_images(owners=['self'], filters=filter['excludes'])
+ images = bc.filter_list_by_attribute(images, exclusions, 'id')
+ print region.name + ": " + str(len(images)) + " EC2 images"
+ for image in images:
if args.verbose:
- print resource.id
+ print image.id
else:
- ec2.deregister_image(resource.id, delete_snapshot=True)
+ ec2.deregister_image(image.id, delete_snapshot=True)
except boto.exception.BotoServerError, e:
log.error(e.error_message)
@@ -29,17 +29,15 @@
# configure command line argument parsing
parser = argparse.ArgumentParser(description='Describe EC2 images in all/some available EC2 regions',
- parents=[bc.build_region_parser(), bc.build_common_parser()])
-parser.add_argument("-f", "--filter", action="append", help="An EC2 image filter. [can be used multiple times]")
-parser.add_argument("-i", "--id", dest="resource_ids", action="append", help="An EC2 image id. [can be used multiple times]")
+ parents=[bc.build_region_parser(), bc.build_filter_parser('EC2 image'), bc.build_common_parser()])
args = parser.parse_args()
# process common command line arguments
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
-filters = bc.build_filter_params(args.filter)
+filter = bc.build_filter(args.filter, args.exclude)
log.info(args.resource_ids)
# execute business logic
@@ -48,12 +46,15 @@
for region in regions:
try:
ec2 = boto.connect_ec2(region=region, **credentials)
- resources = ec2.get_all_images(image_ids=args.resource_ids, owners=['self'], filters=filters)
- print region.name + ": " + str(len(resources)) + " images"
- for resource in resources:
+ images = ec2.get_all_images(image_ids=args.resource_ids, owners=['self'], filters=filter['filters'])
+ if filter['excludes']:
+ exclusions = ec2.get_all_images(owners=['self'], filters=filter['excludes'])
+ images = bc.filter_list_by_attribute(images, exclusions, 'id')
+ print region.name + ": " + str(len(images)) + " images"
+ for image in images:
if args.verbose:
- pprint(vars(resource))
+ pprint(vars(image))
else:
- print resource.id
+ print image.id
except boto.exception.BotoServerError, e:
log.error(e.error_message)
@@ -29,17 +29,15 @@
# configure command line argument parsing
parser = argparse.ArgumentParser(description='Describe EC2 instances in all/some available EC2 regions',
- parents=[bc.build_region_parser(), bc.build_common_parser()])
-parser.add_argument("-f", "--filter", action="append", help="An EC2 instance filter. [can be used multiple times]")
-parser.add_argument("-i", "--id", dest="resource_ids", action="append", help="An EBS instance id. [can be used multiple times]")
+ parents=[bc.build_region_parser(), bc.build_filter_parser('EC2 instance'), bc.build_common_parser()])
args = parser.parse_args()
# process common command line arguments
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
-filters = bc.build_filter_params(args.filter)
+filter = bc.build_filter(args.filter, args.exclude)
log.info(args.resource_ids)
# execute business logic
@@ -48,7 +46,10 @@
for region in regions:
try:
ec2 = boto.connect_ec2(region=region, **credentials)
- reservations = ec2.get_all_instances(instance_ids=args.resource_ids, filters=filters)
+ reservations = ec2.get_all_instances(instance_ids=args.resource_ids, filters=filter['filters'])
+ if filter['excludes']:
+ exclusions = ec2.get_all_instances(filters=filter['excludes'])
+ reservations = bc.filter_list_by_attribute(reservations, exclusions, 'id')
print region.name + ": " + str(len(reservations)) + " instances"
instances = [instance for reservation in reservations for instance in reservation.instances]
for instance in instances:
Oops, something went wrong.

0 comments on commit c0c1e32

Please sign in to comment.