user855443
user855443

Reputation: 2940

indexing a variable with "bracket notation" does not always work in ansible

I am new to ansible and followed the instruction here which gives two notations for referencing key-value dictionaries.

foo['field1']
foo.field1

and says "Bracket notation always works". I try with

  vars: 
    - london: 
      - nodename : music0
      - card: Headphone 
      - mixer: Hardware


    - debug: 
        msg: nodename  "{{ london[0] }} " 
    - debug: 
        msg: nodename  "{{ london['nodename'] }} " 

The first wint reference [0] seems ok:

TASK [debug] *******************************************************************
ok: [127.0.0.1] => {
    "msg": "nodename  \"{u'nodename': u'music0'} \""
}

but not the bracket notation:

fatal: [127.0.0.1]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'list object' has no attribute 'nodename'\n\nThe error appears to be in '/home/frank/Data/ansibleHost/testVars.yml': line 29, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n    - debug:\n      ^ here\n"}

What is the difference to the published example? I admit that I do not understand the error message... the list object should be london which has an attribute - or do I misunderstand the variable declaration?

I would appreciate a recommendation for a comprehensive tutorial!

Upvotes: 2

Views: 737

Answers (1)

β.εηοιτ.βε
β.εηοιτ.βε

Reputation: 39129

To me, it seems your issue is the fact that you are mixing lists and dictionaries.

  • This is a dictionary, you can access elements out of it with london.nodename or london['nodename']

    london: 
      nodename: music0
      card: Headphone 
      mixer: Hardware
    
  • While what you have is a list of dictionary containing other lists of dictionaries:

    foo:
      - london: 
        - nodename: music0
        - card: Headphone 
        - mixer: Hardware
    

    You can access this with a 0-based index syntax: foo.0.london.0.nodename but I higly suspect this is not the data structure you are looking for. In the same fashion as above, foo[0]['london'][0]['nodename'] will work too

  • For a further example of what a list would more looks like:

    fruits:
      - banana
      - apple
      - orange
      - lemon
    

    And then for a further explanation about the 0-based index, you could, for example, access orange via fruits.2 or fruits[2]


If you do not want to change you data structure:

- hosts: all
  gather_facts: no
      
  tasks:
    - debug: 
        msg: "{{ london.0.nodename }}"
      vars: 
        - london: 
          - nodename: music0
          - card: Headphone 
          - mixer: Hardware

Gives:

TASK [debug] ************************************************************
ok: [localhost] => {
    "msg": "music0"
} 

Now why don't you have to say 0.london.0.nodename, you will ask?
This is because vars does not expect a list but rather a dictionary, and Ansible is too kind with you and casts it as a dictionary.

Upvotes: 3

Related Questions