【问题标题】:Map function over values of dict in ansible jinja template在 ansible jinja 模板中映射函数值
【发布时间】:2022-01-05 23:22:40
【问题描述】:

我想将字典的值转换为字符串并将它们小写,然后映射到字典上以使用 = 连接每个项目对,然后使用 , 连接项目。

示例输入:

{"A": "Aardvark", "B": "Beaver", "C": "Cat"}

期望的输出:

A=aardvark,B=beaver,C=cat

我实际上并不关心 A、B、C 到达的顺序,但我想确保我的键和值最终不会混淆,即没有 A=cat 或随便。

我现在正在做的是:

{{ foo.keys() | zip(foo.values() | map("lower")) | map("join", "=") | join(",") }}

到目前为止,它适用于我提供的测试数据。但是,我不确定这是否保证正确,我也不认为这是解决此问题的最有效或最优雅的方法。 有没有更好的方法lower 函数映射到字典中的值?

我尝试使用dict2items 并在map 函数上指定attribute,但是当我这样做时,我收到一个关于意外关键字arg 的错误,而且它真的很难看:

{{ (foo | dict2items | map("lower", attribute="value") | list | items2dict).items() | map("join", "=") | join(",") }}

注意:我现在在 Python 3.5 上使用 Ansible 2.9,但我真的很想要一个无论 Python 版本如何都可以工作的解决方案。

【问题讨论】:

  • 我相信您使用zip 是最好的,因为需要小写值;也总是欢迎您使用命令式版本{% for ... %},因为正如您所经历的那样,ansible 使用的 jinja2 版本对“函数式编程”不是很友好。有时命令式版本要清晰得多,即使更冗长
  • @mdaniel 我考虑过,但是像这样使用逗号分隔的值总是很痛苦

标签: ansible jinja2 python-3.5 ansible-2.x ansible-template


【解决方案1】:

您可以使用自定义过滤器。

在您的 playbook 文件夹中创建一个 filter_plugins/ 文件夹(我已将文件命名为 myfilters.py 和过滤器 cstring

myfilters.py 在文件夹filter_plugins/

#!/usr/bin/python
class FilterModule(object):
    def filters(self):
        return {
            'cstring': self.cstring
        }
    
    def cstring(self, data):
        result = ""
        for k in data:
            result += (',' if result else '') + k + '=' + data[k].lower()
    
        return result

剧本:

- name: "tips1"
  hosts: localhost
  vars:
    foo: {"A": "Aardvark", "B": "Beaver", "C": "Cat"}
  tasks:
    - name: debug users      
      set_fact:
        result: "{{ foo | cstring }}"
  
    - name: display result     
      debug:
        var: result 

结果:

ok: [localhost] => {
    "result": "A=aardvark,B=beaver,C=cat"
}

使用自定义过滤器的优点是只需一个操作即可完成复杂的事情或大量操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多