Merge pull request #12548 from amenonsen/pr-9130-rebase
#9130 rebase: EC2 Inventory Boto Profile Support
This commit is contained in:
commit
4225c0677d
3 changed files with 63 additions and 3 deletions
|
@ -139,3 +139,7 @@ group_by_elasticache_replication_group = True
|
||||||
# tag Name value matches webservers1*
|
# tag Name value matches webservers1*
|
||||||
# (ex. webservers15, webservers1a, webservers123 etc)
|
# (ex. webservers15, webservers1a, webservers123 etc)
|
||||||
# instance_filters = tag:Name=webservers1*
|
# instance_filters = tag:Name=webservers1*
|
||||||
|
|
||||||
|
# A boto configuration profile may be used to separate out credentials
|
||||||
|
# see http://boto.readthedocs.org/en/latest/boto_config_tut.html
|
||||||
|
# boto_profile = some-boto-profile-name
|
||||||
|
|
|
@ -22,6 +22,12 @@ you need to define:
|
||||||
|
|
||||||
export EC2_URL=http://hostname_of_your_cc:port/services/Eucalyptus
|
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 --boto-profile command line argument (e.g. ec2.py --boto-profile prod) or using
|
||||||
|
the AWS_PROFILE variable:
|
||||||
|
|
||||||
|
AWS_PROFILE=prod ansible-playbook -i ec2.py myplaybook.yml
|
||||||
|
|
||||||
For more details, see: http://docs.pythonboto.org/en/latest/boto_config_tut.html
|
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:
|
When run against a specific host, this script returns the following variables:
|
||||||
|
@ -148,9 +154,18 @@ class Ec2Inventory(object):
|
||||||
# Index of hostname (address) to instance ID
|
# Index of hostname (address) to instance ID
|
||||||
self.index = {}
|
self.index = {}
|
||||||
|
|
||||||
|
# Boto profile to use (if any)
|
||||||
|
self.boto_profile = None
|
||||||
|
|
||||||
# Read settings and parse CLI arguments
|
# Read settings and parse CLI arguments
|
||||||
self.read_settings()
|
|
||||||
self.parse_cli_args()
|
self.parse_cli_args()
|
||||||
|
self.read_settings()
|
||||||
|
|
||||||
|
# Make sure that profile_name is not passed at all if not set
|
||||||
|
# as pre 2.24 boto will fall over otherwise
|
||||||
|
if self.boto_profile:
|
||||||
|
if not hasattr(boto.ec2.EC2Connection, 'profile_name'):
|
||||||
|
self.fail_with_error("boto version must be >= 2.24 to use profile")
|
||||||
|
|
||||||
# Cache
|
# Cache
|
||||||
if self.args.refresh_cache:
|
if self.args.refresh_cache:
|
||||||
|
@ -290,8 +305,15 @@ class Ec2Inventory(object):
|
||||||
else:
|
else:
|
||||||
self.all_elasticache_nodes = False
|
self.all_elasticache_nodes = False
|
||||||
|
|
||||||
|
# boto configuration profile (prefer CLI argument)
|
||||||
|
self.boto_profile = self.args.boto_profile
|
||||||
|
if config.has_option('ec2', 'boto_profile') and not self.boto_profile:
|
||||||
|
self.boto_profile = config.get('ec2', 'boto_profile')
|
||||||
|
|
||||||
# Cache related
|
# Cache related
|
||||||
cache_dir = os.path.expanduser(config.get('ec2', 'cache_path'))
|
cache_dir = os.path.expanduser(config.get('ec2', 'cache_path'))
|
||||||
|
if self.boto_profile:
|
||||||
|
cache_dir = os.path.join(cache_dir, 'profile_' + self.boto_profile)
|
||||||
if not os.path.exists(cache_dir):
|
if not os.path.exists(cache_dir):
|
||||||
os.makedirs(cache_dir)
|
os.makedirs(cache_dir)
|
||||||
|
|
||||||
|
@ -373,6 +395,8 @@ class Ec2Inventory(object):
|
||||||
help='Get all the variables about a specific instance')
|
help='Get all the variables about a specific instance')
|
||||||
parser.add_argument('--refresh-cache', action='store_true', default=False,
|
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)')
|
help='Force refresh of cache by making API requests to EC2 (default: False - use cache files)')
|
||||||
|
parser.add_argument('--boto-profile', action='store',
|
||||||
|
help='Use boto profile for connections to EC2')
|
||||||
self.args = parser.parse_args()
|
self.args = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
@ -399,7 +423,25 @@ class Ec2Inventory(object):
|
||||||
conn = boto.connect_euca(host=self.eucalyptus_host)
|
conn = boto.connect_euca(host=self.eucalyptus_host)
|
||||||
conn.APIVersion = '2010-08-31'
|
conn.APIVersion = '2010-08-31'
|
||||||
else:
|
else:
|
||||||
conn = ec2.connect_to_region(region)
|
conn = self.connect_to_aws(ec2, region)
|
||||||
|
return conn
|
||||||
|
|
||||||
|
def boto_fix_security_token_in_profile(self, connect_args):
|
||||||
|
''' monkey patch for boto issue boto/boto#2100 '''
|
||||||
|
profile = 'profile ' + self.boto_profile
|
||||||
|
if boto.config.has_option(profile, 'aws_security_token'):
|
||||||
|
connect_args['security_token'] = boto.config.get(profile, 'aws_security_token')
|
||||||
|
return connect_args
|
||||||
|
|
||||||
|
def connect_to_aws(self, module, region):
|
||||||
|
connect_args = {}
|
||||||
|
|
||||||
|
# only pass the profile name if it's set (as it is not supported by older boto versions)
|
||||||
|
if self.boto_profile:
|
||||||
|
connect_args['profile_name'] = self.boto_profile
|
||||||
|
self.boto_fix_security_token_in_profile(connect_args)
|
||||||
|
|
||||||
|
conn = module.connect_to_region(region, **connect_args)
|
||||||
# connect_to_region will fail "silently" by returning None if the region name is wrong or not supported
|
# connect_to_region will fail "silently" by returning None if the region name is wrong or not supported
|
||||||
if conn is None:
|
if conn is None:
|
||||||
self.fail_with_error("region name: %s likely not supported, or AWS is down. connection to region failed." % region)
|
self.fail_with_error("region name: %s likely not supported, or AWS is down. connection to region failed." % region)
|
||||||
|
@ -435,7 +477,7 @@ class Ec2Inventory(object):
|
||||||
region '''
|
region '''
|
||||||
|
|
||||||
try:
|
try:
|
||||||
conn = rds.connect_to_region(region)
|
conn = self.connect_to_aws(rds, region)
|
||||||
if conn:
|
if conn:
|
||||||
instances = conn.get_all_dbinstances()
|
instances = conn.get_all_dbinstances()
|
||||||
for instance in instances:
|
for instance in instances:
|
||||||
|
|
|
@ -101,6 +101,20 @@ You can test the script by itself to make sure your config is correct::
|
||||||
|
|
||||||
After a few moments, you should see your entire EC2 inventory across all regions in JSON.
|
After a few moments, you should see your entire EC2 inventory across all regions in JSON.
|
||||||
|
|
||||||
|
If you use boto profiles to manage multiple AWS accounts, you can pass ``--profile PROFILE`` name to the ``ec2.py`` script. An example profile might be::
|
||||||
|
|
||||||
|
[profile dev]
|
||||||
|
aws_access_key_id = <dev access key>
|
||||||
|
aws_secret_access_key = <dev secret key>
|
||||||
|
|
||||||
|
[profile prod]
|
||||||
|
aws_access_key_id = <prod access key>
|
||||||
|
aws_secret_access_key = <prod secret key>
|
||||||
|
|
||||||
|
You can then run ``ec2.py --profile prod`` to get the inventory for the prod account, or run playbooks with: ``ansible-playbook -i 'ec2.py --profile prod' myplaybook.yml``.
|
||||||
|
|
||||||
|
Alternatively, use the ``AWS_PROFILE`` variable - e.g. ``AWS_PROFILE=prod ansible-playbook -i ec2.py myplaybook.yml``
|
||||||
|
|
||||||
Since each region requires its own API call, if you are only using a small set of regions, feel free to edit ``ec2.ini`` and list only the regions you are interested in. There are other config options in ``ec2.ini`` including cache control, and destination variables.
|
Since each region requires its own API call, if you are only using a small set of regions, feel free to edit ``ec2.ini`` and list only the regions you are interested in. There are other config options in ``ec2.ini`` including cache control, and destination variables.
|
||||||
|
|
||||||
At their heart, inventory files are simply a mapping from some name to a destination address. The default ``ec2.ini`` settings are configured for running Ansible from outside EC2 (from your laptop for example) -- and this is not the most efficient way to manage EC2.
|
At their heart, inventory files are simply a mapping from some name to a destination address. The default ``ec2.ini`` settings are configured for running Ansible from outside EC2 (from your laptop for example) -- and this is not the most efficient way to manage EC2.
|
||||||
|
|
Loading…
Reference in a new issue