Help with complex json_query

22 views
Skip to first unread message

spiro.m...@mcgill.ca

unread,
Aug 3, 2022, 5:29:27 PM8/3/22
to Ansible Project
Hi,

I have the following data:
    "application_profiles": [
        {
            "app_desc": "",
            "app_name": "NCS_Net_inf",
            "epg_name": [
                "SPAN-destination-analysis",
                "infra_auth_servers",
                "netinf_test_servers",
                "paaa-infra-mgt",
                "vl2003"
            ]
        },
        {
            "app_desc": "dept: MedIT",
            "app_name": "faculty_of_medicine",
            "epg_name": [
                "medit_jump_server"
            ]
        },
        {
            "app_desc": "",
            "app_name": "dc_qa_app_fe",
            "epg_name": [
                "vl3800"
            ]
        }
    ]
}

AND

   "epg_bd_list": [
        {
            "fvAEPg": {
                "attributes": {
                    "name": "SPAN-destination-analysis",
                    "nameAlias": "vl2022"
                },
        {
            "fvAEPg": {
                "attributes": {
                   "name": "vl72",
                    "nameAlias": "Bone_Centre"

                 }
]

I'm trying to do a json_query using the contain function but I cannot seem to figure out how to use it properly.
 - debug:
      msg: "{{ item.fvAEPg.attributes.name }} is in app profile: {{ application_profiles | to_json | from_json | json_query('*.[?epg_name.contains(@, `{{ item.fvAEPg.attributes.name }}`)].app_name') }}"
    loop: "{{ epg_bd_list }}"


I've done a lot of json_query but this is the first time that the variable I am searching for "epg_name" is a list and not a single item.  I managed to make it work if the matching "item.fvAEPg.attributes.name" is the first item in the list.  I'd like to pick out the app_name if the item.fvAEPg.attributes.name is in the list of epg_name.

Thanks,
Spiro

Todd Lewis

unread,
Aug 4, 2022, 12:27:23 AM8/4/22
to ansible...@googlegroups.com, spiro.m...@mcgill.ca, uto...@gmail.com
If you have to resort to json_query, you might as well create real loops. Below is the playbook I used to explore your data. I left in some experiments that helped me along the way. Perhaps something here will be useful to you. I added another element to your epg_bd_list to cover the single element case.

---
- name: json_query playground
  hosts: localhost
  gather_facts: no
  vars:
    application_profiles:
      - app_desc: ""
        app_name: NCS_Net_inf
        epg_name:
           - SPAN-destination-analysis
           - infra_auth_servers
           - netinf_test_servers
           - paaa-infra-mgt
           - vl2003
      - app_desc: "dept: MedIT"
        app_name: faculty_of_medicine
        epg_name:
           - medit_jump_server
      - app_desc: ""
        app_name: dc_qa_app_fe
        epg_name:
           - vl3800
    epg_bd_list:
      - fvAEPg:
          attributes:
            name: SPAN-destination-analysis
            nameAlias: vl2022
      - fvAEPg:
          attributes:
            name: vl72
            nameAlias: Bone_Centre
      - fvAEPg:
          attributes:
            name: medit_jump_server
            nameAlias: Jumpin_Jiminy
  tasks:
    - name: Explorations of ways to examine epg_bd_list
      debug:
        msg:
         - "aaa {{ epg_bd_list | map(attribute='fvAEPg') }}"
         - "bbb {{ epg_bd_list | map(attribute='fvAEPg.attributes.name') }}"
         - "ccc {{ epg_bd_list | map('dict2items') }}"
         - "ddd {{ epg_bd_list | map('dict2items') | flatten | map(attribute='value.attributes.name') }}"

    - name: isolate the app_name from application_profiles
      debug:
        msg:
         - "aaa {{ application_profiles | map(attribute='app_name') }}"

    - name: Uses product of epg_bd_lst.attributes.name and application_profiles to get matching app_names
      debug:
        msg:
         - |
          {% set app_names=[] %}
          {% for app in application_profiles | product(epg_bd_list| map('dict2items') | flatten | map(attribute='value.attributes.name')) %}
          {%   if app[1] in app[0]['epg_name'] %}
          {%      set _ = app_names.append( app[0]['app_name'] ) %}
          {%   endif %}
          {% endfor %}
          {{ app_names }}

#    - name: Would this ever be handy? Maybe
#      debug:
#        msg: "{{ item }}: {{ application_profiles | map(attribute='epg_name') }}"
#      loop: "{{ epg_bd_list | map('dict2items') | flatten | map(attribute='value.attributes.name') }}"
#
#    - name: How about this?
#      debug:
#        msg: "{{ application_profiles | map(attribute='epg_name') | map('select', 'in', item) }}"
#      loop: "{{ epg_bd_list | map('dict2items') | flatten | map(attribute='value.attributes.name') }}"


--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/039c2014-57ef-4649-a578-ea7aa9134840n%40googlegroups.com.

Vladimir Botka

unread,
Aug 4, 2022, 12:52:00 AM8/4/22
to spiro.m...@mcgill.ca, ansible...@googlegroups.com
On Wed, 3 Aug 2022 14:29:27 -0700 (PDT)
"spiro.m...@mcgill.ca" <spiro.m...@mcgill.ca> wrote:

> - debug:
> msg: "{{ item.fvAEPg.attributes.name }} is in app profile: {{
> application_profiles | to_json | from_json |
> json_query('*.[?epg_name.contains(@, `{{ item.fvAEPg.attributes.name
> }}`)].app_name') }}"
> loop: "{{ epg_bd_list }}"

Try this:

- debug:
msg: "{{ _item }} is in app profile: {{ app_profile }}"
loop: "{{ epg_bd_list }}"
vars:
_item: "{{ item.fvAEPg.attributes.name }}"
_query: '[?epg_name.contains(@, `{{ _item }}`)].app_name'
app_profile: "{{ application_profiles|json_query(_query) }}"


Note: In the JSON, the braces {} are not properly balanced. Use YAML
--
Vladimir Botka
Reply all
Reply to author
Forward
0 new messages