1

I use following files: variable file: db.yml

x86_64:  
  alpine:
    version: 3.15.0
  debian:
    version: 11.3.0

aarch64:
  alpine:
    version: 3.15.0
  debian:
    version: 11.3.0

playbook: playbook.yml

---
- name: "Playbook" 
  hosts: localhost
  connection: local
  gather_facts: no

  tasks:
  - name: Import variables
    ansible.builtin.include_vars:
      file: db.yml
      name: db

  - name: DENUG >>> db
    debug:
      var: db


  - name: DENUG >>> db
    debug:
      var: db[item].alpine
    loop: "{{ db.keys()|list }}"
    when: db[item].alpine is defined

Output:

ok: [localhost] => (item=x86_64) => {
    "ansible_loop_var": "item",
    "db[item].alpine": {
        "version": "3.15.0"
    },
    "item": "x86_64"
}
ok: [localhost] => (item=aarch64) => {
    "ansible_loop_var": "item",
    "db[item].alpine": {
        "version": "3.15.0"
    },
    "item": "aarch64"
}

Now I have converted db.yml to new style as following:

x86_64:
  - distribution: alpine
    version: 3.15.0
  - distribution: debian
    version: 11.3.0

aarch64:
  - distribution: alpine
    version: 3.15.0
  - distribution: debian
    version: 11.3.0

Question:
How to run similar command as following:

- name: DENUG >>> db
    debug:
      var: db[item].alpine
    loop: "{{ db.keys()|list }}"
    when: db[item].alpine is defined  

and get the same result as available in the output.
Basically how to loop through this new db.yml to get value for db.x86_64.alpine.version

1 Answer 1

1

For example,

db_list: "{{ dict(_keys|zip(_vals)) }}"
_keys: "{{ db.keys()|list }}"
_vals: "{{ db.values()|map('dict2items')|map('json_query', _query) }}"
_query: "[].{distribution: key, version: value.version}"

gives

  db_list:
    aarch64:
    - distribution: alpine
      version: 3.15.0
    - distribution: debian
      version: 11.3.0
    x86_64:
    - distribution: alpine
      version: 3.15.0
    - distribution: debian
      version: 11.3.0

Generally, create a list including all attributes

db_list: "{{ _val2|zip(_val1)|
             map('flatten')|
             map('zip', ['version', 'arch', 'distribution'])|
             map('map', 'reverse')|
             map('community.general.dict') }}"
_dict: "{{ lookup('ansible.utils.to_paths', db) }}"
_val1: "{{ _dict.keys()|map('split', '.')|list }}"
_val2: "{{ _dict.values()|list }}"

gives

  db_list:
  - arch: x86_64
    distribution: alpine
    version: 3.15.0
  - arch: x86_64
    distribution: debian
    version: 11.3.0
  - arch: aarch64
    distribution: alpine
    version: 3.15.0
  - arch: aarch64
    distribution: debian
    version: 11.3.0

Now, you can select whatever you want, e.g.

  • Iterate a subset of architectures
    - debug:
        msg: "{{ item }}"
      loop: "{{ db_list|selectattr('arch', 'in', ['aarch64', 'x86_64']) }}"
  • Iterate distribution 'debian'
    - debug:
        msg: "{{ item }}"
      loop: "{{ db_list|selectattr('distribution', 'eq', 'debian') }}"
  • Iterate versions less than '11.3.0'
    - debug:
        msg: "{{ item }}"
      loop: "{{ db_list|selectattr('version', 'version', '11.3.0', '<') }}"
  • Iterate distribution 'alpine' in architecture 'aarch64'
    - debug:
        msg: "{{ item }}"
      loop: "{{ db_list|selectattr('arch', 'eq', 'aarch64')|
                        selectattr('distribution', 'eq', 'alpine') }}"
2
  • Vladimir thanks for your feedback but above examples only converts original db.yml to new list db_list. This is great example but my question was a bit different so let me explain. When I run original db.yml and task - name: DENUG >>> db I get the output "db[item].alpine": { "version": "3.15.0" Now, with the new db.yml (second example ) and need to run similar task as - name: DENUG >>> db and get the same result (basically need to find a way how to loop through this new db.yml ) Apr 19, 2022 at 14:41
  • I have re-designed my question Apr 19, 2022 at 14:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .