hey
hey

Reputation: 3242

ansible: how to access yaml defined arrays by their alphanumeric key / index / hash

Let's say, I have a list of servers and a list of directories:

servers:
  - server1:
    ip: 1.1.1.1
  - server2:
    ip: 2.2.2.2

directories:
  - path: /backupF/s1
    name: bmma
    server: server1
  - path: /backupM/s2
    name: cqce
    server: server1
  - path: /backupM/s3
    name: cqce
    server: server2

I would now like to use the data like this:

  - name: write wonderful config file
    lineinfile:
      dest: /testfile
      line: "/go.sh {{ item.path }} {{ servers[item.server].ip }}"
    with_items: "{{ directories }}"

Unfortunately, this does not work. I can access a server within the with_items loop via its index:

    line: "/go.sh {{ item.path }} {{ servers[0].ip }}"

... but not via its name:

    line: "/go.sh {{ item.path }} {{ servers[server1].ip }}"

Is there any possibility?

Upvotes: 2

Views: 2517

Answers (1)

Chris
Chris

Reputation: 414

Your issue is that your servers variable is currently an ordered array i.e. has items 0, 1, 2 etc but what you really want is a dictionary. Arrays vs dicts still confuse me to this day and I've been using Ansible in anger for 18 months.

Looking at your end goal, what I think you are trying to do is produce lines that look like:

  1. /go.sh /backupF/s1 1.1.1.1

  2. /go.sh /backupM/s2 1.1.1.1

  3. /go.sh /backupM/s3 2.2.2.2

If this is the case, all you need to do is refactor your servers variable into a dict, not an array (notice the lack of hyphens and the additional indenting on ip):

servers:
  server1:
    ip: 1.1.1.1
  server2:
    ip: 2.2.2.2

Debug is your friend. Not wanting to output any actual lines in a file, I changed your task to:

  - debug:
      msg: "/go.sh {{ item.path }} {{ servers[item.server].ip }}"
    with_items: "{{ directories }}"

and this produces the following:

ok: [localhost] => (item={u'path': u'/backupF/s1', u'name': u'bmma', u'server': u'server1'}) => {
    "msg": "/go.sh /backupF/s1 1.1.1.1"
}
ok: [localhost] => (item={u'path': u'/backupM/s2', u'name': u'cqce', u'server': u'server1'}) => {
    "msg": "/go.sh /backupM/s2 1.1.1.1"
}
ok: [localhost] => (item={u'path': u'/backupM/s3', u'name': u'cqce', u'server': u'server2'}) => {
    "msg": "/go.sh /backupM/s3 2.2.2.2"
}

Upvotes: 3

Related Questions