From aa36b02ede1269acc64e06d5445cf7ee1a154eaf Mon Sep 17 00:00:00 2001 From: Mark Goddard Date: Tue, 12 May 2020 14:12:21 +0100 Subject: [PATCH] Fix fileglob plugin with non-existent subdirectory (#69451) Since Ansible 2.9.8, if the fileglob plugin is passed a path containing a subdirectory of a non-existent directory, it will fail. For example: lookup('fileglob', '/'): ok lookup('fileglob', '/foo'): (non-existent): ok lookup('fileglob', '/foo/bar'): (non-existent): FAIL The exact error depends on Python 2 or 3, but here is the error on Python 2: AttributeError: 'NoneType' object has no attribute 'endswith' And on Python 3: TypeError: expected str, bytes or os.PathLike object, not NoneType This change fixes the issue by skipping paths that are falsey before passing them to os.path.join(). Fixes: #69450 --- .../69451-fix-fileglob-nonexistent-subdirs.yaml | 4 ++++ lib/ansible/plugins/lookup/fileglob.py | 9 +++++---- test/integration/targets/fileglob/non_existent/play.yml | 6 ++++++ test/integration/targets/fileglob/runme.sh | 6 ++++++ 4 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/69451-fix-fileglob-nonexistent-subdirs.yaml create mode 100644 test/integration/targets/fileglob/non_existent/play.yml diff --git a/changelogs/fragments/69451-fix-fileglob-nonexistent-subdirs.yaml b/changelogs/fragments/69451-fix-fileglob-nonexistent-subdirs.yaml new file mode 100644 index 00000000000..7d12124664e --- /dev/null +++ b/changelogs/fragments/69451-fix-fileglob-nonexistent-subdirs.yaml @@ -0,0 +1,4 @@ +bugfixes: +- Fix an issue with the ``fileglob`` plugin where passing a subdirectory of + non-existent directory would cause it to fail - + https://github.com/ansible/ansible/issues/69450 diff --git a/lib/ansible/plugins/lookup/fileglob.py b/lib/ansible/plugins/lookup/fileglob.py index 2460ba15ddd..503973ce46a 100644 --- a/lib/ansible/plugins/lookup/fileglob.py +++ b/lib/ansible/plugins/lookup/fileglob.py @@ -72,8 +72,9 @@ class LookupModule(LookupBase): found_paths.append(p) for dwimmed_path in found_paths: - globbed = glob.glob(to_bytes(os.path.join(dwimmed_path, term_file), errors='surrogate_or_strict')) - ret.extend(to_text(g, errors='surrogate_or_strict') for g in globbed if os.path.isfile(g)) - if ret: - break + if dwimmed_path: + globbed = glob.glob(to_bytes(os.path.join(dwimmed_path, term_file), errors='surrogate_or_strict')) + ret.extend(to_text(g, errors='surrogate_or_strict') for g in globbed if os.path.isfile(g)) + if ret: + break return ret diff --git a/test/integration/targets/fileglob/non_existent/play.yml b/test/integration/targets/fileglob/non_existent/play.yml new file mode 100644 index 00000000000..e92dff5accf --- /dev/null +++ b/test/integration/targets/fileglob/non_existent/play.yml @@ -0,0 +1,6 @@ +- hosts: localhost + gather_facts: false + tasks: + - name: fileglob should be empty + assert: + that: q("fileglob", seed) | length == 0 diff --git a/test/integration/targets/fileglob/runme.sh b/test/integration/targets/fileglob/runme.sh index 1ca7e1b7adf..1e0297c79d0 100755 --- a/test/integration/targets/fileglob/runme.sh +++ b/test/integration/targets/fileglob/runme.sh @@ -7,3 +7,9 @@ for seed in play_adj play_adj_subdir somepath/play_adj_subsubdir in_role otherpa do ansible-playbook find_levels/play.yml -e "seed='${seed}'" "$@" done + +# non-existent paths +for seed in foo foo/bar foo/bar/baz +do + ansible-playbook non_existent/play.yml -e "seed='${seed}'" "$@" +done