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

标签 ansible jinja2

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

给定变量:

key: bar
foo:
  bar: baz
foo_bar: baz

我已经尝试了这三种方法,但运气不佳,无法在构建时动态访问字典 foo 的键 bar 或键 foo_bar来自 key 的值:

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

    但是,我得到了错误:

    'template error while templating string: expected token '':'', got ''}''. String: {{ foo[{{ key }}] }}'

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

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

    'template error while templating string: expected token ''end of print statement'', got ''{''. String: {{ foo_{{ key }} }}'

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

    在这里,我得到了错误

    The task includes an option with an undefined variable. The error was: 'dict object' has no attribute '{{ key }}'

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

最佳答案

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

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 featurewill 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

关于ansible - 如何让 Ansible 解释变量中的变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67408680/

相关文章:

ansible - 提取没有扩展名的文件名 - Ansible

kubernetes - 使用 Ansible 创建 kubeadm token

javascript - Flask通过url_for()向python发送变量数据

python - jinja2.exceptions.TemplateNotFound 错误

python - jinja2模板中 undefined variable 时如何删除行

ansible - 如何检查文件是否存在于ansible windows中?

jinja2 - 在 jinja2 (ansible) 中为列表元素添加引号

git - 当 git clone 在远程服务器上工作时,无主模式下的 ansible git 任务失败

python - 使用 Werkzeug 和 Jinja2 的上下文处理器

python - 为什么可以在ansible中使用分割过滤器?