lollan
lollan

Reputation: 81

Convert list to values in dictionary with Ansible

I am trying to use the Ansible gather_facts data from a Linux host as input:

    "ansible_fibre_channel_wwn": [
        "1000e0071bd4d0ed",
        "10009440c90f9d85",
        "1000e0071bce95f3",
        "1000e0071bce95f2",
        "1000e0071bd4d0ec",
        "10009440c90f9d84"
    ],

And would like to create a dictionary using the above list items for dictionary values of a new "wwpn" key:

        fc_initiators: [
            {wwpn: '10:00:e0:07:1b:d4:d0:ed'}, 
            {wwpn: '10:00:94:40:c9:0f:9d:85'}, 
            {wwpn: '10:00:e0:07:1b:ce:95:f3'}, 
            {wwpn: '10:00:e0:07:1b:ce:95:f2'}, 
            {wwpn: '10:00:e0:07:1b:d4:d0:ec'}, 
            {wwpn: '10:00:94:40:c9:0f:9d:84'}
        ]

This regex seems sufficient for converting the initial list items into colonized WWPN:

"{{ ansible_fibre_channel_wwn | 
map('regex_replace', '^(..)(..)(..)(..)(..)(..)(..)(..)$', '\\1:\\2:\\3:\\4:\\5:\\6:\\7:\\8')|list }}"

I'm not sure where to start with the list->dictionary conversion though. Any help is much appreciated.

Thanks!

Upvotes: 3

Views: 791

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 68189

"colonize" the items first, e.g.

  wwn_colonized: "{{ ansible_fibre_channel_wwn|
                     map('batch', 2)|
                     map('map', 'join')|
                     map('join', ':') }}"

gives

  wwn_colonized:
  - 10:00:e0:07:1b:d4:d0:ed
  - 10:00:94:40:c9:0f:9d:85
  - 10:00:e0:07:1b:ce:95:f3
  - 10:00:e0:07:1b:ce:95:f2
  - 10:00:e0:07:1b:d4:d0:ec
  - 10:00:94:40:c9:0f:9d:84

Then create the list of the dictionaries. There are more options

  fc_initiators: "{{ wwn_colonized|
                     map('regex_replace', '^(.*)$', 'wwpn: \\1')|
                     map('from_yaml') }}"
  fc_initiators: "{{ ['wwpn']|product(wwn_colonized)|
                     map('join', ': ')|
                     map('from_yaml') }}"
  fc_initiators: "{{ wwn_colonized|
                     map('community.general.dict_kv', 'wwpn') }}"

give the same result

  fc_initiators:
  - wwpn: 10:00:e0:07:1b:d4:d0:ed
  - wwpn: 10:00:94:40:c9:0f:9d:85
  - wwpn: 10:00:e0:07:1b:ce:95:f3
  - wwpn: 10:00:e0:07:1b:ce:95:f2
  - wwpn: 10:00:e0:07:1b:d4:d0:ec
  - wwpn: 10:00:94:40:c9:0f:9d:84

or, the same data in JSON

  fc_initiators|to_nice_json: |-
    [
        {
            "wwpn": "10:00:e0:07:1b:d4:d0:ed"
        },
        {
            "wwpn": "10:00:94:40:c9:0f:9d:85"
        },
        {
            "wwpn": "10:00:e0:07:1b:ce:95:f3"
        },
        {
            "wwpn": "10:00:e0:07:1b:ce:95:f2"
        },
        {
            "wwpn": "10:00:e0:07:1b:d4:d0:ec"
        },
        {
            "wwpn": "10:00:94:40:c9:0f:9d:84"
        }
    ]

Example of a complete playbook for testing

- hosts: localhost

  vars:

    ansible_fibre_channel_wwn:
      - 1000e0071bd4d0ed
      - 10009440c90f9d85
      - 1000e0071bce95f3
      - 1000e0071bce95f2
      - 1000e0071bd4d0ec
      - 10009440c90f9d84

    wwn_colonized: "{{ ansible_fibre_channel_wwn|
                       map('batch', 2)|
                       map('map', 'join')|
                       map('join', ':') }}"
    fc_initiators1: "{{ wwn_colonized|
                        map('regex_replace', '^(.*)$', 'wwpn: \\1')|
                        map('from_yaml') }}"
    fc_initiators2: "{{ ['wwpn']|product(wwn_colonized)|
                        map('join', ': ')|
                        map('from_yaml') }}"
    fc_initiators3: "{{ wwn_colonized|
                        map('community.general.dict_kv', 'wwpn') }}"

  tasks:

    - debug:
        var: wwn_colonized
    - debug:
        var: fc_initiators1
    - debug:
        var: fc_initiators2
    - debug:
        var: fc_initiators3

Upvotes: 4

Related Questions