i have a problem xith a block in an ansible role
Extract of roles/apps_nifi/tasks/main.yml :
- debug:
msg: "nifi_extra_instances_name is defined"
when: nifi_extra_instances_name is defined
- debug:
msg: "nifi_extra_instances_name is not defined"
when: nifi_extra_instances_name is not defined
- name: Import variables for extra instances of Nifi
block:
- set_fact:
nifi_extra_instances_vars: "{{ item.value }}"
when: nifi_extra_instances_name in item.key
loop: "{{ lookup('dict', nifi_extra_instances, wantlist=True) }}"
- set_fact:
"{{ item.key }}": "{{ item.value }}"
loop: "{{ lookup('dict', nifi_extra_instances_vars , wantlist=True) }}"
when: nifi_extra_instances_vars is defined and nifi_extra_instances_vars|length > 0
when: nifi_extra_instances_name is defined
nifi_extra_instances_name is a variable setup when i call the role if it is needed.
plabook main.yml :
- hosts: nifi_hosts
become: yes
roles:
- { role: apps_nifi, tags: nifi }
- { role: apps_nifi-registry, tags: apps_nifi-registry }
- { role: apps_nifi-api, tags: apps_nifi-api, become: no }
#- { role: apps_nifi, tags: "nifi-burn", vars: { nifi_extra_instances_name: burn} }
So the variable nifi_extra_instances_name is not defined in this example, i expect that the code into "block" is not played :
TASK [apps_nifi : debug] **********************************************************************************************************************************************
Wednesday 14 October 2020 10:39:45 +0200 (0:00:12.496) 0:00:20.193 *****
skipping: [XXXXX]
TASK [apps_nifi : debug] **********************************************************************************************************************************************
Wednesday 14 October 2020 10:39:45 +0200 (0:00:00.052) 0:00:20.245 *****
ok: [XXXXX] => {
"msg": "nifi_extra_instances_name is not defined"
}
TASK [apps_nifi : set_fact] *******************************************************************************************************************************************
Wednesday 14 October 2020 10:39:45 +0200 (0:00:00.055) 0:00:20.300 *****
skipping: [XXXX] => (item={u'key': u'burn', u'value': {u'nifi_dir': u'/local/nifi-burn', u'nifi_web_https_port': 9445, u'nifi_ports': [u'9445:9445', u'9094:9094'], u'container_name': u'bdmpusher-burn'}})
TASK [apps_nifi : set_fact] *******************************************************************************************************************************************
Wednesday 14 October 2020 10:39:45 +0200 (0:00:00.058) 0:00:20.359 *****
fatal: [XXXXX]: FAILED! => {"msg": "An unhandled exception occurred while running the lookup plugin 'dict'. Error was a <class 'ansible.errors.AnsibleError'>, original message: with_dict expects a dict"}
any ideas please ?
A when
condition for a block (as well as for e.g. a role
stanza at play level, an import_task
...) is "pushed" up to every affected task. In other words, the condition for the full block is evaluated at every task level.
So the following piece of code:
- block:
- name: do a
debug:
msg: a
when: task_a_condition
- name: do b
debug:
msg: b
when: task_b_condition
when: block_condition
Is the exact equivalent of:
- name: do a
debug:
msg: a
when: task_a_condition and block_condition
- name: do b
debug:
msg: b
when: task_b_condition and block condition
Hence, all when conditions are analyzed in whatever case.
Moreover, when looping, the loop
expression is analyzed first to determine the needed iterations, then the when
condition is analyzed for every item. In your case, it leads to an error because nifi_extra_instances_vars
is undefined (and hence not a dict).
You can fix that on that specific task with the following loop expression leading to an empty loop when needed:
loop: "{{ query('dict', nifi_extra_instances | default({})) }}"
(note: using query
instead of lookup
automatically returns a list)
Now, if you really do not want those tasks to play at all even when skipped, there is IMO a better solution:
block
stanza.include_tasks
with the same when
condition as your current block. In this case it will only apply to the include statement itself, not to the individual tasks. Do not confuse with import_task
which would lead to the exact same result as the block for the current problem.