【问题标题】:how do I use an ansible string variable that contains jinja delimiters?如何使用包含 jinja 分隔符的 ansible 字符串变量?
【发布时间】:2021-07-20 19:13:48
【问题描述】:

这个

- name: ugly
  hosts: localhost
  vars:
    badstr: "asdf{%jkl"
    mydir: "."
    mydict:
      filea:
        Value:  "blue!42!"
      fileb:
        Value:  "a{%isbad"
  tasks:
    - copy:
        dest: "{{ item.key }}"
        content: "{{ item.value.Value }}"
      loop: "{{ mydict|default({})|dict2items }}"

给我这个错误:

fatal: [localhost]: FAILED! => {"msg": "An unhandled exception occurred while templating 'asdf{%jkl'. Error was a <class 'ansible.errors.AnsibleError'>, original message: template error while templating string: Encountered unknown tag 'jkl'.. String: asdf{%jkl"}

“mydict”结构是从插件返回的,我无法定义成员。其中一个“值”包含“{%”。对它的任何引用都会导致错误,无论是作为变量、文件内容还是在模板中。

我尝试了各种不安全、{{、%raw 等的引用和组合。它要么给我错误,要么将变量的名称放在文件中。

如何将值写入文件?还是仅仅将其用作变量?

MacOS 11.3 上的 Ansible 2.8.4,RHEL 7 上的 ansible 2.9。

【问题讨论】:

  • 请编辑您的问题并添加带有问题条目的数据结构示例
  • 已更新,谢谢。
  • 您能否提供有关如何设置这些值的更多详细信息?你说“从插件返回”;你是说 Ansible 模块吗?
  • 我不想讨论这个问题,因为实际的代码很混乱。但它类似于:{{ lookup('aws_ssm', '/PATH/to/params', bypath=true) }}",它返回一个包含值的字典。

标签: ansible jinja2


【解决方案1】:

您可以将!unsafe 用于预期具有这些字符的变量。检查此documentation。当使用!unsafe 时,字符串/变量将永远不会被模板化。

- name: ugly
  hosts: localhost
  vars:
    badstr: !unsafe "asdf{%jkl"
    mydir: "."
    mydict:
      filea:
        Value:  !unsafe "blue!42!"
      fileb:
        Value: !unsafe  "a{%isbad"
  tasks:
    - copy:
        dest: "{{ item.key }}"
        content: "{{ item.value.Value }}"
      loop: "{{ mydict|default({})|dict2items }}"

在处理查找插件返回的值时,Ansible 使用数据 类型称为 unsafe 以阻止模板。将数据标记为不安全 防止恶意用户滥用 Jinja2 模板执行 目标机器上的任意代码。 Ansible 实现确保 不安全的值永远不会被模板化。它比 使用 {% raw %} ... {% endraw %} 标签转义 Jinja2。

您可以在定义的变量中使用相同的不安全数据类型,以 防止模板错误和信息泄露。你可以标记 vars_prompts 提供的值是不安全的。你也可以使用 unsafe 剧本。最常见的用例包括允许 { 或 % 之类的特殊字符,以及看起来像的 JSON 参数 模板,但不应模板化。例如:

---
mypassword: !unsafe 234%234{435lkj{{lkjsdf

【讨论】:

  • 您没有阅读完整的问题。 “badstr”嵌入在插件返回的对象中。我无法添加 !unsafe 。
【解决方案2】:

这里的问题不在于值所在的copy 任务 评估;问题是它们是如何设置的。例如,如果我 创建一个名为 example.sh 的简单 ansible 模块,看起来像 这个:

#!/bin/sh

cat <<EOF
{
    "files": {
    "filea": {
      "Value": "blue!42!"
    },
    "fileb": {
      "Value": "a{%isbad"
    }
    }
}
EOF

我可以像这样写一本剧本:

- name: ugly
  hosts: localhost
  tasks:
    - example:
      register: mydict

    - copy:
        dest: "{{ item.key }}"
        content: "{{ item.value.Value }}"
      loop: "{{ mydict.files|dict2items }}"

这会按预期运行,创建一个文件fileb,内容没有任何错误:

a{%isbad

同样,如果我从 JSON 文件中读取数据并通过from_json 传递它,它也可以正常工作:

- name: ugly
  hosts: localhost
  tasks:
    - set_fact:
        mydict: "{{ lookup('file', 'data.json')|from_json }}"

    - copy:
        dest: "{{ item.key }}"
        content: "{{ item.value.Value }}"
      loop: "{{ mydict.files|dict2items }}"

只有在上下文中定义变量时才会出现问题 Ansible 正在寻找 Jinja 模板——因此,作为 playbook 中的变量,vars 文件,set_fact 的参数, 等等

您可以通过改变自己的方式来解决问题 使用这些值。

【讨论】:

  • 令人着迷。 from_json 返回的字典与其他字典有何不同?上面有没有写着“不要模板”的标志?我可以自己设置那个标志吗?还有哪些其他查找/过滤器可以做到这一点?不幸的是,我拥有的字典是由另一个角色创建的,使用返回字典的查找。它显然没有魔法标志或其他东西。有没有办法修改查找来解决这个问题?
  • 这与 return 无关,而是关于事物在何处定义。如果你在 Ansible 应用模板的某个地方(在剧本中,在变量文件中)定义数据,你就会遇到这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-17
  • 1970-01-01
相关资源
最近更新 更多