Python

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

  • February 3, 2019

我想通過 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 變數(假或未定義都可以),我不想包含 IP。

從列表上方的片​​段中,該列表將僅包含:ipv4_networks:

['10.180.0.200','11.180.0.200']

弄清楚如何正確使用 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 秒 :)

引用自:https://serverfault.com/questions/951393