Gazahoo
Gazahoo

Reputation: 21

Dynamic variable using hostvars within jinja2 loops

How to make dynamic variables work with hostvars within a jinja2 loop?

It works:

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

It also works:

{{ hostvars[inventory_hostname].somevar_state }}

and for test:

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

But it doesn't work:

If somevarlist contains the 'somevar' value

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

or

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

Results:

msg: The task includes an option with an undefined variable... The error was: 'ansible.vars.hostvars.HostVarsVars object' has no attribute 'somevar_state'...

Upvotes: 2

Views: 766

Answers (2)

Gazahoo
Gazahoo

Reputation: 21

My fact 'somevar_state' is dynamically set and derived from another fact that can be present or not in each host. In that case we need to check if the variable is defined on each host before print, otherwise it will fail. Thanks to Vladimir by the debug examples those helped me to understand the problem.

- 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

Upvotes: 0

Vladimir Botka
Vladimir Botka

Reputation: 68394

Use Assignments. For example

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

gives

  msg: |-
    expected value

Q: "The template uses a list in a loop."

A: For example

- 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 %}

gives

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

Upvotes: 2

Related Questions