diff --git a/changelogs/fragments/67340-slurp_error_message.yml b/changelogs/fragments/67340-slurp_error_message.yml new file mode 100644 index 00000000000..a67344e8a55 --- /dev/null +++ b/changelogs/fragments/67340-slurp_error_message.yml @@ -0,0 +1,2 @@ +bugfixes: +- "slurp - Fix error messages for unreadable files and directories(https://github.com/ansible/ansible/issues/67340)." diff --git a/lib/ansible/modules/slurp.py b/lib/ansible/modules/slurp.py index a216b651451..fd64860d32e 100644 --- a/lib/ansible/modules/slurp.py +++ b/lib/ansible/modules/slurp.py @@ -77,6 +77,7 @@ source: ''' import base64 +import errno import os from ansible.module_utils.basic import AnsibleModule @@ -91,13 +92,16 @@ def main(): ) source = module.params['src'] - if not os.path.exists(source): - module.fail_json(msg="file not found: %s" % source) - if not os.access(source, os.R_OK): - module.fail_json(msg="file is not readable: %s" % source) + try: + os.stat(source) + with open(source, 'rb') as source_fh: + source_content = source_fh.read() + except (IOError, OSError) as e: + if e.errno == errno.ENOENT: + module.fail_json(msg="file not found: %s" % source) + elif e.errno == errno.EACCES: + module.fail_json(msg="file is not readable: %s" % source) - with open(source, 'rb') as source_fh: - source_content = source_fh.read() data = base64.b64encode(source_content) module.exit_json(content=data, source=source, encoding='base64') diff --git a/test/integration/targets/slurp/defaults/main.yml b/test/integration/targets/slurp/defaults/main.yml new file mode 100644 index 00000000000..05d1041e760 --- /dev/null +++ b/test/integration/targets/slurp/defaults/main.yml @@ -0,0 +1 @@ +become_test_user: testuser diff --git a/test/integration/targets/slurp/handlers/main.yml b/test/integration/targets/slurp/handlers/main.yml new file mode 100644 index 00000000000..eeda7cedb55 --- /dev/null +++ b/test/integration/targets/slurp/handlers/main.yml @@ -0,0 +1,6 @@ +- name: remove test user and their home dir + user: + name: "{{ become_test_user }}" + state: absent + remove: yes + force: yes diff --git a/test/integration/targets/slurp/tasks/main.yml b/test/integration/targets/slurp/tasks/main.yml index 4f3556fad44..97f3561e215 100644 --- a/test/integration/targets/slurp/tasks/main.yml +++ b/test/integration/targets/slurp/tasks/main.yml @@ -96,3 +96,7 @@ - "slurp_no_args is failed" - "slurp_no_args.msg" - "slurp_no_args is not changed" + +# Ensure unreadable file and directory handling and error messages +# https://github.com/ansible/ansible/issues/67340 +- import_tasks: 'test_unreadable.yml' diff --git a/test/integration/targets/slurp/tasks/test_unreadable.yml b/test/integration/targets/slurp/tasks/test_unreadable.yml new file mode 100644 index 00000000000..12a8e5c844e --- /dev/null +++ b/test/integration/targets/slurp/tasks/test_unreadable.yml @@ -0,0 +1,52 @@ +- name: create test user + user: + name: "{{ become_test_user }}" + create_home: yes + notify: + - "remove test user and their home dir" + +- name: create unreadable file + copy: + content: "Hello, World!" + dest: /tmp/qux.txt + mode: 0600 + owner: root + +- name: test slurp unreadable file + slurp: + src: '/tmp/qux.txt' + register: slurp_unreadable_file + become: true + become_user: "{{ become_test_user }}" + become_method: su + ignore_errors: true + +- name: check slurp unreadable file result + assert: + that: + - "slurp_unreadable_file is failed" + - "slurp_unreadable_file.msg is regex('^file is not readable:')" + - "slurp_unreadable_file is not changed" + +- name: create unreadable directory + file: + path: /tmp/test_data + state: directory + mode: 0700 + owner: root + +- name: test slurp unreadable directory + slurp: + src: /tmp/test_data + register: slurp_unreadable_dir + become: true + become_user: "{{ become_test_user }}" + become_method: su + ignore_errors: true + +- name: check slurp unreadable directory result + assert: + that: + - "slurp_unreadable_dir is failed" + - "slurp_unreadable_dir.msg is regex('^file is not readable:')" + - "slurp_unreadable_dir is not changed"