如何在Ansible/Jinja2中将字符串列表映射为对象列表?

4

我将尝试从CIDR列表中构建安全组规则和路由,但是语法映射还不太正确。

我有一个CIDR列表:

cidrs:
  - 10.12.0.0/16
  - 10.99.0.0/16
  - 192.168.128.0/24

我可以将其转换为一个安全组规则列表,例如:

rules:
  - proto: all
    cidr_ip: 10.12.0.0/16
  - proto: all
    cidr_ip: 10.99.0.0/16
  - proto: all
    cidr_ip: 192.168.128.0/24

这种转换在Jinja2 / Ansible过滤器中的语法是什么?
1个回答

2

1. 在循环中使用过滤器combine

例如,playbook如下:


shell> cat playbook.yml
- hosts: localhost
  vars:
    cidrs:
      - 10.12.0.0/16
      - 10.99.0.0/16
      - 192.168.128.0/24
    protos:
      proto: all
  tasks:
    - set_fact:
        rules: "{{ rules|default([]) +
                   [{'cidr_ip': item}|combine(protos)] }}"
      loop: "{{ cidrs }}"
    - debug:
        var: rules

提供(简化版)

shell> ansible-playbook playbook.yml

  rules:
  - cidr_ip: 10.12.0.0/16
    proto: all
  - cidr_ip: 10.99.0.0/16
    proto: all
  - cidr_ip: 192.168.128.0/24
    proto: all

2. 修改列表和过滤器在 map 中的组合

如果输入是一个字典列表,也就是哈希表,则简单的 map 就可以完成任务。例如,下面的 playbook 给出了相同的结果。

shell> cat playbook.yml
- hosts: localhost
  gather_facts: false
  vars:
    cidrs:
      - cidr_ip: 10.12.0.0/16
      - cidr_ip: 10.99.0.0/16
      - cidr_ip: 192.168.128.0/24
    protos:
      proto: all
  tasks:
    - set_fact:
        rules: "{{ cidrs|map('combine', protos)|list }}"
    - debug:
        var: rules

3. 自定义插件和过滤器在映射中结合使用

过滤器 product 似乎是将简单列表转换为哈希列表的好选择。但是,据我所知,Ansible 中没有将两个项目的列表转换为字典的过滤器。让我们编写这样一个过滤器。例如:

shell> cat filter_plugins/dict.py
def item2dict(t):
    h = {t[0]:t[1]}
    return h

class FilterModule(object):
    ''' Ansible dict filters '''

    def filters(self):
        return {
            'item2dict': item2dict
        }

然后下面的playbook会得到相同的结果。
shell> cat playbook.yml
- hosts: localhost
  vars:
    cidrs:
      - 10.12.0.0/16
      - 10.99.0.0/16
      - 192.168.128.0/24
    protos:
      proto: all
  tasks:
    - set_fact:
        rules: "{{ ['cidr_ip']|product(cidrs)|map('item2dict')|
                   map('combine', protos)|list }}"
    - debug:
        var: rules

循环的使用对我的用例效果最佳。选项2本来会很棒,但我现在只有一个字符串列表而不是对象列表。我还能够简化选项1中的规则,直接使用"{{ rules|default([]) + [{'cidr_ip': item, 'proto': 'all'] }}"。谢谢! - leedm777

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接