27
---
- hosts: test
  tasks:
    - name: print phone details
      debug: msg="user {{ item.key }} is {{ item.value.name }} ({{ item.value.telephone }})"
      with_dict: "{{ users }}"
  vars:
    users:
      alice: "Alice"
      telephone: 123

When I run this playbook, I am getting this error:

One or more undefined variables: 'dict object' has no attribute 'name' 

This one actually works just fine:

debug: msg="user {{ item.key }} is {{ item.value }}"

What am I missing?

EnzoR
  • 3,107
  • 2
  • 22
  • 25
user1692261
  • 1,197
  • 3
  • 16
  • 30
  • Does this answer your question? [How to loop over this dictionary in Ansible?](https://stackoverflow.com/questions/42167747/how-to-loop-over-this-dictionary-in-ansible) – The Fool Apr 05 '21 at 08:27

4 Answers4

18

This is not the exact same code. If you look carefully at the example, you'll see that under users, you have several dicts.

In your case, you have two dicts but with just one key (alice, or telephone) with respective values of "Alice", 123.

You'd rather do :

- hosts: localhost
  gather_facts: no
  tasks:
    - name: print phone details
      debug: msg="user {{ item.key }} is {{ item.value.name }} ({{ item.value.telephone }})"
      with_dict: "{{ users }}"
  vars:
    users:
      alice:
        name: "Alice"
        telephone: 123

(note that I changed host to localhost so I can run it easily, and added gather_facts: no since it's not necessary here. YMMV.)

EnzoR
  • 3,107
  • 2
  • 22
  • 25
leucos
  • 17,661
  • 1
  • 44
  • 34
1

You want to print {{ item.value.name }} but the name is not defined.

users:
  alice: "Alice"
  telephone: 123

should be replaced by

users:
  name: "Alice"
  telephone: 123

Then both the name and the telephone attribute are defined within the dict (users).

Viktor
  • 2,623
  • 3
  • 19
  • 28
0

I found out that with dict only works when giving the dict inline. Not when taking it from vars.

- name: ssh config
  lineinfile:
    dest: /etc/ssh/sshd_config
    regexp: '^#?\s*{{item.key}}\s'
    line: '{{item.key}} {{item.value}}'
    state: present
  with_dict: 
    LoginGraceTime: "1m"
    PermitRootLogin: "yes"
    PubkeyAuthentication: "yes"
    PasswordAuthentication: "no"
    PermitEmptyPasswords: "no"
    IgnoreRhosts: "yes"
    Protocol: 2

If you want to take it from vars which can also be defined globally or on some other place, you can use lookup.

- name: ssh config
  lineinfile:
    dest: /etc/ssh/sshd_config
    regexp: '^#?\s*{{item.key}}\s'
    line: '{{item.key}} {{item.value}}'
    state: present
  loop: "{{ lookup('dict', sshd_config) }}"
  vars:
    sshd_config:
      LoginGraceTime: "1m"
      PermitRootLogin: "yes"
      PubkeyAuthentication: "yes"
      PasswordAuthentication: "no"
      PermitEmptyPasswords: "no"
      IgnoreRhosts: "yes"
      Protocol: 2
The Fool
  • 16,715
  • 5
  • 52
  • 86
-1

small correction:

- name: print phone details
  debug: msg="user {{ item.key }} is {{ item.value.name }} ({{ item.value.telephone }})"
  with_dict: "{{ users }}" <<<<<<<<<<<<<<<<
Nanda
  • 1