turbonerd
turbonerd

Reputation: 1306

Loops within loops

I've set up some application information in my Ansible group_vars like this:

applications:
  - name: app1
  - name: app2
  - name: app3
  - name: app4
    settings:
      log_dir: /var/logs/app4
      associated_files:
        - auth/key.json
  - name: app5
    settings:
      log_dir: /var/logs/app5
      repo_path: new_apps/app5

I'm struggling to get my head around how I can use these "sub loops".

My tasks for each application are:

  1. Create some folders based purely on the name value
  2. Create a log folder if a settings/log_dir value exists
  3. Copy associated files over, if specified

The syntax for these tasks isn't the problem here, I'm comfortable with those - I just need to know how to access the information from this applications variable. Number 3 in particular seems troublesome to me - I need to loop within a loop.

To debug this, I've been trying to run the following task:

- debug:
    msg: "{{ item }}"
  with_subelements:
    - "{{ applications }}"
    - settings

Here's the output:

It's possible/probable that the way I've set the variable up in the first instance is wrong. If there's a better way to do this, it's not a problem to change it.

Upvotes: 0

Views: 1321

Answers (1)

larsks
larsks

Reputation: 312580

You can't use with_subelements because settings is a dictionary, not a list. If you were to restructure your data so that settings is a list, like this:

applications:
  - name: app1
  - name: app2
  - name: app3
  - name: app4
    settings:
      - name: log_dir
        value: /var/logs/app4
      - name: associated_files
        value:
          - auth/key.json
  - name: app5
    settings:
      - name: log_dir
        value: /var/logs/app5
      - name: repo_path
        value: new_apps/app5

You could then write something like the following to iterate over each setting for each application:

---
- hosts: localhost
  gather_facts: false
  vars_files:
    - applications.yml
  tasks:
    - debug:
        msg: "set {{ item.1.name }} to {{ item.1.value }} for {{ item.0.name }}"
      loop: "{{ applications|subelements('settings', skip_missing=true) }}"
      loop_control:
        label: "{{ item.0.name }}.{{ item.1.name }} = {{ item.1.value }}"

(I'm using loop_control here just to make the output nicer.)

Using the sample data you posted in applications.yml, this will produce as output:


PLAY [localhost] *********************************************************************

TASK [debug] *************************************************************************
ok: [localhost] => (item=app4.log_dir = /var/logs/app4) => {
    "msg": "set log_dir to /var/logs/app4 for app4"
}
ok: [localhost] => (item=app4.associated_files = ['auth/key.json']) => {
    "msg": "set associated_files to ['auth/key.json'] for app4"
}
ok: [localhost] => (item=app5.log_dir = /var/logs/app5) => {
    "msg": "set log_dir to /var/logs/app5 for app5"
}
ok: [localhost] => (item=app5.repo_path = new_apps/app5) => {
    "msg": "set repo_path to new_apps/app5 for app5"
}

PLAY RECAP ***************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Upvotes: 4

Related Questions