diff --git a/changelogs/fragments/2913-archive-dest_state.yml b/changelogs/fragments/2913-archive-dest_state.yml new file mode 100644 index 0000000000..9e9e67434e --- /dev/null +++ b/changelogs/fragments/2913-archive-dest_state.yml @@ -0,0 +1,4 @@ +--- +minor_changes: + - archive - added ``dest_state`` return value to describe final state of ``dest`` after successful task execution + (https://github.com/ansible-collections/community.general/pull/2913). diff --git a/plugins/modules/files/archive.py b/plugins/modules/files/archive.py index a2d3376613..822ea1cd9d 100644 --- a/plugins/modules/files/archive.py +++ b/plugins/modules/files/archive.py @@ -137,6 +137,16 @@ state: The state of the input C(path). type: str returned: always +dest_state: + description: + - The state of the I(dest) file. + - C(absent) when the file does not exist. + - C(archive) when the file is an archive. + - C(compress) when the file is compressed, but not an archive. + - C(incomplete) when the file is an archive, but some files under I(path) were not found. + type: str + returned: success + version_added: 3.4.0 missing: description: Any files that were missing from the source. type: list @@ -435,6 +445,7 @@ class Archive(object): return { 'archived': [_to_native(p) for p in self.successes], 'dest': _to_native(self.destination), + 'dest_state': self.destination_state, 'changed': self.changed, 'arcroot': _to_native(self.root), 'missing': [_to_native(p) for p in self.not_found], diff --git a/tests/integration/targets/archive/tasks/broken-link.yml b/tests/integration/targets/archive/tasks/broken-link.yml deleted file mode 100644 index b1e0fb752b..0000000000 --- a/tests/integration/targets/archive/tasks/broken-link.yml +++ /dev/null @@ -1,22 +0,0 @@ ---- -- name: Create broken link - file: - src: /nowhere - dest: "{{ output_dir }}/nowhere.txt" - state: link - force: yes - -- name: Archive broken link (tar.gz) - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/archive_broken_link.tar.gz" - -- name: Archive broken link (tar.bz2) - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/archive_broken_link.tar.bz2" - -- name: Archive broken link (zip) - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/archive_broken_link.zip" diff --git a/tests/integration/targets/archive/tasks/main.yml b/tests/integration/targets/archive/tasks/main.yml index 35a8f1edf3..e0757b0ead 100644 --- a/tests/integration/targets/archive/tasks/main.yml +++ b/tests/integration/targets/archive/tasks/main.yml @@ -22,6 +22,7 @@ # along with Ansible. If not, see . # Make sure we start fresh +# Test setup - name: Ensure zip is present to create test archive (yum) yum: name=zip state=latest when: ansible_facts.pkg_mgr == 'yum' @@ -82,400 +83,45 @@ - sub - sub/subfile.txt -- name: archive using gz - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/archive_01.gz" - format: gz - register: archive_gz_result_01 - -- debug: msg="{{ archive_gz_result_01 }}" - -- name: verify that the files archived - file: path={{output_dir}}/archive_01.gz state=file - -- name: check if gz file exists and includes all text files - assert: - that: - - "{{ archive_gz_result_01.changed }}" - - "{{ 'archived' in archive_gz_result_01 }}" - - "{{ archive_gz_result_01['archived'] | length }} == 3" - -- name: archive using zip - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/archive_01.zip" - format: zip - register: archive_zip_result_01 - -- debug: msg="{{ archive_zip_result_01 }}" - -- name: verify that the files archived - file: path={{output_dir}}/archive_01.zip state=file - -- name: check if zip file exists - assert: - that: - - "{{ archive_zip_result_01.changed }}" - - "{{ 'archived' in archive_zip_result_01 }}" - - "{{ archive_zip_result_01['archived'] | length }} == 3" - -- name: archive using bz2 - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/archive_01.bz2" - format: bz2 - register: archive_bz2_result_01 - -- debug: msg="{{ archive_bz2_result_01 }}" - -- name: verify that the files archived - file: path={{output_dir}}/archive_01.bz2 state=file - -- name: check if bzip file exists - assert: - that: - - "{{ archive_bz2_result_01.changed }}" - - "{{ 'archived' in archive_bz2_result_01 }}" - - "{{ archive_bz2_result_01['archived'] | length }} == 3" - -- name: archive using xz - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/archive_01.xz" - format: xz - register: archive_xz_result_01 - -- debug: msg="{{ archive_xz_result_01 }}" - -- name: verify that the files archived - file: path={{output_dir}}/archive_01.xz state=file - -- name: check if xz file exists - assert: - that: - - "{{ archive_xz_result_01.changed }}" - - "{{ 'archived' in archive_xz_result_01 }}" - - "{{ archive_xz_result_01['archived'] | length }} == 3" - -- name: archive and set mode to 0600 - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/archive_02.gz" - format: gz - mode: "u+rwX,g-rwx,o-rwx" - register: archive_bz2_result_02 - -- name: Test that the file modes were changed - stat: - path: "{{ output_dir }}/archive_02.gz" - register: archive_02_gz_stat - -- debug: msg="{{ archive_02_gz_stat}}" - -- name: Test that the file modes were changed - assert: - that: - - archive_02_gz_stat is not changed - - "archive_02_gz_stat.stat.mode == '0600'" - - "'archived' in archive_bz2_result_02" - - "{{ archive_bz2_result_02['archived']| length}} == 3" - -- name: remove our gz - file: path="{{ output_dir }}/archive_02.gz" state=absent - - -- name: archive and set mode to 0600 - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/archive_02.zip" - format: zip - mode: "u+rwX,g-rwx,o-rwx" - register: archive_zip_result_02 - -- name: Test that the file modes were changed - stat: - path: "{{ output_dir }}/archive_02.zip" - register: archive_02_zip_stat - -- name: Test that the file modes were changed - assert: - that: - - archive_02_zip_stat is not changed - - "archive_02_zip_stat.stat.mode == '0600'" - - "'archived' in archive_zip_result_02" - - "{{ archive_zip_result_02['archived']| length}} == 3" - -- name: remove our zip - file: path="{{ output_dir }}/archive_02.zip" state=absent - - -- name: archive and set mode to 0600 - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/archive_02.bz2" - format: bz2 - mode: "u+rwX,g-rwx,o-rwx" - register: archive_bz2_result_02 - -- name: Test that the file modes were changed - stat: - path: "{{ output_dir }}/archive_02.bz2" - register: archive_02_bz2_stat - -- name: Test that the file modes were changed - assert: - that: - - archive_02_bz2_stat is not changed - - "archive_02_bz2_stat.stat.mode == '0600'" - - "'archived' in archive_bz2_result_02" - - "{{ archive_bz2_result_02['archived']| length}} == 3" - -- name: remove our bz2 - file: path="{{ output_dir }}/archive_02.bz2" state=absent - -- name: archive and set mode to 0600 - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/archive_02.xz" - format: xz - mode: "u+rwX,g-rwx,o-rwx" - register: archive_xz_result_02 - -- name: Test that the file modes were changed - stat: - path: "{{ output_dir }}/archive_02.xz" - register: archive_02_xz_stat - -- name: Test that the file modes were changed - assert: - that: - - archive_02_xz_stat is not changed - - "archive_02_xz_stat.stat.mode == '0600'" - - "'archived' in archive_xz_result_02" - - "{{ archive_xz_result_02['archived']| length}} == 3" - -- name: remove our xz - file: path="{{ output_dir }}/archive_02.xz" state=absent - -- name: archive multiple files as list - archive: - path: - - "{{ output_dir }}/empty.txt" - - "{{ output_dir }}/foo.txt" - - "{{ output_dir }}/bar.txt" - dest: "{{ output_dir }}/archive_list.gz" - format: gz - register: archive_gz_list_result - -- name: verify that the files archived - file: path={{output_dir}}/archive_list.gz state=file - -- name: check if gz file exists and includes all text files - assert: - that: - - "{{ archive_gz_list_result.changed }}" - - "{{ 'archived' in archive_gz_list_result }}" - - "{{ archive_gz_list_result['archived'] | length }} == 3" - -- name: remove our gz - file: path="{{ output_dir }}/archive_list.gz" state=absent - -- name: test that gz archive that contains non-ascii filenames - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/test-archive-nonascii-くらとみ.tar.gz" - format: gz - register: nonascii_result_0 - -- name: Check that file is really there - stat: - path: "{{ output_dir }}/test-archive-nonascii-くらとみ.tar.gz" - register: nonascii_stat0 - -- name: Assert that nonascii tests succeeded - assert: - that: - - nonascii_result_0 is changed - - "nonascii_stat0.stat.exists == true" - -- name: remove nonascii test - file: path="{{ output_dir }}/test-archive-nonascii-くらとみ.tar.gz" state=absent - -- name: test that bz2 archive that contains non-ascii filenames - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/test-archive-nonascii-くらとみ.bz2" - format: bz2 - register: nonascii_result_1 - -- name: Check that file is really there - stat: - path: "{{ output_dir }}/test-archive-nonascii-くらとみ.bz2" - register: nonascii_stat_1 - -- name: Assert that nonascii tests succeeded - assert: - that: - - nonascii_result_1 is changed - - "nonascii_stat_1.stat.exists == true" - -- name: remove nonascii test - file: path="{{ output_dir }}/test-archive-nonascii-くらとみ.bz2" state=absent - -- name: test that xz archive that contains non-ascii filenames - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/test-archive-nonascii-くらとみ.xz" - format: xz - register: nonascii_result_1 - -- name: Check that file is really there - stat: - path: "{{ output_dir }}/test-archive-nonascii-くらとみ.xz" - register: nonascii_stat_1 - -- name: Assert that nonascii tests succeeded - assert: - that: - - nonascii_result_1 is changed - - "nonascii_stat_1.stat.exists == true" - -- name: remove nonascii test - file: path="{{ output_dir }}/test-archive-nonascii-くらとみ.xz" state=absent - -- name: test that zip archive that contains non-ascii filenames - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/test-archive-nonascii-くらとみ.zip" - format: zip - register: nonascii_result_2 - -- name: Check that file is really there - stat: - path: "{{ output_dir }}/test-archive-nonascii-くらとみ.zip" - register: nonascii_stat_2 - -- name: Assert that nonascii tests succeeded - assert: - that: - - nonascii_result_2 is changed - - "nonascii_stat_2.stat.exists == true" - -- name: remove nonascii test - file: path="{{ output_dir }}/test-archive-nonascii-くらとみ.zip" state=absent - -- name: Test exclusion_patterns option - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/test-archive-exclusion-patterns.tgz" - exclusion_patterns: b?r.* - register: exclusion_patterns_result - -- name: Assert that exclusion_patterns only archives included files - assert: - that: - - exclusion_patterns_result is changed - - "'bar.txt' not in exclusion_patterns_result.archived" - -- name: Test that excluded paths do not influence archive root - archive: - path: - - "{{ output_dir }}/sub/subfile.txt" - - "{{ output_dir }}" - exclude_path: - - "{{ output_dir }}" - dest: "{{ output_dir }}/test-archive-root.tgz" - register: archive_root_result - -- name: Assert that excluded paths do not influence archive root - assert: - that: - - archive_root_result.arcroot != output_dir - -- name: Remove archive root test - file: - path: "{{ output_dir }}/test-archive-root.tgz" - state: absent - -- name: Test Single Target with format={{ item }} - archive: - path: "{{ output_dir }}/foo.txt" - dest: "{{ output_dir }}/test-single-target.{{ item }}" - format: "{{ item }}" - register: "single_target_test" - loop: - - zip - - tar - - gz - - bz2 - - xz - -# Dummy tests until ``dest_state`` result value can be implemented -- name: Assert that single target tests are effective - assert: - that: - - single_target_test.results[0] is changed - - single_target_test.results[1] is changed - - single_target_test.results[2] is changed - - single_target_test.results[3] is changed - - single_target_test.results[4] is changed - -- name: Retrieve contents of single target archives - ansible.builtin.unarchive: - src: "{{ output_dir }}/test-single-target.zip" - dest: . - list_files: true - check_mode: true - ignore_errors: true - register: single_target_test_contents - -- name: Assert that file names in single-file zip archives are preserved - assert: - that: - - "'oo.txt' not in single_target_test_contents.files" - - "'foo.txt' in single_target_test_contents.files" - # ``unarchive`` fails for RHEL and FreeBSD on ansible 2.x - when: single_target_test_contents is success and single_target_test_contents is not skipped - -- name: Remove single target test with format={{ item }} - file: - path: "{{ output_dir }}/test-single-target.{{ item }}" - state: absent - loop: - - zip - - tar - - gz - - bz2 - - xz - -- name: Test that missing files result in incomplete state - archive: - path: - - "{{ output_dir }}/*.txt" - - "{{ output_dir }}/dne.txt" - exclude_path: "{{ output_dir }}/foo.txt" - dest: "{{ output_dir }}/test-incomplete-archive.tgz" - register: incomplete_archive_result - -- name: Assert that incomplete archive has incomplete state - assert: - that: - - incomplete_archive_result is changed - - "'{{ output_dir }}/dne.txt' in incomplete_archive_result.missing" - - "'{{ output_dir }}/foo.txt' not in incomplete_archive_result.missing" - -- name: Remove incomplete archive - file: - path: "{{ output_dir }}/test-incomplete-archive.tgz" - state: absent - +- name: Define formats to test + set_fact: + formats: + - tar + - zip + - gz + - bz2 + - xz + +# Run tests +- name: Run core tests + include_tasks: + file: ../tests/core.yml + loop: "{{ formats }}" + loop_control: + loop_var: format + +- name: Run exclusions tests + include_tasks: + file: ../tests/exclusions.yml + loop: "{{ formats }}" + loop_control: + loop_var: format + +- name: Run remove tests + include_tasks: + file: ../tests/remove.yml + loop: "{{ formats }}" + loop_control: + loop_var: format + +- name: Run broken link tests + include_tasks: + file: ../tests/broken-link.yml + loop: "{{ formats }}" + loop_control: + loop_var: format + +# Test cleanup - name: Remove backports.lzma if previously installed (pip) pip: name=backports.lzma state=absent when: backports_lzma_pip is changed - -- name: import remove tests - import_tasks: remove.yml - -- name: import broken-link tests - import_tasks: broken-link.yml diff --git a/tests/integration/targets/archive/tasks/remove.yml b/tests/integration/targets/archive/tasks/remove.yml deleted file mode 100644 index 9f085e901a..0000000000 --- a/tests/integration/targets/archive/tasks/remove.yml +++ /dev/null @@ -1,186 +0,0 @@ ---- -- name: archive using gz and remove src files - archive: - path: "{{ output_dir }}/*.txt" - dest: "{{ output_dir }}/archive_remove_01.gz" - format: gz - remove: yes - register: archive_remove_result_01 - -- debug: msg="{{ archive_remove_result_01 }}" - -- name: verify that the files archived - file: path={{ output_dir }}/archive_remove_01.gz state=file - -- name: check if gz file exists and includes all text files and src files has been removed - assert: - that: - - "{{ archive_remove_result_01.changed }}" - - "{{ 'archived' in archive_remove_result_01 }}" - - "{{ archive_remove_result_01['archived'] | length }} == 3" - -- name: remove our gz - file: path="{{ output_dir }}/archive_remove_01.gz" state=absent - -- name: check if src files has been removed - assert: - that: - - "'{{ output_dir }}/{{ item }}' is not exists" - with_items: - - foo.txt - - bar.txt - - empty.txt - -- name: prep our files again - copy: src={{ item }} dest={{ output_dir }}/{{ item }} - with_items: - - foo.txt - - bar.txt - - empty.txt - -- name: create a temporary directory to be check if it will be removed - file: - path: "{{ output_dir }}/tmpdir" - state: directory - -- name: prep our files in tmpdir - copy: src={{ item }} dest={{ output_dir }}/tmpdir/{{ item }} - with_items: - - foo.txt - - bar.txt - - empty.txt - -- name: archive using gz and remove src directory - archive: - path: "{{ output_dir }}/tmpdir" - dest: "{{ output_dir }}/archive_remove_02.gz" - format: gz - remove: yes - register: archive_remove_result_02 - -- debug: msg="{{ archive_remove_result_02 }}" - -- name: verify that the files archived - file: path={{ output_dir }}/archive_remove_02.gz state=file - -- name: check if gz file exists and includes all text files - assert: - that: - - "{{ archive_remove_result_02.changed }}" - - "{{ 'archived' in archive_remove_result_02 }}" - - "{{ archive_remove_result_02['archived'] | length }} == 3" - -- name: remove our gz - file: path="{{ output_dir }}/archive_remove_02.gz" state=absent - -- name: check if src folder has been removed - assert: - that: - - "'{{ output_dir }}/tmpdir' is not exists" - -- name: create temporary directory again - file: - path: "{{ output_dir }}/tmpdir" - state: directory - -- name: prep our files in tmpdir again - copy: src={{ item }} dest={{ output_dir }}/tmpdir/{{ item }} - with_items: - - foo.txt - - bar.txt - - empty.txt - -- name: archive using gz and remove src directory excluding one file - archive: - path: "{{ output_dir }}/tmpdir/*" - dest: "{{ output_dir }}/archive_remove_03.gz" - format: gz - remove: yes - exclude_path: "{{ output_dir }}/tmpdir/empty.txt" - register: archive_remove_result_03 - -- debug: msg="{{ archive_remove_result_03 }}" - -- name: verify that the files archived - file: path={{ output_dir }}/archive_remove_03.gz state=file - -- name: check if gz file exists and includes all text files - assert: - that: - - "{{ archive_remove_result_03.changed }}" - - "{{ 'archived' in archive_remove_result_03 }}" - - "{{ archive_remove_result_03['archived'] | length }} == 2" - -- name: remove our gz - file: path="{{ output_dir }}/archive_remove_03.gz" state=absent - -- name: verify that excluded file is still present - file: path={{ output_dir }}/tmpdir/empty.txt state=file - -- name: prep our files in tmpdir again - copy: src={{ item }} dest={{ output_dir }}/tmpdir/{{ item }} - with_items: - - foo.txt - - bar.txt - - empty.txt - - sub - - sub/subfile.txt - -- name: archive using gz and remove src directory - archive: - path: - - "{{ output_dir }}/tmpdir/*.txt" - - "{{ output_dir }}/tmpdir/sub/*" - dest: "{{ output_dir }}/archive_remove_04.gz" - format: gz - remove: yes - exclude_path: "{{ output_dir }}/tmpdir/sub/subfile.txt" - register: archive_remove_result_04 - -- debug: msg="{{ archive_remove_result_04 }}" - -- name: verify that the files archived - file: path={{ output_dir }}/archive_remove_04.gz state=file - -- name: remove our gz - file: path="{{ output_dir }}/archive_remove_04.gz" state=absent - -- name: verify that excluded sub file is still present - file: path={{ output_dir }}/tmpdir/sub/subfile.txt state=file - -- name: prep our files in tmpdir again - copy: src={{ item }} dest={{ output_dir }}/tmpdir/{{ item }} - with_items: - - foo.txt - - bar.txt - - empty.txt - - sub - - sub/subfile.txt - -- name: archive using gz and remove src directory - archive: - path: - - "{{ output_dir }}/tmpdir/" - dest: "{{ output_dir }}/archive_remove_05.gz" - format: gz - remove: yes - exclude_path: "{{ output_dir }}/tmpdir/sub/subfile.txt" - register: archive_remove_result_05 - -- name: verify that the files archived - file: path={{ output_dir }}/archive_remove_05.gz state=file - -- name: Verify source files were removed - file: - path: "{{ output_dir }}/tmpdir" - state: absent - register: archive_source_file_removal_05 - -- name: Verify that task status is success - assert: - that: - - archive_remove_result_05 is success - - archive_source_file_removal_05 is not changed - -- name: remove our gz - file: path="{{ output_dir }}/archive_remove_05.gz" state=absent diff --git a/tests/integration/targets/archive/tests/broken-link.yml b/tests/integration/targets/archive/tests/broken-link.yml new file mode 100644 index 0000000000..cc1e07aaf1 --- /dev/null +++ b/tests/integration/targets/archive/tests/broken-link.yml @@ -0,0 +1,31 @@ +--- +- block: + - name: Create link - broken link ({{ format }}) + file: + src: /nowhere + dest: "{{ output_dir }}/nowhere.txt" + state: link + force: yes + + - name: Archive - broken link ({{ format }}) + archive: + path: "{{ output_dir }}/*.txt" + dest: "{{ output_dir }}/archive_broken_link.{{ format }}" + format: "{{ format }}" + + - name: Verify archive exists - broken link ({{ format }}) + file: + path: "{{ output_dir }}/archive_broken_link.{{ format }}" + state: file + + - name: Remove archive - broken link ({{ format }}) + file: + path: "{{ output_dir }}/archive_broken_link.{{ format }}" + state: absent + + - name: Remove link - broken link ({{ format }}) + file: + path: "{{ output_dir }}/nowhere.txt" + state: absent + # 'zip' does not support symlink's + when: format != 'zip' diff --git a/tests/integration/targets/archive/tests/core.yml b/tests/integration/targets/archive/tests/core.yml new file mode 100644 index 0000000000..f12e5083cc --- /dev/null +++ b/tests/integration/targets/archive/tests/core.yml @@ -0,0 +1,188 @@ +#################################################################### +# WARNING: These are designed specifically for Ansible tests # +# and should not be used as examples of how to write Ansible roles # +#################################################################### + +# Test code for the archive module. +# (c) 2017, Abhijeet Kasurde + +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +# Make sure we start fresh + +# Core functionality tests +- name: Archive - no options ({{ format }}) + archive: + path: "{{ output_dir }}/*.txt" + dest: "{{ output_dir }}/archive_no_opts.{{ format }}" + format: "{{ format }}" + register: archive_no_options + +- name: Verify that archive exists - no options ({{ format }}) + file: + path: "{{output_dir}}/archive_no_opts.{{ format }}" + state: file + +- name: Verify that archive result is changed and includes all files - no options ({{ format }}) + assert: + that: + - archive_no_options is changed + - "archive_no_options.dest_state == 'archive'" + - "{{ archive_no_options.archived | length }} == 3" + - +- name: Remove the archive - no options ({{ format }}) + file: + path: "{{ output_dir }}/archive_no_options.{{ format }}" + state: absent + +- name: Archive - file options ({{ format }}) + archive: + path: "{{ output_dir }}/*.txt" + dest: "{{ output_dir }}/archive_file_options.{{ format }}" + format: "{{ format }}" + mode: "u+rwX,g-rwx,o-rwx" + register: archive_file_options + +- name: Retrieve archive file information - file options ({{ format }}) + stat: + path: "{{ output_dir }}/archive_file_options.{{ format }}" + register: archive_file_options_stat + +- name: Test that the file modes were changed + assert: + that: + - archive_file_options_stat is not changed + - "archive_file_options.mode == '0600'" + - "{{ archive_file_options.archived | length }} == 3" + +- name: Remove the archive - file options ({{ format }}) + file: + path: "{{ output_dir }}/archive_file_options.{{ format }}" + state: absent + +- name: Archive - non-ascii ({{ format }}) + archive: + path: "{{ output_dir }}/*.txt" + dest: "{{ output_dir }}/archive_nonascii_くらとみ.{{ format }}" + format: "{{ format }}" + register: archive_nonascii + +- name: Retrieve archive file information - non-ascii ({{ format }}) + stat: + path: "{{ output_dir }}/archive_nonascii_くらとみ.{{ format }}" + register: archive_nonascii_stat + +- name: Test that archive exists - non-ascii ({{ format }}) + assert: + that: + - archive_nonascii is changed + - archive_nonascii_stat.stat.exists == true + +- name: Remove the archive - non-ascii ({{ format }}) + file: + path: "{{ output_dir }}/archive_nonascii_くらとみ.{{ format }}" + state: absent + +- name: Archive - single target ({{ format }}) + archive: + path: "{{ output_dir }}/foo.txt" + dest: "{{ output_dir }}/archive_single_target.{{ format }}" + format: "{{ format }}" + register: archive_single_target + +- name: Assert archive has correct state - single target ({{ format }}) + assert: + that: + - archive_single_target.dest_state == state_map[format] + vars: + state_map: + tar: archive + zip: archive + gz: compress + bz2: compress + xz: compress + +- block: + - name: Retrieve contents of archive - single target ({{ format }}) + ansible.builtin.unarchive: + src: "{{ output_dir }}/archive_single_target.{{ format }}" + dest: . + list_files: true + check_mode: true + ignore_errors: true + register: archive_single_target_contents + + - name: Assert that file names are preserved - single target ({{ format }}) + assert: + that: + - "'oo.txt' not in archive_single_target_contents.files" + - "'foo.txt' in archive_single_target_contents.files" + # ``unarchive`` fails for RHEL and FreeBSD on ansible 2.x + when: archive_single_target_contents is success and archive_single_target_contents is not skipped + when: "format == 'zip'" + +- name: Remove archive - single target ({{ format }}) + file: + path: "{{ output_dir }}/archive_single_target.{{ format }}" + state: absent + +- name: Archive - path list ({{ format }}) + archive: + path: + - "{{ output_dir }}/empty.txt" + - "{{ output_dir }}/foo.txt" + - "{{ output_dir }}/bar.txt" + dest: "{{ output_dir }}/archive_path_list.{{ format }}" + format: "{{ format }}" + register: archive_path_list + +- name: Verify that archive exists - path list ({{ format }}) + file: + path: "{{output_dir}}/archive_path_list.{{ format }}" + state: file + +- name: Assert that archive contains all files - path list ({{ format }}) + assert: + that: + - archive_path_list is changed + - "{{ archive_path_list.archived | length }} == 3" + +- name: Remove archive - path list ({{ format }}) + file: + path: "{{ output_dir }}/archive_path_list.{{ format }}" + state: absent + +- name: Archive - missing paths ({{ format }}) + archive: + path: + - "{{ output_dir }}/*.txt" + - "{{ output_dir }}/dne.txt" + exclude_path: "{{ output_dir }}/foo.txt" + dest: "{{ output_dir }}/archive_missing_paths.{{ format }}" + format: "{{ format }}" + register: archive_missing_paths + +- name: Assert that incomplete archive has incomplete state - missing paths ({{ format }}) + assert: + that: + - archive_missing_paths is changed + - "archive_missing_paths.dest_state == 'incomplete'" + - "'{{ output_dir }}/dne.txt' in archive_missing_paths.missing" + - "'{{ output_dir }}/foo.txt' not in archive_missing_paths.missing" + +- name: Remove archive - missing paths ({{ format }}) + file: + path: "{{ output_dir }}/archive_missing_paths.{{ format }}" + state: absent diff --git a/tests/integration/targets/archive/tests/exclusions.yml b/tests/integration/targets/archive/tests/exclusions.yml new file mode 100644 index 0000000000..0b65f85851 --- /dev/null +++ b/tests/integration/targets/archive/tests/exclusions.yml @@ -0,0 +1,40 @@ +--- +- name: Archive - exclusion patterns ({{ format }}) + archive: + path: "{{ output_dir }}/*.txt" + dest: "{{ output_dir }}/archive_exclusion_patterns.{{ format }}" + format: "{{ format }}" + exclusion_patterns: b?r.* + register: archive_exclusion_patterns + +- name: Assert that only included files are archived - exclusion patterns ({{ format }}) + assert: + that: + - archive_exclusion_patterns is changed + - "'bar.txt' not in archive_exclusion_patterns.archived" + +- name: Remove archive - exclusion patterns ({{ format }}) + file: + path: "{{ output_dir }}/archive_exclusion_patterns.{{ format }}" + state: absent + +- name: Archive - exclude path ({{ format }}) + archive: + path: + - "{{ output_dir }}/sub/subfile.txt" + - "{{ output_dir }}" + exclude_path: + - "{{ output_dir }}" + dest: "{{ output_dir }}/archive_exclude_paths.{{ format }}" + format: "{{ format }}" + register: archive_excluded_paths + +- name: Assert that excluded paths do not influence archive root - exclude path ({{ format }}) + assert: + that: + - archive_excluded_paths.arcroot != output_dir + +- name: Remove archive - exclude path ({{ format }}) + file: + path: "{{ output_dir }}/archive_exclude_paths.{{ format }}" + state: absent diff --git a/tests/integration/targets/archive/tests/remove.yml b/tests/integration/targets/archive/tests/remove.yml new file mode 100644 index 0000000000..26849ac850 --- /dev/null +++ b/tests/integration/targets/archive/tests/remove.yml @@ -0,0 +1,207 @@ +--- +- name: Archive - remove source files ({{ format }}) + archive: + path: "{{ output_dir }}/*.txt" + dest: "{{ output_dir }}/archive_remove_source_files.{{ format }}" + format: "{{ format }}" + remove: yes + register: archive_remove_source_files + +- name: Verify archive exists - remove source files ({{ format }}) + file: + path: "{{ output_dir }}/archive_remove_source_files.{{ format }}" + state: file + +- name: Verify all files were archived - remove source files ({{ format }}) + assert: + that: + - archive_remove_source_files is changed + - "{{ archive_remove_source_files.archived | length }} == 3" + +- name: Remove Archive - remove source files ({{ format }}) + file: + path: "{{ output_dir }}/archive_remove_source_files.{{ format }}" + state: absent + +- name: Assert that source files were removed - remove source files ({{ format }}) + assert: + that: + - "'{{ output_dir }}/{{ item }}' is not exists" + with_items: + - foo.txt + - bar.txt + - empty.txt + +- name: Copy source files - remove source directory ({{ format }}) + copy: + src: "{{ item }}" + dest: "{{ output_dir }}/{{ item }}" + with_items: + - foo.txt + - bar.txt + - empty.txt + +- name: Create temporary directory - remove source directory ({{ format }}) + file: + path: "{{ output_dir }}/tmpdir" + state: directory + +- name: Copy source files to temporary directory - remove source directory ({{ format }}) + copy: + src: "{{ item }}" + dest: "{{ output_dir }}/tmpdir/{{ item }}" + with_items: + - foo.txt + - bar.txt + - empty.txt + +- name: Archive - remove source directory ({{ format }}) + archive: + path: "{{ output_dir }}/tmpdir" + dest: "{{ output_dir }}/archive_remove_source_directory.{{ format }}" + format: "{{ format }}" + remove: yes + register: archive_remove_source_directory + +- name: Verify archive exists - remove source directory ({{ format }}) + file: + path: "{{ output_dir }}/archive_remove_source_directory.{{ format }}" + state: file + +- name: Verify archive contains all files - remove source directory ({{ format }}) + assert: + that: + - archive_remove_source_directory is changed + - "{{ archive_remove_source_directory.archived | length }} == 3" + +- name: Remove archive - remove source directory ({{ format }}) + file: + path: "{{ output_dir }}/archive_remove_source_directory.{{ format }}" + state: absent + +- name: Verify source directory was removed - remove source directory ({{ format }}) + assert: + that: + - "'{{ output_dir }}/tmpdir' is not exists" + +- name: Create temporary directory - remove source excluding path ({{ format }}) + file: + path: "{{ output_dir }}/tmpdir" + state: directory + +- name: Copy source files to temporary directory - remove source excluding path ({{ format }}) + copy: + src: "{{ item }}" + dest: "{{ output_dir }}/tmpdir/{{ item }}" + with_items: + - foo.txt + - bar.txt + - empty.txt + +- name: Archive - remove source excluding path ({{ format }}) + archive: + path: "{{ output_dir }}/tmpdir/*" + dest: "{{ output_dir }}/archive_remove_source_excluding_path.{{ format }}" + format: "{{ format }}" + remove: yes + exclude_path: "{{ output_dir }}/tmpdir/empty.txt" + register: archive_remove_source_excluding_path + +- name: Verify archive exists - remove source excluding path ({{ format }}) + file: + path: "{{ output_dir }}/archive_remove_source_excluding_path.{{ format }}" + state: file + +- name: Verify all files except excluded are archived - remove source excluding path ({{ format }}) + assert: + that: + - archive_remove_source_excluding_path is changed + - "{{ archive_remove_source_excluding_path.archived | length }} == 2" + +- name: Remove archive - remove source excluding path ({{ format }}) + file: + path: "{{ output_dir }}/archive_remove_source_excluding_path.{{ format }}" + state: absent + +- name: Verify that excluded file still exists - remove source excluding path ({{ format }}) + file: + path: "{{ output_dir }}/tmpdir/empty.txt" + state: file + +- name: Copy source files to temporary directory - remove source excluding sub path ({{ format }}) + copy: + src: "{{ item }}" + dest: "{{ output_dir }}/tmpdir/{{ item }}" + with_items: + - foo.txt + - bar.txt + - empty.txt + - sub + - sub/subfile.txt + +- name: Archive - remove source excluding sub path ({{ format }}) + archive: + path: + - "{{ output_dir }}/tmpdir/*.txt" + - "{{ output_dir }}/tmpdir/sub/*" + dest: "{{ output_dir }}/archive_remove_source_excluding_sub_path.{{ format }}" + format: "{{ format }}" + remove: yes + exclude_path: "{{ output_dir }}/tmpdir/sub/subfile.txt" + register: archive_remove_source_excluding_sub_path + +- name: Verify archive exists - remove source excluding sub path ({{ format }}) + file: + path: "{{ output_dir }}/archive_remove_source_excluding_sub_path.{{ format }}" + state: file + +- name: Remove archive - remove source excluding sub path ({{ format }}) + file: + path: "{{ output_dir }}/archive_remove_source_excluding_sub_path.{{ format }}" + state: absent + +- name: Verify that sub path still exists - remove source excluding sub path ({{ format }}) + file: + path: "{{ output_dir }}/tmpdir/sub/subfile.txt" + state: file + +- name: Copy source files to temporary directory - remove source with nested paths ({{ format }}) + copy: + src: "{{ item }}" + dest: "{{ output_dir }}/tmpdir/{{ item }}" + with_items: + - foo.txt + - bar.txt + - empty.txt + - sub + - sub/subfile.txt + +- name: Archive - remove source with nested paths ({{ format }}) + archive: + path: "{{ output_dir }}/tmpdir/" + dest: "{{ output_dir }}/archive_remove_source_nested_paths.{{ format }}" + format: "{{ format }}" + remove: yes + register: archive_remove_nested_paths + +- name: Verify archive exists - remove source with nested paths ({{ format }}) + file: + path: "{{ output_dir }}/archive_remove_source_nested_paths.{{ format }}" + state: file + +- name: Verify source files were removed - remove source with nested paths ({{ format }}) + file: + path: "{{ output_dir }}/tmpdir" + state: absent + register: archive_remove_nested_paths_status + +- name: Assert tasks status - remove source with nested paths ({{ format }}) + assert: + that: + - archive_remove_nested_paths is success + - archive_remove_nested_paths_status is not changed + +- name: Remove archive - remove source with nested paths ({{ format }}) + file: + path: "{{ output_dir }}/archive_remove_source_nested_paths.{{ format }}" + state: absent