diff options
Diffstat (limited to '')
55 files changed, 2068 insertions, 0 deletions
diff --git a/test/integration/targets/inventory-invalid-group/aliases b/test/integration/targets/inventory-invalid-group/aliases new file mode 100644 index 0000000..1d28bdb --- /dev/null +++ b/test/integration/targets/inventory-invalid-group/aliases @@ -0,0 +1,2 @@ +shippable/posix/group5 +context/controller diff --git a/test/integration/targets/inventory-invalid-group/inventory.ini b/test/integration/targets/inventory-invalid-group/inventory.ini new file mode 100644 index 0000000..762c9da --- /dev/null +++ b/test/integration/targets/inventory-invalid-group/inventory.ini @@ -0,0 +1,5 @@ +[local-] +testhost ansible_connection=local + +[all:vars] +ansible_python_interpreter="{{ ansible_playbook_python }}" diff --git a/test/integration/targets/inventory-invalid-group/runme.sh b/test/integration/targets/inventory-invalid-group/runme.sh new file mode 100755 index 0000000..8c40554 --- /dev/null +++ b/test/integration/targets/inventory-invalid-group/runme.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -eux +set -o pipefail + +command=(ansible-playbook -v -i inventory.ini test.yml) + never='Invalid characters were found in group names but not replaced' +always='Invalid characters were found in group names and automatically' + +ANSIBLE_TRANSFORM_INVALID_GROUP_CHARS=never "${command[@]}" -l "local-" 2>&1 | grep -c -e "${never}" +ANSIBLE_TRANSFORM_INVALID_GROUP_CHARS=always "${command[@]}" -l "local_" 2>&1 | grep -c -e "${always}" +ANSIBLE_TRANSFORM_INVALID_GROUP_CHARS=ignore "${command[@]}" -l "local-" 2>&1 | grep -cv -e "${never}" -e "${always}" +ANSIBLE_TRANSFORM_INVALID_GROUP_CHARS=silently "${command[@]}" -l "local_" 2>&1 | grep -cv -e "${never}" -e "${always}" diff --git a/test/integration/targets/inventory-invalid-group/test.yml b/test/integration/targets/inventory-invalid-group/test.yml new file mode 100644 index 0000000..2208f9d --- /dev/null +++ b/test/integration/targets/inventory-invalid-group/test.yml @@ -0,0 +1,3 @@ +- hosts: testhost + gather_facts: no + tasks: [] 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 diff --git a/test/integration/targets/inventory_advanced_host_list/aliases b/test/integration/targets/inventory_advanced_host_list/aliases new file mode 100644 index 0000000..b598321 --- /dev/null +++ b/test/integration/targets/inventory_advanced_host_list/aliases @@ -0,0 +1 @@ +shippable/posix/group3 diff --git a/test/integration/targets/inventory_advanced_host_list/runme.sh b/test/integration/targets/inventory_advanced_host_list/runme.sh new file mode 100755 index 0000000..41b1f8b --- /dev/null +++ b/test/integration/targets/inventory_advanced_host_list/runme.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +set -eux + +export ANSIBLE_INVENTORY_ENABLED=advanced_host_list + +# A few things to make it easier to grep against adhoc +export ANSIBLE_LOAD_CALLBACK_PLUGINS=True +export ANSIBLE_STDOUT_CALLBACK=oneline + +adhoc="$(ansible -i 'local[0:10],' -m ping --connection=local -e ansible_python_interpreter="{{ ansible_playbook_python }}" all -v)" + +for i in $(seq 0 10); do + grep -qE "local${i} \| SUCCESS.*\"ping\": \"pong\"" <<< "$adhoc" +done + +set +e +parse_fail="$(ansible -i 'local[1:j],' -m ping --connection=local all -v 2>&1)" +set -e + +grep -q "Failed to parse local\[1:j\], with advanced_host_list" <<< "$parse_fail" + +# Intentionally missing comma, ensure we don't fatal. +no_comma="$(ansible -i 'local[1:5]' -m ping --connection=local all -v 2>&1)" +grep -q "No inventory was parsed" <<< "$no_comma" + +# Intentionally botched range (missing end number), ensure we don't fatal. +no_end="$(ansible -i 'local[1:],' -m ping --connection=local -e ansible_python_interpreter="{{ ansible_playbook_python }}" all -vvv 2>&1)" +grep -q "Unable to parse address from hostname, leaving unchanged:" <<< "$no_end" +grep -q "host range must specify end value" <<< "$no_end" +grep -q "local\[3:\] \| SUCCESS" <<< "$no_end" + +# Unset adhoc stuff +unset ANSIBLE_LOAD_CALLBACK_PLUGINS ANSIBLE_STDOUT_CALLBACK + +ansible-playbook -i 'local100,local[100:110:2]' test_advanced_host_list.yml -v "$@" diff --git a/test/integration/targets/inventory_advanced_host_list/test_advanced_host_list.yml b/test/integration/targets/inventory_advanced_host_list/test_advanced_host_list.yml new file mode 100644 index 0000000..918078a --- /dev/null +++ b/test/integration/targets/inventory_advanced_host_list/test_advanced_host_list.yml @@ -0,0 +1,9 @@ +- hosts: all + connection: local + vars: + ansible_python_interpreter: "{{ ansible_playbook_python }}" + tasks: + - assert: + that: + - inventory_hostname in ["local100", "local102", "local104", "local106", "local108", "local110", "local118"] + - inventory_hostname not in ["local101", "local103", "local105", "local107", "local109", "local111"] diff --git a/test/integration/targets/inventory_cache/aliases b/test/integration/targets/inventory_cache/aliases new file mode 100644 index 0000000..498fedd --- /dev/null +++ b/test/integration/targets/inventory_cache/aliases @@ -0,0 +1,2 @@ +shippable/posix/group4 +context/controller diff --git a/test/integration/targets/inventory_cache/cache/.keep b/test/integration/targets/inventory_cache/cache/.keep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/integration/targets/inventory_cache/cache/.keep diff --git a/test/integration/targets/inventory_cache/cache_host.yml b/test/integration/targets/inventory_cache/cache_host.yml new file mode 100644 index 0000000..3630641 --- /dev/null +++ b/test/integration/targets/inventory_cache/cache_host.yml @@ -0,0 +1,4 @@ +plugin: cache_host +cache: true +cache_plugin: jsonfile +cache_connection: ./cache diff --git a/test/integration/targets/inventory_cache/exercise_cache.yml b/test/integration/targets/inventory_cache/exercise_cache.yml new file mode 100644 index 0000000..6fd8712 --- /dev/null +++ b/test/integration/targets/inventory_cache/exercise_cache.yml @@ -0,0 +1,4 @@ +plugin: exercise_cache +cache: true +cache_plugin: jsonfile +cache_connection: ./cache diff --git a/test/integration/targets/inventory_cache/plugins/inventory/cache_host.py b/test/integration/targets/inventory_cache/plugins/inventory/cache_host.py new file mode 100644 index 0000000..628aba1 --- /dev/null +++ b/test/integration/targets/inventory_cache/plugins/inventory/cache_host.py @@ -0,0 +1,56 @@ +# Copyright (c) 2021 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 = ''' + inventory: cache_host + short_description: add a host to inventory and cache it + description: add a host to inventory and cache it + extends_documentation_fragment: + - inventory_cache + options: + plugin: + required: true + description: name of the plugin (cache_host) +''' + +from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable +import random + + +class InventoryModule(BaseInventoryPlugin, Cacheable): + + NAME = 'cache_host' + + def verify_file(self, path): + if not path.endswith(('cache_host.yml', 'cache_host.yaml',)): + return False + return super(InventoryModule, self).verify_file(path) + + def parse(self, inventory, loader, path, cache=None): + super(InventoryModule, self).parse(inventory, loader, path) + self._read_config_data(path) + + cache_key = self.get_cache_key(path) + # user has enabled cache and the cache is not being flushed + read_cache = self.get_option('cache') and cache + # user has enabled cache and the cache is being flushed + update_cache = self.get_option('cache') and not cache + + host = None + if read_cache: + try: + host = self._cache[cache_key] + except KeyError: + # cache expired + update_cache = True + + if host is None: + host = 'testhost{0}'.format(random.randint(0, 50)) + + self.inventory.add_host(host, 'all') + + if update_cache: + self._cache[cache_key] = host diff --git a/test/integration/targets/inventory_cache/plugins/inventory/exercise_cache.py b/test/integration/targets/inventory_cache/plugins/inventory/exercise_cache.py new file mode 100644 index 0000000..cca2aa0 --- /dev/null +++ b/test/integration/targets/inventory_cache/plugins/inventory/exercise_cache.py @@ -0,0 +1,344 @@ +# 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 = ''' + inventory: exercise_cache + short_description: run tests against the specified cache plugin + description: + - This plugin doesn't modify inventory. + - Load a cache plugin and test the inventory cache interface is dict-like. + - Most inventory cache write methods only apply to the in-memory cache. + - The 'flush' and 'set_cache' methods should be used to apply changes to the backing cache plugin. + - The inventory cache read methods prefer the in-memory cache, and fall back to reading from the cache plugin. + extends_documentation_fragment: + - inventory_cache + options: + plugin: + required: true + description: name of the plugin (exercise_cache) + cache_timeout: + ini: [] + env: [] + cli: [] + default: 0 # never expire +''' + +from ansible.errors import AnsibleError +from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable +from ansible.utils.display import Display + +from time import sleep + + +display = Display() + + +class InventoryModule(BaseInventoryPlugin, Cacheable): + + NAME = 'exercise_cache' + + test_cache_methods = [ + 'test_plugin_name', + 'test_update_cache_if_changed', + 'test_set_cache', + 'test_load_whole_cache', + 'test_iter', + 'test_len', + 'test_get_missing_key', + 'test_get_expired_key', + 'test_initial_get', + 'test_get', + 'test_items', + 'test_keys', + 'test_values', + 'test_pop', + 'test_del', + 'test_set', + 'test_update', + 'test_flush', + ] + + def verify_file(self, path): + if not path.endswith(('exercise_cache.yml', 'exercise_cache.yaml',)): + return False + return super(InventoryModule, self).verify_file(path) + + def parse(self, inventory, loader, path, cache=None): + super(InventoryModule, self).parse(inventory, loader, path) + self._read_config_data(path) + + try: + self.exercise_test_cache() + except AnsibleError: + raise + except Exception as e: + raise AnsibleError("Failed to run cache tests: {0}".format(e)) from e + + def exercise_test_cache(self): + failed = [] + for test_name in self.test_cache_methods: + try: + getattr(self, test_name)() + except AssertionError: + failed.append(test_name) + finally: + self.cache.flush() + self.cache.update_cache_if_changed() + + if failed: + raise AnsibleError(f"Cache tests failed: {', '.join(failed)}") + + def test_equal(self, a, b): + try: + assert a == b + except AssertionError: + display.warning(f"Assertion {a} == {b} failed") + raise + + def test_plugin_name(self): + self.test_equal(self.cache._plugin_name, self.get_option('cache_plugin')) + + def test_update_cache_if_changed(self): + self.cache._retrieved = {} + self.cache._cache = {'foo': 'bar'} + + self.cache.update_cache_if_changed() + + self.test_equal(self.cache._retrieved, {'foo': 'bar'}) + self.test_equal(self.cache._cache, {'foo': 'bar'}) + + def test_set_cache(self): + cache_key1 = 'key1' + cache1 = {'hosts': {'h1': {'foo': 'bar'}}} + cache_key2 = 'key2' + cache2 = {'hosts': {'h2': {}}} + + self.cache._cache = {cache_key1: cache1, cache_key2: cache2} + self.cache.set_cache() + + self.test_equal(self.cache._plugin.contains(cache_key1), True) + self.test_equal(self.cache._plugin.get(cache_key1), cache1) + self.test_equal(self.cache._plugin.contains(cache_key2), True) + self.test_equal(self.cache._plugin.get(cache_key2), cache2) + + def test_load_whole_cache(self): + cache_data = { + 'key1': {'hosts': {'h1': {'foo': 'bar'}}}, + 'key2': {'hosts': {'h2': {}}}, + } + self.cache._cache = cache_data + self.cache.set_cache() + self.cache._cache = {} + + self.cache.load_whole_cache() + self.test_equal(self.cache._cache, cache_data) + + def test_iter(self): + cache_data = { + 'key1': {'hosts': {'h1': {'foo': 'bar'}}}, + 'key2': {'hosts': {'h2': {}}}, + } + self.cache._cache = cache_data + self.test_equal(sorted(list(self.cache)), ['key1', 'key2']) + + def test_len(self): + cache_data = { + 'key1': {'hosts': {'h1': {'foo': 'bar'}}}, + 'key2': {'hosts': {'h2': {}}}, + } + self.cache._cache = cache_data + self.test_equal(len(self.cache), 2) + + def test_get_missing_key(self): + # cache should behave like a dictionary + # a missing key with __getitem__ should raise a KeyError + try: + self.cache['keyerror'] + except KeyError: + pass + else: + assert False + + # get should return the default instead + self.test_equal(self.cache.get('missing'), None) + self.test_equal(self.cache.get('missing', 'default'), 'default') + + def _setup_expired(self): + self.cache._cache = {'expired': True} + self.cache.set_cache() + + # empty the in-memory info to test loading the key + # keys that expire mid-use do not cause errors + self.cache._cache = {} + self.cache._retrieved = {} + self.cache._plugin._cache = {} + + self.cache._plugin.set_option('timeout', 1) + self.cache._plugin._timeout = 1 + sleep(2) + + def _cleanup_expired(self): + # Set cache timeout back to never + self.cache._plugin.set_option('timeout', 0) + self.cache._plugin._timeout = 0 + + def test_get_expired_key(self): + if not hasattr(self.cache._plugin, '_timeout'): + # DB-backed caches do not have a standard timeout interface + return + + self._setup_expired() + try: + self.cache['expired'] + except KeyError: + pass + else: + assert False + finally: + self._cleanup_expired() + + self._setup_expired() + try: + self.test_equal(self.cache.get('expired'), None) + self.test_equal(self.cache.get('expired', 'default'), 'default') + finally: + self._cleanup_expired() + + def test_initial_get(self): + # test cache behaves like a dictionary + + # set the cache to test getting a key that exists + k1 = {'hosts': {'h1': {'foo': 'bar'}}} + k2 = {'hosts': {'h2': {}}} + self.cache._cache = {'key1': k1, 'key2': k2} + self.cache.set_cache() + + # empty the in-memory info to test loading the key from the plugin + self.cache._cache = {} + self.cache._retrieved = {} + self.cache._plugin._cache = {} + + self.test_equal(self.cache['key1'], k1) + + # empty the in-memory info to test loading the key from the plugin + self.cache._cache = {} + self.cache._retrieved = {} + self.cache._plugin._cache = {} + + self.test_equal(self.cache.get('key1'), k1) + + def test_get(self): + # test cache behaves like a dictionary + + # set the cache to test getting a key that exists + k1 = {'hosts': {'h1': {'foo': 'bar'}}} + k2 = {'hosts': {'h2': {}}} + self.cache._cache = {'key1': k1, 'key2': k2} + self.cache.set_cache() + + self.test_equal(self.cache['key1'], k1) + self.test_equal(self.cache.get('key1'), k1) + + def test_items(self): + self.test_equal(self.cache.items(), {}.items()) + + test_items = {'hosts': {'host1': {'foo': 'bar'}}} + self.cache._cache = test_items + self.test_equal(self.cache.items(), test_items.items()) + + def test_keys(self): + self.test_equal(self.cache.keys(), {}.keys()) + + test_items = {'hosts': {'host1': {'foo': 'bar'}}} + self.cache._cache = test_items + self.test_equal(self.cache.keys(), test_items.keys()) + + def test_values(self): + self.test_equal(list(self.cache.values()), list({}.values())) + + test_items = {'hosts': {'host1': {'foo': 'bar'}}} + self.cache._cache = test_items + self.test_equal(list(self.cache.values()), list(test_items.values())) + + def test_pop(self): + try: + self.cache.pop('missing') + except KeyError: + pass + else: + assert False + + self.test_equal(self.cache.pop('missing', 'default'), 'default') + + self.cache._cache = {'cache_key': 'cache'} + self.test_equal(self.cache.pop('cache_key'), 'cache') + + # test backing plugin cache isn't modified + cache_key1 = 'key1' + cache1 = {'hosts': {'h1': {'foo': 'bar'}}} + cache_key2 = 'key2' + cache2 = {'hosts': {'h2': {}}} + + self.cache._cache = {cache_key1: cache1, cache_key2: cache2} + self.cache.set_cache() + + self.test_equal(self.cache.pop('key1'), cache1) + self.test_equal(self.cache._cache, {cache_key2: cache2}) + self.test_equal(self.cache._plugin._cache, {cache_key1: cache1, cache_key2: cache2}) + + def test_del(self): + try: + del self.cache['missing'] + except KeyError: + pass + else: + assert False + + cache_key1 = 'key1' + cache1 = {'hosts': {'h1': {'foo': 'bar'}}} + cache_key2 = 'key2' + cache2 = {'hosts': {'h2': {}}} + + self.cache._cache = {cache_key1: cache1, cache_key2: cache2} + self.cache.set_cache() + + del self.cache['key1'] + + self.test_equal(self.cache._cache, {cache_key2: cache2}) + self.test_equal(self.cache._plugin._cache, {cache_key1: cache1, cache_key2: cache2}) + + def test_set(self): + cache_key = 'key1' + hosts = {'hosts': {'h1': {'foo': 'bar'}}} + self.cache[cache_key] = hosts + + self.test_equal(self.cache._cache, {cache_key: hosts}) + self.test_equal(self.cache._plugin._cache, {}) + + def test_update(self): + cache_key1 = 'key1' + cache1 = {'hosts': {'h1': {'foo': 'bar'}}} + cache_key2 = 'key2' + cache2 = {'hosts': {'h2': {}}} + + self.cache._cache = {cache_key1: cache1} + self.cache.update({cache_key2: cache2}) + self.test_equal(self.cache._cache, {cache_key1: cache1, cache_key2: cache2}) + + def test_flush(self): + cache_key1 = 'key1' + cache1 = {'hosts': {'h1': {'foo': 'bar'}}} + cache_key2 = 'key2' + cache2 = {'hosts': {'h2': {}}} + + self.cache._cache = {cache_key1: cache1, cache_key2: cache2} + self.cache.set_cache() + + # Unlike the dict write methods, cache.flush() flushes the backing plugin + self.cache.flush() + + self.test_equal(self.cache._cache, {}) + self.test_equal(self.cache._plugin._cache, {}) diff --git a/test/integration/targets/inventory_cache/runme.sh b/test/integration/targets/inventory_cache/runme.sh new file mode 100755 index 0000000..942eb82 --- /dev/null +++ b/test/integration/targets/inventory_cache/runme.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +set -eux + +export ANSIBLE_INVENTORY_PLUGINS=./plugins/inventory + +cleanup() { + for f in ./cache/ansible_inventory*; do + if [ -f "$f" ]; then rm -rf "$f"; fi + done +} + +trap 'cleanup' EXIT + +# Test no warning when writing to the cache for the first time +test "$(ansible-inventory -i cache_host.yml --graph 2>&1 | tee out.txt | grep -c '\[WARNING\]')" = 0 +writehost="$(grep "testhost[0-9]\{1,2\}" out.txt)" + +# Test reading from the cache +test "$(ansible-inventory -i cache_host.yml --graph 2>&1 | tee out.txt | grep -c '\[WARNING\]')" = 0 +readhost="$(grep 'testhost[0-9]\{1,2\}' out.txt)" + +test "$readhost" = "$writehost" + +ansible-inventory -i exercise_cache.yml --graph diff --git a/test/integration/targets/inventory_constructed/aliases b/test/integration/targets/inventory_constructed/aliases new file mode 100644 index 0000000..70a7b7a --- /dev/null +++ b/test/integration/targets/inventory_constructed/aliases @@ -0,0 +1 @@ +shippable/posix/group5 diff --git a/test/integration/targets/inventory_constructed/constructed.yml b/test/integration/targets/inventory_constructed/constructed.yml new file mode 100644 index 0000000..be02858 --- /dev/null +++ b/test/integration/targets/inventory_constructed/constructed.yml @@ -0,0 +1,19 @@ +plugin: ansible.builtin.constructed +keyed_groups: + - key: hostvar0 + - key: hostvar1 + - key: hostvar2 + + - key: hostvar0 + separator: 'separator' + - key: hostvar1 + separator: 'separator' + - key: hostvar2 + separator: 'separator' + + - key: hostvar0 + prefix: 'prefix' + - key: hostvar1 + prefix: 'prefix' + - key: hostvar2 + prefix: 'prefix' diff --git a/test/integration/targets/inventory_constructed/invs/1/group_vars/stuff.yml b/test/integration/targets/inventory_constructed/invs/1/group_vars/stuff.yml new file mode 100644 index 0000000..a67b90f --- /dev/null +++ b/test/integration/targets/inventory_constructed/invs/1/group_vars/stuff.yml @@ -0,0 +1 @@ +iamdefined: group4testing diff --git a/test/integration/targets/inventory_constructed/invs/1/host_vars/testing.yml b/test/integration/targets/inventory_constructed/invs/1/host_vars/testing.yml new file mode 100644 index 0000000..0ffe382 --- /dev/null +++ b/test/integration/targets/inventory_constructed/invs/1/host_vars/testing.yml @@ -0,0 +1 @@ +hola: lola diff --git a/test/integration/targets/inventory_constructed/invs/1/one.yml b/test/integration/targets/inventory_constructed/invs/1/one.yml new file mode 100644 index 0000000..ad5a5e0 --- /dev/null +++ b/test/integration/targets/inventory_constructed/invs/1/one.yml @@ -0,0 +1,5 @@ +all: + children: + stuff: + hosts: + testing: diff --git a/test/integration/targets/inventory_constructed/invs/2/constructed.yml b/test/integration/targets/inventory_constructed/invs/2/constructed.yml new file mode 100644 index 0000000..ca26e2c --- /dev/null +++ b/test/integration/targets/inventory_constructed/invs/2/constructed.yml @@ -0,0 +1,7 @@ +plugin: ansible.builtin.constructed +use_vars_plugins: true +keyed_groups: + - key: iamdefined + prefix: c + - key: hola + prefix: c diff --git a/test/integration/targets/inventory_constructed/keyed_group_default_value.yml b/test/integration/targets/inventory_constructed/keyed_group_default_value.yml new file mode 100644 index 0000000..d69e8ec --- /dev/null +++ b/test/integration/targets/inventory_constructed/keyed_group_default_value.yml @@ -0,0 +1,5 @@ +plugin: ansible.builtin.constructed +keyed_groups: + - key: tags + prefix: tag + default_value: "running" diff --git a/test/integration/targets/inventory_constructed/keyed_group_list_default_value.yml b/test/integration/targets/inventory_constructed/keyed_group_list_default_value.yml new file mode 100644 index 0000000..4481db3 --- /dev/null +++ b/test/integration/targets/inventory_constructed/keyed_group_list_default_value.yml @@ -0,0 +1,5 @@ +plugin: ansible.builtin.constructed +keyed_groups: + - key: roles + default_value: storage + prefix: host diff --git a/test/integration/targets/inventory_constructed/keyed_group_str_default_value.yml b/test/integration/targets/inventory_constructed/keyed_group_str_default_value.yml new file mode 100644 index 0000000..256d330 --- /dev/null +++ b/test/integration/targets/inventory_constructed/keyed_group_str_default_value.yml @@ -0,0 +1,5 @@ +plugin: ansible.builtin.constructed +keyed_groups: + - key: os + default_value: "fedora" + prefix: host diff --git a/test/integration/targets/inventory_constructed/keyed_group_trailing_separator.yml b/test/integration/targets/inventory_constructed/keyed_group_trailing_separator.yml new file mode 100644 index 0000000..d69899d --- /dev/null +++ b/test/integration/targets/inventory_constructed/keyed_group_trailing_separator.yml @@ -0,0 +1,5 @@ +plugin: ansible.builtin.constructed +keyed_groups: + - key: tags + prefix: tag + trailing_separator: False diff --git a/test/integration/targets/inventory_constructed/no_leading_separator_constructed.yml b/test/integration/targets/inventory_constructed/no_leading_separator_constructed.yml new file mode 100644 index 0000000..5ff8f93 --- /dev/null +++ b/test/integration/targets/inventory_constructed/no_leading_separator_constructed.yml @@ -0,0 +1,20 @@ +plugin: ansible.builtin.constructed +keyed_groups: + - key: hostvar0 + - key: hostvar1 + - key: hostvar2 + + - key: hostvar0 + separator: 'separator' + - key: hostvar1 + separator: 'separator' + - key: hostvar2 + separator: 'separator' + + - key: hostvar0 + prefix: 'prefix' + - key: hostvar1 + prefix: 'prefix' + - key: hostvar2 + prefix: 'prefix' +leading_separator: False diff --git a/test/integration/targets/inventory_constructed/runme.sh b/test/integration/targets/inventory_constructed/runme.sh new file mode 100755 index 0000000..91bbd66 --- /dev/null +++ b/test/integration/targets/inventory_constructed/runme.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash + +set -eux + +ansible-inventory -i static_inventory.yml -i constructed.yml --graph | tee out.txt + +grep '@_hostvalue1' out.txt +grep '@_item0' out.txt +grep '@_key0_value0' out.txt +grep '@prefix_hostvalue1' out.txt +grep '@prefix_item0' out.txt +grep '@prefix_key0_value0' out.txt +grep '@separatorhostvalue1' out.txt +grep '@separatoritem0' out.txt +grep '@separatorkey0separatorvalue0' out.txt + +ansible-inventory -i static_inventory.yml -i no_leading_separator_constructed.yml --graph | tee out.txt + +grep '@hostvalue1' out.txt +grep '@item0' out.txt +grep '@key0_value0' out.txt +grep '@key0separatorvalue0' out.txt +grep '@prefix_hostvalue1' out.txt +grep '@prefix_item0' out.txt +grep '@prefix_key0_value0' out.txt + +# keyed group with default value for key's value empty (dict) +ansible-inventory -i tag_inventory.yml -i keyed_group_default_value.yml --graph | tee out.txt + +grep '@tag_name_host0' out.txt +grep '@tag_environment_test' out.txt +grep '@tag_status_running' out.txt + +# keyed group with default value for key's value empty (list) +ansible-inventory -i tag_inventory.yml -i keyed_group_list_default_value.yml --graph | tee out.txt + +grep '@host_db' out.txt +grep '@host_web' out.txt +grep '@host_storage' out.txt + +# keyed group with default value for key's value empty (str) +ansible-inventory -i tag_inventory.yml -i keyed_group_str_default_value.yml --graph | tee out.txt + +grep '@host_fedora' out.txt + + +# keyed group with 'trailing_separator' set to 'False' for key's value empty +ansible-inventory -i tag_inventory.yml -i keyed_group_trailing_separator.yml --graph | tee out.txt + +grep '@tag_name_host0' out.txt +grep '@tag_environment_test' out.txt +grep '@tag_status' out.txt + + +# test using use_vars_plugins +ansible-inventory -i invs/1/one.yml -i invs/2/constructed.yml --graph | tee out.txt + +grep '@c_lola' out.txt +grep '@c_group4testing' out.txt diff --git a/test/integration/targets/inventory_constructed/static_inventory.yml b/test/integration/targets/inventory_constructed/static_inventory.yml new file mode 100644 index 0000000..d050df4 --- /dev/null +++ b/test/integration/targets/inventory_constructed/static_inventory.yml @@ -0,0 +1,8 @@ +all: + hosts: + host0: + hostvar0: + key0: value0 + hostvar1: hostvalue1 + hostvar2: + - item0 diff --git a/test/integration/targets/inventory_constructed/tag_inventory.yml b/test/integration/targets/inventory_constructed/tag_inventory.yml new file mode 100644 index 0000000..acf810e --- /dev/null +++ b/test/integration/targets/inventory_constructed/tag_inventory.yml @@ -0,0 +1,12 @@ +all: + hosts: + host0: + tags: + name: "host0" + environment: "test" + status: "" + os: "" + roles: + - db + - web + - "" diff --git a/test/integration/targets/inventory_ini/aliases b/test/integration/targets/inventory_ini/aliases new file mode 100644 index 0000000..3005e4b --- /dev/null +++ b/test/integration/targets/inventory_ini/aliases @@ -0,0 +1 @@ +shippable/posix/group4 diff --git a/test/integration/targets/inventory_ini/inventory.ini b/test/integration/targets/inventory_ini/inventory.ini new file mode 100644 index 0000000..a0c99ad --- /dev/null +++ b/test/integration/targets/inventory_ini/inventory.ini @@ -0,0 +1,5 @@ +[local] +testhost ansible_connection=local ansible_become=no ansible_become_user=ansibletest1 + +[all:vars] +ansible_python_interpreter="{{ ansible_playbook_python }}" diff --git a/test/integration/targets/inventory_ini/runme.sh b/test/integration/targets/inventory_ini/runme.sh new file mode 100755 index 0000000..81bf147 --- /dev/null +++ b/test/integration/targets/inventory_ini/runme.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -eux + +ansible-playbook -v -i inventory.ini test_ansible_become.yml diff --git a/test/integration/targets/inventory_ini/test_ansible_become.yml b/test/integration/targets/inventory_ini/test_ansible_become.yml new file mode 100644 index 0000000..55bbe7d --- /dev/null +++ b/test/integration/targets/inventory_ini/test_ansible_become.yml @@ -0,0 +1,11 @@ +- hosts: testhost + gather_facts: no + tasks: + - name: Test proper bool evaluation of ansible_become (issue #70476) + shell: whoami + register: output + + - name: Assert we are NOT the become user specified + assert: + that: + - "output.stdout != 'ansibletest1'" diff --git a/test/integration/targets/inventory_script/aliases b/test/integration/targets/inventory_script/aliases new file mode 100644 index 0000000..b598321 --- /dev/null +++ b/test/integration/targets/inventory_script/aliases @@ -0,0 +1 @@ +shippable/posix/group3 diff --git a/test/integration/targets/inventory_script/inventory.json b/test/integration/targets/inventory_script/inventory.json new file mode 100644 index 0000000..69ba547 --- /dev/null +++ b/test/integration/targets/inventory_script/inventory.json @@ -0,0 +1,1045 @@ +{ + "None": { + "hosts": [ + "DC0_C0_RP0_VM0_cd0681bf-2f18-5c00-9b9b-8197c0095348", + "DC0_C0_RP0_VM1_f7c371d6-2003-5a48-9859-3bc9a8b08908", + "DC0_H0_VM0_265104de-1472-547c-b873-6dc7883fb6cb", + "DC0_H0_VM1_39365506-5a0a-5fd0-be10-9586ad53aaad" + ] + }, + "_meta": { + "hostvars": { + "DC0_C0_RP0_VM0_cd0681bf-2f18-5c00-9b9b-8197c0095348": { + "alarmactionsenabled": null, + "ansible_host": "None", + "ansible_ssh_host": "None", + "ansible_uuid": "239fb366-6d93-430e-939a-0b6ab272d98f", + "availablefield": [], + "capability": { + "bootoptionssupported": false, + "bootretryoptionssupported": false, + "changetrackingsupported": false, + "consolepreferencessupported": false, + "cpufeaturemasksupported": false, + "disablesnapshotssupported": false, + "diskonlysnapshotonsuspendedvmsupported": null, + "disksharessupported": false, + "dynamicproperty": [], + "dynamictype": null, + "featurerequirementsupported": false, + "guestautolocksupported": false, + "hostbasedreplicationsupported": false, + "locksnapshotssupported": false, + "memoryreservationlocksupported": false, + "memorysnapshotssupported": false, + "multiplecorespersocketsupported": false, + "multiplesnapshotssupported": false, + "nestedhvsupported": false, + "npivwwnonnonrdmvmsupported": false, + "pervmevcsupported": null, + "poweredoffsnapshotssupported": false, + "poweredonmonitortypechangesupported": false, + "quiescedsnapshotssupported": false, + "recordreplaysupported": false, + "reverttosnapshotsupported": false, + "s1acpimanagementsupported": false, + "securebootsupported": null, + "sesparsedisksupported": false, + "settingdisplaytopologysupported": false, + "settingscreenresolutionsupported": false, + "settingvideoramsizesupported": false, + "snapshotconfigsupported": false, + "snapshotoperationssupported": false, + "swapplacementsupported": false, + "toolsautoupdatesupported": false, + "toolssynctimesupported": false, + "virtualexecusageignored": null, + "virtualmmuusageignored": null, + "virtualmmuusagesupported": false, + "vmnpivwwndisablesupported": false, + "vmnpivwwnsupported": false, + "vmnpivwwnupdatesupported": false, + "vpmcsupported": false + }, + "config": { + "alternateguestname": "", + "annotation": null, + "bootoptions": null, + "changetrackingenabled": null, + "changeversion": "", + "consolepreferences": null, + "contentlibiteminfo": null, + "cpuaffinity": null, + "cpuallocation": {}, + "cpufeaturemask": [], + "cpuhotaddenabled": null, + "cpuhotremoveenabled": null, + "createdate": null, + "datastoreurl": [], + "defaultpowerops": {}, + "dynamicproperty": [], + "dynamictype": null, + "extraconfig": [], + "files": {}, + "firmware": null, + "flags": {}, + "forkconfiginfo": null, + "ftinfo": null, + "guestautolockenabled": null, + "guestfullname": "otherGuest", + "guestid": "otherGuest", + "guestintegrityinfo": null, + "guestmonitoringmodeinfo": null, + "hardware": {}, + "hotplugmemoryincrementsize": null, + "hotplugmemorylimit": null, + "initialoverhead": null, + "instanceuuid": "bfff331f-7f07-572d-951e-edd3701dc061", + "keyid": null, + "latencysensitivity": null, + "locationid": null, + "managedby": null, + "maxmksconnections": null, + "memoryaffinity": null, + "memoryallocation": {}, + "memoryhotaddenabled": null, + "memoryreservationlockedtomax": null, + "messagebustunnelenabled": null, + "migrateencryption": null, + "modified": {}, + "name": "DC0_C0_RP0_VM0", + "nestedhvenabled": null, + "networkshaper": null, + "npivdesirednodewwns": null, + "npivdesiredportwwns": null, + "npivnodeworldwidename": [], + "npivonnonrdmdisks": null, + "npivportworldwidename": [], + "npivtemporarydisabled": null, + "npivworldwidenametype": null, + "repconfig": null, + "scheduledhardwareupgradeinfo": null, + "sgxinfo": null, + "swapplacement": null, + "swapstorageobjectid": null, + "template": false, + "tools": {}, + "uuid": "cd0681bf-2f18-5c00-9b9b-8197c0095348", + "vappconfig": null, + "vassertsenabled": null, + "vcpuconfig": [], + "version": "vmx-13", + "vflashcachereservation": null, + "vmstorageobjectid": null, + "vmxconfigchecksum": null, + "vpmcenabled": null + }, + "configissue": [], + "configstatus": "green", + "customvalue": [], + "datastore": [ + { + "_moId": "/tmp/govcsim-DC0-LocalDS_0-949174843@folder-5", + "name": "LocalDS_0" + } + ], + "effectiverole": [ + -1 + ], + "guest": { + "appheartbeatstatus": null, + "appstate": null, + "disk": [], + "dynamicproperty": [], + "dynamictype": null, + "generationinfo": [], + "guestfamily": null, + "guestfullname": null, + "guestid": null, + "guestkernelcrashed": null, + "guestoperationsready": null, + "gueststate": "", + "gueststatechangesupported": null, + "hostname": null, + "hwversion": null, + "interactiveguestoperationsready": null, + "ipaddress": null, + "ipstack": [], + "net": [], + "screen": null, + "toolsinstalltype": null, + "toolsrunningstatus": "guestToolsNotRunning", + "toolsstatus": "toolsNotInstalled", + "toolsversion": "0", + "toolsversionstatus": null, + "toolsversionstatus2": null + }, + "guestheartbeatstatus": null, + "layout": { + "configfile": [], + "disk": [], + "dynamicproperty": [], + "dynamictype": null, + "logfile": [], + "snapshot": [], + "swapfile": null + }, + "layoutex": { + "disk": [], + "dynamicproperty": [], + "dynamictype": null, + "file": [], + "snapshot": [], + "timestamp": {} + }, + "name": "DC0_C0_RP0_VM0", + "network": [], + "overallstatus": "green", + "parentvapp": null, + "permission": [], + "recenttask": [], + "resourcepool": { + "_moId": "resgroup-26", + "name": "Resources" + }, + "rootsnapshot": [], + "runtime": { + "boottime": null, + "cleanpoweroff": null, + "connectionstate": "connected", + "consolidationneeded": false, + "cryptostate": null, + "dasvmprotection": null, + "device": [], + "dynamicproperty": [], + "dynamictype": null, + "faulttolerancestate": null, + "featuremask": [], + "featurerequirement": [], + "host": { + "_moId": "host-47", + "name": "DC0_C0_H2" + }, + "instantclonefrozen": null, + "maxcpuusage": null, + "maxmemoryusage": null, + "memoryoverhead": null, + "minrequiredevcmodekey": null, + "needsecondaryreason": null, + "nummksconnections": 0, + "offlinefeaturerequirement": [], + "onlinestandby": false, + "paused": null, + "powerstate": "poweredOn", + "question": null, + "quiescedforkparent": null, + "recordreplaystate": null, + "snapshotinbackground": null, + "suspendinterval": null, + "suspendtime": null, + "toolsinstallermounted": false, + "vflashcacheallocation": null + }, + "snapshot": null, + "storage": { + "dynamicproperty": [], + "dynamictype": null, + "perdatastoreusage": [], + "timestamp": {} + }, + "summary": { + "config": {}, + "customvalue": [], + "dynamicproperty": [], + "dynamictype": null, + "guest": {}, + "overallstatus": "green", + "quickstats": {}, + "runtime": {}, + "storage": {}, + "vm": {} + }, + "tag": [], + "triggeredalarmstate": [], + "value": [] + }, + "DC0_C0_RP0_VM1_f7c371d6-2003-5a48-9859-3bc9a8b08908": { + "alarmactionsenabled": null, + "ansible_host": "None", + "ansible_ssh_host": "None", + "ansible_uuid": "64b6ca93-f35f-4749-abeb-fc1fabae6c79", + "availablefield": [], + "capability": { + "bootoptionssupported": false, + "bootretryoptionssupported": false, + "changetrackingsupported": false, + "consolepreferencessupported": false, + "cpufeaturemasksupported": false, + "disablesnapshotssupported": false, + "diskonlysnapshotonsuspendedvmsupported": null, + "disksharessupported": false, + "dynamicproperty": [], + "dynamictype": null, + "featurerequirementsupported": false, + "guestautolocksupported": false, + "hostbasedreplicationsupported": false, + "locksnapshotssupported": false, + "memoryreservationlocksupported": false, + "memorysnapshotssupported": false, + "multiplecorespersocketsupported": false, + "multiplesnapshotssupported": false, + "nestedhvsupported": false, + "npivwwnonnonrdmvmsupported": false, + "pervmevcsupported": null, + "poweredoffsnapshotssupported": false, + "poweredonmonitortypechangesupported": false, + "quiescedsnapshotssupported": false, + "recordreplaysupported": false, + "reverttosnapshotsupported": false, + "s1acpimanagementsupported": false, + "securebootsupported": null, + "sesparsedisksupported": false, + "settingdisplaytopologysupported": false, + "settingscreenresolutionsupported": false, + "settingvideoramsizesupported": false, + "snapshotconfigsupported": false, + "snapshotoperationssupported": false, + "swapplacementsupported": false, + "toolsautoupdatesupported": false, + "toolssynctimesupported": false, + "virtualexecusageignored": null, + "virtualmmuusageignored": null, + "virtualmmuusagesupported": false, + "vmnpivwwndisablesupported": false, + "vmnpivwwnsupported": false, + "vmnpivwwnupdatesupported": false, + "vpmcsupported": false + }, + "config": { + "alternateguestname": "", + "annotation": null, + "bootoptions": null, + "changetrackingenabled": null, + "changeversion": "", + "consolepreferences": null, + "contentlibiteminfo": null, + "cpuaffinity": null, + "cpuallocation": {}, + "cpufeaturemask": [], + "cpuhotaddenabled": null, + "cpuhotremoveenabled": null, + "createdate": null, + "datastoreurl": [], + "defaultpowerops": {}, + "dynamicproperty": [], + "dynamictype": null, + "extraconfig": [], + "files": {}, + "firmware": null, + "flags": {}, + "forkconfiginfo": null, + "ftinfo": null, + "guestautolockenabled": null, + "guestfullname": "otherGuest", + "guestid": "otherGuest", + "guestintegrityinfo": null, + "guestmonitoringmodeinfo": null, + "hardware": {}, + "hotplugmemoryincrementsize": null, + "hotplugmemorylimit": null, + "initialoverhead": null, + "instanceuuid": "6132d223-1566-5921-bc3b-df91ece09a4d", + "keyid": null, + "latencysensitivity": null, + "locationid": null, + "managedby": null, + "maxmksconnections": null, + "memoryaffinity": null, + "memoryallocation": {}, + "memoryhotaddenabled": null, + "memoryreservationlockedtomax": null, + "messagebustunnelenabled": null, + "migrateencryption": null, + "modified": {}, + "name": "DC0_C0_RP0_VM1", + "nestedhvenabled": null, + "networkshaper": null, + "npivdesirednodewwns": null, + "npivdesiredportwwns": null, + "npivnodeworldwidename": [], + "npivonnonrdmdisks": null, + "npivportworldwidename": [], + "npivtemporarydisabled": null, + "npivworldwidenametype": null, + "repconfig": null, + "scheduledhardwareupgradeinfo": null, + "sgxinfo": null, + "swapplacement": null, + "swapstorageobjectid": null, + "template": false, + "tools": {}, + "uuid": "f7c371d6-2003-5a48-9859-3bc9a8b08908", + "vappconfig": null, + "vassertsenabled": null, + "vcpuconfig": [], + "version": "vmx-13", + "vflashcachereservation": null, + "vmstorageobjectid": null, + "vmxconfigchecksum": null, + "vpmcenabled": null + }, + "configissue": [], + "configstatus": "green", + "customvalue": [], + "datastore": [ + { + "_moId": "/tmp/govcsim-DC0-LocalDS_0-949174843@folder-5", + "name": "LocalDS_0" + } + ], + "effectiverole": [ + -1 + ], + "guest": { + "appheartbeatstatus": null, + "appstate": null, + "disk": [], + "dynamicproperty": [], + "dynamictype": null, + "generationinfo": [], + "guestfamily": null, + "guestfullname": null, + "guestid": null, + "guestkernelcrashed": null, + "guestoperationsready": null, + "gueststate": "", + "gueststatechangesupported": null, + "hostname": null, + "hwversion": null, + "interactiveguestoperationsready": null, + "ipaddress": null, + "ipstack": [], + "net": [], + "screen": null, + "toolsinstalltype": null, + "toolsrunningstatus": "guestToolsNotRunning", + "toolsstatus": "toolsNotInstalled", + "toolsversion": "0", + "toolsversionstatus": null, + "toolsversionstatus2": null + }, + "guestheartbeatstatus": null, + "layout": { + "configfile": [], + "disk": [], + "dynamicproperty": [], + "dynamictype": null, + "logfile": [], + "snapshot": [], + "swapfile": null + }, + "layoutex": { + "disk": [], + "dynamicproperty": [], + "dynamictype": null, + "file": [], + "snapshot": [], + "timestamp": {} + }, + "name": "DC0_C0_RP0_VM1", + "network": [], + "overallstatus": "green", + "parentvapp": null, + "permission": [], + "recenttask": [], + "resourcepool": { + "_moId": "resgroup-26", + "name": "Resources" + }, + "rootsnapshot": [], + "runtime": { + "boottime": null, + "cleanpoweroff": null, + "connectionstate": "connected", + "consolidationneeded": false, + "cryptostate": null, + "dasvmprotection": null, + "device": [], + "dynamicproperty": [], + "dynamictype": null, + "faulttolerancestate": null, + "featuremask": [], + "featurerequirement": [], + "host": { + "_moId": "host-33", + "name": "DC0_C0_H0" + }, + "instantclonefrozen": null, + "maxcpuusage": null, + "maxmemoryusage": null, + "memoryoverhead": null, + "minrequiredevcmodekey": null, + "needsecondaryreason": null, + "nummksconnections": 0, + "offlinefeaturerequirement": [], + "onlinestandby": false, + "paused": null, + "powerstate": "poweredOn", + "question": null, + "quiescedforkparent": null, + "recordreplaystate": null, + "snapshotinbackground": null, + "suspendinterval": null, + "suspendtime": null, + "toolsinstallermounted": false, + "vflashcacheallocation": null + }, + "snapshot": null, + "storage": { + "dynamicproperty": [], + "dynamictype": null, + "perdatastoreusage": [], + "timestamp": {} + }, + "summary": { + "config": {}, + "customvalue": [], + "dynamicproperty": [], + "dynamictype": null, + "guest": {}, + "overallstatus": "green", + "quickstats": {}, + "runtime": {}, + "storage": {}, + "vm": {} + }, + "tag": [], + "triggeredalarmstate": [], + "value": [] + }, + "DC0_H0_VM0_265104de-1472-547c-b873-6dc7883fb6cb": { + "alarmactionsenabled": null, + "ansible_host": "None", + "ansible_ssh_host": "None", + "ansible_uuid": "6616671b-16b0-494c-8201-737ca506790b", + "availablefield": [], + "capability": { + "bootoptionssupported": false, + "bootretryoptionssupported": false, + "changetrackingsupported": false, + "consolepreferencessupported": false, + "cpufeaturemasksupported": false, + "disablesnapshotssupported": false, + "diskonlysnapshotonsuspendedvmsupported": null, + "disksharessupported": false, + "dynamicproperty": [], + "dynamictype": null, + "featurerequirementsupported": false, + "guestautolocksupported": false, + "hostbasedreplicationsupported": false, + "locksnapshotssupported": false, + "memoryreservationlocksupported": false, + "memorysnapshotssupported": false, + "multiplecorespersocketsupported": false, + "multiplesnapshotssupported": false, + "nestedhvsupported": false, + "npivwwnonnonrdmvmsupported": false, + "pervmevcsupported": null, + "poweredoffsnapshotssupported": false, + "poweredonmonitortypechangesupported": false, + "quiescedsnapshotssupported": false, + "recordreplaysupported": false, + "reverttosnapshotsupported": false, + "s1acpimanagementsupported": false, + "securebootsupported": null, + "sesparsedisksupported": false, + "settingdisplaytopologysupported": false, + "settingscreenresolutionsupported": false, + "settingvideoramsizesupported": false, + "snapshotconfigsupported": false, + "snapshotoperationssupported": false, + "swapplacementsupported": false, + "toolsautoupdatesupported": false, + "toolssynctimesupported": false, + "virtualexecusageignored": null, + "virtualmmuusageignored": null, + "virtualmmuusagesupported": false, + "vmnpivwwndisablesupported": false, + "vmnpivwwnsupported": false, + "vmnpivwwnupdatesupported": false, + "vpmcsupported": false + }, + "config": { + "alternateguestname": "", + "annotation": null, + "bootoptions": null, + "changetrackingenabled": null, + "changeversion": "", + "consolepreferences": null, + "contentlibiteminfo": null, + "cpuaffinity": null, + "cpuallocation": {}, + "cpufeaturemask": [], + "cpuhotaddenabled": null, + "cpuhotremoveenabled": null, + "createdate": null, + "datastoreurl": [], + "defaultpowerops": {}, + "dynamicproperty": [], + "dynamictype": null, + "extraconfig": [], + "files": {}, + "firmware": null, + "flags": {}, + "forkconfiginfo": null, + "ftinfo": null, + "guestautolockenabled": null, + "guestfullname": "otherGuest", + "guestid": "otherGuest", + "guestintegrityinfo": null, + "guestmonitoringmodeinfo": null, + "hardware": {}, + "hotplugmemoryincrementsize": null, + "hotplugmemorylimit": null, + "initialoverhead": null, + "instanceuuid": "b4689bed-97f0-5bcd-8a4c-07477cc8f06f", + "keyid": null, + "latencysensitivity": null, + "locationid": null, + "managedby": null, + "maxmksconnections": null, + "memoryaffinity": null, + "memoryallocation": {}, + "memoryhotaddenabled": null, + "memoryreservationlockedtomax": null, + "messagebustunnelenabled": null, + "migrateencryption": null, + "modified": {}, + "name": "DC0_H0_VM0", + "nestedhvenabled": null, + "networkshaper": null, + "npivdesirednodewwns": null, + "npivdesiredportwwns": null, + "npivnodeworldwidename": [], + "npivonnonrdmdisks": null, + "npivportworldwidename": [], + "npivtemporarydisabled": null, + "npivworldwidenametype": null, + "repconfig": null, + "scheduledhardwareupgradeinfo": null, + "sgxinfo": null, + "swapplacement": null, + "swapstorageobjectid": null, + "template": false, + "tools": {}, + "uuid": "265104de-1472-547c-b873-6dc7883fb6cb", + "vappconfig": null, + "vassertsenabled": null, + "vcpuconfig": [], + "version": "vmx-13", + "vflashcachereservation": null, + "vmstorageobjectid": null, + "vmxconfigchecksum": null, + "vpmcenabled": null + }, + "configissue": [], + "configstatus": "green", + "customvalue": [], + "datastore": [ + { + "_moId": "/tmp/govcsim-DC0-LocalDS_0-949174843@folder-5", + "name": "LocalDS_0" + } + ], + "effectiverole": [ + -1 + ], + "guest": { + "appheartbeatstatus": null, + "appstate": null, + "disk": [], + "dynamicproperty": [], + "dynamictype": null, + "generationinfo": [], + "guestfamily": null, + "guestfullname": null, + "guestid": null, + "guestkernelcrashed": null, + "guestoperationsready": null, + "gueststate": "", + "gueststatechangesupported": null, + "hostname": null, + "hwversion": null, + "interactiveguestoperationsready": null, + "ipaddress": null, + "ipstack": [], + "net": [], + "screen": null, + "toolsinstalltype": null, + "toolsrunningstatus": "guestToolsNotRunning", + "toolsstatus": "toolsNotInstalled", + "toolsversion": "0", + "toolsversionstatus": null, + "toolsversionstatus2": null + }, + "guestheartbeatstatus": null, + "layout": { + "configfile": [], + "disk": [], + "dynamicproperty": [], + "dynamictype": null, + "logfile": [], + "snapshot": [], + "swapfile": null + }, + "layoutex": { + "disk": [], + "dynamicproperty": [], + "dynamictype": null, + "file": [], + "snapshot": [], + "timestamp": {} + }, + "name": "DC0_H0_VM0", + "network": [], + "overallstatus": "green", + "parentvapp": null, + "permission": [], + "recenttask": [], + "resourcepool": { + "_moId": "resgroup-22", + "name": "Resources" + }, + "rootsnapshot": [], + "runtime": { + "boottime": null, + "cleanpoweroff": null, + "connectionstate": "connected", + "consolidationneeded": false, + "cryptostate": null, + "dasvmprotection": null, + "device": [], + "dynamicproperty": [], + "dynamictype": null, + "faulttolerancestate": null, + "featuremask": [], + "featurerequirement": [], + "host": { + "_moId": "host-21", + "name": "DC0_H0" + }, + "instantclonefrozen": null, + "maxcpuusage": null, + "maxmemoryusage": null, + "memoryoverhead": null, + "minrequiredevcmodekey": null, + "needsecondaryreason": null, + "nummksconnections": 0, + "offlinefeaturerequirement": [], + "onlinestandby": false, + "paused": null, + "powerstate": "poweredOn", + "question": null, + "quiescedforkparent": null, + "recordreplaystate": null, + "snapshotinbackground": null, + "suspendinterval": null, + "suspendtime": null, + "toolsinstallermounted": false, + "vflashcacheallocation": null + }, + "snapshot": null, + "storage": { + "dynamicproperty": [], + "dynamictype": null, + "perdatastoreusage": [], + "timestamp": {} + }, + "summary": { + "config": {}, + "customvalue": [], + "dynamicproperty": [], + "dynamictype": null, + "guest": {}, + "overallstatus": "green", + "quickstats": {}, + "runtime": {}, + "storage": {}, + "vm": {} + }, + "tag": [], + "triggeredalarmstate": [], + "value": [] + }, + "DC0_H0_VM1_39365506-5a0a-5fd0-be10-9586ad53aaad": { + "alarmactionsenabled": null, + "ansible_host": "None", + "ansible_ssh_host": "None", + "ansible_uuid": "50401ff9-720a-4166-b9e6-d7cd0d9a4dc9", + "availablefield": [], + "capability": { + "bootoptionssupported": false, + "bootretryoptionssupported": false, + "changetrackingsupported": false, + "consolepreferencessupported": false, + "cpufeaturemasksupported": false, + "disablesnapshotssupported": false, + "diskonlysnapshotonsuspendedvmsupported": null, + "disksharessupported": false, + "dynamicproperty": [], + "dynamictype": null, + "featurerequirementsupported": false, + "guestautolocksupported": false, + "hostbasedreplicationsupported": false, + "locksnapshotssupported": false, + "memoryreservationlocksupported": false, + "memorysnapshotssupported": false, + "multiplecorespersocketsupported": false, + "multiplesnapshotssupported": false, + "nestedhvsupported": false, + "npivwwnonnonrdmvmsupported": false, + "pervmevcsupported": null, + "poweredoffsnapshotssupported": false, + "poweredonmonitortypechangesupported": false, + "quiescedsnapshotssupported": false, + "recordreplaysupported": false, + "reverttosnapshotsupported": false, + "s1acpimanagementsupported": false, + "securebootsupported": null, + "sesparsedisksupported": false, + "settingdisplaytopologysupported": false, + "settingscreenresolutionsupported": false, + "settingvideoramsizesupported": false, + "snapshotconfigsupported": false, + "snapshotoperationssupported": false, + "swapplacementsupported": false, + "toolsautoupdatesupported": false, + "toolssynctimesupported": false, + "virtualexecusageignored": null, + "virtualmmuusageignored": null, + "virtualmmuusagesupported": false, + "vmnpivwwndisablesupported": false, + "vmnpivwwnsupported": false, + "vmnpivwwnupdatesupported": false, + "vpmcsupported": false + }, + "config": { + "alternateguestname": "", + "annotation": null, + "bootoptions": null, + "changetrackingenabled": null, + "changeversion": "", + "consolepreferences": null, + "contentlibiteminfo": null, + "cpuaffinity": null, + "cpuallocation": {}, + "cpufeaturemask": [], + "cpuhotaddenabled": null, + "cpuhotremoveenabled": null, + "createdate": null, + "datastoreurl": [], + "defaultpowerops": {}, + "dynamicproperty": [], + "dynamictype": null, + "extraconfig": [], + "files": {}, + "firmware": null, + "flags": {}, + "forkconfiginfo": null, + "ftinfo": null, + "guestautolockenabled": null, + "guestfullname": "otherGuest", + "guestid": "otherGuest", + "guestintegrityinfo": null, + "guestmonitoringmodeinfo": null, + "hardware": {}, + "hotplugmemoryincrementsize": null, + "hotplugmemorylimit": null, + "initialoverhead": null, + "instanceuuid": "12f8928d-f144-5c57-89db-dd2d0902c9fa", + "keyid": null, + "latencysensitivity": null, + "locationid": null, + "managedby": null, + "maxmksconnections": null, + "memoryaffinity": null, + "memoryallocation": {}, + "memoryhotaddenabled": null, + "memoryreservationlockedtomax": null, + "messagebustunnelenabled": null, + "migrateencryption": null, + "modified": {}, + "name": "DC0_H0_VM1", + "nestedhvenabled": null, + "networkshaper": null, + "npivdesirednodewwns": null, + "npivdesiredportwwns": null, + "npivnodeworldwidename": [], + "npivonnonrdmdisks": null, + "npivportworldwidename": [], + "npivtemporarydisabled": null, + "npivworldwidenametype": null, + "repconfig": null, + "scheduledhardwareupgradeinfo": null, + "sgxinfo": null, + "swapplacement": null, + "swapstorageobjectid": null, + "template": false, + "tools": {}, + "uuid": "39365506-5a0a-5fd0-be10-9586ad53aaad", + "vappconfig": null, + "vassertsenabled": null, + "vcpuconfig": [], + "version": "vmx-13", + "vflashcachereservation": null, + "vmstorageobjectid": null, + "vmxconfigchecksum": null, + "vpmcenabled": null + }, + "configissue": [], + "configstatus": "green", + "customvalue": [], + "datastore": [ + { + "_moId": "/tmp/govcsim-DC0-LocalDS_0-949174843@folder-5", + "name": "LocalDS_0" + } + ], + "effectiverole": [ + -1 + ], + "guest": { + "appheartbeatstatus": null, + "appstate": null, + "disk": [], + "dynamicproperty": [], + "dynamictype": null, + "generationinfo": [], + "guestfamily": null, + "guestfullname": null, + "guestid": null, + "guestkernelcrashed": null, + "guestoperationsready": null, + "gueststate": "", + "gueststatechangesupported": null, + "hostname": null, + "hwversion": null, + "interactiveguestoperationsready": null, + "ipaddress": null, + "ipstack": [], + "net": [], + "screen": null, + "toolsinstalltype": null, + "toolsrunningstatus": "guestToolsNotRunning", + "toolsstatus": "toolsNotInstalled", + "toolsversion": "0", + "toolsversionstatus": null, + "toolsversionstatus2": null + }, + "guestheartbeatstatus": null, + "layout": { + "configfile": [], + "disk": [], + "dynamicproperty": [], + "dynamictype": null, + "logfile": [], + "snapshot": [], + "swapfile": null + }, + "layoutex": { + "disk": [], + "dynamicproperty": [], + "dynamictype": null, + "file": [], + "snapshot": [], + "timestamp": {} + }, + "name": "DC0_H0_VM1", + "network": [], + "overallstatus": "green", + "parentvapp": null, + "permission": [], + "recenttask": [], + "resourcepool": { + "_moId": "resgroup-22", + "name": "Resources" + }, + "rootsnapshot": [], + "runtime": { + "boottime": null, + "cleanpoweroff": null, + "connectionstate": "connected", + "consolidationneeded": false, + "cryptostate": null, + "dasvmprotection": null, + "device": [], + "dynamicproperty": [], + "dynamictype": null, + "faulttolerancestate": null, + "featuremask": [], + "featurerequirement": [], + "host": { + "_moId": "host-21", + "name": "DC0_H0" + }, + "instantclonefrozen": null, + "maxcpuusage": null, + "maxmemoryusage": null, + "memoryoverhead": null, + "minrequiredevcmodekey": null, + "needsecondaryreason": null, + "nummksconnections": 0, + "offlinefeaturerequirement": [], + "onlinestandby": false, + "paused": null, + "powerstate": "poweredOn", + "question": null, + "quiescedforkparent": null, + "recordreplaystate": null, + "snapshotinbackground": null, + "suspendinterval": null, + "suspendtime": null, + "toolsinstallermounted": false, + "vflashcacheallocation": null + }, + "snapshot": null, + "storage": { + "dynamicproperty": [], + "dynamictype": null, + "perdatastoreusage": [], + "timestamp": {} + }, + "summary": { + "config": {}, + "customvalue": [], + "dynamicproperty": [], + "dynamictype": null, + "guest": {}, + "overallstatus": "green", + "quickstats": {}, + "runtime": {}, + "storage": {}, + "vm": {} + }, + "tag": [], + "triggeredalarmstate": [], + "value": [] + } + } + }, + "all": { + "children": [ + "ungrouped", + "None", + "guests" + ] + }, + "guests": { + "hosts": [ + "DC0_C0_RP0_VM0_cd0681bf-2f18-5c00-9b9b-8197c0095348", + "DC0_C0_RP0_VM1_f7c371d6-2003-5a48-9859-3bc9a8b08908", + "DC0_H0_VM0_265104de-1472-547c-b873-6dc7883fb6cb", + "DC0_H0_VM1_39365506-5a0a-5fd0-be10-9586ad53aaad" + ] + } +} diff --git a/test/integration/targets/inventory_script/inventory.sh b/test/integration/targets/inventory_script/inventory.sh new file mode 100755 index 0000000..b3f1d03 --- /dev/null +++ b/test/integration/targets/inventory_script/inventory.sh @@ -0,0 +1,7 @@ +#!/bin/sh +# This script mimics the output from what the contrib/inventory/vmware_inventory.py +# dynamic inventory script produced. +# This ensures we are still covering the same code that the original tests gave us +# and subsequently ensures that ansible-inventory produces output consistent with +# that of a dynamic inventory script +cat inventory.json diff --git a/test/integration/targets/inventory_script/runme.sh b/test/integration/targets/inventory_script/runme.sh new file mode 100755 index 0000000..bb4fcea --- /dev/null +++ b/test/integration/targets/inventory_script/runme.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -eux + +diff -uw <(ansible-inventory -i inventory.sh --list --export) inventory.json diff --git a/test/integration/targets/inventory_yaml/aliases b/test/integration/targets/inventory_yaml/aliases new file mode 100644 index 0000000..b598321 --- /dev/null +++ b/test/integration/targets/inventory_yaml/aliases @@ -0,0 +1 @@ +shippable/posix/group3 diff --git a/test/integration/targets/inventory_yaml/empty.json b/test/integration/targets/inventory_yaml/empty.json new file mode 100644 index 0000000..e1ae068 --- /dev/null +++ b/test/integration/targets/inventory_yaml/empty.json @@ -0,0 +1,10 @@ +{ + "_meta": { + "hostvars": {} + }, + "all": { + "children": [ + "ungrouped" + ] + } +} diff --git a/test/integration/targets/inventory_yaml/runme.sh b/test/integration/targets/inventory_yaml/runme.sh new file mode 100755 index 0000000..a8818dd --- /dev/null +++ b/test/integration/targets/inventory_yaml/runme.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# handle empty/commented out group keys correctly https://github.com/ansible/ansible/issues/47254 +ANSIBLE_VERBOSITY=0 diff -w <(ansible-inventory -i ./test.yml --list) success.json + +ansible-inventory -i ./test_int_hostname.yml --list 2>&1 | grep 'Host pattern 1234 must be a string' diff --git a/test/integration/targets/inventory_yaml/success.json b/test/integration/targets/inventory_yaml/success.json new file mode 100644 index 0000000..a8b15f9 --- /dev/null +++ b/test/integration/targets/inventory_yaml/success.json @@ -0,0 +1,61 @@ +{ + "_meta": { + "hostvars": { + "alice": { + "status": "single" + }, + "bobby": { + "in_trouble": true, + "popular": false + }, + "cindy": { + "in_trouble": true, + "popular": true + }, + "greg": { + "in_trouble": true, + "popular": true + }, + "jan": { + "in_trouble": true, + "popular": false + }, + "marcia": { + "in_trouble": true, + "popular": true + }, + "peter": { + "in_trouble": true, + "popular": false + } + } + }, + "all": { + "children": [ + "cousins", + "kids", + "the-maid", + "ungrouped" + ] + }, + "cousins": { + "children": [ + "redheads" + ] + }, + "kids": { + "hosts": [ + "bobby", + "cindy", + "greg", + "jan", + "marcia", + "peter" + ] + }, + "the-maid": { + "hosts": [ + "alice" + ] + } +} diff --git a/test/integration/targets/inventory_yaml/test.yml b/test/integration/targets/inventory_yaml/test.yml new file mode 100644 index 0000000..9755396 --- /dev/null +++ b/test/integration/targets/inventory_yaml/test.yml @@ -0,0 +1,27 @@ +all: + children: + kids: + hosts: + marcia: + popular: True + jan: + popular: False + cindy: + popular: True + greg: + popular: True + peter: + popular: False + bobby: + popular: False + vars: + in_trouble: True + cousins: + children: + redheads: + hosts: + #oliver: # this used to cause an error and deliver incomplete inventory + the-maid: + hosts: + alice: + status: single diff --git a/test/integration/targets/inventory_yaml/test_int_hostname.yml b/test/integration/targets/inventory_yaml/test_int_hostname.yml new file mode 100644 index 0000000..d2285cb --- /dev/null +++ b/test/integration/targets/inventory_yaml/test_int_hostname.yml @@ -0,0 +1,5 @@ +all: + children: + kids: + hosts: + 1234: {} |