Kirill Zelepukin
Kirill Zelepukin

Reputation: 23

Extracting data from nested dict in ansible with conditional checks in the list?

I'm stuck with the following issue.
My JSON data looks like this:

[
   {
      "clusters":[
         {
            "id":"1",
            "name":"cluster1"
         },
         {
            "id":"2",
            "name":"cluster2"
         }
      ],
      "tag":"a"
   },
   {
      "clusters":[
         {
            "id":"3",
            "name":"cluster2"
         }
      ],
      "tag":"b"
   }
]

What I am trying to do is extracting the tag values which are connected to a certain cluster (say, cluster1). So, I need to check if cluster1 is in the list of clusters[*].name somehow.

Here is my playbook:

- name: "Test"
  hosts: localhost
  gather_facts: False

  vars:
  - test:
        - clusters:
            - name: "cluster1"
              id: "1"
            - name: "cluster2"
              id: "2"
          tag: "a"
        - clusters:
            - name: "cluster2"
              id: "3"
          tag: "b"

  - set_fact:
      tags_test: "{{ test | community.general.json_query('[?clusters[].name==`cluster1`].tag') }}"

  - debug:
      msg: "{{ tags_test }}"

What I am expecting to get is the tag value: "a".

This is the result:

TASK [debug] ******************************************************
ok: [localhost] => {
    "msg": []
}

I also tried combining json_query with selectattr, but, no luck.

Upvotes: 1

Views: 106

Answers (2)

Vladimir Botka
Vladimir Botka

Reputation: 68034

Create the dictionary of the tags and clusters first

  tag_clusters: "{{ test|json_query(tag_clusters_query)|items2dict }}"
  tag_clusters_query: '[].{key: tag, value: clusters[].name}'

gives

  tag_clusters:
    a:
    - cluster1
    - cluster2
    b:
    - cluster2

Then, selectattr and map the key(s)

  tags_test: "{{ tag_clusters|dict2items|
                 selectattr('value', 'contains', 'cluster1')|
                 map(attribute='key') }}"

gives

  tags_test:
  - a

Upvotes: 0

β.εηοιτ.βε
β.εηοιτ.βε

Reputation: 39129

With JMESPath you have to nest your conditions because you are looking for an object named cluster1 inside the the JSON array clusters which is nested in another array:

[?clusters[?name==`cluster1`]].tag|[0]

So as a task,

- set_fact:
    tags_test: >-
      {{ test | community.general.json_query(
           '[?clusters[?name==`cluster1`]].tag|[0]'
      ) }}

Upvotes: 2

Related Questions