Skip to content

Commit

Permalink
Merge pull request #55 from sopel/issue-53-add-cn-regions
Browse files Browse the repository at this point in the history
Refactor region selection to facilitate regular expressions

[Closes #53]
  • Loading branch information
sopel committed Feb 26, 2014
2 parents 108d6c4 + b54bf75 commit 7e97a73
Show file tree
Hide file tree
Showing 39 changed files with 152 additions and 135 deletions.
38 changes: 12 additions & 26 deletions botocross/__init__.py
Expand Up @@ -21,6 +21,7 @@

import argparse
import logging
import re
botocross_log = logging.getLogger('botocross')

def configure_logger(logger, level):
Expand Down Expand Up @@ -78,9 +79,8 @@ def build_common_parser():

def build_region_parser():
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument("-r", "--region", help="A region substring selector (e.g. 'us-west')")
parser.add_argument("--include_govcloud", action='store_true', help="Include 'GovCloud' regions. [default: False]")
parser.add_argument("--only_govcloud", action='store_true', help="Return only 'GovCloud' region(s). [default: False]")
parser.add_argument("-r", "--region", default="(ap|eu|sa|us)-[enws]",
help="A regular expression based region substring selector [default '(ap|eu|sa|us)-[enws]']")
return parser

def build_filter_parser(resource_name, add_ids=True):
Expand All @@ -104,7 +104,7 @@ def build_backup_parser(resource_name, expire_only=False, backup_retention=None)
parser.add_argument("-br", "--backup_retention", type=int, default=backup_retention,
help="The number of backups to retain (correlated via backup_set). [default: {0}]".format(default_retention_help))
parser.add_argument("-bs", "--backup_set", default='default',
help="A backup set name (determines retention correlation). [default: 'default'")
help="A backup set name (determines retention correlation). [default: 'default']")
if not expire_only:
parser.add_argument("-bt", "--backup_timeout", default=None,
help="Maximum duration to await successful resource creation - an ISO 8601 duration, e.g. 'PT8H' (8 hours). [default: None, i.e. don't await]")
Expand All @@ -115,21 +115,15 @@ def build_backup_parser(resource_name, expire_only=False, backup_retention=None)
def parse_credentials(args):
return {'aws_access_key_id': args.aws_access_key_id, 'aws_secret_access_key': args.aws_secret_access_key}

def is_region_selected(region, name):
return True if region.name.find(name) != -1 else False

def is_govcloud(region):
return True if region.name.find('gov') != -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, include_govcloud=False, only_govcloud=False):
if not (include_govcloud or only_govcloud):
regions = filter(lambda x: not is_govcloud(x), regions)
if only_govcloud:
regions = filter(lambda x: is_govcloud(x), regions)
def is_region_selected(region, name):
pattern = re.compile(name, re.IGNORECASE)
return True if re.search(pattern, region.name) != None else False

def filter_regions(regions, region):
if region:
botocross_log.info("... (filtered by region '" + region + "')")
regions = filter(lambda x: is_region_selected(x, region), regions)
Expand All @@ -138,19 +132,11 @@ def filter_regions(regions, region, include_govcloud=False, only_govcloud=False)
# REVIEW: remove this S3 legacy induced partial duplication, if possible.
def is_region_selected_s3(region, name):
from botocross.s3 import RegionMap
return True if RegionMap[region].find(name) != -1 else False

# REVIEW: remove this S3 legacy induced partial duplication, if possible.
def is_govcloud_s3(region):
from botocross.s3 import RegionMap
return True if RegionMap[region].find('gov') != -1 else False
pattern = re.compile(name, re.IGNORECASE)
return True if re.search(pattern, RegionMap[region]) != None else False

# REVIEW: remove this S3 legacy induced partial duplication, if possible.
def filter_regions_s3(regions, region, include_govcloud=False, only_govcloud=False):
if not (include_govcloud or only_govcloud):
regions = filter(lambda x: not is_govcloud_s3(x), regions)
if only_govcloud:
regions = filter(lambda x: is_govcloud_s3(x), regions)
def filter_regions_s3(regions, region):
if region:
botocross_log.info("... (filtered by S3 region '" + region + "')")
regions = filter(lambda x: is_region_selected_s3(x, region), regions)
Expand Down
3 changes: 2 additions & 1 deletion botocross/s3/__init__.py
Expand Up @@ -31,7 +31,8 @@
'APNortheast': 'ap-northeast-1',
'APSoutheast': 'ap-southeast-1',
'APSoutheast2': 'ap-southeast-2',
'USGovWest': 'us-gov-west-1'}
'USGovWest': 'us-gov-west-1',
'CNNorth1': 'cn-north-1'}

# NOTE: S3 region handling differs in an unfortunate way (likely a legacy issue) and requires special treatment.
def class_iterator(Class):
Expand Down
2 changes: 1 addition & 1 deletion scripts/authorize-securitygroups.py
Expand Up @@ -65,7 +65,7 @@ def authorizeIp():
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)

# execute business logic
group_name = args.name if args.name else ""
Expand Down
2 changes: 1 addition & 1 deletion scripts/create-buckets.py
Expand Up @@ -39,7 +39,7 @@
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
locations = bc.filter_regions_s3(class_iterator(Location), args.region, args.include_govcloud, args.only_govcloud)
locations = bc.filter_regions_s3(class_iterator(Location), args.region)

# execute business logic
log.info("Creating S3 buckets named '" + args.bucket + "':")
Expand Down
2 changes: 1 addition & 1 deletion scripts/create-images.py
Expand Up @@ -40,7 +40,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
filter = bc.build_filter(args.filter, args.exclude)

# execute business logic
Expand Down
2 changes: 1 addition & 1 deletion scripts/create-securitygroups.py
Expand Up @@ -39,7 +39,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)

# execute business logic
log.info("Creating EC2 security groups named '" + args.group + "':")
Expand Down
2 changes: 1 addition & 1 deletion scripts/create-snapshots.py
Expand Up @@ -39,7 +39,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
filter = bc.build_filter(args.filter, args.exclude)

# execute business logic
Expand Down
2 changes: 1 addition & 1 deletion scripts/create-stacks.py
Expand Up @@ -45,7 +45,7 @@
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.cloudformation.regions(), args.region, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.cloudformation.regions(), args.region)

def processParameter(parameter, region_name, account_id):
replacement = parameter[1].replace('{REGION}', region_name).replace('{ACCOUNT}', account_id)
Expand Down
2 changes: 1 addition & 1 deletion scripts/create-topics.py
Expand Up @@ -38,7 +38,7 @@
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.sns.regions(), args.region, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.sns.regions(), args.region)

# execute business logic
log.info("Creating SNS topics named '" + args.topic + "':")
Expand Down
2 changes: 1 addition & 1 deletion scripts/delete-buckets.py
Expand Up @@ -40,7 +40,7 @@
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
locations = bc.filter_regions_s3(class_iterator(Location), args.region, args.include_govcloud, args.only_govcloud)
locations = bc.filter_regions_s3(class_iterator(Location), args.region)

# execute business logic
log.info("Deleting S3 buckets named '" + args.bucket + "':")
Expand Down
2 changes: 1 addition & 1 deletion scripts/delete-keypairs.py
Expand Up @@ -37,7 +37,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)

# execute business logic
log.info("Deleting key pair named '" + args.key_name + "':")
Expand Down
2 changes: 1 addition & 1 deletion scripts/delete-keys.py
Expand Up @@ -40,7 +40,7 @@
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
locations = bc.filter_regions_s3(class_iterator(Location), args.region, args.include_govcloud, args.only_govcloud)
locations = bc.filter_regions_s3(class_iterator(Location), args.region)

# execute business logic
log.info("Deleting from S3 buckets named '" + args.bucket + "':")
Expand Down
2 changes: 1 addition & 1 deletion scripts/delete-securitygroups.py
Expand Up @@ -40,7 +40,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)

# execute business logic
groupname = args.name if args.name else ""
Expand Down
2 changes: 1 addition & 1 deletion scripts/delete-snapshots.py
Expand Up @@ -36,7 +36,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
filter = bc.build_filter(args.filter, args.exclude)
log.info(args.resource_ids)

Expand Down
2 changes: 1 addition & 1 deletion scripts/delete-stacks.py
Expand Up @@ -37,7 +37,7 @@
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.cloudformation.regions(), args.region, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.cloudformation.regions(), args.region)

# execute business logic
log.info("Deleting CloudFormation stacks named '" + args.stack_name_or_id + "':")
Expand Down
2 changes: 1 addition & 1 deletion scripts/delete-topics.py
Expand Up @@ -37,7 +37,7 @@
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.sns.regions(), args.region, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.sns.regions(), args.region)

def createTopicArn(region_name, topic_name):
from botocross.iam.accountinfo import AccountInfo
Expand Down
2 changes: 1 addition & 1 deletion scripts/deregister-images.py
Expand Up @@ -36,7 +36,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
filter = bc.build_filter(args.filter, args.exclude)
log.info(args.resource_ids)

Expand Down
2 changes: 1 addition & 1 deletion scripts/describe-images.py
Expand Up @@ -36,7 +36,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
filter = bc.build_filter(args.filter, args.exclude)
log.info(args.resource_ids)

Expand Down
2 changes: 1 addition & 1 deletion scripts/describe-instances.py
Expand Up @@ -36,7 +36,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
filter = bc.build_filter(args.filter, args.exclude)
log.info(args.resource_ids)

Expand Down
2 changes: 1 addition & 1 deletion scripts/describe-regions.py
Expand Up @@ -35,7 +35,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)

# execute business logic
log.info("Describing regions for EC2:")
Expand Down
2 changes: 1 addition & 1 deletion scripts/describe-securitygroups.py
Expand Up @@ -38,7 +38,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
filter = bc.build_filter(args.filter, args.exclude)

# execute business logic
Expand Down
2 changes: 1 addition & 1 deletion scripts/describe-snapshots.py
Expand Up @@ -36,7 +36,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
filter = bc.build_filter(args.filter, args.exclude)
log.info(args.resource_ids)

Expand Down
2 changes: 1 addition & 1 deletion scripts/describe-stacks.py
Expand Up @@ -38,7 +38,7 @@
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.cloudformation.regions(), args.region, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.cloudformation.regions(), args.region)

# execute business logic
log.info("Describing CloudFormation stacks:")
Expand Down
2 changes: 1 addition & 1 deletion scripts/describe-tags.py
Expand Up @@ -37,7 +37,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
filters = bc.build_filter_params(args.filter)

# execute business logic
Expand Down
2 changes: 1 addition & 1 deletion scripts/describe-volumes.py
Expand Up @@ -36,7 +36,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
filter = bc.build_filter(args.filter, args.exclude)
log.info(args.resource_ids)

Expand Down
2 changes: 1 addition & 1 deletion scripts/expire-images.py
Expand Up @@ -38,7 +38,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
filter = bc.build_filter(args.filter, args.exclude)

# execute business logic
Expand Down
2 changes: 1 addition & 1 deletion scripts/expire-snapshots.py
Expand Up @@ -38,7 +38,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)
filter = bc.build_filter(args.filter, args.exclude)

# execute business logic
Expand Down
2 changes: 1 addition & 1 deletion scripts/import-keypairs.py
Expand Up @@ -38,7 +38,7 @@
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)

# execute business logic
log.info("Importing key pair named '" + args.key_name + "':")
Expand Down
2 changes: 1 addition & 1 deletion scripts/list-subscriptions.py
Expand Up @@ -37,7 +37,7 @@
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.sns.regions(), args.region, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.sns.regions(), args.region)

# execute business logic
log.info("Describing SNS topics:")
Expand Down
2 changes: 1 addition & 1 deletion scripts/list-topics.py
Expand Up @@ -35,7 +35,7 @@
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.sns.regions(), args.region, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.sns.regions(), args.region)

# execute business logic
log.info("Describing SNS topics:")
Expand Down
2 changes: 1 addition & 1 deletion scripts/read-buckets.py
Expand Up @@ -40,7 +40,7 @@
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
locations = bc.filter_regions_s3(class_iterator(Location), args.region, args.include_govcloud, args.only_govcloud)
locations = bc.filter_regions_s3(class_iterator(Location), args.region)

# execute business logic
log.info("Reading S3 buckets named '" + args.bucket + "':")
Expand Down
2 changes: 1 addition & 1 deletion scripts/revoke-securitygroups.py
Expand Up @@ -65,7 +65,7 @@ def revokeIp():
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, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.ec2.regions(), args.region)

# execute business logic
group_name = args.name if args.name else ""
Expand Down
2 changes: 1 addition & 1 deletion scripts/subscribe-topics.py
Expand Up @@ -39,7 +39,7 @@
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.sns.regions(), args.region, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.sns.regions(), args.region)

# execute business logic
log.info("Subscribing to SNS topics named '" + args.topic + ' with protocol ' + args.protocol + ' and endpoint ' + args.endpoint + "':")
Expand Down
2 changes: 1 addition & 1 deletion scripts/update-stacks.py
Expand Up @@ -45,7 +45,7 @@
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.cloudformation.regions(), args.region, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.cloudformation.regions(), args.region)

def processParameter(parameter, region_name, account_id):
replacement = parameter[1].replace('{REGION}', region_name).replace('{ACCOUNT}', account_id)
Expand Down
2 changes: 1 addition & 1 deletion scripts/upload-keys.py
Expand Up @@ -42,7 +42,7 @@
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
locations = bc.filter_regions_s3(class_iterator(Location), args.region, args.include_govcloud, args.only_govcloud)
locations = bc.filter_regions_s3(class_iterator(Location), args.region)

# execute business logic
log.info("Uploading to S3 buckets named '" + args.bucket + "':")
Expand Down
2 changes: 1 addition & 1 deletion scripts/validate-template.py
Expand Up @@ -38,7 +38,7 @@
log = logging.getLogger('botocross')
bc.configure_logging(log, args.log_level)
credentials = bc.parse_credentials(args)
regions = bc.filter_regions(boto.cloudformation.regions(), args.region, args.include_govcloud, args.only_govcloud)
regions = bc.filter_regions(boto.cloudformation.regions(), args.region)

def processArgument(argument, region_name):
return argument.replace('{REGION}', region_name)
Expand Down

0 comments on commit 7e97a73

Please sign in to comment.