diff options
Diffstat (limited to 'test/integration/targets/inventory')
13 files changed, 221 insertions, 0 deletions
diff --git a/test/integration/targets/inventory/1/2/3/extra_vars_relative.yml b/test/integration/targets/inventory/1/2/3/extra_vars_relative.yml new file mode 100644 index 0000000..fa50a5a --- /dev/null +++ b/test/integration/targets/inventory/1/2/3/extra_vars_relative.yml @@ -0,0 +1,19 @@ +- hosts: localhost + gather_facts: false + vars: + conditions: + - my is defined + - my == 'var' + - "'webservers' in groups" + - "'web_host.example.com' in groups['webservers']" + tasks: + - name: Make sure all is loaded + assert: + that: '{{conditions}}' + + - name: Reload inventory, forces extra vars re-eval from diff basedir + meta: refresh_inventory + + - name: Make sure all is loaded, again + assert: + that: '{{conditions}}' diff --git a/test/integration/targets/inventory/1/2/inventory.yml b/test/integration/targets/inventory/1/2/inventory.yml new file mode 100644 index 0000000..b6c31ad --- /dev/null +++ b/test/integration/targets/inventory/1/2/inventory.yml @@ -0,0 +1,3 @@ +plugin: ansible.builtin.constructed +groups: + webservers: inventory_hostname.startswith('web') diff --git a/test/integration/targets/inventory/1/vars.yml b/test/integration/targets/inventory/1/vars.yml new file mode 100644 index 0000000..c114584 --- /dev/null +++ b/test/integration/targets/inventory/1/vars.yml @@ -0,0 +1 @@ +my: var diff --git a/test/integration/targets/inventory/aliases b/test/integration/targets/inventory/aliases new file mode 100644 index 0000000..1d28bdb --- /dev/null +++ b/test/integration/targets/inventory/aliases @@ -0,0 +1,2 @@ +shippable/posix/group5 +context/controller 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 0000000..ee6f5fd --- /dev/null +++ b/test/integration/targets/inventory/extra_vars_constructed.yml @@ -0,0 +1,5 @@ +plugin: ansible.builtin.constructed +strict: true +use_extra_vars: True +compose: + example: " 'hello' + from_extras" diff --git a/test/integration/targets/inventory/host_vars_constructed.yml b/test/integration/targets/inventory/host_vars_constructed.yml new file mode 100644 index 0000000..eec5250 --- /dev/null +++ b/test/integration/targets/inventory/host_vars_constructed.yml @@ -0,0 +1,6 @@ +plugin: ansible.legacy.contructed_with_hostvars +groups: + host_var1_defined: host_var1 is defined +keyed_groups: + - key: host_var2 + prefix: host_var2 diff --git a/test/integration/targets/inventory/inv_with_host_vars.yml b/test/integration/targets/inventory/inv_with_host_vars.yml new file mode 100644 index 0000000..7403505 --- /dev/null +++ b/test/integration/targets/inventory/inv_with_host_vars.yml @@ -0,0 +1,5 @@ +all: + hosts: + host1: + host_var1: 'defined' + host_var2: 'defined' diff --git a/test/integration/targets/inventory/inv_with_int.yml b/test/integration/targets/inventory/inv_with_int.yml new file mode 100644 index 0000000..5b2f21d --- /dev/null +++ b/test/integration/targets/inventory/inv_with_int.yml @@ -0,0 +1,6 @@ +all: + hosts: + testing123: + x: + a: 1 + 0: 2 diff --git a/test/integration/targets/inventory/inventory_plugins/contructed_with_hostvars.py b/test/integration/targets/inventory/inventory_plugins/contructed_with_hostvars.py new file mode 100644 index 0000000..7ca445a --- /dev/null +++ b/test/integration/targets/inventory/inventory_plugins/contructed_with_hostvars.py @@ -0,0 +1,44 @@ +# Copyright (c) 2022 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = ''' + name: constructed_with_hostvars + options: + plugin: + description: the load name of the plugin + extends_documentation_fragment: + - constructed +''' + +from ansible.errors import AnsibleParserError +from ansible.module_utils._text import to_native +from ansible.plugins.inventory import BaseInventoryPlugin, Constructable + + +class InventoryModule(BaseInventoryPlugin, Constructable): + + NAME = 'constructed_with_hostvars' + + def verify_file(self, path): + return super(InventoryModule, self).verify_file(path) and path.endswith(('constructed.yml', 'constructed.yaml')) + + def parse(self, inventory, loader, path, cache=True): + super(InventoryModule, self).parse(inventory, loader, path, cache) + config = self._read_config_data(path) + + strict = self.get_option('strict') + try: + for host in inventory.hosts: + hostvars = {} + + # constructed groups based on conditionals + self._add_host_to_composed_groups(self.get_option('groups'), hostvars, host, strict=strict, fetch_hostvars=True) + + # constructed groups based variable values + self._add_host_to_keyed_groups(self.get_option('keyed_groups'), hostvars, host, strict=strict, fetch_hostvars=True) + + except Exception as e: + raise AnsibleParserError("failed to parse %s: %s " % (to_native(path), to_native(e)), orig_exc=e) diff --git a/test/integration/targets/inventory/playbook.yml b/test/integration/targets/inventory/playbook.yml new file mode 100644 index 0000000..5e07361 --- /dev/null +++ b/test/integration/targets/inventory/playbook.yml @@ -0,0 +1,4 @@ +- hosts: all + gather_facts: false + tasks: + - ping: diff --git a/test/integration/targets/inventory/runme.sh b/test/integration/targets/inventory/runme.sh new file mode 100755 index 0000000..8dcac40 --- /dev/null +++ b/test/integration/targets/inventory/runme.sh @@ -0,0 +1,114 @@ +#!/usr/bin/env bash + +set -eux + +empty_limit_file="$(mktemp)" +touch "${empty_limit_file}" + +tmpdir="$(mktemp -d)" + +cleanup() { + if [[ -f "${empty_limit_file}" ]]; then + rm -rf "${empty_limit_file}" + fi + rm -rf "$tmpdir" +} + +trap 'cleanup' EXIT + +# https://github.com/ansible/ansible/issues/52152 +# Ensure that non-matching limit causes failure with rc 1 +if ansible-playbook -i ../../inventory --limit foo playbook.yml; then + echo "Non-matching limit should cause failure" + exit 1 +fi + +# Ensure that non-existing limit file causes failure with rc 1 +if ansible-playbook -i ../../inventory --limit @foo playbook.yml; then + echo "Non-existing limit file should cause failure" + exit 1 +fi + +if ! ansible-playbook -i ../../inventory --limit @"$tmpdir" playbook.yml 2>&1 | grep 'must be a file'; then + echo "Using a directory as a limit file should throw proper AnsibleError" + exit 1 +fi + +# Ensure that empty limit file does not cause IndexError #59695 +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"' + +# test host vars from previous inventory sources +ansible-inventory -i ./inv_with_host_vars.yml -i ./host_vars_constructed.yml --graph "$@" | tee out.txt +if [[ "$(grep out.txt -ce '.*host_var[1|2]_defined')" != 2 ]]; then + cat out.txt + echo "Expected groups host_var1_defined and host_var2_defined to both exist" + exit 1 +fi + +# Do not fail when all inventories fail to parse. +# Do not fail when any inventory fails to parse. +ANSIBLE_INVENTORY_UNPARSED_FAILED=False ANSIBLE_INVENTORY_ANY_UNPARSED_IS_FAILED=False ansible -m ping localhost -i /idontexist "$@" + +# Fail when all inventories fail to parse. +# Do not fail when just one inventory fails to parse. +if ANSIBLE_INVENTORY_UNPARSED_FAILED=True ANSIBLE_INVENTORY_ANY_UNPARSED_IS_FAILED=False ansible -m ping localhost -i /idontexist; then + echo "All inventories failed/did not exist, should cause failure" + echo "ran with: ANSIBLE_INVENTORY_UNPARSED_FAILED=True ANSIBLE_INVENTORY_ANY_UNPARSED_IS_FAILED=False" + exit 1 +fi + +# Same as above but ensuring no failure we *only* fail when all inventories fail to parse. +# Fail when all inventories fail to parse. +# Do not fail when just one inventory fails to parse. +ANSIBLE_INVENTORY_UNPARSED_FAILED=True ANSIBLE_INVENTORY_ANY_UNPARSED_IS_FAILED=False ansible -m ping localhost -i /idontexist -i ../../inventory "$@" +# Fail when all inventories fail to parse. +# Do not fail when just one inventory fails to parse. + +# Fail when any inventories fail to parse. +if ANSIBLE_INVENTORY_ANY_UNPARSED_IS_FAILED=True ansible -m ping localhost -i /idontexist -i ../../inventory; then + echo "One inventory failed/did not exist, should NOT cause failure" + echo "ran with: ANSIBLE_INVENTORY_UNPARSED_FAILED=True ANSIBLE_INVENTORY_ANY_UNPARSED_IS_FAILED=False" + exit 1 +fi + +# Test parsing an empty config +set +e +ANSIBLE_INVENTORY_UNPARSED_FAILED=True ANSIBLE_INVENTORY_ENABLED=constructed ansible-inventory -i ./test_empty.yml --list "$@" +rc_failed_inventory="$?" +set -e +if [[ "$rc_failed_inventory" != 1 ]]; then + echo "Config was empty so inventory was not parsed, should cause failure" + exit 1 +fi + +# Ensure we don't throw when an empty directory is used as inventory +ansible-playbook -i "$tmpdir" playbook.yml + +# Ensure we can use a directory of inventories +cp ../../inventory "$tmpdir" +ansible-playbook -i "$tmpdir" playbook.yml + +# ... even if it contains another empty directory +mkdir "$tmpdir/empty" +ansible-playbook -i "$tmpdir" playbook.yml + +if ANSIBLE_INVENTORY_ANY_UNPARSED_IS_FAILED=True ansible -m ping localhost -i "$tmpdir"; then + echo "Empty directory should cause failure when ANSIBLE_INVENTORY_ANY_UNPARSED_IS_FAILED=True" + exit 1 +fi + +# ensure we don't traceback on inventory due to variables with int as key +ansible-inventory -i inv_with_int.yml --list "$@" + +# test in subshell relative paths work mid play for extra vars in inventory refresh +{ + cd 1/2 + ansible-playbook -e @../vars.yml -i 'web_host.example.com,' -i inventory.yml 3/extra_vars_relative.yml "$@" +} diff --git a/test/integration/targets/inventory/strategy.yml b/test/integration/targets/inventory/strategy.yml new file mode 100644 index 0000000..5c1cbd2 --- /dev/null +++ b/test/integration/targets/inventory/strategy.yml @@ -0,0 +1,12 @@ +- name: Check that 'invalid' group works, problem exposed in #58980 + hosts: localhost + tasks: + - name: add a host to a group, that has - to trigger substitution + add_host: + name: localhost + groups: Not-Working + + - name: group hosts by distribution, with dash to trigger substitution + group_by: + key: "{{ ansible_distribution }}-{{ ansible_distribution_version }}" + changed_when: false diff --git a/test/integration/targets/inventory/test_empty.yml b/test/integration/targets/inventory/test_empty.yml new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/integration/targets/inventory/test_empty.yml |