NeitoFR
NeitoFR

Reputation: 807

Ansible beginner - List object has no attribute 'name'

I have an issue with looping on vars,

- hosts: all
  become: yes
  vars:
    user: 
      - name: "neito"
        pubkey: "{{ lookup('file', '~/.ssh/vsphere_vm.pub') }}"
        privkey: "{{ lookup('file', '~/.ssh/vsphere_vm') }}"
  tasks:
    - name: "Add SSH public key"
      authorized_key:
        user: "{{ item.name }}"
        key: "{{ item.pubkey }}"
      loop:
        - "{{ user }}"

when running this playbook I have the following error : The error was: 'list object' has no attribute 'name'

The {{ item.name }} seems to be undefined for Ansible, I guess I'm missing something obvious here but I can't find what. (I was following this get started post

Edit 1 :

By declaring the vars like following it works :

vars:
    user:
      {
        name: "neito",
        pubkey: "{{ lookup('file', '~/.ssh/vsphere_vm.pub') }}",
        privkey: "{{ lookup('file', '~/.ssh/vsphere_vm') }}",
      }

Could someone still point me out why the first syntax didn't work?

Upvotes: 3

Views: 9559

Answers (3)

ilias-sp
ilias-sp

Reputation: 6685

Please check the loops documentation:

You can define the list in a variables file, or in the ‘vars’ section of your play, then refer to the name of the list in the task:

loop: "{{ somelist }}"

If you modify your original task to:

tasks:
  - name: "Add SSH public key"
    authorized_key:
      user: "{{ item.name }}"
      key: "{{ item.pubkey }}"
    loop: "{{ user }}"

you should be good to go.

Upvotes: 5

NeitoFR
NeitoFR

Reputation: 807

The problem was the - dash in front of the "{{ user }}":

loop:
  - "{{ user }}"

Needs to be :

loop: "{{ user }}"

Upvotes: 7

Czaporka
Czaporka

Reputation: 2407

Originally you defined user as a 1-element list. The little dash (-) at the beginning denoted an element of a list.

user:
  - name: "neito"
    pubkey: "{{ lookup('file', '~/.ssh/vsphere_vm.pub') }}"
    privkey: "{{ lookup('file', '~/.ssh/vsphere_vm') }}"
# in YAML, the below is equivalent to the above
user:
  [
    {
      name: "neito",
      pubkey: "{{ lookup('file', '~/.ssh/vsphere_vm.pub') }}",
      privkey: "{{ lookup('file', '~/.ssh/vsphere_vm') }}"
    }
  ]

The brackets are alternative syntax to the dashes. On a similar note, curly braces are also an alternative to specifying each property on a new line, with increased indentation. So you could rewrite your second example in the following way:

user:
  name: "neito"
  pubkey: "{{ lookup('file', '~/.ssh/vsphere_vm.pub') }}"
  privkey: "{{ lookup('file', '~/.ssh/vsphere_vm') }}" """)

Thanks to the fact that the brackets and curly braces are also valid in YAML, you can actually parse JSON files as YAML and it will work 100% (but not the other way around).

Upvotes: 0

Related Questions