Reputation: 220
EDIT: I resolved this a different way by getting a checksum of the 7z contents and checking
a) if the directory existed b) if it did - did it's contents checksum match
I have an ansible playbook which uses a 7zip shell command, but I want to check if the 7z has been inflated already so I have the following
- name: Get zip listing
shell: '7z l {{ sz_file }} | tail -n +21 | head -n -2 | cut -c 54-'
register: sz_contents
- name: Compare zip listing to file contents
stat:
path: '{{ extract_dir }}/{{ item }}'
register: result
with_items: '{{ sz_contents.stdout_lines }}'
- name: Inflate 7z file if needed
shell: 7z x {{ sz_file }}
when: ???
I want the following to happen:
Upvotes: 0
Views: 1173
Reputation: 311750
It sounds like you want to make the extract task conditional on whether the compare tasks succeeds or fails, and you want the compare task to fail as soon as it finds a file that doesn't exist.
We can get most of the way there.
Normally, the stat
module doesn't trigger a failure when you point
it at a path that doesn't exist. For example, the following playbook:
- hosts: localhost
gather_facts: false
tasks:
- stat:
path: /does-not-exist
register: result
- debug:
var: result
Yields:
TASK [stat] ***********************************************************************************
ok: [localhost]
TASK [debug] **********************************************************************************
ok: [localhost] => {
"result": {
"changed": false,
"failed": false,
"stat": {
"exists": false
}
}
}
Ansible provides us with the failed_when
directive to control when a
task fails. This means we can rewrite your compare task to fail on a
missing file like this:
- name: Compare zip listing to file contents
stat:
path: '{{ extract_dir }}/{{ item }}'
register: result
failed_when: not result.stat.exists
ignore_errors: true
with_items: '{{ sz_contents.stdout_lines }}'
The failed_when
directive tells Ansible to consider the task
"failed" if the file passed to stat
doesn't exist, and the
ignore_errors
directive tells Ansible to continue executing the
playbook rather than aborting when the task fails.
We can make the extract task condition on this one with a simple
when
directive:
- name: Inflate 7z file if needed
shell: 7z x {{ sz_file }}
when: result is failed
The only problem with this solution is that Ansible won't exit a loop
when an individual item causes a failure, so it's going to check
through all of sz_contents.stdout_lines
regardless.
Update
I was discussing this issue on irc and @bcoca pointed out the when
is evaluated before register
, so we can actually get the behavior
you want by writing the compare task like this:
- name: Compare zip listing to file contents
stat:
path: '{{ extract_dir }}/{{ item }}'
register: result
when: result is defined or result is success
failed_when: not result.stat.exists
ignore_errors: true
with_items: '{{ sz_contents.stdout_lines }}'
The when
statement will cause all loop iterations after the first
failure to be skipped.
Upvotes: 1