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?
Answers:
It’s an array. Index it.
msg: "The home folder of the first user is {{main_user.results[0].home}}"
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
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?
It’s an array. Index it.
msg: "The home folder of the first user is {{main_user.results[0].home}}"
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