diff --git a/changelogs/fragments/82027_find.yml b/changelogs/fragments/82027_find.yml new file mode 100644 index 00000000000..a1b5cdbba37 --- /dev/null +++ b/changelogs/fragments/82027_find.yml @@ -0,0 +1,3 @@ +--- +bugfixes: + - find - do not fail on Permission errors (https://github.com/ansible/ansible/issues/82027). diff --git a/lib/ansible/modules/find.py b/lib/ansible/modules/find.py index c85d19e7b99..5e8e36a2327 100644 --- a/lib/ansible/modules/find.py +++ b/lib/ansible/modules/find.py @@ -262,6 +262,7 @@ skipped_paths: version_added: '2.12' ''' +import errno import fnmatch import grp import os @@ -446,10 +447,6 @@ def statinfo(st): } -def handle_walk_errors(e): - raise e - - def main(): module = AnsibleModule( argument_spec=dict( @@ -495,6 +492,12 @@ def main(): filelist = [] skipped = {} + def handle_walk_errors(e): + if e.errno in (errno.EPERM, errno.EACCES): + skipped[e.filename] = to_text(e) + return + raise e + if params['age'] is None: age = None else: diff --git a/test/integration/targets/find/aliases b/test/integration/targets/find/aliases index a6dafcf8cd8..aa171eb4fce 100644 --- a/test/integration/targets/find/aliases +++ b/test/integration/targets/find/aliases @@ -1 +1,4 @@ shippable/posix/group1 +destructive +needs/root +setup/always/setup_passlib_controller # required for setup_test_user diff --git a/test/integration/targets/find/meta/main.yml b/test/integration/targets/find/meta/main.yml index cb6005d042c..c384e11d076 100644 --- a/test/integration/targets/find/meta/main.yml +++ b/test/integration/targets/find/meta/main.yml @@ -1,3 +1,4 @@ dependencies: - prepare_tests + - setup_test_user - setup_remote_tmp_dir diff --git a/test/integration/targets/find/tasks/main.yml b/test/integration/targets/find/tasks/main.yml index 791a975e9b7..76e3615ab22 100644 --- a/test/integration/targets/find/tasks/main.yml +++ b/test/integration/targets/find/tasks/main.yml @@ -421,5 +421,61 @@ - '"{{ remote_tmp_dir_test }}/astest/.hidden.txt" in astest_list' - '"checksum" in result.files[0]' +# Test permission error is correctly handled by find module +- vars: + test_dir: /tmp/permission_test + block: + - name: Set up content + file: + path: "{{ test_dir }}/{{ item.name }}" + state: "{{ item.state }}" + mode: "{{ item.mode }}" + owner: "{{ item.owner | default(omit) }}" + group: "{{ item.group | default(omit) }}" + loop: + - name: readable + state: directory + owner: "{{ test_user_name }}" + mode: "1711" + - name: readable/1-unreadable + state: directory + mode: "0700" + - name: readable/2-readable + state: touch + owner: "{{ test_user_name }}" + mode: "0777" + + - name: Find a file in readable directory + find: + paths: "{{ test_dir }}/readable/" + patterns: "*" + recurse: true + register: permission_issue + become_user: "{{ test_user_name }}" + + - name: Find a file in readable directory + find: + paths: "{{ test_dir }}/readable/" + patterns: "*" + recurse: true + register: permission_issue + become_user: "{{ test_user_name }}" + become: yes + + - name: Check if the skipped_paths are populated correctly with permission error + assert: + that: + - permission_issue is success + - not permission_issue.changed + - permission_issue.skipped_paths|length == 1 + - "'{{ test_dir }}/readable/1-unreadable' in permission_issue.skipped_paths" + - "'Permission denied' in permission_issue.skipped_paths['{{ test_dir }}/readable/1-unreadable']" + - permission_issue.matched == 1 + always: + - name: cleanup test directory + file: + dest: "{{ test_dir }}" + state: absent + - name: Run mode tests import_tasks: mode.yml