【问题标题】:How can I make Ansible interpret a variable inside a variable?如何让 Ansible 在变量中解释变量?
【发布时间】:2021-07-28 05:04:36
【问题描述】:

每当我尝试让 Ansible 解释一个嵌套变量——也就是说,另一个变量中的一个变量——我都无法得到我期望的结果。

给定变量:

key: bar
foo:
  bar: baz
foo_bar: baz

当从key 的值构造时,我尝试了这三种方法来动态访问字典foo 的键bar 或键foo_bar,但运气不佳:

  • - ansible.builtin.debug:
        msg: "{{ foo[{{ key }}] }}"
    

    但是,我得到了错误:

    '模板化字符串时出现模板错误:预期标记'':'',得到''}''。字符串:{{ foo[{{ key }}] }}'

  • - ansible.builtin.debug:
          msg: "{{ foo_{{ key }} }}"
    

    但是,我遇到了类似的错误

    '模板字符串时模板错误:预期标记''打印语句结束'',得到''{''。字符串:{{ foo_{{ key }} }}'

  • - ansible.builtin.debug:
        msg: "{{ foo['{{ key }}'] }}"
    

    在这里,我得到了错误

    任务包含一个带有未定义变量的选项。错误是:'dict object' 没有属性'{{ key }}'

我希望得到foo.barfoo_bar 的值,所以baz
实现这一目标的正确方法是什么?

【问题讨论】:

    标签: ansible jinja2


    【解决方案1】:

    正如 Ansible 的常见问题解答中所建议的,小胡子不会堆叠

    另一条规则是“胡须不堆叠”。我们经常看到这样的:

    {{ somevar_{{other_var}} }}
    

    上述内容无法如您所愿,如果您需要使用动态变量,请酌情使用以下内容:

    {{ hostvars[inventory_hostname]['somevar_' ~ other_var] }}
    

    对于“非主机变量”,您可以使用 vars lookup 插件:

    {{ lookup('vars', 'somevar_' ~ other_var) }}
    

    来源:https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#when-should-i-use-also-how-to-interpolate-variables-or-dynamic-variable-names


    因此,这将适用于两种情况:

    1. 当尝试从变量访问字典的键时,您只需按原样使用变量,请记住,当您在 expression delimiters {{ ... }} 中时,如果未包含在其中,字符串将被解释为变量单引号或双引号。

      - ansible.builtin.debug:
          msg: "{{ foo[key] }}"
        vars:
          key: bar
          foo:
            bar: baz
      
    2. 当尝试从变量构造变量的名称或字典的键时,您必须使用concatenation operator, ~

      - ansible.builtin.debug:
          msg: "{{ foo['foo_' ~ key] }}"
        vars:
          key: bar
          foo:
            foo_bar: baz
      

      您可能还需要使用vars lookup 来访问动态变量:

      - ansible.builtin.debug:
          msg: "{{ lookup('vars', 'foo_' ~ key) }}"
        vars:
          key: bar
          foo_bar: baz
      

    旁注:

    • 请使用 vars 查找 — lookup('vars', 'somevar_' ~ other_var) — 而不要使用 vars 字典 — vars['somevar_' ~ other_var],如 it was never intended to be an Ansible featurewill be removed in future version

      历史很短,vars 是以前代码的遗留物,它使用它来将变量传递给模板,它从未打算供外部使用,而且大多数时候没有任何模板。

      不相关的更改允许它“有时”模板化,但这从来都不是故意的,它没有被删除的唯一原因是因为有些人依赖它,这是通过查看代码和/或其他人已经发现的一直在使用它。尽管我们长期以来一直打算弃用和删除 vars 构造,但缺乏触发运行时消息的好方法使我们无法这样做。

      我们通过查找 varnamesvars 创建了 2 个备选方案,它们可能不如 dict 灵活,但也不会因为不需要的访问而占用内存,因为大多数用户只想匹配现有变量的一小部分.

      来源:https://github.com/ansible/ansible/issues/74904#issuecomment-854137949

    • 使用正确的连接运算符 ~ 比使用 Ansible 文档中建议的数学运算符 + 更可取,原因在 Jinja 文档中提出:

      通常对象是数字,但如果两者都是字符串或列表,您可以通过这种方式连接它们。然而,这不是连接字符串的首选方式!对于字符串连接,请查看~ 运算符。

      来源:https://jinja.palletsprojects.com/en/2.11.x/templates/#math

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-18
      • 2021-10-26
      • 1970-01-01
      • 1970-01-01
      • 2021-03-24
      • 2015-12-18
      • 2017-08-30
      • 1970-01-01
      相关资源
      最近更新 更多