From 1e27d4052a95d8f19c63d6a37909b3ec690ac832 Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Mon, 18 Jan 2021 09:33:51 -0500 Subject: [PATCH] fix inventory source parse error handling (#73160) fixes #51025 added test cases --- ..._inventory_source_parse_error_handling.yml | 2 ++ lib/ansible/inventory/manager.py | 21 ++++++++++++------- test/integration/targets/inventory/runme.sh | 12 +++++++++++ 3 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 changelogs/fragments/fix_inventory_source_parse_error_handling.yml diff --git a/changelogs/fragments/fix_inventory_source_parse_error_handling.yml b/changelogs/fragments/fix_inventory_source_parse_error_handling.yml new file mode 100644 index 00000000000..6782a7529f7 --- /dev/null +++ b/changelogs/fragments/fix_inventory_source_parse_error_handling.yml @@ -0,0 +1,2 @@ +bugfixes: + - Correct the inventory source error parse handling, specifically make the config INVENTORY_ANY_UNPARSED_IS_FAILED work as expected. diff --git a/lib/ansible/inventory/manager.py b/lib/ansible/inventory/manager.py index cfc38180848..8849a8c185a 100644 --- a/lib/ansible/inventory/manager.py +++ b/lib/ansible/inventory/manager.py @@ -306,19 +306,24 @@ class InventoryManager(object): failures.append({'src': source, 'plugin': plugin_name, 'exc': AnsibleError(e), 'tb': tb}) else: display.vvv("%s declined parsing %s as it did not pass its verify_file() method" % (plugin_name, source)) - else: - if not parsed and failures: + + if not parsed: + # only warn/error if NOT using the default or using it and the file is present + # TODO: handle 'non file' inventorya and detect vs hardcode default + if source != '/etc/ansible/hosts' or os.path.exists(source): + + if failures: # only if no plugin processed files should we show errors. for fail in failures: display.warning(u'\n* Failed to parse %s with %s plugin: %s' % (to_text(fail['src']), fail['plugin'], to_text(fail['exc']))) if 'tb' in fail: display.vvv(to_text(fail['tb'])) - if C.INVENTORY_ANY_UNPARSED_IS_FAILED: - raise AnsibleError(u'Completely failed to parse inventory source %s' % (source)) - if not parsed: - if source != '/etc/ansible/hosts' or os.path.exists(source): - # only warn if NOT using the default and if using it, only if the file is present - display.warning("Unable to parse %s as an inventory source" % source) + + # final erorr/warning on inventory source failure + if C.INVENTORY_ANY_UNPARSED_IS_FAILED: + raise AnsibleError(u'Completely failed to parse inventory source %s' % (source)) + else: + display.warning("Unable to parse %s as an inventory source" % source) # clear up, jic self._inventory.current_source = None diff --git a/test/integration/targets/inventory/runme.sh b/test/integration/targets/inventory/runme.sh index 02b6bca4e0d..1f5470cfa36 100755 --- a/test/integration/targets/inventory/runme.sh +++ b/test/integration/targets/inventory/runme.sh @@ -37,3 +37,15 @@ ANSIBLE_TRANSFORM_INVALID_GROUP_CHARS=never ansible-playbook -i ../../inventory # test extra vars ansible-inventory -i testhost, -i ./extra_vars_constructed.yml --list -e 'from_extras=hey ' "$@"|grep '"example": "hellohey"' + +# test parse inventory fail is not an error per config +ANSIBLE_INVENTORY_UNPARSED_FAILED=False ANSIBLE_INVENTORY_ANY_UNPARSED_IS_FAILED=False ansible -m ping localhost -i /idontexist "$@" + +# test no inventory parse is an error with var +[ "$(ANSIBLE_INVENTORY_UNPARSED_FAILED=True ANSIBLE_INVENTORY_ANY_UNPARSED_IS_FAILED=False ansible -m ping localhost -i /idontexist)" != "0" ] + +# test single inventory no parse is not an error with var +ANSIBLE_INVENTORY_UNPARSED_FAILED=True ANSIBLE_INVENTORY_ANY_UNPARSED_IS_FAILED=False ansible -m ping localhost -i /idontexist -i ../../invenotory "$@" + +# test single inventory no parse is an error with any var +[ "$(ANSIBLE_INVENTORY_ANY_UNPARSED_IS_FAILED=True ansible -m ping localhost -i /idontexist -i ../../invenotory)" != "0" ]