如何让 Ansible 解释变量中的变量?

How can I make Ansible interpret a variable inside a variable?

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

给定变量:

key: bar
foo:
  bar: baz
foo_bar: baz

我已经尝试了这三种方法,但运气不佳,无法动态访问字典 foo 的键 bar 或键 foo_bar,当从 [=17 的值构造时=]:

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

正如 Ansible 的 常见问题 中所建议的那样,胡子不堆叠

Another rule is ‘moustaches don’t stack’. We often see this:

{{ somevar_{{other_var}} }}

The above DOES NOT WORK as you expect, if you need to use a dynamic variable use the following as appropriate:

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

For ‘non host vars’ you can use the vars lookup plugin:

{{ 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 feature and will be removed in future version

    Short history, vars is a leftover from previous code that used it to pass variables to template, it was never intended for external use and most of the time didn't template anything.

    Unrelated changes allowed it to template 'sometimes' but this was never on purpose, the only reason it was not removed is because some people relied on it, that had discovered by looking at the code and/or other people that had already been using it. Even though it has been our intention for a long time to deprecate and remove the vars construct, lack of a good way to trigger a runtime message has kept us from doing so.

    We created 2 alternatives via lookups varnames and vars, which might not be as flexible as a dict but also would not chew up memory for unneeded access, since most users just want to match a small subset of existing variables.

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

  • 使用正确的连接运算符 ~ 比 Ansible 文档中建议的数学运算符 + 更明智在 Jinja 文档中:

    Usually the objects are numbers, but if both are strings or lists, you can concatenate them this way. This, however, is not the preferred way to concatenate strings! For string concatenation, have a look-see at the ~ operator.

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