使用 Ansible 比较两个字典列表并使用两者中的元素创建新结构的更有效方法

问题描述 投票:0回答:1

我有一个 Ansible 剧本,负责使用 API 创建项目。为了检查我刚刚创建的内容是否正常工作,我从另一个 API 端点提取创建后的状态信息。然后,我需要根据刚刚创建的信息检查状态信息,以确保一切正常工作。

收集的有关状态的信息存储在另一个字典列表中,其中包含两个列表中的信息。然后检查生成的信息以查看一切是否正常运行。我有一些代码可以部分解决这个问题,但它充满循环并且效率不高。

因此我想知道是否有人可以帮助我解决上述问题?

有关我正在创建的内容的信息已从 .csv 文件中读取,结果列表如下所示(出于隐私考虑,数据已被故意混淆和截断,但结构是正确的)输出按照

ansible.builtin.debug
变量
csv_test_data
上的输出,它存储 csv 文件的内容,由
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] }}"

json list dictionary ansible lookup
1个回答
0
投票

创建 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剧本示例

- 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
© www.soinside.com 2019 - 2024. All rights reserved.