在 Ansible 中使用 json_query 来查询字典列表中包含的字典列表
Use json_query in Ansible to query a list of dictionaries contained within a list of dictionaries
我在使用 json_query 搜索以下数据结构时遇到问题,我想从中创建两个单独的列表。
对于成员列表包含子路径键且值包含特定值的条目,列表 1 应包含每个字典中的名称键。
对于成员列表不包含子路径键且名称包含特定值的条目,列表 2 应包含每个字典中的名称键。
到目前为止我能得到的最接近的是找到那些成员字典有 subPath
键的字典:
- name: debug
debug:
msg: "{{ device_facts.gtm_a_pools | json_query(query) }}"
vars:
query: "[].members[?!subPath][].name"
或没有子路径键:
- name: debug
debug:
msg: "{{ device_facts.gtm_a_pools | json_query(query) }}"
vars:
query: "[].members[?subPath][].name"
但是这是从成员字典中返回名称键,当我想要的是基于上述两个标准的每个 gtm_a_pools 字典中的名称键(一个具有子路径的列表和一个列表对于没有的人)。
使用以下数据结构:
- 列表 1 = ['a2-test_pool']
- 列表 2 = ['aci_pool']
"gtm_a_pools": [
{
"alternate_mode": "global-availability",
"dynamic_ratio": "no",
"enabled": "yes",
"fallback_mode": "return-to-dns",
"full_path": "/Common/a2-test_pool",
"load_balancing_mode": "global-availability",
"manual_resume": "no",
"max_answers_returned": 1,
"members": [
{
"disabled": "no",
"enabled": "yes",
"limitMaxBps": 0,
"limitMaxBpsStatus": "disabled",
"limitMaxConnections": 0,
"limitMaxConnectionsStatus": "disabled",
"limitMaxPps": 0,
"limitMaxPpsStatus": "disabled",
"member_order": 0,
"monitor": "default",
"name": "a2-test_443_vs",
"partition": "Common",
"ratio": 1,
"subPath": "test-dmz-dc1-pair:/Common"
},
{
"disabled": "no",
"enabled": "yes",
"limitMaxBps": 0,
"limitMaxBpsStatus": "disabled",
"limitMaxConnections": 0,
"limitMaxConnectionsStatus": "disabled",
"limitMaxPps": 0,
"limitMaxPpsStatus": "disabled",
"member_order": 1,
"monitor": "default",
"name": "dc2-a2-test_443_vs",
"partition": "Common",
"ratio": 1,
"subPath": "test-dmz-dc2-pair:/Common"
}
],
"name": "a2-test_pool",
"partition": "Common",
"qos_hit_ratio": 5,
"qos_hops": 0,
"qos_kilobytes_second": 3,
"qos_lcs": 30,
"qos_packet_rate": 1,
"qos_rtt": 50,
"qos_topology": 0,
"qos_vs_capacity": 0,
"qos_vs_score": 0,
"ttl": 30,
"verify_member_availability": "yes"
},
{
"alternate_mode": "round-robin",
"dynamic_ratio": "no",
"enabled": "yes",
"fallback_mode": "return-to-dns",
"full_path": "/Common/aci_pool",
"load_balancing_mode": "round-robin",
"manual_resume": "no",
"max_answers_returned": 1,
"members": [
{
"disabled": "no",
"enabled": "yes",
"limitMaxBps": 0,
"limitMaxBpsStatus": "disabled",
"limitMaxConnections": 0,
"limitMaxConnectionsStatus": "disabled",
"limitMaxPps": 0,
"limitMaxPpsStatus": "disabled",
"member_order": 0,
"monitor": "default",
"name": "prod_dc1_servers:aci",
"partition": "Common",
"ratio": 1
},
{
"disabled": "no",
"enabled": "yes",
"limitMaxBps": 0,
"limitMaxBpsStatus": "disabled",
"limitMaxConnections": 0,
"limitMaxConnectionsStatus": "disabled",
"limitMaxPps": 0,
"limitMaxPpsStatus": "disabled",
"member_order": 1,
"monitor": "default",
"name": "prod_dc1_servers:aci",
"partition": "Common",
"ratio": 1
}
],
"name": "aci_pool",
"partition": "Common",
"qos_hit_ratio": 5,
"qos_hops": 0,
"qos_kilobytes_second": 3,
"qos_lcs": 30,
"qos_packet_rate": 1,
"qos_rtt": 50,
"qos_topology": 0,
"qos_vs_capacity": 0,
"qos_vs_score": 0,
"ttl": 30,
"verify_member_availability": "yes"
}
]
问:"根据上述两个标准从每个 gtm_a_pools 字典中命名键(一个列表有子路径,一个列表没有子路径)"
A:代替json_query,迭代列表并比较成员的数量,例如
- set_fact:
list1: "{{ list1|default([]) + [item.name] }}"
loop: "{{ gtm_a_pools }}"
when: item_length == subPath_length
vars:
subPath_length: "{{ item.members|map('intersect', ['subPath'])|flatten|length }}"
item_length: "{{ item.members|length }}"
给予
list1:
- a2-test_pool
如果"without subPath"表示"any member without subPath"
- set_fact:
list2: "{{ list2|default([]) + [item.name] }}"
loop: "{{ gtm_a_pools }}"
when: item_length != subPath_length
vars:
subPath_length: "{{ item.members|map('intersect', ['subPath'])|flatten|length }}"
item_length: "{{ item.members|length }}"
给予
list2:
- aci_pool
如果“没有子路径”意味着“没有子路径的所有成员”下面的任务给出相同的结果
- set_fact:
list2: "{{ list2|default([]) + [item.name] }}"
loop: "{{ gtm_a_pools }}"
when: subPath_length|int == 0
vars:
subPath_length: "{{ item.members|map('intersect', ['subPath'])|flatten|length }}"
谢谢你,弗拉基米尔!
在等待某人的回复时,我想到了这个,所以我想在这里分享它。我要说的是,这可能不一定解释列表 2 的两种情况,其中我解释了“没有子路径的所有成员”与“没有子路径的任何成员”。因此,我将上面的解决方案用于 运行 最后的验证以处理整个负载并进行比较,并输出具有混合成员类型的任何池:
---
- name: Determine if Server List product is Generic Host (static) or otherwise
bigip_device_info:
gather_subset:
- gtm-servers
provider: "{{ vcmp_guest_provider }}"
delegate_to: localhost
register: device_facts
# server_type = generic-host vs. bigip
# bigip = dynamic
# generic-host = static
- name: Set type fact
set_fact:
server_type: "{{ device_facts | json_query(jmesquery) | join }}"
vars:
jmesquery: "gtm_servers[?name == '{{ gtm_source_server }}'].product"
- name: debug
debug:
var: server_type
- name: Gather GTM pools
bigip_device_info:
gather_subset:
- gtm-a-pools
provider: "{{ vcmp_guest_provider }}"
delegate_to: localhost
register: device_facts
- name: Create list of pools that use discovered objects and are part of {{ gtm_source_server }}
set_fact:
pool_list: "{{ pool_list | default([]) + [ item.0 ] }}"
loop: "{{ pool_name | zip(payload) | list }}"
when:
- item.1 | json_query('members[*].subPath') | length > 0
- item.1 | json_query('members[*].subPath') is search(gtm_source_server)
- server_type == "bigip"
vars:
pool_name: "{{ device_facts | json_query('gtm_a_pools[*].name') }}"
payload: "{{ device_facts | json_query('gtm_a_pools[*]') }}"
no_log: true
- name: Create list of pools that use static objects and are part of {{ gtm_source_server }}
set_fact:
pool_list: "{{ pool_list | default([]) + [ item.0 ] }}"
loop: "{{ pool_name | zip(payload) | list }}"
when:
- item.1 | json_query('members[*].subPath') | length == 0
- item.1 | json_query('members[*].name') is search(gtm_source_server)
- server_type == "generic-host"
vars:
pool_name: "{{ device_facts | json_query('gtm_a_pools[*].name') }}"
payload: "{{ device_facts | json_query('gtm_a_pools[*]') }}"
no_log: true
- debug:
var: pool_list
- name: Check if any pools contain a mix of static and dynamic members
set_fact:
counter: "{{ counter | default([]) + [ item.name + ' has ' + subPath_length + ' dynamic entries and ' + member_length + ' static entries.' ] }}"
loop: "{{ device_facts | json_query('gtm_a_pools[*]') }}"
vars:
subPath_length: "{{ item.members|map('intersect', ['subPath'])|flatten|length }}"
member_length: "{{ item.members|length }}"
when:
- subPath_length | int > 0
- member_length != subPath_length
no_log: true
- debug:
msg: "{{ counter | default('No mixture found') }}"
我在使用 json_query 搜索以下数据结构时遇到问题,我想从中创建两个单独的列表。
对于成员列表包含子路径键且值包含特定值的条目,列表 1 应包含每个字典中的名称键。
对于成员列表不包含子路径键且名称包含特定值的条目,列表 2 应包含每个字典中的名称键。
到目前为止我能得到的最接近的是找到那些成员字典有 subPath
键的字典:
- name: debug
debug:
msg: "{{ device_facts.gtm_a_pools | json_query(query) }}"
vars:
query: "[].members[?!subPath][].name"
或没有子路径键:
- name: debug
debug:
msg: "{{ device_facts.gtm_a_pools | json_query(query) }}"
vars:
query: "[].members[?subPath][].name"
但是这是从成员字典中返回名称键,当我想要的是基于上述两个标准的每个 gtm_a_pools 字典中的名称键(一个具有子路径的列表和一个列表对于没有的人)。
使用以下数据结构:
- 列表 1 = ['a2-test_pool']
- 列表 2 = ['aci_pool']
"gtm_a_pools": [
{
"alternate_mode": "global-availability",
"dynamic_ratio": "no",
"enabled": "yes",
"fallback_mode": "return-to-dns",
"full_path": "/Common/a2-test_pool",
"load_balancing_mode": "global-availability",
"manual_resume": "no",
"max_answers_returned": 1,
"members": [
{
"disabled": "no",
"enabled": "yes",
"limitMaxBps": 0,
"limitMaxBpsStatus": "disabled",
"limitMaxConnections": 0,
"limitMaxConnectionsStatus": "disabled",
"limitMaxPps": 0,
"limitMaxPpsStatus": "disabled",
"member_order": 0,
"monitor": "default",
"name": "a2-test_443_vs",
"partition": "Common",
"ratio": 1,
"subPath": "test-dmz-dc1-pair:/Common"
},
{
"disabled": "no",
"enabled": "yes",
"limitMaxBps": 0,
"limitMaxBpsStatus": "disabled",
"limitMaxConnections": 0,
"limitMaxConnectionsStatus": "disabled",
"limitMaxPps": 0,
"limitMaxPpsStatus": "disabled",
"member_order": 1,
"monitor": "default",
"name": "dc2-a2-test_443_vs",
"partition": "Common",
"ratio": 1,
"subPath": "test-dmz-dc2-pair:/Common"
}
],
"name": "a2-test_pool",
"partition": "Common",
"qos_hit_ratio": 5,
"qos_hops": 0,
"qos_kilobytes_second": 3,
"qos_lcs": 30,
"qos_packet_rate": 1,
"qos_rtt": 50,
"qos_topology": 0,
"qos_vs_capacity": 0,
"qos_vs_score": 0,
"ttl": 30,
"verify_member_availability": "yes"
},
{
"alternate_mode": "round-robin",
"dynamic_ratio": "no",
"enabled": "yes",
"fallback_mode": "return-to-dns",
"full_path": "/Common/aci_pool",
"load_balancing_mode": "round-robin",
"manual_resume": "no",
"max_answers_returned": 1,
"members": [
{
"disabled": "no",
"enabled": "yes",
"limitMaxBps": 0,
"limitMaxBpsStatus": "disabled",
"limitMaxConnections": 0,
"limitMaxConnectionsStatus": "disabled",
"limitMaxPps": 0,
"limitMaxPpsStatus": "disabled",
"member_order": 0,
"monitor": "default",
"name": "prod_dc1_servers:aci",
"partition": "Common",
"ratio": 1
},
{
"disabled": "no",
"enabled": "yes",
"limitMaxBps": 0,
"limitMaxBpsStatus": "disabled",
"limitMaxConnections": 0,
"limitMaxConnectionsStatus": "disabled",
"limitMaxPps": 0,
"limitMaxPpsStatus": "disabled",
"member_order": 1,
"monitor": "default",
"name": "prod_dc1_servers:aci",
"partition": "Common",
"ratio": 1
}
],
"name": "aci_pool",
"partition": "Common",
"qos_hit_ratio": 5,
"qos_hops": 0,
"qos_kilobytes_second": 3,
"qos_lcs": 30,
"qos_packet_rate": 1,
"qos_rtt": 50,
"qos_topology": 0,
"qos_vs_capacity": 0,
"qos_vs_score": 0,
"ttl": 30,
"verify_member_availability": "yes"
}
]
问:"根据上述两个标准从每个 gtm_a_pools 字典中命名键(一个列表有子路径,一个列表没有子路径)"
A:代替json_query,迭代列表并比较成员的数量,例如
- set_fact:
list1: "{{ list1|default([]) + [item.name] }}"
loop: "{{ gtm_a_pools }}"
when: item_length == subPath_length
vars:
subPath_length: "{{ item.members|map('intersect', ['subPath'])|flatten|length }}"
item_length: "{{ item.members|length }}"
给予
list1:
- a2-test_pool
如果"without subPath"表示"any member without subPath"
- set_fact:
list2: "{{ list2|default([]) + [item.name] }}"
loop: "{{ gtm_a_pools }}"
when: item_length != subPath_length
vars:
subPath_length: "{{ item.members|map('intersect', ['subPath'])|flatten|length }}"
item_length: "{{ item.members|length }}"
给予
list2:
- aci_pool
如果“没有子路径”意味着“没有子路径的所有成员”下面的任务给出相同的结果
- set_fact:
list2: "{{ list2|default([]) + [item.name] }}"
loop: "{{ gtm_a_pools }}"
when: subPath_length|int == 0
vars:
subPath_length: "{{ item.members|map('intersect', ['subPath'])|flatten|length }}"
谢谢你,弗拉基米尔!
在等待某人的回复时,我想到了这个,所以我想在这里分享它。我要说的是,这可能不一定解释列表 2 的两种情况,其中我解释了“没有子路径的所有成员”与“没有子路径的任何成员”。因此,我将上面的解决方案用于 运行 最后的验证以处理整个负载并进行比较,并输出具有混合成员类型的任何池:
---
- name: Determine if Server List product is Generic Host (static) or otherwise
bigip_device_info:
gather_subset:
- gtm-servers
provider: "{{ vcmp_guest_provider }}"
delegate_to: localhost
register: device_facts
# server_type = generic-host vs. bigip
# bigip = dynamic
# generic-host = static
- name: Set type fact
set_fact:
server_type: "{{ device_facts | json_query(jmesquery) | join }}"
vars:
jmesquery: "gtm_servers[?name == '{{ gtm_source_server }}'].product"
- name: debug
debug:
var: server_type
- name: Gather GTM pools
bigip_device_info:
gather_subset:
- gtm-a-pools
provider: "{{ vcmp_guest_provider }}"
delegate_to: localhost
register: device_facts
- name: Create list of pools that use discovered objects and are part of {{ gtm_source_server }}
set_fact:
pool_list: "{{ pool_list | default([]) + [ item.0 ] }}"
loop: "{{ pool_name | zip(payload) | list }}"
when:
- item.1 | json_query('members[*].subPath') | length > 0
- item.1 | json_query('members[*].subPath') is search(gtm_source_server)
- server_type == "bigip"
vars:
pool_name: "{{ device_facts | json_query('gtm_a_pools[*].name') }}"
payload: "{{ device_facts | json_query('gtm_a_pools[*]') }}"
no_log: true
- name: Create list of pools that use static objects and are part of {{ gtm_source_server }}
set_fact:
pool_list: "{{ pool_list | default([]) + [ item.0 ] }}"
loop: "{{ pool_name | zip(payload) | list }}"
when:
- item.1 | json_query('members[*].subPath') | length == 0
- item.1 | json_query('members[*].name') is search(gtm_source_server)
- server_type == "generic-host"
vars:
pool_name: "{{ device_facts | json_query('gtm_a_pools[*].name') }}"
payload: "{{ device_facts | json_query('gtm_a_pools[*]') }}"
no_log: true
- debug:
var: pool_list
- name: Check if any pools contain a mix of static and dynamic members
set_fact:
counter: "{{ counter | default([]) + [ item.name + ' has ' + subPath_length + ' dynamic entries and ' + member_length + ' static entries.' ] }}"
loop: "{{ device_facts | json_query('gtm_a_pools[*]') }}"
vars:
subPath_length: "{{ item.members|map('intersect', ['subPath'])|flatten|length }}"
member_length: "{{ item.members|length }}"
when:
- subPath_length | int > 0
- member_length != subPath_length
no_log: true
- debug:
msg: "{{ counter | default('No mixture found') }}"