Proper approach to looping over nested data?

Hiya Ansible - I have some repetitive tasks I’d like to perform, but am struggling to figure out how exactly to get ansible to execute them. I figure my use cases should be pretty common, so I’m hoping to hear how others might have solved this.

First off, I have to create multiple users on multiple hosts. I have a role that I already use for managing users (basically a wrapper around user{add,mod,del}. The role’s main.yml simply decides which other task file to include based on a ‘cmd’ parameter, so performing a “user add” is as simple as passing “-e cmd=useradd” at the CLI (Would have been nice to be able to use tags for that, but…).

So, now that I have multiple users, I’d like to do something like:

  • include: add.yml
  • with_dict: userlist

Where ‘userlist’ is something like:

userlist:

  • name: alice
    home: default
    shell: /bin/bash
  • name: bob
    shell: /bin/nologin

Except that looping over an include is specifically deprecated as of my version (1.9.1). I figure that must have been done for a good reason, so what is the canonical approach in ansible for my use case? Or should I just accept that ansible can’t do this, and do the looping in the shell?

Second issue is somewhat related, in that it involves looping and wondering about a canonical approach…

I have an app that uses ini-style files. The app is clustered, and so different machines take on different roles based on their config. The approach I’ve taken is to have a common role, and then specialist roles which depend upon common. The common role does things like create the service user, install from archive, and lay down basic configs. Or, at least I’d like it to lay down configs…

There’s the ‘ini_file’ module which would be perfect for this… except there doesn’t seem to be a loop operation which exposes the data properly.

First, the data structure:

confs:

  • file: /path/to/configA
    stanza: blockA
    values:
  • val1: true
  • val2: false
  • val3: etc
  • file: /path/to/configB

Now, if I use ‘with_subelement’ to loop over this structure thusly:

  • debug: "File {{ item.0.file }} should contain {{ item.1.key }} with value {{ item.1.value }}
    with_subelements: confs

It actually has the audacity to error with the message:

One or more undefined variables: ‘dict object’ has no attribute ‘key’

Um… how is it a dict object yet has no key? But more importantly, how exactly do I loop over data for use with the “ini_file” module? The loop needs to expose at least four pieces of data: a destination file, a config header, a config key, and a config value. Does ansible support that in any way? Or is ansible a tool for people who like to type and repeat themselves?