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