Ansible字典:所有值的隐式评估?

时间:2019-05-15 21:04:26

标签: ansible jinja2

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

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

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

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

因此,假设该剧本在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"}

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

1 个答案:

答案 0 :(得分: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'] }}"