我有一个静态变量,它保存清单中所有主机的IP地址(如何动态获取是一个单独的问题),如下所示:
server_ips:
www1.example.com:
ipv4:
- 192.168.0.10
- 192.168.0.11
ipv6:
- '2a00:abcd:1234::100'
- '2a00:abcd:1234::101'
www2.example.com:
ipv4:
ipv6:
- '2a00:abcd:1234::200'
- '2a00:abcd:1234::201'
db1.example.com:
ipv4:
- 192.168.1.2
ipv6:
这些名称与我的清单中的主机一致:
[webservers]
www1.example.com
www2.example.com
[dbservers]
db1.example.com
对于在dbservers
组上运行的任务,我需要一个webserver
组中所有IP的列表(这使查询事实直接变得棘手,因为可能没有为那些主机收集事实) -在这种情况下,它需要提取:
- 192.168.0.10
- 192.168.0.11
- '2a00:abcd:1234::100'
- '2a00:abcd:1234::101'
- '2a00:abcd:1234::200'
- '2a00:abcd:1234::201'
这些任务将执行以下操作,例如配置防火墙和数据库访问:
- name: Allow web server access to DB server
ufw:
rule: allow
name: mysql
from_ip: "{{ item }}"
loop: "{{ <loop expression goes here> }}"
这是我遇到问题的loop
表达式中的内容。
查询有两个部分:提取主机列表,然后收集ip地址-分别对ipv4和ipv6做就可以了。
我可以用类似这样的表达式来达到目的>
{{ server_ips | map('extract', groups['webservers']) }}
{{ server_ips | intersect(groups['webservers']) }}
但是,这两者似乎都使结果变平,因此尽管它们找到了正确的项目,但是ipv4
和ipv6
列表元素不存在,因此我无法继续进行下一步。交换这些列表也没有帮助。
subelements
查找似乎是获取IP部分(虽然我实际上需要子子元素)并跳过空条目的一种好方法,但是我看不出如何达到这一点。
我应该如何进行查找?
答案 0 :(得分:0)
您尝试重新设计功能,Ansible已提供。您可以定义自己的DIY库存,尽管Ansible已经有一个库存。尽管Ansible知道如何遍历其库存,但您仍定义了自己的DIY库存迭代。
如果要将数据分配给各个主机,请使用Best Practices中所示的host_vars
目录。
host_vars/www1.example.com.yml
:
ipv4:
- 192.168.0.10
- 192.168.0.11
ipv6:
- '2a00:abcd:1234::100'
- '2a00:abcd:1234::101'
host_vars/www2.example.com.yml
:
ipv4:
ipv6:
- '2a00:abcd:1234::200'
- '2a00:abcd:1234::201'
然后,您为每个主机定义一个任务,并将{{ipv4}}
或{{ipv6}}
列表用于您要执行的任何操作。
如果您需要在其他主机(如防火墙)上执行操作,请使用Ansible's delegation。
这将从您的server_ips
字典中提取所有IP地址:
- hosts: localhost
connection: local
gather_facts: no
vars:
server_ips:
www1.example.com:
ipv4:
- 192.168.0.10
- 192.168.0.11
ipv6:
- '2a00:abcd:1234::100'
- '2a00:abcd:1234::101'
www2.example.com:
ipv4:
ipv6:
- '2a00:abcd:1234::200'
- '2a00:abcd:1234::201'
xyz.example.com:
ipv4:
- 192.168.1.2
ipv6:
ipv4: >-
{% set ipv4 = [] -%}
{% for ips in server_ips.values() | selectattr ('ipv4') | map (attribute='ipv4') | list -%}
{% for ip in ips -%}
{% set _ = ipv4.append(ip) -%}
{% endfor -%}
{% endfor -%}
{{ ipv4 }}
ipv6: >-
{% set ipv6 = [] -%}
{% for ips in server_ips.values() | selectattr ('ipv6') | map (attribute='ipv6') | list -%}
{% for ip in ips -%}
{% set _ = ipv6.append(ip) -%}
{% endfor -%}
{% endfor -%}
{{ ipv6 }}
ips: >-
{{ ipv4 + ipv6 }}
tasks:
- debug: var=server_ips
- debug: var=ipv4
- debug: var=ipv6
- debug: var=ips
但是要构建防火墙规则,您必须构建交叉产品。您必须遍历所有来源的每个目的地,以获得所有规则。