Using filters to wrangle registered variables with Ansible

Today I ran into an issue where I needed to use Ansible's with_items feature on the registered result of a previous task, one that also ran with_items. To be more clear, here's what my object looked like (in JSON for clarity):

{
    "changed": false,
    "msg": "All items completed",
    "results": [
        {
            "machines": [
                {
                    "ip": "127.0.0.1",
                    "name": "machine1"
                },
                {
                    "ip": "127.0.0.1",
                    "name": "machine2"
                }
            ]
        },
        {
            "machines": [
                {
                    "ip": "127.0.0.1",
                    "name": "machine3"
                },
                {
                    "ip": "127.0.0.1",
                    "name": "machine4"
                }
            ]
        }
    ]
}

The problem is, I needed to use with_items again, but for each machine this time, not each result.

Solution

I played with a few different ways of doing it, but settled on using Jinja2's filters for the job:

"{{ my_with_items_registed_var.results|map(attribute='machines')|list }}"

To break it down, my variable is named my_with_items_registed_var. This is the variable I registered previously through my first with_items step. When using with_items and register, Ansible create an item in a results array for each item that would have been registered in the normal case (where no with_items is involed).

The filters come into play when we need to pull out specifically the machines array. For this functionality, we use the map() filter; specifying machines as the attribute we want mapped.

Finally, we need to convert the generator back to a list with list. I'm not 100% sure here, but it seems to flatten the machines arrays into one, as I was expected to need to do this after. If anyone know, please drop me a line @bbhoss.

Conclusion

This all seems fairly simple in conclusion, but I couldn't easily find this information via searching, so hopefully this will be helpful to someone in the future.