使用 jinja2 模板时 ansible 中的未定义变量错误

undefined variable error in ansible when using jinja2 templates

我在练习ansible。我已经完成了所有基础知识,现在我正在构建并使用 jinja2 模板。当我需要为组构建报告并将它们上传到各自的 dns 服务器时,有一个练习。美洲组所有服务器的报告将上传到dns_server_america,亚洲也是如此。

dns_server_america ansible_host=172.20.1.100 ansible_ssh_pass=Passw0rd ansible_user=root
dns_server_asia ansible_host=172.20.1.101 ansible_ssh_pass=Passw0rd ansible_user=root

[america]
web0001 ansible_hostname=web0001.company.com ansible_host=10.1.1.101 
web0002 ansible_hostname=web0002.company.com ansible_host=10.1.1.102 


[asia]
web2001 ansible_hostname=web2001.company.com ansible_host=10.1.1.201 
web2002 ansible_hostname=web2002.company.com ansible_host=10.1.1.202 

这是 YAML。

- name: Generate dns hosts files on americas servers
  hosts: dns_server_america
  tasks:
  - template: src=templates/hosts.j2 dest=/tmp/hosts.txt
    vars:
      GROUP_NAME: america

- name: Generate dns hosts files on asia servers
  hosts: dns_server_asia
  tasks:
  - template: src=templates/hosts.j2 dest=/tmp/hosts.txt
    vars:
      GROUP_NAME: asia

这是 jinja2 模板。

{% for host in groups[GROUP_NAME] %}
{{ host }} {{ hostvars[host]['ansible_host'] }}
{% endfor %}

为什么我们不在 jinja2 模板中引用 [host][GROUP_NAME]。 Ansible 说当变量放在方括号中时,它们应该用引号括起来。当我用引号括起来时,我收到一条错误消息 "undefined variable",当我删除引号时,我能够成功 运行 剧本。请指教,我可能遗漏了什么或者我理解变量的理论可能是错误的。

Q: "Why are we not quoting [host] and [GROUP_NAME] in the jinja2 template?"

A:hostGROUP_NAME都是变量。索引中需要变量的值。如果变量的名称被引用 'host''GROUP_NAME' 则使用变量的名称而不是变量的名称值。


直接和间接

例如模板

shell> cat test.txt.j2
{{ dict[index] }}
{{ dict['index'] }}

和剧本

shell> cat playbook.yml
- hosts: localhost
  vars:
    dict:
      index: value of attribute index
      attr1: value of attribute attr1
  tasks:
    - template:
        src: test.txt.j2
        dest: test.txt
      vars:
        index: attr1

给予

shell> cat test.txt
value of attribute attr1
value of attribute index

这不仅限于模板。一般是有效的。例如

    - debug:
        msg:
          - "{{ dict[index] }}"
          - "{{ dict['index'] }}"
      vars:
        index: attr1

给予

  msg:
  - value of attribute attr1
  - value of attribute index

点状

可以使用 "dotted" 参考。例如

    - debug:
        var: dict.index

给予

  dict.index: value of attribute index

"dotted" 引用可用于嵌套字典。例如嵌套字典

    dict:
      index:
        var1: value of attribute index
      attr1:
        var1: value of attribute attr1

两个版本都按预期工作

    - debug:
        msg:
          - "{{ dict.index.var1 }}"
          - "{{ dict['index'].var1 }}"
      vars:
        index: attr1

给予

  msg:
  - value of attribute index
  - value of attribute index

模板中的点引用

但是使用模板的时候是有区别的。当引用放在方括号 [] 中时,所有后续引用也必须放在方括号中。否则,模板将失败。例如

shell> cat test.txt.j2
{{ dict.index.var1 }}        # OK
{{ dict.index['var1'] }}     # OK
{{ dict['index']['var1'] }}  # OK
{{ dict['index'].var1 }}     # WRONG: has no attribute var1

会失败

fatal: [localhost]: FAILED! => changed=false 
  msg: 'AnsibleUndefinedVariable:
        ''ansible.parsing.yaml.objects.AnsibleUnicode object''
        has no attribute ''var1'''