Considering the following test playbook:
---
- name: Playbook
hosts: localhost
become: false
gather_facts: false
vars:
plugins:
- name: diff
enabled: true
dependencies:
- python3-jsonpatch
- python3-kubernetes
repository:
name: helm-diff
org: databus23
version: v3.9.6
- name: git
enabled: false
repository:
name: helm-git
org: aslafy-z
version: v0.16.0
tasks:
- name: Loop
block:
- name: List plugin names
ansible.builtin.debug:
msg: '{{ item.name }}'
when: item.enabled
with_items: '{{ plugins }}'
- name: List dependencies
ansible.builtin.debug:
msg: '{{ item }}'
with_items: "{{ plugins | selectattr('enabled', 'eq', true) | selectattr('dependencies', 'defined') | map(attribute='dependencies') }}"
Which produces the expected results:
TASK [List plugin names] ***
ok: [localhost] => (item={'name': 'diff', 'enabled': True, 'dependencies': ['python3-jsonpatch', 'python3-kubernetes'], 'repository': {'name': 'helm-diff', 'org': 'databus23'}, 'version': 'v3.9.6'}) =>
msg: diff
TASK [List dependencies] ***
ok: [localhost] => (item=python3-jsonpatch) =>
msg: python3-jsonpatch
ok: [localhost] => (item=python3-kubernetes) =>
msg: python3-kubernetes
Is there a better way to render the use of with_items
more compact into second task, ideally with a combined with
condition, as used into first task?
I will have multiple tasks using the same with_items
loops listed above, I don't know if there is a way to group multiple tasks under the same with_items
loop.
Edit: While @larks's suggestion is a great approach, I ended using the following conditions which IMO, produces a clean readable code:
tasks:
- name: Loop
block:
- name: List plugin names
ansible.builtin.debug:
msg: '{{ item.name }}'
loop: "{{ plugins }}"
when: item.enabled
- name: List dependencies
ansible.builtin.debug:
msg: '{{ item.dependencies }}'
loop: '{{ plugins }}'
when:
- item.enabled
- item.dependencies is defined
If you use the json_query
filter, you could write your task like this:
- name: List dependencies
ansible.builtin.debug:
msg: "{{ item }}"
loop: "{{ plugins | json_query('[].dependencies[]') }}"
That produces as output:
TASK [List dependencies] **********************************************************************************************************************
ok: [localhost] => (item=python3-jsonpatch) => {
"msg": "python3-jsonpatch"
}
ok: [localhost] => (item=python3-kubernetes) => {
"msg": "python3-kubernetes"
}
Depending on your goal, you could drop the loop
and instead write:
- name: List dependencies
ansible.builtin.debug:
msg: "{{ plugins | json_query('[].dependencies[]') }}"
Which produces a single merged list of dependencies:
TASK [List dependencies] **********************************************************************************************************************
ok: [localhost] => {
"msg": [
"python3-jsonpatch",
"python3-kubernetes"
]
}