Ansible – How to get the value of a variable that's inside a List of Dicts?

Question:

I need to get the value of the $HOME path of newly created users with the module ansible.builtin.user. Here’s the playbook:

---
- name: Create users 
  vars:
    users:
      user1:
        passwd: 
        uid: '1111'
        comment: 'Test User'
        shell: '/bin/zsh'
      user2:
        passwd:
        uid: '1111'
        comment: 'Test User'
        shell: '/bin/zsh'


  tasks:

  - name: Create user "{{ item.key }}"
    ansible.builtin.user:
      name: "{{ item.key }}"
      comment: "{{ item.value.comment }}"
      uid: "{{ item.value.uid }}"
      shell: "{{ item.value.shell }}"
      password: "{{ item.value.passwd }}"
    loop: "{{ lookup('dict', users, wantlist=True) }}"
    register: main_user

    - name: debug
      debug:
        msg: "The home folder is {{main_user.results.home}}"

Ok, the problem here is that the variable main_user has the following contents:

ok: [192.168.0.98] => {
    "msg": {
        "changed": true,
        "msg": "All items completed",
        "results": [
            {
                "ansible_loop_var": "item",
                "changed": true,
                "comment": "Test",
                "create_home": true,
                "failed": false,
                "group": 100,
                "home": "/home/user",
                "invocation": {
                    "module_args": {
                        "append": false,
                        "authorization": null,
                        "comment": "Test",
                        "create_home": true,

And I can’t figure it out how to get the value of results.home.

Expected:

ok: [192.168.0.98] => {
    "msg": {
        "changed": true,
        "msg: "The home folder is home/user"

Can someone please show me some light?

Asked By: kegham

||

Answers:

It’s an array. Index it.

msg: "The home folder of the first user is {{main_user.results[0].home}}"
Answered By: KamilCuk

For example, given the dictionary users

  users:
    alice: {comment: Alice, shell: /bin/sh, uuid: 1004}
    bob: {comment: Bob, shell: /bin/sh, uuid: 1007}

Create the users. Only the parameter name is required by the module user. You can make other parameters optional by the filer default(omit)

    - user:
        name: "{{ item.key }}"
        comment: "{{ item.value.comment|d(omit) }}"
        uid: "{{ item.value.uid|d(omit) }}"
        shell: "{{ item.value.shell|d(omit) }}"
      loop: "{{ users|dict2items }}"
      register: user

Take a look at the registered variable user. There are three categories of the attributes in the items of the list user.results

  • dictionary item: item of the loop
  • dictionary invocation: parameters of the module including defaults
  • results returned by the module

You can select any piece of information you need. For example, if you want to create a dictionary of the name and home returned by the module select the attributes

  name_home: "{{ user.results|json_query('[].[name, home]') }}"

gives

 name_home:
  - [alice, /home/alice]
  - [bob, /home/bob]

and create a dictionary

name_home_dict: "{{ dict(user.results|json_query('[].[name, home]')) }}"

gives

  name_home_dict:
    alice: /home/alice
    bob: /home/bob

Searching for a user’s home is trivial now. The same way you can create other dictionaries. For example,

  name_uid_dict:
    alice: 1004
    bob: 1005
  name_shell_dict:
    alice: /bin/sh
    bob: /bin/sh

,or you can create a dictionary with multiple attributes

    name_attr: "{{ dict(user.results|json_query(name_attr_query)) }}"
    name_attr_query: '[].[name, {home: home, uid: uid, shell: shell}]'

gives

  name_attr:
    alice:
      home: /home/alice
      shell: /bin/sh
      uid: 1004
    bob:
      home: /home/bob
      shell: /bin/sh
      uid: 1005

Example of a complete playbook for testing

- hosts: all

  vars:

    users:
      alice:
        comment: Alice
        shell: /bin/sh
        uuid: 1004
      bob:
        comment: Bob
        shell: /bin/sh
        uuid: 1007

    name_home: "{{ user.results|json_query('[].[name, home]') }}"
    name_home_dict: "{{ dict(user.results|json_query('[].[name, home]')) }}"
    name_uid_dict: "{{ dict(user.results|json_query('[].[name, uid]')) }}"
    name_shell_dict: "{{ dict(user.results|json_query('[].[name, shell]')) }}"

    name_attr: "{{ dict(user.results|json_query(name_attr_query)) }}"
    name_attr_query: '[].[name, {home: home, uid: uid, shell: shell}]'
      
  tasks:

    - debug:
        var: users|to_yaml

    - user:
        name: "{{ item.key }}"
        comment: "{{ item.value.comment|d(omit) }}"
        uid: "{{ item.value.uid|d(omit) }}"
        shell: "{{ item.value.shell|d(omit) }}"
      loop: "{{ users|dict2items }}"
      register: user
    - debug:
        var: user
      when: debug|d(false)|bool

    - debug:
        var: name_home|to_yaml
    - debug:
        var: name_home_dict
    - debug:
        var: name_uid_dict
    - debug:
        var: name_shell_dict
    - debug:
        var: name_attr

Answered By: Vladimir Botka
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.