How does merging hashes work?

How does merging hashes work?

I’ve set “hash_behaviour=merge” in my ansible.cfg file. So my hashes should merge. But they don’t. Or at least, not in a way that makes sense to me. Here’s pretty much what I have:

file: group_vars/testgroup
stuff:
substuff:

  • path: /b/a/c
    owner: root
    group: root
    recurse: no
  • path: /for/the/breakfast
    owner: someone
    group: root
    recurse: no

file: host_vars/testserver
stuff:
substuff:

  • path: /another/dir
    owner: root
    group: root
    recurse: no
  • path: /yet/another/dir
    owner: someone
    group: root
    recurse: no

testserver is in the testgroup.

What I expect is to get all 4 directories created or modified. What I get is only the directories in the host_vars file.

Now, if I do something like:

file: group_vars/testgroup
stuff:
substuff:
blah: this is blah
blah2: this is blah2

file: host_vars/testserver
stuff:
substuff:
blah3: this is blah3
blah4: this is blah4

I do get all four “blah”'s. But that syntax is rather bad for adding things like owner and group…

So, why doesn’t the first one work?

If the sub-entries are dictionaries, they will be merged as well. The issue appears that the substuff entry is a list, so it’s just re-assigning/copying those entries. If you make substuff a dictionary, I believe this will work as you expect.

Yeah, I just figured out that the ‘-’ indicates a list…

The problem is that when I switch to something like:

nfs_automount:
mountpoints:
adminshare:
path: /path/to/dir/
owner: root
group: root
mode: 755
recurse: no
test:
path: /mounts/test/
owner: root
group: root
mode: 755
recurse: no

And try to run a task like:

name: ensure nfs mountpoints exist
file: path={{ nfs_automount.mountpoints[item].path }} state=directory group={{ nfs_automount.mountpoints[item].group }} owner={{ nfs_automount.mountpoints[item].owner }} mode={{ nfs_automount.mountpoints[item].mode }}
with_items: nfs_automount.mountpoints|default()
notify: restart nfs_automount
tags: nfs_automount

It errors saying: with_items expects a list.

So, I need a list in order to loop through the items. But I need a dictionary in order to merge things…

What I’d like to do is have some group values in the group_vars file, but be able to override/add to them in the host_vars file.

Is there a decent way I can do that? Or do I just need to copy the vars from group_vars into host_vars when I need to add/override them?

Well, it took some experimenting, but I figured it out thanks to https://groups.google.com/d/msg/ansible-project/M-FNUK9Wz98/1wF23CZ-6pIJ

To summarize, I had to pass the dictionary to dictsort so that it would create a list. Then I had to figure out the correct syntax to reference the values. Below is what I ended up with.

  • name: ensure nfs mountpoints exist
    file: path={{ item[1].path }} state=directory group={{ item[1].group }} owner={{ item[1].owner }} mode={{ item[1].mode }}
    with_items: nfs_automount.mountpoints|dictsort
    notify: restart nfs_automount
    tags: nfs_automount