4

I'm trying to build an array/list of JSON objects in Ansible. My playbook is called by specifying --extra-vars "userids=123456,654321".

I then try to build the list with the following. "TBD" is just a place-holder. I will fill those values with data retrieved from SQL queries later in the playbook.

- name: Initiate User List
      set_fact:
        all_users: []    

    - name: Add new JSON Objects to List
      set_fact:
        all_users: "{{ all_users+ [{ 'UserID': '{{ item }}', 'UserType': 'TBD', 'UserName': 'TBD' }] }}"
      loop: "{{ userids.split(',') }}"

    - name: Debug
      debug:
        var: all_users

The list sort of builds, but it is skipping the first item in the list. This is the resulting output:

TASK [Initiate User List] *************************************************************************************************************************************************************
ok: [localhost]

TASK [Add new JSON Objects to List] ******************************************************************************************************************************************************
ok: [localhost] => (item=123456)
ok: [localhost] => (item=654321)

TASK [Debug] *****************************************************************************************************************************************************************************
ok: [localhost] => {
    "all_users": [
        {
            "UserID": "654321",
            "UserType": "TBD",
            "UserName": "TBD"
        },
        {
            "UserID": "{{ item }}",
            "UserType": "TBD",
            "UserName": "TBD"
        }
    ]
}

I'm not sure what I'm missing. I tried doing a "set_fact" before the looping task to perform the split() first, but that didn't help. I also tried "with_items" instead of loop, no luck

1 Answer 1

3

Do not use nested curly braces "{{ ... {{ item }} ... }}". Correct syntax is

all_users: "{{ all_users+ [{ 'UserID': item,
                             'UserType': 'TBD',
                             'UserName': 'TBD' }] }}"

Next, it's more convenient to submit a list of userids. Then the split filter is not necessary. For example the playbook

shell> cat playbook.yml
- hosts: localhost
  tasks:
    - name: Initiate User List
      set_fact:
        all_users: []
    - name: Add new JSON Objects to List
      set_fact:
        all_users: "{{ all_users +
                       [{ 'UserID': item,
                          'UserType': 'TBD',
                          'UserName': 'TBD' }] }}"
      loop: "{{ userids }}"
    - name: Debug
      debug:
        var: all_users

gives

shell> ansible-playbook -e "userids=['123456','654321']" playbook.yml
...
    "all_users": [
        {
            "UserID": "123456",
            "UserName": "TBD",
            "UserType": "TBD"
        },
        {
            "UserID": "654321",
            "UserName": "TBD",
            "UserType": "TBD"
        }
    ]


Remove the single-quotes from the items in the list userids if the attribute UserID shall be stored as integer type instead of string. For example

shell> ansible-playbook -e "userids=[123456,654321]" playbook.yml

gives (there are no quotes around the values of UserID)

    "all_users": [
        {
            "UserID": 123456,
            "UserName": "TBD",
            "UserType": "TBD"
        },
        {
            "UserID": 654321,
            "UserName": "TBD",
            "UserType": "TBD"
        }
    ]

Then use a dictionary to create the list of users. For example,

shell> cat playbook.yml
- hosts: localhost
  vars:
    my_users:
      123456:
        name: Alice Admin
        type: admin
      654321:
        name: Bob Business
        type: sales
  tasks:
    - name: Initiate User List
      set_fact:
        all_users: []
    - name: Add new JSON Objects to List
      set_fact:
        all_users: "{{ all_users +
                       [{ 'UserID': item,
                          'UserType': my_users[item].type,
                          'UserName': my_users[item].name }] }}"
      loop: "{{ userids }}"
    - name: Debug
      debug:
        var: all_users

gives

shell> ansible-playbook -e "userids=[123456,654321]" playbook.yml
...
    "all_users": [
        {
            "UserID": 123456,
            "UserName": "Alice Admin",
            "UserType": "admin"
        },
        {
            "UserID": 654321,
            "UserName": "Bob Business",
            "UserType": "sales"
        }
    ]
2
  • Thanks! removig the extra {{ }} as well as the single quotes around 'item' did the trick. I had removed the {{ }} at one point, but didn't remove the single quotes, so the result just had "item" for both userIDs.
    – JScott
    May 15, 2020 at 16:20
  • OMG, man! BIG Thanks!!!
    – don Rumata
    Jan 28, 2021 at 13:03

You must log in to answer this question.

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