diff --git a/library/files/unarchive b/library/files/unarchive index 661f389969..ab04e57475 100644 --- a/library/files/unarchive +++ b/library/files/unarchive @@ -43,7 +43,13 @@ options: required: false choices: [ "yes", "no" ] default: "yes" -author: Dylan Martin + creates: + description: + - a filename, when it already exists, this step will B(not) be run. + required: no + default: null + version_added: "1.6" +author: Dylan Martin todo: - detect changed/unchanged for .zip files - handle common unarchive args, like preserve owner/timestamp etc... @@ -168,6 +174,7 @@ def main(): original_basename = dict(required=False), # used to handle 'dest is a directory' via template, a slight hack dest = dict(required=True), copy = dict(default=True, type='bool'), + creates = dict(required=False), ), add_file_common_args=True, ) @@ -175,6 +182,7 @@ def main(): src = os.path.expanduser(module.params['src']) dest = os.path.expanduser(module.params['dest']) copy = module.params['copy'] + creates = module.params['creates'] # did tar file arrive? if not os.path.exists(src): @@ -185,6 +193,20 @@ def main(): if not os.access(src, os.R_OK): module.fail_json(msg="Source '%s' not readable" % src) + if creates: + # do not run the command if the line contains creates=filename + # and the filename already exists. This allows idempotence + # of command executions. + v = os.path.expanduser(creates) + if os.path.exists(v): + module.exit_json( + stdout="skipped, since %s exists" % v, + skipped=True, + changed=False, + stderr=False, + rc=0 + ) + # is dest OK to receive tar file? if not os.path.exists(os.path.dirname(dest)): module.fail_json(msg="Destination directory '%s' does not exist" % (os.path.dirname(dest))) diff --git a/test/integration/roles/test_unarchive/tasks/main.yml b/test/integration/roles/test_unarchive/tasks/main.yml index 817096617b..56b31e6b2d 100644 --- a/test/integration/roles/test_unarchive/tasks/main.yml +++ b/test/integration/roles/test_unarchive/tasks/main.yml @@ -64,6 +64,33 @@ - name: remove our tar.gz unarchive destination file: path={{output_dir}}/test-unarchive-tar-gz state=absent +- name: create our tar.gz unarchive destination for creates + file: path={{output_dir}}/test-unarchive-tar-gz state=directory + +- name: unarchive a tar.gz file with creates set + unarchive: src={{output_dir}}/test-unarchive.tar.gz dest={{output_dir | expanduser}}/test-unarchive-tar-gz copy=no creates={{output_dir}}/test-unarchive-tar-gz/foo-unarchive.txt + register: unarchive02b + +- name: verify that the file was marked as changed + assert: + that: + - "unarchive02b.changed == true" + +- name: verify that the file was unarchived + file: path={{output_dir}}/test-unarchive-tar-gz/foo-unarchive.txt state=file + +- name: unarchive a tar.gz file with creates over an existing file + unarchive: src={{output_dir}}/test-unarchive.tar.gz dest={{output_dir | expanduser}}/test-unarchive-tar-gz copy=no creates={{output_dir}}/test-unarchive-tar-gz/foo-unarchive.txt + register: unarchive02c + +- name: verify that the file was not marked as changed + assert: + that: + - "unarchive02c.changed == false" + +- name: remove our tar.gz unarchive destination + file: path={{output_dir}}/test-unarchive-tar-gz state=absent + - name: create our zip unarchive destination file: path={{output_dir}}/test-unarchive-zip state=directory