From 8c992ccbc7a60ad7d6e8ac4b6130ec01c8075303 Mon Sep 17 00:00:00 2001 From: Peter Schiffer Date: Wed, 14 Mar 2018 19:09:06 +0100 Subject: [PATCH] Allow filtering of instances by tags in GCE dynamic inventory (#35770) * Allow filtering of instances by tags in GCE dynamic inventory * Optimize instance tags configuration * Fix for PEP8 --- contrib/inventory/gce.ini | 6 +++++- contrib/inventory/gce.py | 25 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/contrib/inventory/gce.ini b/contrib/inventory/gce.ini index 24cf28ea39..741eb06a98 100644 --- a/contrib/inventory/gce.ini +++ b/contrib/inventory/gce.ini @@ -46,10 +46,14 @@ gce_service_account_pem_file_path = gce_project_id = gce_zone = -# Filter inventory based on on state. Leave undefined to return instances regardless of state. +# Filter inventory based on state. Leave undefined to return instances regardless of state. # example: Uncomment to only return inventory in the running or provisioning state #instance_states = RUNNING,PROVISIONING +# Filter inventory based on instance tags. Leave undefined to return instances regardless of tags. +# example: Uncomment to only return inventory with the http-server or https-server tag +#instance_tags = http-server,https-server + [inventory] # The 'inventory_ip_type' parameter specifies whether 'ansible_ssh_host' should diff --git a/contrib/inventory/gce.py b/contrib/inventory/gce.py index 9a0cef0b59..d0cc6b1553 100755 --- a/contrib/inventory/gce.py +++ b/contrib/inventory/gce.py @@ -222,6 +222,7 @@ class GceInventory(object): 'gce_project_id': '', 'gce_zone': '', 'libcloud_secrets': '', + 'instance_tags': '', 'inventory_ip_type': '', 'cache_path': '~/.ansible/tmp', 'cache_max_age': '300' @@ -247,6 +248,16 @@ class GceInventory(object): if states: self.instance_states = states.split(',') + # Set the instance_tags filter, env var overrides config from file + # and cli param overrides all + if self.args.instance_tags: + self.instance_tags = self.args.instance_tags + else: + self.instance_tags = os.environ.get( + 'GCE_INSTANCE_TAGS', config.get('gce', 'instance_tags')) + if self.instance_tags: + self.instance_tags = self.instance_tags.split(',') + # Caching cache_path = config.get('cache', 'cache_path') cache_max_age = config.getint('cache', 'cache_max_age') @@ -338,6 +349,8 @@ class GceInventory(object): help='List instances (default: True)') parser.add_argument('--host', action='store', help='Get all information about an instance') + parser.add_argument('--instance-tags', action='store', + help='Only include instances with this tags, separated by comma') parser.add_argument('--pretty', action='store_true', default=False, help='Pretty format (default: False)') parser.add_argument( @@ -430,6 +443,18 @@ class GceInventory(object): if self.instance_states and not node.extra['status'] in self.instance_states: continue + # This check filters on the desired instance tags defined in the + # config file with the instance_tags config option, env var GCE_INSTANCE_TAGS, + # or as the cli param --instance-tags. + # + # If the instance_tags list is _empty_ then _ALL_ instances are returned. + # + # If the instance_tags list is _populated_ then check the current + # instance tags against the instance_tags list. If the instance has + # at least one tag from the instance_tags list, it is returned. + if self.instance_tags and not set(self.instance_tags) & set(node.extra['tags']): + continue + name = node.name meta["hostvars"][name] = self.node_to_dict(node)