I need to check if deploy.db file exists. If it does not exist, then I need to perform a set of tasks for which I'm using block.
Below is how i run the playbook
ansible-playbook test.yml -e Layer=APP -e BASEPATH="/logs" -e Filenames="file1,file2,file3"
Below is my complete playbook:
---
- name: "Play 1"
hosts: localhost
gather_facts: false
tasks:
- name: Construct
debug:
msg: "Run"
- block:
- stat: path="{{ BASEPATH }}/deploy.db"
register: currdb
- file: path="{{ BASEPATH }}/deploy.db" state=touch recurse=no
when: currdb.stat.exists == False
- shell: "echo done>>{{ BASEPATH }}/deploy.db"
when: currdb.stat.exists == False
when: Layer == 'APP'
with_items:
- "{{ Filenames.split(',') }}"
I'm getting the below error running the playbook:
ERROR! 'with_items' is not a valid attribute for a Block
The error appears to be in '/app/test.yml': line 9, column 6, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- block:
^ here
After researching a bit, I understand that neither with_items nor loop is supported by block module and the solution is to include task file.
I'm however, not sure how to get that to work. Can you please suggest what tweaks I need to inorder for my playbook to work ?
Considering i m on the latest version of Ansible are there other solutions.
Ansible allows you to loop over a list of hashes. This can be seen from the example given below.
A Playbook can have multiple Plays and a Play can have one or multiple Tasks. In a Task a Module is called, like the Modules in the previous chapter. The goal of a Play is to map a group of hosts to a list of Tasks.
For long running asynchronous tasks, it's good to set poll=0 so that Ansible can immediately jump to the next task after starting the current one without waiting for the result. Register: It is basically used to register the results on a task in a variable.
Save this answer. Show activity on this post. To answer your question: No, as of now Ansible can't run loops in parallel.
'with_items' is not a valid attribute for a Block
The error message says it all: you cannot loop over a block.
If you need to loop over a set of tasks, put them in a separate file and use include_tasks
Below is an implementation based on your example illustrating the solution.
Since your question and code lacks some precision and since I pointed out some bad practices, please note that:
filenames
you loop on (I inferred it was supposed to the deploy.db
file). Note the use of loop_control
to disambiguate the variable name in the included file (i.e. db_filename
).copy
in place of shell
and dropped the touch
phase.basepath
dir exists.unique
filter after filenames.split(',')
as well as a trim
filter on each value to remove possible duplicates and eventual spaces added by error in the coma separated list.not
keyword and bool
filter (for extra security) rather than a bare compare to a boolean False
value.Here is the included file create_db_each.yml
---
- name: Check if file exists
stat:
path: "{{ basepath }}/{{ db_filename }}"
register: currdb
- name: Create the file with "done" line if not present
copy:
content: "done"
dest: "{{ basepath }}/{{ db_filename }}"
when: not currdb.stat.exists | bool
used in the following create_db.yml
playbook
---
- name: "Create my dbs"
hosts: localhost
gather_facts: false
tasks:
- name: Make sure the base directory exists
file:
path: "{{ basepath }}"
state: directory
- name: load each db
include_tasks: "create_db_each.yml"
when: layer == 'APP'
loop: "{{ filenames.split(',') | unique | map('trim') }}"
loop_control:
loop_var: db_filename
which gives
notes:
OK
everywherefilenames
parameter value to illustrate the use of unique
and trim
$ ansible-playbook -e basepath=/tmp/my/base/path -e "filenames='a.bla, b.toto, c , z.txt,a.bla'" -e layer=APP create_db.yml
PLAY [Create my dbs] ************************************************
TASK [Make sure the base directory exists] **************************
changed: [localhost]
TASK [load each db] *************************************************
included: /home/olcla/Sources/ZZ_tests/ansitests/create_db_each.yml for localhost => (item=a.bla)
included: /home/olcla/Sources/ZZ_tests/ansitests/create_db_each.yml for localhost => (item=b.toto)
included: /home/olcla/Sources/ZZ_tests/ansitests/create_db_each.yml for localhost => (item=c)
included: /home/olcla/Sources/ZZ_tests/ansitests/create_db_each.yml for localhost => (item=z.txt)
TASK [Check if file exists] *****************************************
ok: [localhost]
TASK [Create the file with "done" line if not present] **************
changed: [localhost]
TASK [Check if file exists] *****************************************
ok: [localhost]
TASK [Create the file with "done" line if not present] **************
changed: [localhost]
TASK [Check if file exists] *****************************************
ok: [localhost]
TASK [Create the file with "done" line if not present] **************
changed: [localhost]
TASK [Check if file exists] *****************************************
ok: [localhost]
TASK [Create the file with "done" line if not present] **************
changed: [localhost]
PLAY RECAP **********************************************************
localhost: ok=13 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$ tree /tmp/my/base/path/
/tmp/my/base/path/
├── a.bla
├── b.toto
├── c
└── z.txt
$ for f in /tmp/my/base/path/*; do cat $f; echo; done
done
done
done
done
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With