Using subelements in Ansible to loop through multiple lists.
Tags: ansible, galaxy, lists, loops
Published: 2018-11-04 21:14:02

---
title: Using subelements in Ansible to loop through multiple lists.
published: true
tags: ansible,galaxy,lists,loops
canonical_url: https://buildahomelab.com/2018/11/03/subelements-ansible-loop-nested-lists/
---

While working on my Ansible Galaxy [users role](https://galaxy.ansible.com/engonzal/users) I came across a situation where I needed to loop through a list inside a dictionary inside a list.  For this specific case I had a list of users, and each user could have multiple authorized sshkeys stored in a “pubkeys” value.  To add each sshkey I used subelements in Ansible to loop through multiple lists.

Here’s an example variable.  Note that there are two users, one user has two public keys, and the other has one:

```
host\_local\_users:
 - name: user1
 pubkeys:
 - 'ssh-rsa myr4nd0mk3y engonzal@home'
 - 'ssh-rsa my000r4nd0m000k3y000tw0 engonzal@workstation'
 - name: user2
 pubkeys:
 - 'ssh-rsa myr4nd0mk3y engonzal@home'
```

## Creating a Task

In this case “host\_local\_users” is a list.  Each item of “host\_local\_users” is a dictionary.  The key “pubkeys” is a list.  Now say we want to have a task that adds each key under pubkeys for the user in “name”.  That would look something like this:

```
- name: Add public keys to authorized\_hosts
 authorized\_key:
 user: "{{ item.0.name }}"
 state: "{{ item.0.state | default('present') }}"
 key: "{{ item.1 }}"
 loop: "{{ host\_local\_users | subelements('pubkeys', 'skip\_missing=True') }}"
```

There’s a lot going on in this one task!  First note that the “loop” parameter is using our “host\_local\_users” variable.  We’re using the “subelements” filter to pick out the list of ssh keys for each user.  Each item of host\_local\_users is represented by “item.0”.  Each item of pubkeys is represented by “item.1” (note that we provided ‘pubkeys’ to the “subelements” filter).  

## Running the task

In practice this will run the authorized\_key task 3 times even though there are only two users, it looks like this:

```
TASK [engonzal.users : Add public keys to authorized_hosts] ********************
changed: [instance] => (item=[{u'pubkeys': [u'ssh-rsa myr4nd0mk3y engonzal@home', u'ssh-rsa my000r4nd0m000k3y000tw0 engonzal@workstation'], u'name': u'user1'}, u'ssh-rsa myr4nd0mk3y engonzal@home'])

changed: [instance] => (item=[{u'pubkeys': [u'ssh-rsa myr4nd0mk3y engonzal@home', u'ssh-rsa my000r4nd0m000k3y000tw0 engonzal@workstation'], u'name': u'user1'}, u'ssh-rsa my000r4nd0m000k3y000tw0 engonzal@workstation'])

changed: [instance] => (item=[{u'pubkeys': [u'ssh-rsa myr4nd0mk3y engonzal@home'], u'name': u'user2'}, u'ssh-rsa myr4nd0mk3y engonzal@home'])
```

This run added two ssh pubkeys for user1 and one ssh pubkey for user2 based on what we put in the variable “host\_local\_users”.

I thought it was pretty cool that Ansible allowed these types of complex variables.  Many would argue that for some problems it makes more sense to use bash or a programming language for complicated tasks.  I’ve found that making those scripts idempotent adds a whole other layer of complexity that Ansible already has baked in.

To get Ansible setup checkout my post on how to [install Ansible using virtualenvs.](https://dev.to/engonzal/setup-ansible-with-python-virtualenv-38go-temp-slug-4960710)  To see subelements in practice take a look at the tasks in my [“users” role on Github.](https://github.com/engonzal/ansible_role_users/blob/master/tasks/main.yml)

The post [Using subelements in Ansible to loop through multiple lists.](https://buildahomelab.com/2018/11/03/subelements-ansible-loop-nested-lists/) appeared first on [Build a Homelab](https://buildahomelab.com).