我对Ansible行为感到有些困惑:当我请求单个键的值时,它会评估字典中的所有值。
这是我的情况。我有一本有两个键的字典:dev
和prod
。每个密钥的值都是通过特定的Jinja2表达式定义的,该表达式涉及使用AWS KMS进行解密。大致看起来像这样:
mydict:
dev: '{{ "dev-ciphertext" | kms_decrypt }}'
prod: '{{ "prod-ciphertext" | kms_decrypt }}'
kms_decrypt
是一个自定义过滤器,用于解密密文。由于dev
和prod
环境是分开的,并且剧本在仅对其中一种环境有效的加密上下文中运行,因此一次只能评估一个表达式。尝试从另一个键检索值将失败。
因此,假设该剧本在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"}
我意识到有很多方法可以解决此问题,但是谁能解释为什么仅查询单个键时整个字典值都会得到评估?这对我来说似乎没有意义-至少从性能的角度来看。
答案 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'] }}"