summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Coca <bcoca@users.noreply.github.com>2017-08-21 16:06:15 -0400
committerGitHub <noreply@github.com>2017-08-21 16:06:15 -0400
commita897193bcee28e3698362e8b47cebc53f585dd61 (patch)
treed53343ba62fa1db4beb5c9a4a6c33829aaaa1026
parentec11cd2696f7b698d69f266f89369d2f0de67c8b (diff)
downloadansible-a897193bcee28e3698362e8b47cebc53f585dd61.tar.gz
Moar constructive (#28254)
* made composite vars and groups generic now you can do both in every plugin that chooses to suport it renamed constructed_groups as it now also constructs vars ... to constructed moved most of constructed_groups logic into base class to easily share * documented inventory_hostname * typo fix
-rw-r--r--CHANGELOG.md2
-rw-r--r--examples/ansible.cfg2
-rw-r--r--lib/ansible/plugins/inventory/__init__.py25
-rw-r--r--lib/ansible/plugins/inventory/constructed.py (renamed from lib/ansible/plugins/inventory/constructed_groups.py)47
-rw-r--r--[-rwxr-xr-x]lib/ansible/plugins/inventory/virtualbox.py12
5 files changed, 61 insertions, 27 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f084bf2fc4..27f1d31bd5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -134,7 +134,7 @@ Ansible Changes By Release
#### New Inventory Plugins:
- advanced_host_list
-- constructed_groups
+- constructed
- host_list
- ini
- script
diff --git a/examples/ansible.cfg b/examples/ansible.cfg
index d6892b2bac..7abae073f2 100644
--- a/examples/ansible.cfg
+++ b/examples/ansible.cfg
@@ -73,7 +73,7 @@
#callback_whitelist = timer, mail
# enable inventory plugins, default: 'host_list', 'script', 'yaml', 'ini'
-#inventory_enabled = host_list, aws, openstack, docker
+#inventory_enabled = host_list, virtualbox, yaml, constructed
# Determine whether includes in tasks and handlers are "static" by
# default. As of 2.0, includes are dynamic by default. Setting these
diff --git a/lib/ansible/plugins/inventory/__init__.py b/lib/ansible/plugins/inventory/__init__.py
index ddad67861f..658d38168f 100644
--- a/lib/ansible/plugins/inventory/__init__.py
+++ b/lib/ansible/plugins/inventory/__init__.py
@@ -50,6 +50,7 @@ class BaseInventoryPlugin(object):
self.loader = loader
self.inventory = inventory
+ self.templar = Templar(loader=loader)
def verify_file(self, path):
''' Verify if file is usable by this plugin, base does minimal accessability check '''
@@ -81,9 +82,31 @@ class BaseInventoryPlugin(object):
def _compose(self, template, variables):
''' helper method for pluigns to compose variables for Ansible based on jinja2 expression and inventory vars'''
- t = Templar(loader=self.loader, variables=variables)
+ t = self.templar
+ t.set_available_variables(variables)
return t.do_template('%s%s%s' % (t.environment.variable_start_string, template, t.environment.variable_end_string), disable_lookups=True)
+ def _set_composite_vars(self, compose, variables, host):
+ ''' loops over compose entries to create vars for hosts '''
+ if compose and isinstance(compose, dict):
+ for varname in compose:
+ composite = self._compose(compose[varname], variables)
+ self.inventory.set_variable(host, varname, composite)
+
+ def _add_host_to_composed_groups(self, groups, variables, host):
+ ''' helper to create complex groups for plugins based on jinaj2 conditionals, hosts that meet the conditional are added to group'''
+ # process each 'group entry'
+ if groups and isinstance(groups, dict):
+ self.templar.set_available_variables(variables)
+ for group_name in groups:
+ conditional = "{%% if %s %%} True {%% else %%} False {%% endif %%}" % groups[group_name]
+ result = self.templar.template(conditional)
+ if result and bool(result):
+ # ensure group exists
+ self.inventory.add_group(group_name)
+ # add host to group
+ self.inventory.add_child(group_name, host)
+
class BaseFileInventoryPlugin(BaseInventoryPlugin):
""" Parses a File based Inventory Source"""
diff --git a/lib/ansible/plugins/inventory/constructed_groups.py b/lib/ansible/plugins/inventory/constructed.py
index 302b289bdb..52a6769577 100644
--- a/lib/ansible/plugins/inventory/constructed_groups.py
+++ b/lib/ansible/plugins/inventory/constructed.py
@@ -17,16 +17,28 @@
#############################################
'''
DOCUMENTATION:
- name: constructed_groups
+ name: constructed
plugin_type: inventory
version_added: "2.4"
- short_description: Uses Jinja2 expressions to construct groups.
+ short_description: Uses Jinja2 to construct vars and groups based on existing inventory.
description:
- - Uses a YAML configuration file to identify group and the Jinja2 expressions that qualify a host for membership.
- - Only variables already in inventory are available for expressions (no facts).
+ - Uses a YAML configuration file to define var expresisions and group conditionals
+ - The Jinja2 conditionals that qualify a host for membership.
+ - The JInja2 exprpessions are calculated and assigned to the variables
+ - Only variables already available from previous inventories can be used for templating.
- Failed expressions will be ignored (assumes vars were missing).
+ compose:
+ description: create vars from jinja2 expressions
+ type: dictionary
+ default: {}
+ groups:
+ description: add hosts to group based on Jinja2 conditionals
+ type: dictionary
+ default: {}
EXAMPLES: | # inventory.config file in YAML format
- plugin: constructed_groups
+ plugin: comstructed
+ compose:
+ var_sum: var1 + var2
groups:
# simple name matching
webservers: inventory_hostname.startswith('web')
@@ -48,15 +60,14 @@ import os
from ansible.errors import AnsibleParserError
from ansible.plugins.inventory import BaseInventoryPlugin
-from ansible.template import Templar
from ansible.module_utils._text import to_native
from ansible.utils.vars import combine_vars
class InventoryModule(BaseInventoryPlugin):
- """ constructs groups using Jinaj2 template expressions """
+ """ constructs groups and vars using Jinaj2 template expressions """
- NAME = 'constructed_groups'
+ NAME = 'constructed'
def __init__(self):
@@ -87,8 +98,6 @@ class InventoryModule(BaseInventoryPlugin):
raise AnsibleParserError("%s is empty or not a constructed groups config file" % (to_native(path)))
try:
- templar = Templar(loader=loader)
-
# Go over hosts (less var copies)
for host in inventory.hosts:
@@ -96,16 +105,12 @@ class InventoryModule(BaseInventoryPlugin):
hostvars = inventory.hosts[host].get_vars()
if host in inventory.cache: # adds facts if cache is active
hostvars = combine_vars(hostvars, inventory.cache[host])
- templar.set_available_variables(hostvars)
-
- # process each 'group entry'
- for group_name in data.get('groups', {}):
- conditional = u"{%% if %s %%} True {%% else %%} False {%% endif %%}" % data['groups'][group_name]
- result = templar.template(conditional)
- if result and bool(result):
- # ensure group exists
- inventory.add_group(group_name)
- # add host to group
- inventory.add_child(group_name, host)
+
+ # create composite vars
+ self._set_composite_vars(data.get('compose'), hostvars, host)
+
+ # constructed groups based on conditionals
+ self._add_host_to_composed_groups(data.get('groups'), hostvars, host)
+
except Exception as e:
raise AnsibleParserError("failed to parse %s: %s " % (to_native(path), to_native(e)))
diff --git a/lib/ansible/plugins/inventory/virtualbox.py b/lib/ansible/plugins/inventory/virtualbox.py
index 0dab7c4253..98013e7d22 100755..100644
--- a/lib/ansible/plugins/inventory/virtualbox.py
+++ b/lib/ansible/plugins/inventory/virtualbox.py
@@ -24,6 +24,7 @@ DOCUMENTATION:
description:
- Get inventory hosts from the local virtualbox installation.
- Uses a <name>.vbox.yaml (or .vbox.yml) YAML configuration file.
+ - The inventory_hostname is always the 'Name' of the virtualbox instance.
options:
running_only:
description: toggles showing all vms vs only those currently running
@@ -42,6 +43,10 @@ DOCUMENTATION:
description: create vars from jinja2 expressions, these are created AFTER the query block
type: dictionary
default: {}
+ groups:
+ description: add hosts to group based on Jinja2 conditionals, these also run after query block
+ type: dictionary
+ default: {}
EXAMPLES:
# file must be named vbox.yaml or vbox.yml
simple_config_file:
@@ -94,14 +99,15 @@ class InventoryModule(BaseInventoryPlugin):
hostvars[host][varname] = self._query_vbox_data(host, data['query'][varname])
# create composite vars
- if data.get('compose') and isinstance(data['compose'], dict):
- for varname in data['compose']:
- hostvars[host][varname] = self._compose(data['compose'][varname], hostvars[host])
+ self._set_composite_vars(data.get('compose'), hostvars, host)
# actually update inventory
for key in hostvars[host]:
self.inventory.set_variable(host, key, hostvars[host][key])
+ # constructed groups based on conditionals
+ self._add_host_to_composed_groups(data.get('groups'), hostvars, host)
+
def _populate_from_source(self, source_data, config_data):
hostvars = {}
prevkey = pref_k = ''