From 4f0e2fff957c67415958e71a03fe4fc7dabce87e Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Tue, 10 Nov 2020 11:46:15 -0500 Subject: [PATCH] avoid fatal exception on invalid collection name (#72296) * avoid fatal exception on invalid collection name used in ansible-doc filter --- .../skip_invalid_coll_name_when_listing.yml | 2 ++ lib/ansible/collections/list.py | 34 ++++++++++++------- test/integration/targets/ansible-doc/runme.sh | 7 ++++ 3 files changed, 30 insertions(+), 13 deletions(-) create mode 100644 changelogs/fragments/skip_invalid_coll_name_when_listing.yml diff --git a/changelogs/fragments/skip_invalid_coll_name_when_listing.yml b/changelogs/fragments/skip_invalid_coll_name_when_listing.yml new file mode 100644 index 00000000000..3883795e00a --- /dev/null +++ b/changelogs/fragments/skip_invalid_coll_name_when_listing.yml @@ -0,0 +1,2 @@ +bugfixes: + - Skip invalid collection names when listing in ansible-doc instead of throwing exception. Issue#72257 diff --git a/lib/ansible/collections/list.py b/lib/ansible/collections/list.py index 8e8bc664901..a1d99017067 100644 --- a/lib/ansible/collections/list.py +++ b/lib/ansible/collections/list.py @@ -8,6 +8,7 @@ import os from collections import defaultdict +from ansible.errors import AnsibleError from ansible.collections import is_collection_path from ansible.module_utils._text import to_bytes from ansible.utils.collection_loader import AnsibleCollectionConfig @@ -54,6 +55,17 @@ def list_collection_dirs(search_paths=None, coll_filter=None): :return: list of collection directory paths """ + collection = None + namespace = None + if coll_filter is not None: + if '.' in coll_filter: + try: + (namespace, collection) = coll_filter.split('.') + except ValueError: + raise AnsibleError("Invalid collection pattern supplied: %s" % coll_filter) + else: + namespace = coll_filter + collections = defaultdict(dict) for path in list_valid_collection_paths(search_paths): @@ -62,32 +74,28 @@ def list_collection_dirs(search_paths=None, coll_filter=None): b_coll_root = to_bytes(os.path.join(path, 'ansible_collections')) if os.path.exists(b_coll_root) and os.path.isdir(b_coll_root): - coll = None - if coll_filter is None: + + if namespace is None: namespaces = os.listdir(b_coll_root) else: - if '.' in coll_filter: - (nsp, coll) = coll_filter.split('.') - else: - nsp = coll_filter - namespaces = [nsp] + namespaces = [namespace] for ns in namespaces: b_namespace_dir = os.path.join(b_coll_root, to_bytes(ns)) if os.path.isdir(b_namespace_dir): - if coll is None: + if collection is None: colls = os.listdir(b_namespace_dir) else: - colls = [coll] + colls = [collection] - for collection in colls: + for mycoll in colls: # skip dupe collections as they will be masked in execution - if collection not in collections[ns]: - b_coll = to_bytes(collection) + if mycoll not in collections[ns]: + b_coll = to_bytes(mycoll) b_coll_dir = os.path.join(b_namespace_dir, b_coll) if is_collection_path(b_coll_dir): - collections[ns][collection] = b_coll_dir + collections[ns][mycoll] = b_coll_dir yield b_coll_dir diff --git a/test/integration/targets/ansible-doc/runme.sh b/test/integration/targets/ansible-doc/runme.sh index 7d203825ea7..c4bea83d4c3 100755 --- a/test/integration/targets/ansible-doc/runme.sh +++ b/test/integration/targets/ansible-doc/runme.sh @@ -18,6 +18,13 @@ current_out="$(ansible-doc --playbook-dir ./ testns.testcol.fakemodule)" expected_out="$(cat fakemodule.output)" test "$current_out" == "$expected_out" +# ensure we do work with valid collection name for list +ansible-doc --list testns.testcol --playbook-dir ./ 2>&1 | grep -v "Invalid collection pattern" + +# ensure we dont break on invalid collection name for list +ansible-doc --list testns.testcol.fakemodule --playbook-dir ./ 2>&1 | grep "Invalid collection pattern" + + # test listing diff plugin types from collection for ptype in cache inventory lookup vars do