New2Python
New2Python

Reputation: 415

Ansible how to create list of dictionary keys

I am probably missing something simple. I have the dictionary in vars.yml

    deploy_env:
      dev:
        schemas:
          year1:
            - main
            - custom
          year2:
            - main
            - custom
            - security
          year3:
            - main
            - custom

Then in my playbook.yml, I have something like

    - set_fact:
        years: "{{ deploy_env.dev.schemas }}"
    
    - name: Create schemas
      shell: "mysql ....params go here... {{ item }}"
      with_nested:
        - "{{ years }}"

The above works fine if schemas in vars.yml were a simple list ie:

    deploy_env:
      dev:
        schemas:
          - year1
          - year2
          - year3

But as soon as I add additional items under each year (making this a dictionary(?) I start getting errors on the line:

       - "{{ years }}

I basically want to populate {{ years }} with year1,year2,year3 values for this task.

I've looked at many examples but everything I looked at was soo complex and it was about how to create dictionaries which is not helpful.

Upvotes: 16

Views: 37586

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 68034

It is possible to create a list of the dictionary's keys. For example,

    - set_fact:
        years: "{{ deploy_env.dev.schemas.keys()|list }}"
    - debug:
        var: item
      loop: "{{ years }}"

gives (abridged)

    item: year1
    item: year2
    item: year3

Note: The method key() is redundant in the above expression. By default, a dictionary conversion to a list returns the list of the dictionary's keys. For example, the below iteration gives the same result

      loop: "{{ deploy_env.dev.schemas | list }}"

See: Python dictionary keys() Method


List vs Dictionary

Quoting from the question:

"... I add additional items under each year (making this a dictionary(?) ..."

Adding items doesn't change a list to a dictionary. A dash - in YAML introduces an item of a list.

Example of a list:

    schemas:
      - year1
      - year2
      - year3

Example of a list of hashes with single lists:

    schemas:
      - year1:
          - main
          - custom
      - year2:
          - main
          - custom
          - security
      - year3:
          - main
          - custom

Example of a dictionary:

    schemas:
      year1:
        - main
        - custom
      year2:
        - main
        - custom
        - security
      year3:
        - main
        - custom

Notes:

  • Some filters convert a dictionary when used as an argument where a list is expected, to the list of its keys. For example, the filter difference manipulates lists
    - debug:
        msg: "{{ deploy_env.dev.schemas|difference(['year2']) }}"

gives

msg:
  - year1
  - year3

  • Example of a complete playbook for testing
- hosts: localhost

  vars:

    deploy_env:
      dev:
        schemas:
          year1: [main, custom]
          year2: [main, custom, security]
          year3: [main, custom]

  tasks:

    - set_fact:
        years: "{{ deploy_env.dev.schemas.keys()|list }}"
    - debug:
        var: item
      loop: "{{ years }}"

    - debug:
        msg: "{{ deploy_env.dev.schemas|difference(['year2']) }}"

Upvotes: 20

Related Questions