From 35ff4ea95b4d5fc3bbb633162ca11050a951b68a Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Thu, 6 May 2021 16:14:33 -0400 Subject: [PATCH] warn on walking through pathing issues (#74514) * warn show pathing issues when wallking through provided paths moved issues from msg to actual warnings AND a specific return field fixes #25314 Co-authored-by: Sam Doran --- changelogs/fragments/find_walk_warnings.yml | 2 ++ lib/ansible/modules/find.py | 30 +++++++++++++++----- test/integration/targets/find/tasks/main.yml | 3 +- 3 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 changelogs/fragments/find_walk_warnings.yml diff --git a/changelogs/fragments/find_walk_warnings.yml b/changelogs/fragments/find_walk_warnings.yml new file mode 100644 index 00000000000..248aa976395 --- /dev/null +++ b/changelogs/fragments/find_walk_warnings.yml @@ -0,0 +1,2 @@ +bugfixes: + - find does not ignore errors from os.walk anymore and issues warnings as expected. diff --git a/lib/ansible/modules/find.py b/lib/ansible/modules/find.py index 47bba1666c9..6841274e119 100644 --- a/lib/ansible/modules/find.py +++ b/lib/ansible/modules/find.py @@ -220,6 +220,12 @@ examined: returned: success type: int sample: 34 +skipped_paths: + description: skipped paths and reasons they were skipped + returned: success + type: dict + sample: {"/laskdfj": "'/laskdfj' is not a directory"} + version_added: '2.12' ''' import fnmatch @@ -372,6 +378,10 @@ def statinfo(st): } +def handle_walk_errors(e): + raise e + + def main(): module = AnsibleModule( argument_spec=dict( @@ -407,6 +417,7 @@ def main(): params['patterns'] = ['*'] filelist = [] + skipped = {} if params['age'] is None: age = None @@ -431,15 +442,16 @@ def main(): module.fail_json(size=params['size'], msg="failed to process size") now = time.time() - msg = '' + msg = 'All paths examined' looked = 0 + has_warnings = False for npath in params['paths']: npath = os.path.expanduser(os.path.expandvars(npath)) try: if not os.path.isdir(npath): raise Exception("'%s' is not a directory" % to_native(npath)) - for root, dirs, files in os.walk(npath, followlinks=params['follow']): + for root, dirs, files in os.walk(npath, onerror=handle_walk_errors, followlinks=params['follow']): looked = looked + len(files) + len(dirs) for fsobj in (files + dirs): fsname = os.path.normpath(os.path.join(root, fsobj)) @@ -456,7 +468,9 @@ def main(): try: st = os.lstat(fsname) except (IOError, OSError) as e: - msg += "Skipped entry '%s' due to this access issue: %s\n" % (fsname, to_text(e)) + module.warn("Skipped entry '%s' due to this access issue: %s\n" % (fsname, to_text(e))) + skipped[fsname] = to_text(e) + has_warnings = True continue r = {'path': fsname} @@ -498,12 +512,14 @@ def main(): if not params['recurse']: break except Exception as e: - warn = "Skipped '%s' path due to this access issue: %s\n" % (npath, to_text(e)) - module.warn(warn) - msg += warn + module.warn("Skipped '%s' path due to this access issue: %s\n" % (npath, to_text(e))) + skipped[npath] = to_text(e) + has_warnings = True + if has_warnings: + msg = 'Not all paths examined, check warnings for details' matched = len(filelist) - module.exit_json(files=filelist, changed=False, msg=msg, matched=matched, examined=looked) + module.exit_json(files=filelist, changed=False, msg=msg, matched=matched, examined=looked, skipped_paths=skipped) if __name__ == '__main__': diff --git a/test/integration/targets/find/tasks/main.yml b/test/integration/targets/find/tasks/main.yml index dad88b1f583..366ef312535 100644 --- a/test/integration/targets/find/tasks/main.yml +++ b/test/integration/targets/find/tasks/main.yml @@ -207,7 +207,8 @@ - assert: that: - failed_path.files == [] - - failed_path.msg.startswith("Skipped '{{mypath}}' path due to this access issue") + - 'failed_path.msg == "Not all paths examined, check warnings for details"' + - mypath in failed_path.skipped_paths - name: test number of examined directories/files block: