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.

1 Answer 1

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
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

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.
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.
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.
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
Yes, I preferred with 1-indexed label and it works great. Thanks for pointing that out @β.εηοιτ.βε.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.