我有一个字典,其数组值来自Ansible vars文件。
ipfilter:
zone1:
- { application: "app 1", local_ip: 1.1.1.1 }
- { application: "app 1", local_ip: 1.1.1.1 }
- { application: "app 2", local_ip: 2.2.2.2 }
zone2:
- { application: "app 3", local_ip: 3.3.3.3 }
- { application: "app 4", local_ip: 4.4.4.4 }
- { application: "app 4", local_ip: 4.4.4.4 }
问题是,application
和local_ip
的元组不是唯一的,因为对象包含我在示例中省略的其他数据,因为它与以下脚本无关
该脚本是Ansible向Solaris服务器提供的Jinja模板:
#! /bin/bash
set -eu
cat <<';' |
{% for zone, rules in ipfilter.items() %}
{% for rule in rules %}
{{zone}} {{rule.application}} {{rule.local_ip}}
{% endfor %}
{% endfor %}
;
sort | uniq | while read zone application local_ip; do
ipfcfg delete "$zone" "$application" "$local_ip"
done
外部循环遍历字典,内部循环遍历数组值。
我无法使用Jinja制作独特的元组列表。因此我不得不在Bash中使用sort | uniq | while read
循环。这远非完美,并且有其自身的局限性。
如何使Jinja中的元组列表成为唯一的?
答案 0 :(得分:1)
要从您的示例获取唯一列表对,您只需使用:
ipfilter.values() | sum(start=[]) | unique
但是这不适用于您的情况,因为您已从原始数据中省略了其他键,因此unique
过滤器将无效。
你必须在任务之前使用一些Ansible变量模板化魔法来解决这个问题:
# construct list of tuples
- set_fact:
tmp_app: '{"app":"{{item.application}}","ip":"{{item.local_ip}}"}'
with_items: "{{ ipfilter.values() | sum(start=[]) }}"
register: tmp_apps
# pass uniq list to template
- template:
src: script.j2
dest: script.sh
vars:
uniq_apps: "{{ tmp_apps.results | map(attribute='ansible_facts.tmp_app') | list | unique }}"
和script.j2:
#! /bin/bash
set -eu
{% for app in uniq_apps %}
ipfcfg delete "{{app.app}}" "{{app.ip}}"
{% endfor %}
答案 1 :(得分:0)
感谢Konstantin Suvorov's和Sean Vieira's回答另一个问题,我能够在Jinja完成所有工作。
#! /bin/bash
set -eu
{% set all_rules = [] %}
{% for zone, rules in ipfilter.items() %}
{% for rule in rules %}
{% set x = all_rules.extend([{'zone': zone, 'application': rule.application, 'local_ip': rule.local_ip}]) %}
{% endfor %}
{% endfor %}
{% for item in all_rules|unique %}
ipfcfg delete {{item.zone|quote}} {{item.application|quote}} {{item.local_ip|quote}}
{% endfor %}