1

I've been trying to figure out for hours how to do the following with Ansible, and looping through a JSON output.

Let me explain, here is my playbook:

- hosts: myhosts
  connection: local
  gather_facts: yes
  tasks:
    - name: set_fact 
      set_fact: 
        disk_info: "{{ disks | json_query('[*].{disk_size: disksize}')}}"

    - name: print set_fact
      debug:
        msg: "{{ disk_info }}"

    - name: iterate on disk_info one and increase index 1..n
      debug:
        msg: "{{ item }} {{ my_idx }}"
      loop:
        - "{{ disk_info }}"
      loop_control:
        index_var: my_idx

Here is the json output that task - name: print outputs:

TASK [print] ****************************************************
ok: [hostname1] => {
    "msg": [
        {
            "disk_size": "200"
        },
        {
            "disk_size": "200"
        },
        {
            "disk_size": "200"
        }
    ]
}
ok: [hostname2] => {
    "msg": [
        {
            "disk_size": “300"
        }
    ]
}
ok: [hostname3] => {
    "msg": [
        {
            "disk_size": "250”
        }
    ]
}
ok: [hostname4] => {
    "msg": [
        {
            "disk_size": “500"
        },
        {
            "disk_size": “600”
        }
    ]
}

Here the output I'm getting from my task (- name: iterate on disk_info one and increase index 1..n)

ok: [hostname1] => (item=[{'disk_size': '200'}, {'disk_size': '200'}, {'disk_size': '200'}]) => {
    "msg": "[{'disk_size': '200'}, {'disk_size': '200'}, {'disk_size': '200'}] 0"
}
ok: [hostname2] => (item=[{'disk_size': ‘300'}]) => {
    "msg": "[{'disk_size': ‘300'}] 0"
}
ok: [hostname4] => (item=[{'disk_size': ‘500'}, {'disk_size': '600’}]) => {
    "msg": "[{'disk_size': ’500'}, {'disk_size': '600’}] 0"
}

Expected output:

Hostname1:
disk_size1: 200
disk_size2: 200
disk_size3: 200

Hostname2:
disk_size1: 300

Hostname3:
disk_size1: 500
disk_size2: 600

The expected output can be something similar but adding the index.

β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83
ayuuk ja'ay
  • 382
  • 1
  • 3
  • 13

1 Answers1

0

Are you trying to add the index to the structure, or to textual output? To get your expected output, your last task should loop over the list (instead of a list that contains the list) and output the data in that form:

    - name: iterate on disk_info one and increase index 1..n
      debug:
        msg: "disk_size{{ my_idx }}: {{ item.disk_size }}"
      loop: "{{ disk_info }}"
      loop_control:
        index_var: my_idx

Creating a structure is more difficult, but not impossible. I'm going to demonstrate without using json_query or set_fact, which should be avoided unless you're doing something that's impossible without them.

- hosts: my_hosts
  vars:
    # You didn't provide an example of your input structure, so I'm assuming it
    # looks something like this.
    disks:
      - name: foo
        disksize: 200
      - name: bar
        disksize: 200
    disk_info: "{{ dict(range(0, disks | length) | map('regex_replace', '^', 'disk_size') | zip(disks | map(attribute='disksize'))) }}"
  tasks:
    - debug:
        msg: "{{ disk_info }}"

Result:

TASK [debug] *******************************************************************
ok: [harmless-ghoul.syslog.x.mail.umich.edu] => {
    "msg": {
        "disk_size0": 200,
        "disk_size1": 200
    }
}
flowerysong
  • 2,921
  • 4
  • 13
  • Hi @flowerysong, Thanks for your quick reply, I really appreciate that. I just want a textual output. I changed the last task as your mentioned in the first example but I'm still getting this error output. {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'disk_size'\n\. It looks like disk_size cannot be accessed with item.disk_size. Am I missing something here? Thanks. – ayuuk ja'ay Nov 13 '21 at 22:01
  • Did you correct the `loop` line as I showed? EDIT: Well, it does say `dict object`, so probably. I don't see any dicts in the output you provided that don't have `disk_size`, so without more information about your new error I can't really guess what you might have done wrong. – flowerysong Nov 13 '21 at 22:02
  • Oh wow! You're a saviour. This works great and this is what I wanted. Just a question regarding to the loop line. Why does that make a difference the way I had it and yours? Thanks so much again. – ayuuk ja'ay Nov 13 '21 at 22:05
  • If you want a 1-indexed label rather than a 0-indexed one, use `extended: yes` instead under `loop_control`, then use `ansible_loop.index` instead of `my_idx` – β.εηοιτ.βε Nov 13 '21 at 22:10
  • Yes, I preferred with 1-indexed label and it works great. Thanks for pointing that out @β.εηοιτ.βε. – ayuuk ja'ay Nov 13 '21 at 22:27