diff options
author | willthames <will@thames.id.au> | 2014-02-13 03:52:38 +0100 |
---|---|---|
committer | Abhijit Menon-Sen <ams@2ndQuadrant.com> | 2015-09-28 18:05:46 +0200 |
commit | 9c967dd05492ab837914fd588f7d9cbe22654ec4 (patch) | |
tree | 8502ec1d18dac73d506077ca7505b3bb220ae419 /contrib | |
parent | Fix docs build (diff) | |
download | ansible-9c967dd05492ab837914fd588f7d9cbe22654ec4.tar.xz ansible-9c967dd05492ab837914fd588f7d9cbe22654ec4.zip |
Allow ec2 inventory to use a boto profile
This allows the EC2 inventory plugin to be used with
the same configuration against different EC2 accounts
Profile can be passed using --profile variable or using
EC2_PROFILE environment variable e.g.
```
EC2_PROFILE=prod ansible-playbook -i ec2.py playbook.yml
```
Added documentation on profiles to EC2 dynamic inventory doc
Only tries to use profiles if --profile argument is given
or EC2_PROFILE is set to maintain compatibility will boto < 2.24.
Works around a minor bug in boto where if you try and use
a security token with a profile it fails (boto/boto#2100)
Diffstat (limited to 'contrib')
-rwxr-xr-x | contrib/inventory/ec2.py | 51 |
1 files changed, 47 insertions, 4 deletions
diff --git a/contrib/inventory/ec2.py b/contrib/inventory/ec2.py index 7ed9b83e77..6af748f918 100755 --- a/contrib/inventory/ec2.py +++ b/contrib/inventory/ec2.py @@ -22,6 +22,12 @@ you need to define: export EC2_URL=http://hostname_of_your_cc:port/services/Eucalyptus +If you're using boto profiles (requires boto>=2.24.0) you can choose a profile +using the --profile command line argument (e.g. ec2.py --profile prod) or using +the EC2_PROFILE variable: + + EC2_PROFILE=prod ansible-playbook -i ec2.py myplaybook.yml + For more details, see: http://docs.pythonboto.org/en/latest/boto_config_tut.html When run against a specific host, this script returns the following variables: @@ -148,9 +154,20 @@ class Ec2Inventory(object): # Index of hostname (address) to instance ID self.index = {} - # Read settings and parse CLI arguments - self.read_settings() + # Parse CLI arguments and read settings self.parse_cli_args() + self.read_settings() + + # boto profile to use (if any) + # Make sure that profile_name is not passed at all if not set + # as pre 2.24 boto will fall over otherwise + if self.args.profile: + if not hasattr(boto.ec2.EC2Connection, 'profile_name'): + sys.stderr.write("boto version must be >= 2.24 to use profile\n") + sys.exit(1) + self.profile = dict(profile_name=self.args.profile) + else: + self.profile = dict() # Cache if self.args.refresh_cache: @@ -292,6 +309,8 @@ class Ec2Inventory(object): # Cache related cache_dir = os.path.expanduser(config.get('ec2', 'cache_path')) + if self.args.profile: + cache_dir = os.path.join(cache_dir, 'profile_' + self.args.profile) if not os.path.exists(cache_dir): os.makedirs(cache_dir) @@ -373,6 +392,8 @@ class Ec2Inventory(object): help='Get all the variables about a specific instance') parser.add_argument('--refresh-cache', action='store_true', default=False, help='Force refresh of cache by making API requests to EC2 (default: False - use cache files)') + parser.add_argument('--profile', action='store', default=os.environ.get('EC2_PROFILE'), + help='Use boto profile for connections to EC2') self.args = parser.parse_args() @@ -405,6 +426,21 @@ class Ec2Inventory(object): self.fail_with_error("region name: %s likely not supported, or AWS is down. connection to region failed." % region) return conn + def boto_fix_security_token_in_profile(self, conn): + ''' monkey patch for boto issue boto/boto#2100 ''' + profile = 'profile ' + self.profile.get('profile_name') + if boto.config.has_option(profile, 'aws_security_token'): + conn.provider.set_security_token(boto.config.get(profile, 'aws_security_token')) + return conn + + + def connect_to_aws(self, module, region): + conn = module.connect_to_region(region, **self.profile) + if 'profile_name' in self.profile: + conn = self.boto_fix_security_token_in_profile(conn) + return conn + + def get_instances_by_region(self, region): ''' Makes an AWS EC2 API call to the list of instances in a particular region ''' @@ -416,8 +452,14 @@ class Ec2Inventory(object): for filter_key, filter_values in self.ec2_instance_filters.items(): reservations.extend(conn.get_all_instances(filters = { filter_key : filter_values })) else: - reservations = conn.get_all_instances() + conn = self.connect_to_aws(ec2, region) + + # connect_to_region will fail "silently" by returning None if the region name is wrong or not supported + if conn is None: + print("region name: %s likely not supported, or AWS is down. connection to region failed." % region) + sys.exit(1) + reservations = conn.get_all_instances() for reservation in reservations: for instance in reservation.instances: self.add_instance(instance, region) @@ -430,12 +472,13 @@ class Ec2Inventory(object): error = "Error connecting to %s backend.\n%s" % (backend, e.message) self.fail_with_error(error, 'getting EC2 instances') + def get_rds_instances_by_region(self, region): ''' Makes an AWS API call to the list of RDS instances in a particular region ''' try: - conn = rds.connect_to_region(region) + conn = self.connect_to_aws(rds, region) if conn: instances = conn.get_all_dbinstances() for instance in instances: |