mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-22 04:40:22 -07:00
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)
This commit is contained in:
parent
fd267989fb
commit
9c967dd054
2 changed files with 61 additions and 4 deletions
|
@ -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:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue