如何在Ansible Jinja模板中用单个for循环同时遍历两个列表
问题原因
你写的for validator_ip,validator in 列表1,列表2属于Jinja2的并行遍历语法,要求两个遍历的列表长度完全一致,每次循环分别取两个列表相同位置的元素赋值,你的两个列表长度不匹配才会抛出解包错误,而且这个逻辑本身就不能实现把两个列表所有元素都拼接的需求。
可行实现方案
推荐使用Jinja2列表推导实现,代码简洁易读,不需要额外的循环边界判断:
#!/bin/sh /usr/local/bin/haproxy-ea-health-check \ -reference-servers="{{ [ for ip in trusted_validators_ips | difference([ansible_default_ipv4.address]) : 'http://' ~ ip ~ ':9100' ] + [ for h in groups[network+'_reference'] | difference([inventory_hostname]) : 'http://' ~ hostvars[h].hostname ~ '.' ~ hostvars[h].domainname ~ ':9100' ] | join(',') }}" \
如果习惯使用传统for循环写法,也可以用分段循环的方式实现:
#!/bin/sh {% set cleaned_ips = trusted_validators_ips | difference([ansible_default_ipv4.address]) %} {% set cleaned_hosts = groups[network+'_reference'] | difference([inventory_hostname]) %} /usr/local/bin/haproxy-ea-health-check \ -reference-servers="{% for ip in cleaned_ips %}http://{{ ip }}:9100{% if not loop.last %},{% endif %}{% endfor %}{% if cleaned_ips | length > 0 and cleaned_hosts | length > 0 %},{% endif %}{% for h in cleaned_hosts %}http://{{ hostvars[h].hostname }}.{{ hostvars[h].domainname }}:9100{% if not loop.last %},{% endif %}{% endfor %}" \
渲染效果
两种写法最终都会输出你需要的合并后的参数格式:
#!/bin/sh /usr/local/bin/haproxy-ea-health-check \ -reference-servers="http://192.168.1.200:9100,http://192.168.1.201:9100,http://192.168.1.202:9100,http://192.168.1.203:9100,http://server1.domain.com:9100,http://server2.domain.com:9100,http://server3.domain.com:9100" \
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

