user1692261
user1692261

Reputation: 1217

Ansible: can't access dictionary value - got error: 'dict object' has no attribute

---
- 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?

Upvotes: 29

Views: 145371

Answers (4)

The Fool
The Fool

Reputation: 20597

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

Upvotes: 1

leucos
leucos

Reputation: 18279

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.)

Upvotes: 19

Peter de Zwart
Peter de Zwart

Reputation: 71

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).

Upvotes: 1

Nanda
Nanda

Reputation: 1

small correction:

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

Upvotes: -1

Related Questions