Reputation: 21
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
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
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