提问人:Steven Wybraniec 提问时间:10/12/2023 更新时间:10/19/2023 访问量:46
一种更有效的方法,使用 Ansible 比较两个词典列表,并使用两者中的元素创建新结构
A more efficient way of using Ansible to compare two lists of dictionaries, and creating a new structure with elements from both
问:
我有一个 Ansible playbook,负责使用 API 创建项目。为了检查我刚刚创建的内容是否正常工作,我从另一个 API 端点提取创建后的状态信息。然后,我需要根据刚刚创建的内容检查状态信息,以确保一切正常。
收集的有关状态的信息存储在另一个字典列表中,该列表包含来自两个列表的信息。然后检查生成的信息,看看是否一切正常。我有一些代码可以部分解决这个问题,但它充满了循环并且效率不高。
因此,我想知道是否有人可以帮助我解决上述问题?
有关我正在创建的内容的信息是从.csv文件中读取的,结果列表如下所示(为了保护隐私,数据被故意混淆和截断,但结构是正确的)输出是根据存储 csv 文件内容的变量的输出,由以下人员读取:ansible.builtin.debug
csv_test_data
community.general.read_csv
ok: [...] => {
"csv_test_data" : {
"changed": false,
"dict": {},
"failed": false,
"list": [
{
"Service GroupWebservice": "SERVICE_GROUP_01",
"ServiceGroupWebsite": "SITE_GROUP_01",
"ServiceIP1": "1.1.1.1",
"Service1ServerName": "SERVER0101",
"ServiceIP2": "2.2.2.2",
"Service2ServerName": "SERVER0102",
"WebServiceIP1": "10.10.10.10",
"WebService1ServerName": "WEBSERVER0101",
"WebServiceIP2": "11.11.11.11",
"WebService2ServerName": "WEBSERVER0102",
"EnvironmentName": "TEST",
"CustomerName": "CUSTOMER01",
"WebserviceMonitorName": "MON_WEBSERVICE_01",
"WebsiteMonitorName": "MON_WEBSITE_01"
},
{
"Service GroupWebservice": "SERVICE_GROUP_02",
"ServiceGroupWebsite": "SITE_GROUP_02",
"ServiceIP1": "5.5.5.5",
"Service1ServerName": "SERVER0201",
"ServiceIP2": "6.6.6.6",
"Service2ServerName": "SERVER0202",
"WebServiceIP1": "15.15.15.15",
"WebService1ServerName": "WEBSERVER0201",
"WebServiceIP2": "16.16.16.16",
"WebService2ServerName": "WEBSERVER0202",
"EnvironmentName": "TEST",
"CustomerName": "CUSTOMER02",
"WebserviceMonitorName": "MON_WEBSERVICE_02",
"WebsiteMonitorName": "MON_WEBSITE_02"
},
...
]
}
}
我正在检查的状态信息包含在从 API 端点提取的另一个字典列表中。这包含有关运行状况监视器的所有实例的状态信息;即比我刚刚创建的要多,所以我需要与这些信息的子集进行比较。同样,该结构是正确的,并且直接取自变量的输出,但它混淆和截断了数据。ansible.builtin.debug
get_reponse_oper
ok: [...] => {
"get_response_oper": {
...
"changed": false,
"failed": false,
"json": {
"health-stat": {
...
"oper": {
"health-check-list" [
{
...
"down-cause": 101,
"down-state": 10,
"health-monitor": "default",
"ip-address": "200.200.200.200",
"server": "SOMESERVER",
"status": "DOWN"
},
{
...
"down-cause": 7,
"down-state": 8,
"health-monitor": "MON_WEBSERVICE_01",
"ip-address": "1.1.1.1",
"server": "SERVER0101",
"status": "UP"
},
{
...
"down-cause": 7,
"down-state": 8,
"health-monitor": "MON_WEBSERVICE_01",
"ip-address": "2.2.2.2",
"server": "SERVER0102",
"status": "UP"
},
{
...
"down-cause": 41,
"down-state": 10,
"health-monitor": "MON_WEBSITE_02",
"ip-address": "15.15.15.15",
"server": "WEBSERVER0201",
"status": "DOWN"
},
...
]
}
}
}
}
}
就我生成的内容而言,我希望生成要创建的字典列表,以便我可以查看/检查每个已创建项目的状态。
在此列表中,每个客户将有一个条目,即初始创建.csv文件中的每一行一个条目(每个客户有四个 IP 地址,两个用于服务器,两个用于 Web 服务器)。
每个监视器的状态取自第二个列表(存储在 中),使用从第一个列表中获取的和/或交叉引用。health-check-list
"ip-address"
"server"
{
"health_monitor_statuses": [
{
"customer": "CUSTOMER01",
"serviceIp1": "UP",
"serviceIP2": "UP",
"site1IP1": "UP",
"site2IP2": "UP"
},
{
"customer": "CUSTOMER02",
"serviceIp1": "DOWN",
"serviceIP2": "DOWN",
"site1IP1": "DOWN",
"site2IP2": "DOWN"
}
]
}
最后,我将遍历创建的health_monitor_statuses列表,如果看到任何条目,则失败。"DOWN"
"UNKN"
我相信这在 Ansible 中是可能的/合理的。任何帮助/指导将不胜感激。
我尝试了许多不同的方法来解决这个问题。
最新的由任务文件组成,该文件在每个客户的循环中调用。任务文件代码如下:
我真的不喜欢代码,因为有太多的循环,而且它并没有让我感到非常快速/高效。这让我觉得一定有更好的方法。
---
- name: "Find the status for the first service IP address {{ health_monitor_test.ServiceIP1 }}."
no_log: true
ansible.builtin.set_fact:
health_check_service1_status: "{{ checking_service1.status }}"
loop:
"{{ health_monitor_status_list }}"
loop_control:
loop_var: checking_service1
when: checking_service1['ip-address'] == health_monitor_test.ServiceIP1
- name: "Find the status for the second service IP address {{ health_monitor_test.ServiceIP2 }}."
no_log: true
ansible.builtin.set_fact:
health_check_service2_status: "{{ checking_service2.status }}"
loop:
"{{ health_monitor_status_list }}"
loop_control:
loop_var: checking_service2
when: checking_service2['ip-address'] == health_monitor_test.ServiceIP2
- name: "Find the status for the first web site IP address {{ health_monitor_test.WebServiceIP1 }}."
no_log: true
ansible.builtin.set_fact:
health_check_site1_status: "{{ checking_site1.status }}"
loop:
"{{ health_monitor_status_list }}"
loop_control:
loop_var: checking_site1
when: checking_site1['ip-address'] == health_monitor_test.WebServiceIP1
- name: "Find the status for the second web site IP address {{ health_monitor_test.WebServiceIP2 }}."
no_log: true
ansible.builtin.set_fact:
health_check_site2_status: "{{ checking_site2.status }}"
loop:
"{{ health_monitor_status_list }}"
loop_control:
loop_var: checking_site2
when: checking_site2['ip-address'] == health_monitor_test.WebServiceIP2
- name: "Create the basic structure that will store the health monitor statuses."
ansible.builtin.set_fact:
temp: "{
'customer' : {{ health_monitor_test.CustomerName }},
'serviceIp1' : {{ health_check_service1_status | default('undefined') }},
'service2Ip' : {{ health_check_service2_status | default('undefined') }},
'site1Ip' : {{ health_check_site1_status | default('undefined') }},
'site2Ip' : {{ health_check_site2_status | default('undefined') }}
}"
- name: "Add the heartbeat statuses for customer {{ health_monitor_test.TMC_Manifest_CustomerName }} to the main structure."
no_log: true
ansible.builtin.set_fact:
health_monitor_statuses: "{{ health_monitor_statuses + [temp] }}"
答:
创建 IP 及其状态的字典
hcd: "{{ health_check_list|
items2dict(key_name='ip-address', value_name='status') }}"
给
hcd:
1.1.1.1: UP
10.10.10.10: UP
11.11.11.11: UP
15.15.15.15: DOWN
16.16.16.16: DOWN
2.2.2.2: UP
5.5.5.5: DOWN
6.6.6.6: DOWN
然后,使用 Jinja 并创建您想要的内容
health_monitor_statuses: |
{% filter from_yaml %}
{% for i in csv_test_data.list %}
- customer: {{ i.CustomerName }}
serviceIP1: {{ hcd[i.ServiceIP1] }}
serviceIP2: {{ hcd[i.ServiceIP2] }}
siteIP1: {{ hcd[i.WebServiceIP1] }}
siteIP2: {{ hcd[i.WebServiceIP2] }}
{% endfor %}
{% endfilter %}
给
health_monitor_statuses:
- customer: CUSTOMER01
serviceIP1: UP
serviceIP2: UP
siteIP1: UP
siteIP2: UP
- customer: CUSTOMER02
serviceIP1: DOWN
serviceIP2: DOWN
siteIP1: DOWN
siteIP2: DOWN
用于测试的 mre playbook 示例
- hosts: all
vars:
csv_test_data:
list:
- CustomerName: CUSTOMER01
ServiceIP1: 1.1.1.1
ServiceIP2: 2.2.2.2
WebServiceIP1: 10.10.10.10
WebServiceIP2: 11.11.11.11
- CustomerName: CUSTOMER02
ServiceIP1: 5.5.5.5
ServiceIP2: 6.6.6.6
WebServiceIP1: 15.15.15.15
WebServiceIP2: 16.16.16.16
health_check_list:
- {ip-address: 1.1.1.1, status: UP}
- {ip-address: 2.2.2.2, status: UP}
- {ip-address: 5.5.5.5, status: DOWN}
- {ip-address: 6.6.6.6, status: DOWN}
- {ip-address: 10.10.10.10, status: UP}
- {ip-address: 11.11.11.11, status: UP}
- {ip-address: 15.15.15.15, status: DOWN}
- {ip-address: 16.16.16.16, status: DOWN}
hcd: "{{ health_check_list|
items2dict(key_name='ip-address', value_name='status') }}"
health_monitor_statuses: |
{% filter from_yaml %}
{% for i in csv_test_data.list %}
- customer: {{ i.CustomerName }}
serviceIP1: {{ hcd[i.ServiceIP1] }}
serviceIP2: {{ hcd[i.ServiceIP2] }}
siteIP1: {{ hcd[i.WebServiceIP1] }}
siteIP2: {{ hcd[i.WebServiceIP2] }}
{% endfor %}
{% endfilter %}
tasks:
- debug:
var: csv_test_data
- debug:
var: health_check_list
- debug:
var: hcd
- debug:
var: health_monitor_statuses
评论