From f8aa30765963cbcfdce67c86079bbf1261100a66 Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Wed, 19 Aug 2020 12:56:28 -0400 Subject: [PATCH] add extra vars to inventory plugins (#70970) * add extra vars to inventory plugins * disable by default for backwards compat * also allow extra vars for options --- .../fragments/give_compose_extra_vars.yml | 5 +++++ lib/ansible/cli/inventory.py | 1 + .../plugins/doc_fragments/constructed.py | 10 ++++++++++ lib/ansible/plugins/inventory/__init__.py | 18 +++++++++++++++--- .../inventory/extra_vars_constructed.yml | 5 +++++ test/integration/targets/inventory/runme.sh | 3 +++ 6 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 changelogs/fragments/give_compose_extra_vars.yml create mode 100644 test/integration/targets/inventory/extra_vars_constructed.yml diff --git a/changelogs/fragments/give_compose_extra_vars.yml b/changelogs/fragments/give_compose_extra_vars.yml new file mode 100644 index 00000000000..137f54e8f26 --- /dev/null +++ b/changelogs/fragments/give_compose_extra_vars.yml @@ -0,0 +1,5 @@ +minor_changes: + - Allow inventory plugins access to extra vars by default + - Toggle allowing usage of extra_vars in compose + - Add option to pass extra vars to ansible-inventory + - Enable extra vars for inventory plugin options diff --git a/lib/ansible/cli/inventory.py b/lib/ansible/cli/inventory.py index 9f423747e5a..5fd6aa667eb 100644 --- a/lib/ansible/cli/inventory.py +++ b/lib/ansible/cli/inventory.py @@ -64,6 +64,7 @@ class InventoryCLI(CLI): opt_help.add_inventory_options(self.parser) opt_help.add_vault_options(self.parser) opt_help.add_basedir_options(self.parser) + opt_help.add_runtask_options(self.parser) # remove unused default options self.parser.add_argument('-l', '--limit', help=argparse.SUPPRESS, action=opt_help.UnrecognizedArgument, nargs='?') diff --git a/lib/ansible/plugins/doc_fragments/constructed.py b/lib/ansible/plugins/doc_fragments/constructed.py index f2788da0b0d..8e134cb8d9f 100644 --- a/lib/ansible/plugins/doc_fragments/constructed.py +++ b/lib/ansible/plugins/doc_fragments/constructed.py @@ -29,4 +29,14 @@ options: description: Add hosts to group based on the values of a variable. type: list default: [] + use_extra_vars: + version_added: '2.11' + description: Merge extra vars into the available variables for composition (highest precedence). + type: bool + default: False + ini: + - section: inventory_plugins + key: use_extra_vars + env: + - name: ANSIBLE_INVENTORY_USE_EXTRA_VARS ''' diff --git a/lib/ansible/plugins/inventory/__init__.py b/lib/ansible/plugins/inventory/__init__.py index b7777ef881a..27e3c5d485d 100644 --- a/lib/ansible/plugins/inventory/__init__.py +++ b/lib/ansible/plugins/inventory/__init__.py @@ -34,7 +34,7 @@ from ansible.module_utils.parsing.convert_bool import boolean from ansible.module_utils.six import string_types from ansible.template import Templar from ansible.utils.display import Display -from ansible.utils.vars import combine_vars +from ansible.utils.vars import combine_vars, load_extra_vars display = Display() @@ -159,6 +159,7 @@ class BaseInventoryPlugin(AnsiblePlugin): self._options = {} self.inventory = None self.display = display + self._vars = {} def parse(self, inventory, loader, path, cache=True): ''' Populates inventory from the given data. Raises an error on any parse failure @@ -177,6 +178,7 @@ class BaseInventoryPlugin(AnsiblePlugin): self.loader = loader self.inventory = inventory self.templar = Templar(loader=loader) + self._vars = load_extra_vars(loader) def verify_file(self, path): ''' Verify if file is usable by this plugin, base does minimal accessibility check @@ -229,7 +231,7 @@ class BaseInventoryPlugin(AnsiblePlugin): # configs are dictionaries raise AnsibleParserError('inventory source has invalid structure, it should be a dictionary, got: %s' % type(config)) - self.set_options(direct=config) + self.set_options(direct=config, var_options=self._vars) if 'cache' in self._options and self.get_option('cache'): cache_option_keys = [('_uri', 'cache_connection'), ('_timeout', 'cache_timeout'), ('_prefix', 'cache_prefix')] cache_options = dict((opt[0], self.get_option(opt[1])) for opt in cache_option_keys if self.get_option(opt[1]) is not None) @@ -354,7 +356,17 @@ class Constructable(object): def _compose(self, template, variables): ''' helper method for plugins to compose variables for Ansible based on jinja2 expression and inventory vars''' t = self.templar - t.available_variables = variables + + try: + use_extra = self.get_option('use_extra_vars') + except Exception: + use_extra = False + + if use_extra: + t.available_variables = combine_vars(variables, self._vars) + else: + t.available_variables = variables + return t.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, strict=False): diff --git a/test/integration/targets/inventory/extra_vars_constructed.yml b/test/integration/targets/inventory/extra_vars_constructed.yml new file mode 100644 index 00000000000..66bee863fbd --- /dev/null +++ b/test/integration/targets/inventory/extra_vars_constructed.yml @@ -0,0 +1,5 @@ +plugin: constructed +strict: true +use_extra_vars: True +compose: + example: " 'hello' + from_extras" diff --git a/test/integration/targets/inventory/runme.sh b/test/integration/targets/inventory/runme.sh index 3cd533cde7b..02b6bca4e0d 100755 --- a/test/integration/targets/inventory/runme.sh +++ b/test/integration/targets/inventory/runme.sh @@ -34,3 +34,6 @@ ansible-playbook -i ../../inventory --limit @"${empty_limit_file}" playbook.yml ansible-playbook -i ../../inventory "$@" strategy.yml ANSIBLE_TRANSFORM_INVALID_GROUP_CHARS=always ansible-playbook -i ../../inventory "$@" strategy.yml ANSIBLE_TRANSFORM_INVALID_GROUP_CHARS=never ansible-playbook -i ../../inventory "$@" strategy.yml + +# test extra vars +ansible-inventory -i testhost, -i ./extra_vars_constructed.yml --list -e 'from_extras=hey ' "$@"|grep '"example": "hellohey"'