Add configurable option to support nested inventory groups.

pull/8009/head
Chris Church 11 years ago
parent 14cf3c4d2a
commit 4036df11cf

@ -53,3 +53,6 @@ cache_path = ~/.ansible/tmp
# seconds, a new API call will be made, and the cache file will be updated. # seconds, a new API call will be made, and the cache file will be updated.
# To disable the cache, set this value to 0 # To disable the cache, set this value to 0
cache_max_age = 300 cache_max_age = 300
# Organize groups into a nested/hierarchy instead of a flat namespace.
nested_groups = False

@ -230,8 +230,12 @@ class Ec2Inventory(object):
self.cache_path_cache = cache_dir + "/ansible-ec2.cache" self.cache_path_cache = cache_dir + "/ansible-ec2.cache"
self.cache_path_index = cache_dir + "/ansible-ec2.index" self.cache_path_index = cache_dir + "/ansible-ec2.index"
self.cache_max_age = config.getint('ec2', 'cache_max_age') self.cache_max_age = config.getint('ec2', 'cache_max_age')
# Configure nested groups instead of flat namespace.
if config.has_option('ec2', 'nested_groups'):
self.nested_groups = config.getboolean('ec2', 'nested_groups')
else:
self.nested_groups = False
def parse_cli_args(self): def parse_cli_args(self):
''' Command line argument processing ''' ''' Command line argument processing '''
@ -321,7 +325,6 @@ class Ec2Inventory(object):
for instance in reservation.instances: for instance in reservation.instances:
return instance return instance
def add_instance(self, instance, region): def add_instance(self, instance, region):
''' Adds an instance to the inventory and index, as long as it is ''' Adds an instance to the inventory and index, as long as it is
addressable ''' addressable '''
@ -345,25 +348,40 @@ class Ec2Inventory(object):
# Inventory: Group by instance ID (always a group of 1) # Inventory: Group by instance ID (always a group of 1)
self.inventory[instance.id] = [dest] self.inventory[instance.id] = [dest]
if self.nested_groups:
self.push_group(self.inventory, 'instances', instance.id)
# Inventory: Group by region # Inventory: Group by region
self.push(self.inventory, region, dest) if self.nested_groups:
self.push_group(self.inventory, 'regions', region)
else:
self.push(self.inventory, region, dest)
# Inventory: Group by availability zone # Inventory: Group by availability zone
self.push(self.inventory, instance.placement, dest) self.push(self.inventory, instance.placement, dest)
if self.nested_groups:
self.push_group(self.inventory, region, instance.placement)
# Inventory: Group by instance type # Inventory: Group by instance type
self.push(self.inventory, self.to_safe('type_' + instance.instance_type), dest) type_name = self.to_safe('type_' + instance.instance_type)
self.push(self.inventory, type_name, dest)
if self.nested_groups:
self.push_group(self.inventory, 'types', type_name)
# Inventory: Group by key pair # Inventory: Group by key pair
if instance.key_name: if instance.key_name:
self.push(self.inventory, self.to_safe('key_' + instance.key_name), dest) key_name = self.to_safe('key_' + instance.key_name)
self.push(self.inventory, key_name, dest)
if self.nested_groups:
self.push_group(self.inventory, 'keys', key_name)
# Inventory: Group by security group # Inventory: Group by security group
try: try:
for group in instance.groups: for group in instance.groups:
key = self.to_safe("security_group_" + group.name) key = self.to_safe("security_group_" + group.name)
self.push(self.inventory, key, dest) self.push(self.inventory, key, dest)
if self.nested_groups:
self.push_group(self.inventory, 'security_groups', key)
except AttributeError: except AttributeError:
print 'Package boto seems a bit older.' print 'Package boto seems a bit older.'
print 'Please upgrade boto >= 2.3.0.' print 'Please upgrade boto >= 2.3.0.'
@ -373,12 +391,17 @@ class Ec2Inventory(object):
for k, v in instance.tags.iteritems(): for k, v in instance.tags.iteritems():
key = self.to_safe("tag_" + k + "=" + v) key = self.to_safe("tag_" + k + "=" + v)
self.push(self.inventory, key, dest) self.push(self.inventory, key, dest)
if self.nested_groups:
self.push_group(self.inventory, 'tags', self.to_safe("tag_" + k))
self.push_group(self.inventory, self.to_safe("tag_" + k), key)
# Inventory: Group by Route53 domain names if enabled # Inventory: Group by Route53 domain names if enabled
if self.route53_enabled: if self.route53_enabled:
route53_names = self.get_instance_route53_names(instance) route53_names = self.get_instance_route53_names(instance)
for name in route53_names: for name in route53_names:
self.push(self.inventory, name, dest) self.push(self.inventory, name, dest)
if self.nested_groups:
self.push_group(self.inventory, 'route53', name)
# Global Tag: tag all EC2 instances # Global Tag: tag all EC2 instances
self.push(self.inventory, 'ec2', dest) self.push(self.inventory, 'ec2', dest)
@ -410,21 +433,34 @@ class Ec2Inventory(object):
# Inventory: Group by instance ID (always a group of 1) # Inventory: Group by instance ID (always a group of 1)
self.inventory[instance.id] = [dest] self.inventory[instance.id] = [dest]
if self.nested_groups:
self.push_group(self.inventory, 'instances', instance.id)
# Inventory: Group by region # Inventory: Group by region
self.push(self.inventory, region, dest) if self.nested_groups:
self.push_group(self.inventory, 'regions', region)
else:
self.push(self.inventory, region, dest)
# Inventory: Group by availability zone # Inventory: Group by availability zone
self.push(self.inventory, instance.availability_zone, dest) self.push(self.inventory, instance.availability_zone, dest)
if self.nested_groups:
self.push_group(self.inventory, region, instance.availability_zone)
# Inventory: Group by instance type # Inventory: Group by instance type
self.push(self.inventory, self.to_safe('type_' + instance.instance_class), dest) type_name = self.to_safe('type_' + instance.instance_class)
self.push(self.inventory, type_name, dest)
if self.nested_groups:
self.push_group(self.inventory, 'types', type_name)
# Inventory: Group by security group # Inventory: Group by security group
try: try:
if instance.security_group: if instance.security_group:
key = self.to_safe("security_group_" + instance.security_group.name) key = self.to_safe("security_group_" + instance.security_group.name)
self.push(self.inventory, key, dest) self.push(self.inventory, key, dest)
if self.nested_groups:
self.push_group(self.inventory, 'security_groups', key)
except AttributeError: except AttributeError:
print 'Package boto seems a bit older.' print 'Package boto seems a bit older.'
print 'Please upgrade boto >= 2.3.0.' print 'Please upgrade boto >= 2.3.0.'
@ -432,13 +468,19 @@ class Ec2Inventory(object):
# Inventory: Group by engine # Inventory: Group by engine
self.push(self.inventory, self.to_safe("rds_" + instance.engine), dest) self.push(self.inventory, self.to_safe("rds_" + instance.engine), dest)
if self.nested_groups:
self.push_group(self.inventory, 'rds_engines', self.to_safe("rds_" + instance.engine))
# Inventory: Group by parameter group # Inventory: Group by parameter group
self.push(self.inventory, self.to_safe("rds_parameter_group_" + instance.parameter_group.name), dest) self.push(self.inventory, self.to_safe("rds_parameter_group_" + instance.parameter_group.name), dest)
if self.nested_groups:
self.push_group(self.inventory, 'rds_parameter_groups', self.to_safe("rds_parameter_group_" + instance.parameter_group.name))
# Global Tag: all RDS instances # Global Tag: all RDS instances
self.push(self.inventory, 'rds', dest) self.push(self.inventory, 'rds', dest)
self.inventory["_meta"]["hostvars"][dest] = self.get_host_info_dict_from_instance(instance)
def get_route53_records(self): def get_route53_records(self):
''' Get and store the map of resource records to domain names that ''' Get and store the map of resource records to domain names that
@ -553,14 +595,23 @@ class Ec2Inventory(object):
return self.json_format_dict(self.get_host_info_dict_from_instance(instance), True) return self.json_format_dict(self.get_host_info_dict_from_instance(instance), True)
def push(self, my_dict, key, element): def push(self, my_dict, key, element):
''' Pushed an element onto an array that may not have been defined in ''' Push an element onto an array that may not have been defined in
the dict ''' the dict '''
group_info = my_dict.setdefault(key, [])
if key in my_dict: if isinstance(group_info, dict):
my_dict[key].append(element); host_list = group_info.setdefault('hosts', [])
host_list.append(element)
else: else:
my_dict[key] = [element] group_info.append(element)
def push_group(self, my_dict, key, element):
''' Push a group as a child of another group. '''
parent_group = my_dict.setdefault(key, {})
if not isinstance(parent_group, dict):
parent_group = my_dict[key] = {'hosts': parent_group}
child_groups = parent_group.setdefault('children', [])
if element not in child_groups:
child_groups.append(element)
def get_inventory_from_cache(self): def get_inventory_from_cache(self):
''' Reads the inventory from the cache file and returns it as a JSON ''' Reads the inventory from the cache file and returns it as a JSON

Loading…
Cancel
Save