Ansible:如何获取嵌套字典列表的子元素

Ansible:如何获取嵌套字典列表的子元素

我想通过 Ansible 构建我们的 DNS 区域。用户只需为正向查找区域 (例如 foo.bar) 维护一个变量。反向查找区域 (0.0.10.in-appr.arpa) 应由 Ansible 自动生成。

正向查找区域变量应如下所示

dns_zone_config:
    - name: "internal.foo.bar"
      acl:
        - 10.180.0.0/24
        - 10.180.8.0/24
      hosts:
        - name: "fileshare"
          ip: 10.180.0.200
    - name: "infra.foo.bar"
      acl:
        - acl-intern
      hosts:
        - name: "testhost1"
          ip: 11.180.0.100
          no_ptr_record: true
        - name: "testhost2"
          ipv6: fe80::1
        - name: "testhost3"
          ip: 11.180.0.200
    - name: "mx.foo.bar"
      mx:
        - name: "xxxx"
          priority: xxxx
          target: xxxx

dns_zone_config 是一个字典列表,可能包含一个名为“hosts”的键,而该键又是一个字典列表。

我现在的方式是这样的:

- name: Collect all networks
  include_tasks: 01-networks.yml
  loop: "{{ dns_zone_config }}"
  when: item_dns_zone_config.hosts is defined
  loop_control:
    loop_var: item_dns_zone_config

#from 01-networks.yml
- name: Determine IPv4 networks
  set_fact:
    ipv4_networks: "{{ (ipv4_networks | default([])) + [ item.ip ] }}"
  loop: "{{ item_dns_zone_config.hosts }}"
  when: item.ip is defined and (item.no_ptr_record is not defined or not item.no_ptr_record)

我重复遍历 dns_zone_config 及其主机条目。这非常低效且缓慢。我确信这个问题可以更智能地解决 :D

基本上我只需要所有区域的所有 IP 列表。我尝试了 json_query() 和 selectattr() 过滤器,但令我苦恼的是,并非每个主机条目都定义了 IPv4 或 IPv6 地址。如果定义了 no_ptr_record: true 变量(false 或未定义也可以),则我不想包含 IP。

从上面的代码片段来看,列表只包含:ipv4_networks:

['10.180.0.200','11.180.0.200']

答案1

弄清楚如何正确使用 json_query。

  - debug:                                                                      
      msg: "{{ dns_zone_config | json_query(_query) }}"                         
    vars:                                                                       
      _query: "[].hosts[?!no_ptr_record][].[ip,ipv6][]"    

结果是:

TASK [debug] ***********************************************************************************
ok: [localhost] => {
    "msg": [
        "10.180.0.200",
        "fe80::1",
        "11.180.0.200"
    ]
}

只需 1-2 秒,而不是双循环约 30 秒 :)

相关内容