【问题标题】:Ansible dictionary: implicit evaluation of all values?Ansible 字典:所有值的隐式评估?
【发布时间】:2019-05-15 21:04:26
【问题描述】:

我对 Ansible 的行为有点困惑:看起来当我请求单个键的值时,它会评估字典中的所有值。

这是我的情况。我有一本带有两个键的字典:devprod。每个密钥的值都是通过特定的 Jinja2 表达式定义的,该表达式涉及使用 AWS KMS 进行解密。大致是这样的:

mydict:
  dev: '{{ "dev-ciphertext" | kms_decrypt }}'
  prod: '{{ "prod-ciphertext" | kms_decrypt }}'

kms_decrypt 是一个自定义过滤器,用于解密密文。由于 devprod 环境是分开的,并且 playbook 在仅对其中一种环境有效的加密上下文中运行,因此一次只能评估一个表达式。尝试从另一个键检索值将失败。

假设剧本在dev 环境的上下文中运行,当我评估mydict['dev'] 时,我希望它返回解密后的dev-ciphertext。但是,实际上我得到的是prod-ciphertext 解密失败,因为加密上下文不匹配。

我可以用一个更简单的例子来说明相同的行为。我没有重新创建解密机制,而是通过一个未定义的变量定义了一个字典值:

- hosts: localhost
  become: no
  vars:
    dev_value: '123'
    mydict:
     dev: '{{ dev_value }}'
     prod: '{{ prod_value }}'
  tasks:
    - debug:
        msg: "{{ mydict['dev'] }}"

不管mydict['prod'] 从未被明确查询过,我仍然得到一个错误,表明它不能被评估:

TASK [debug] *********************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'prod_value' is undefined\n\nThe error appears to have been in 'ansible/test.yml': line 9, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n  tasks:\n    - debug:\n      ^ here\n"}

我意识到有很多方法可以解决这个问题,但是谁能解释为什么只查询一个键时会评估整个字典值?这对我来说似乎没有意义 - 至少从性能的角度来看。

【问题讨论】:

    标签: ansible jinja2


    【解决方案1】:

    Jinja 模板在所有情况下都会呈现 - 没有“懒惰的 jinja”之类的东西,只有通过 when: 或类似守卫的懒惰任务

    因此,如果您的代码中还没有散布my_dict["dev"],那么我建议您使用一个合理的名称,例如my_env 或其他名称,并且只声明一个对活动环境有意义的值:

    - hosts: localhost
      become: no
      vars:
        dev_value: '123'
      tasks:
      - set_fact:
          my_env: '{{ "prod-ciphertext" | kms_decrypt }}'
        when: some_environment_variable == "prod"
      - set_fact:
          my_env: '{{ "dev-ciphertext" | kms_decrypt }}'
        when: some_environment_variable == "dev"
    

    否则,您可以保护表达式——为了清楚起见,它们总是会被评估——如果它们不适用,则返回默认值:

    - hosts: localhost
      become: no
      vars:
        dev_value: '123'
        my_dict:
          prod: '{{ ("prod-ciphertext" | kms_decrypt)
                   if the_magic_env == "prod" else {} }}'
          dev: '{{ ("dev-ciphertext" | kms_decrypt)
                   if the_magic_env == "dev" else {} }}'
      tasks:
        - debug:
            msg: "{{ mydict['dev'] }}"
    

    【讨论】:

    • 感谢您的详细解释和建议的解决方法!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    • 2017-07-13
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 2016-02-12
    相关资源
    最近更新 更多