在 jinja2 循环中使用 hostvars 的动态变量

Dynamic variable using hostvars within jinja2 loops

如何使动态变量在 jinja2 循环中与 hostvars 一起工作?

有效:

{{ hostvars[inventory_hostname]['somevar_state'] }}

它也有效:

{{ hostvars[inventory_hostname].somevar_state }}

和测试:

{{ hostvars[inventory_hostname]['' ~ 'somevar_state' ~ ''}}

但是不行:

如果 somevarlist 包含 'somevar' 值

{% for var in somevarlist %}
{{ hostvars[inventory_hostname][var + '_state'] }}
{% endfor %}

{{ hostvars[inventory_hostname]['' ~ var ~ '_state' ~ ''] }}

结果:

消息:任务包含一个带有未定义变量的选项...错误是:'ansible.vars.hostvars.HostVarsVars object' 没有属性 'somevar_state'...

使用Assignments。例如

    - set_fact:
        somevar_state: expected value
    - debug:
        msg: |
          {% set x = var ~ '_state' %}
          {{ hostvars[inventory_hostname][x] }}
      vars:
        var: somevar

给予

  msg: |-
    expected value

问:"模板在循环中使用列表。"

答:例如

- hosts: localhost
  vars:
    somevarlist: [var1, var2, var3]
  tasks:
    - set_fact:
        var1_state: expected value 1
        var2_state: expected value 2
        var3_state: expected value 3
    - debug:
        msg: |
          {% for var in somevarlist %}
          {% set x = var ~ '_state' %}
          {{ hostvars[inventory_hostname][x] }}
          {% endfor %}

给予

  msg: |-
    expected value 1
    expected value 2
    expected value 3

我的事实 'somevar_state' 是动态设置的,并且派生自每个主机中可能存在或不存在的另一个事实。在那种情况下,我们需要在打印之前检查变量是否在每个主机上定义,否则将失败。感谢 Vladimir 提供的调试示例帮助我理解了问题。

- name: add lines to file
  blockinfile:
    path: myoutfile
    block: |
      {% for host in ansible_play_batch %}
      {% for sname in myservices %}
      {% set service = sname | lower ~ '_state' %}
      {% if hostvars[host][service] is defined and hostvars[host][service] %}
      {{ host }}: {{ service }}: {{ hostvars[host][service] }}
      {% endif %}
      {% endfor %}
      {% endfor %}
  delegate_to: localhost