ansible 剧本中的 jinja2 '{% set ... %}' 处理

jinja2 '{% set ... %}' processing in ansible playbook

我不明白如何在 ansible 剧本中使用 jinja2 模板命令。

我的理解是剧本应该在执行前作为 jinja2 模板处理,但显然不是在文件被解析为 yaml 之前,因为在文件顶部使用 jinja2 命令会产生语法错误,例如:

{% set test_var = "test_value" %}
- hosts: all
  remote_user: "my_user"
  tasks:
    - debug: var=test_var
    {% set another_var = "another_value" %}
    - debug: var=another_var
$ ansible-playbook -vv -K ansible/playbooks/test.yml
ERROR! Syntax Error while loading YAML.
  found character '%' that cannot start any token
...

如果我注释 jinja2 命令以避免此解析错误,顶部的第一个命令会被处理,但剧本中间的其他命令不会被处理:

# {% set test_var = "test_value" %}
- hosts: all
  remote_user: "my_user"
  tasks:
    - debug: var=test_var # this works
    # {% set another_var = "another_value" %}
    - debug: var=another_var
    # ok: [localhost] => {
    #   "another_var": "VARIABLE IS NOT DEFINED!: 'another_var' is undefined"
    # }

我不明白 ansible 是如何处理 playbook 模板的。难道不应该有一个只处理 jinja2 语法的第一遍,然后输出删除了 jinja2 语法的 yaml 吗?

$ ansible-playbook --version
ansible-playbook 2.9.1
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/me/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/me/.local/lib/python3.7/site-packages/ansible
  executable location = /home/me/.local/bin/ansible-playbook
  python version = 3.7.3 (default, Apr  3 2019, 19:16:38) [GCC 8.0.1 20180414 (experimental) [trunk revision 259383]]

谢谢!

jinja2在ansible运行时处理的是yaml vars的内容,而不是yaml文件本身。这是分几步完成的,如果您想准确了解幕后内容,请深入了解 ansible 代码。

只是为了让您走上正轨,这是您在问题中尝试过的可靠方法。

- hosts: all
  remote_user: "my_user"

  # These are playbook vars set at playbook level
  # Vars can also be in inventories, roles....
  # see https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html
  vars:
    test_var: test_value

  tasks:

    - name: debug my test_var
      debug:
        var: test_var

    - name: if you need to set var at run time you can use set_fact
      set_fact:
        # Jinja2 templating will be honored here
        another_var: "another_{{ test_var }}"

    - name: debug var we just valued
      debug:
        var: another_var