Iterating through two lists in Ansible

Viewed 986

I'm writing an ansible playbook that creates users in an internal system through a call to an API where the request body contains all of the user information in json format.

Right now my playbook hold all of those variables in a list of dictionaries like this:

userInfoDict: "{{[ {'FirstName': 'John', 'LastName': 'Lennon', 'Number': '', 'email': 'john@example.com'}, {'FirstName': 'Paul', 'LastName': 'McCartney', 'Number': '', 'email': 'paul@example.com'} ]}}" 

Where the "Number" field is blank, I have a play to grab available phone numbers from an internal DB, and that list of numbers is held in a variable called numberList

What I want to do, is to iterate through UserInfoDict, and set the Number field to the next value in my list of numbers, But I haven't been able to do that.

Is there any way to do something like this in ansible? Where you access an object at an index of a list?

 - set_fact:
      finalUserInfo: "{{userInfoDict[i].Number : item}}"
   loop: "{{numberList}}

Something like this ^

1 Answers

You can use the zip filter to combine the two lists together. This implies that you have an entry in your numberList for each element in your userInfoDict (side note: which is a misleading var name IMO since it is a list). I created such a list below from what I understood from your question.

You can loop directly on the zipped lists and access their relevant values.

If you absolutely need to create a new list of dicts with the combined info, there are several ways to do so. I used the json_query filter as a demo below (this requires pip install jmespath on the controller).

(Note: in the below playbook, the rather ugly ... to_json | from_json ... is needed to overcome a bug in jmespath <-> ansible communication where each elements of the zipped lists are otherwise interpreted as strings.)

---
- name: Zip demo
  hosts: localhost
  gather_facts: false

  vars:
    userInfoDict: [{'FirstName':'John','LastName':'Lennon','Number':'','email':'john@example.com'},{'FirstName':'Paul','LastName':'McCartney','Number':'','email':'paul@example.com'}]
    numberList: ["+33123456789", "+33612345678"]

  tasks:
    - name: Looping over zipped lists directly
      vars:
        fancy_message: |-
          User first name is: {{ item.0.FirstName }}
          User last name is: {{ item.0.LastName }}
          User number is: {{ item.1 }}
          User email is: {{ item.0.email }}
      debug:
        msg: "{{ fancy_message.split('\n') }}"
      loop: "{{ userInfoDict | zip(numberList) | list }}"
      loop_control:
        label: "{{ item.0.FirstName }} {{ item.0.LastName }}"

    - name: Creating a new list of dicts with json_query
      vars:
        new_dict_query: >-
          [*].{
            "FirstName": [0].FirstName,
            "LastName": [0].LastName,
            "Number": [1],
            "email": [0].email
          }
        new_dict_list: >-
          {{
             userInfoDict
             | zip(numberList)
             | list
             | to_json
             | from_json
             | json_query(new_dict_query)
           }}
      debug:
        var: new_dict_list

which gives:

PLAY [Zip demo] *****************************************************************************************************************************************************************************************************************************

TASK [Looping over zipped lists directly] ***************************************************************************************************************************************************************************************************
ok: [localhost] => (item=John Lennon) => {
    "msg": [
        "User first name is: John",
        "User last name is: Lennon",
        "User number is: +33123456789",
        "User email is: john@example.com"
    ]
}
ok: [localhost] => (item=Paul McCartney) => {
    "msg": [
        "User first name is: Paul",
        "User last name is: McCartney",
        "User number is: +33612345678",
        "User email is: paul@example.com"
    ]
}

TASK [Creating a new list of dicts with json_query] *****************************************************************************************************************************************************************************************
ok: [localhost] => {
    "new_dict_list": [
        {
            "FirstName": "John",
            "LastName": "Lennon",
            "Number": "+33123456789",
            "email": "john@example.com"
        },
        {
            "FirstName": "Paul",
            "LastName": "McCartney",
            "Number": "+33612345678",
            "email": "paul@example.com"
        }
    ]
}

PLAY RECAP **********************************************************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
Related