Nested looping with with_dict and with_file, in Ansible v 1.7.2

  • I am almost certain this is not possible in Ansible (at least not in version 1.7.2), but just to be thorough in my investigation, after exhausting all lookups on google, stackoverflow, serverfault, etc. I am posting it now here.
  • I have a list of usernames in a dictionary, something like this:

`
keymap:
userx:
property1: xyz
property2: abc

usery:
property1: xyz
property2: abc
`

  • And then I have a set of files, essentially named like this in a folder:

**$ /tmp/pub_keys/username_hostname**

  • I need to merge all the keys for one user from all the hosts into one authorized key.

  • So all keys from userx in one file, and all keys from usery in one file and so on.

  • To grab the keys from the files over all hosts, I tried with the following just to test, and it works fine.
    lookup('file', '/tmp/pub_keys/username_'+ansible_hostname+'.pub' )
    Next Step, was to try the following,

  • `

    lookup('fileglob', '/tmp/pub_keys/username_'+'*'+'.pub').split(',')

    `
    which also worked fine. So I can merge the keys, using the authorized_keys module, for ONE user.

  • This make my problem quite similar to this one: https://serverfault.com/questions/649721/how-can-i-have-a-nested-loop-with-a-fileglob-pattern

  • To get the list of all users, I need to use the with_dict module to get the usernames from the dictionary keymap, as named above.

  • But it seems there is no way to make with_dict and with_file work together.

  • I tried a number of permutations with with_nested and using lookup with fileglob, but to no avail. The entire list of all permutations tried is maybe too much to copy paste here.

  • I tried setting variables using set_facts and vars to avoid using the with_dict in the same play, but I could not get the vars defined in one play to be visible in a different play (my bad, I am an ansible n00b).

  • The only thing that I did not try is with_subelements. And anyways, I think it is not usable in my case, since I do not know beforehand ‘the list of hosts for a given user’, in the dictionary.

  • To expand on, what not working means, (before I get burnt at the stake for saying, those words ), I explain below:

  • When I use a construct like the one listed here: https://docs.ansible.com/ansible/playbooks_loops.html#nested-loops, which in my case then becomes,

  • `

    - name: give users access to multiple databases
      authorized_key: user="{{item.0}}" key="{{lookup('file', item.1)}}"
      with_nested:
        - {{users}}
        - key: "{{ lookup('fileglob', '/tmp/public_keys/'+item.key+'_'+ansible_hostname+'.pub').splitlines() }}"
    
    

    `

  • The key returned in the above case, does not grab the list of files, but instead starts returning, the literal string "{{ lookup('fileglob', … and so on till the end of the string.

  • Replacing fileglob with pipe or file, did not get rid of the problem. It seems the problem stems from my (right or wrong) use of with_nested

  • Things that I avoided using, but will most certainly work: are using python and/or the shell to do delegate this work from ansible to bash or python. I was trying to solve this problem natively using ansible and ansible alone.

  • https://stackoverflow.com/questions/24250418/finding-file-name-in-files-section-of-current-ansible-role

tl,dr

Is it possible to use, with_dict together with with_file to achieve a nested-loop construct in ansible 1.7.2? It seems not.
And especially so after reading the 2nd answer to this question: https://stackoverflow.com/questions/31566568/double-loop-ansible

p.s. why ansible 1.7.2, it comes standard with Debian 8.5 (jessie)?

  • p.s. why ansible 1.7.2, it comes standard with Debian 8.5 (jessie)?

Err, :open_mouth: I wanted to explain, why am I using, Ansible 1.7.2. and not something new, since it comes standard with the Debian 8.5 distribution. I know it is old. But that is not in my hand. Anyways.