Repository: ansible/ansible
Pull request: warn on walking through pathing issues
  fixes #25314

##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
- Feature Pull Request

##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below -->
find

##### ADDITIONAL INFO
```
ansible -m find -a 'path=/root warn=true' localhost
[WARNING]: find had a problem: [Errno 13] Permission denied: '/root'
localhost | SUCCESS => {
    "changed": false,
    "examined": 0,
    "files": [],
    "matched": 0,
    "msg": ""
}
```


Problem statement:
find module does not error when encountering a path with permission denied
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
find module

##### ANSIBLE VERSION
```
ansible 2.2.1.0
  config file = /home/ansible/DPP-Deployer_LVC_TEST/ansible.cfg
  configured module search path = Default w/o overrides
```

##### CONFIGURATION

##### OS / ENVIRONMENT
CentOS Linux release 7.3.1611 (Core)

##### SUMMARY
The find module does not return an error when encountering a permission denied error for a given path. The task finished correctly although a permission denied was encountered which should ideally result in an error. 

##### STEPS TO REPRODUCE
Prepare a test directory with a file
```bash
#mkdir /tmp/denied
#touch /tmp/denied/file
#chmod -R 600 /tmp/denied
```
Run Ansible find
```yaml
- find:
    paths: "/tmp/denied"
    recurse: yes
  register: files

- debug:
    msg: "Found Files:: {{ files }}"
```
Confusion ensues. 

##### EXPECTED RESULTS
find module would return an error due to permission denied of the given path. 

##### ACTUAL RESULTS
```yaml
ok: [192.168.0.144] => {
    "changed": false,
    "examined": 0,
    "files": [],
    "invocation": {
        "module_args": {
            "age": null,
            "age_stamp": "mtime",
            "contains": null,
            "file_type": "file",
            "follow": true,
            "get_checksum": false,
            "hidden": true,
            "paths": [
                "/tmp/denied/"
            ],
            "patterns": [
                "*"
            ],
            "recurse": true,
            "size": null,
            "use_regex": false
        },
        "module_name": "find"
    },
    "matched": 0,
    "msg": ""
}

ok: [192.168.0.144] => {
    "msg": "Found Files:: {u'files': [], u'msg': u'', u'changed': False, u'examined': 0, u'matched': 0}"
}
```

Hints from issue discussion:
Files identified in the description:
* [lib/ansible/modules/files/find.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/files/find.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
Files identified in the description:
* [`lib/ansible/modules/find.py`](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/find.py)

If these files are incorrect, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
We think this should give a warning instead of an error.

Commit message: Add 'warn' option to find to show pathing issues

  fixes #25314

Patch to review:
diff --git a/changelogs/fragments/find_warn.yml b/changelogs/fragments/find_warn.yml
new file mode 100644
index 00000000000000..d58bc68fcee4a7
--- /dev/null
+++ b/changelogs/fragments/find_warn.yml
@@ -0,0 +1,2 @@
+minor_changes:
+  - find now can optionally warn about issues encountered while traversing the requested paths.
diff --git a/lib/ansible/modules/find.py b/lib/ansible/modules/find.py
index 47bba1666c9cf8..9f6d79890e356e 100644
--- a/lib/ansible/modules/find.py
+++ b/lib/ansible/modules/find.py
@@ -129,6 +129,11 @@
             - Default is unlimited depth.
         type: int
         version_added: "2.6"
+    warn:
+        description:
+            - Retrun warnings on any issues encountered while walking the paths.
+        type: bool
+        version_added: "2.12"
 seealso:
 - module: ansible.windows.win_find
 '''
@@ -232,6 +237,7 @@
 
 from ansible.module_utils._text import to_text, to_native
 from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils._text import to_text
 
 
 def pfilter(f, patterns=None, excludes=None, use_regex=False):
@@ -390,6 +396,7 @@ def main():
             get_checksum=dict(type='bool', default=False),
             use_regex=dict(type='bool', default=False),
             depth=dict(type='int'),
+            warn=dict(type='bool'),
         ),
         supports_check_mode=True,
     )
@@ -433,13 +440,18 @@ def main():
     now = time.time()
     msg = ''
     looked = 0
+
+    def handle_errors(e):
+        if params['warn']:
+            module.warn('find had a problem: ' + to_text(e))
+
     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_errors, followlinks=params['follow']):
                 looked = looked + len(files) + len(dirs)
                 for fsobj in (files + dirs):
                     fsname = os.path.normpath(os.path.join(root, fsobj))


Code review comments:
diff_hunk: @@ -129,6 +129,11 @@
             - Default is unlimited depth.
         type: int
         version_added: "2.6"
+    warn:
+        description:
+            - Retrun warnings on any issues encountered while walking the paths.
path: lib/ansible/modules/find.py
text: @user1:
```suggestion
            - Return warnings on any issues encountered while walking the paths.
```