How to use hostvars in template

6,437 views
Skip to first unread message

Piet83

unread,
Jul 29, 2014, 4:05:09 AM7/29/14
to ansible...@googlegroups.com
Hello,

Is it possible to use variables defined in a ansible host file for a template? Lets say this is the host file:

[webservers]
server1   city
=amsterdam
server2   city
=london

[databaseserver]
server3   city
=amsterdam
server4   city
=london




How can I use for instance the ip address of server3 which is in group databaseservers in amsterdam?  Is this possible? I would like to use this to fill iptables with ip addresses depending on group and city.


Regards,

Peter


Brian Coca

unread,
Jul 29, 2014, 8:23:04 AM7/29/14
to ansible...@googlegroups.com
just do  {{ city }}​, if it is the 'current host', to access vars of other hosts {{ hostvars['server3'].city }}

Piet83

unread,
Jul 29, 2014, 11:02:23 AM7/29/14
to ansible...@googlegroups.com
Ok but what if I don't know the server name but only that it is an database server in amsterdam?

Something like this, but then with the right syntax?

{{ groups["databaseserver"] | {{ hostvars["amsterdam"] }} | {{ ansible_eth0.ipv4.address }} }} 

Op dinsdag 29 juli 2014 14:23:04 UTC+2 schreef Brian Coca:

Michael DeHaan

unread,
Jul 29, 2014, 11:07:57 AM7/29/14
to ansible...@googlegroups.com
The above imaginary syntax will not work, but this will :)  The groups array contains the names of each host in each group, and this picks out the first one in inventory order.

{{ hostvars[groups['databaseserver'][0]].ansible_eth0.ipv4.address }}

If using a template file versus inline in the playbook, I'd do this:

{# set db_head_node = groups['databaseserver'][0] #}
{{ hostvars[db_head_node].blarg }}

for readability purposes




--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/0ec5b636-9383-4a80-9c51-28831b33406a%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Piet83

unread,
Jul 30, 2014, 8:06:52 AM7/30/14
to ansible...@googlegroups.com
Thank you Michael for the right syntax :)

Is it also possible to select one host in the goup array based on a city defined as variable for a particular host? In other words, I don't know on what position in the array the servername is I need. I only know it is in group databaseserver and that it has amterdam defined as variable city.

By the way if I try this in a template:

{{ hostvars[groups['databaseserver'][0]].ansible_eth0.ipv4.address }}



I get the following error running a playbook with the above in a template:
fatal: [localhost] => {'msg': "One or more undefined variables: 'dict' object has no attribute 'ansible_eth0'", 'failed': True}
fatal
: [localhost] => {'msg': "One or more undefined variables: 'dict' object has no attribute 'ansible_eth0'", 'failed': True}

FATAL
: all hosts have already failed -- aborting







Op dinsdag 29 juli 2014 17:07:57 UTC+2 schreef Michael DeHaan:

Michael DeHaan

unread,
Jul 30, 2014, 8:15:43 AM7/30/14
to ansible...@googlegroups.com
I would use group_by to create a dynamic group first in a prior play, like so:

- hosts: webservers
  tasks:
     - group_by: name=webserver-{{ city | default('no_city') }}

And then you could use, in the template, replace the groupname 'webserver' with 'webserver-amsterdam' like so:

groups['webserver-amsterdam'][0]

to select the first one.

Others may prefer deep Jinja2 magic, but I'd find that more readable.   You can also use the dynamic group for other types of management in Ansible:

- hosts: webservers-amsterdam
  tasks:
     - yum: name=foo state=latest

etc









Piet83

unread,
Jul 31, 2014, 4:39:54 AM7/31/14
to ansible...@googlegroups.com
When I use the following in my playbook:
 
group_by: name=webservers-{{ city | default('no_city')}}

I get this error when running:

TASK: [group_by name=webservers-amsterdam] ****************************************
fatal: [ansible-test] => 'key' is a required argument.

ansible-test is my target host.

What am I doning wrong?


Op woensdag 30 juli 2014 14:15:43 UTC+2 schreef Michael DeHaan:

Lucas, Sascha

unread,
Jul 31, 2014, 7:21:29 AM7/31/14
to ansible...@googlegroups.com
Hi,

> fatal: [ansible-test] => 'key' is a required argument.

group_by needs key=webservers-{{ city | default('no_city')}}, not name=...

HTH, Sascha.

Stellvertretender Vorsitzender des Aufsichtsrates: Detlef Hillebrand
Geschäftsführung: Michael Krüger
Sitz der Gesellschaft: Halle/Saale
Registergericht: Amtsgericht Stendal | Handelsregister-Nr. HRB 208414
UST-ID-Nr. DE 158253683

Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte Informationen. Wenn Sie nicht der richtige Empfänger sind oder diese E-Mail irrtümlich erhalten haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail. Das unerlaubte Kopieren sowie die unbefugte Weitergabe dieser Mail oder des Inhalts dieser Mail sind nicht gestattet. Diese Kommunikation per E-Mail ist nicht gegen den Zugriff durch Dritte geschützt. Die GISA GmbH haftet ausdrücklich nicht für den Inhalt und die Vollständigkeit von E-Mails und den gegebenenfalls daraus entstehenden Schaden. Sollte trotz der bestehenden Viren-Schutzprogramme durch diese E-Mail ein Virus in Ihr System gelangen, so haftet die GISA GmbH - soweit gesetzlich zulässig - nicht für die hieraus entstehenden Schäden.

Michael DeHaan

unread,
Jul 31, 2014, 4:59:08 PM7/31/14
to ansible...@googlegroups.com
Yep, typo on my part.

I can't keep 100% of this program in my head but only 97.2% :)




--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.

Piet83

unread,
Aug 1, 2014, 8:39:49 AM8/1/14
to ansible...@googlegroups.com
Thank you both!

May I ask an other question about hostvars in templates:

When I use the follwing i a playbook everything goes well:

The variable target is provided by the --extra-vars flag on the command line and mysqluserpass is defined in /etc/ansible/host_vars/ansible-test and encrypted with ansible-vault

{{ hostvars[{{target}}]['mysqluserpass'] }}


So when I use the above in a playbook it fills in the mysqluserpass nicely but when using this in a template to put the the mysql credentials in a file somewhere on the target machine it gives an syntax error:

fatal: [ansible-test] => {'msg': "file: /etc/ansible/templates/CREDS.j2, line number: 2, error: expected token 'colon', got '}'", 'failed': True}
fatal
: [ansible-test] => {'msg': "file: /etc/ansible/templates/CREDS.j2, line number: 2, error: expected token 'colon', got '}'", 'failed': True}


FATAL
: all hosts have already failed -- aborting

I've also tried: {{ hostvars[inventory_hostname]['mysqluserpass'] }} but no results.






Op donderdag 31 juli 2014 22:59:08 UTC+2 schreef Michael DeHaan:

Michael DeHaan

unread,
Aug 1, 2014, 9:13:27 AM8/1/14
to ansible...@googlegroups.com
When using Jinja2 expressions it is not valid to use {{ }} around a variable inside another expression.

You had:

{{ hostvars[{{target}}]['mysqluserpass'] }}

You need

{{ hostvars[target]['mysqluserpass'] }}

Which also, thankfully, is easier to read too.

Can also be written

{{ hostvars[target].mysqluserpass }}




Piet83

unread,
Aug 1, 2014, 9:50:50 AM8/1/14
to ansible...@googlegroups.com
Thank you Michael,

Only if I try both options you suggested I get i both cases:

fatal: [ansible-test] => {'msg': "One or more undefined variables: 'dict' object has no attribute 'mysqluserpass'", 'failed': True}
fatal: [ansible-test] => {'msg': "One or more undefined variables: 'dict' object has no attribute 'mysqluserpass'", 'failed': True}

It looks like it does not pick up the variables defined in my /etc/ansible/host_vars/ansible-test file.

Op vrijdag 1 augustus 2014 15:13:27 UTC+2 schreef Michael DeHaan:

Michael DeHaan

unread,
Aug 1, 2014, 10:30:43 AM8/1/14
to ansible...@googlegroups.com
Can we see the host_vars file contents?


Piet83

unread,
Aug 1, 2014, 10:52:17 AM8/1/14
to ansible...@googlegroups.com
Of course:

ansible-vault edit /etc/ansible/host_vars/ansible-test

---
mysqlrootpass
: XXXXXXXXXXXXXXXXXX
mysqluserpass
: XXXXXXXXXXXXXXXXXX





Op vrijdag 1 augustus 2014 16:30:43 UTC+2 schreef Michael DeHaan:

Michael DeHaan

unread,
Aug 1, 2014, 3:26:58 PM8/1/14
to ansible...@googlegroups.com
My thought might be you are running things with an inventory file that is not in /etc/ansible, so it's looking for a host_vars directory beside that inventory file.

Other than that I don't know what might be up...




--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.

Piet83

unread,
Aug 4, 2014, 3:36:12 AM8/4/14
to ansible...@googlegroups.com
You are right Michael! We had /etc/ansible/production/hosts and /etc/ansible/staging/hosts. I've changed this to /etc/ansible/production and /etc/ansible/staging files.

Thank you very much!

Op vrijdag 1 augustus 2014 21:26:58 UTC+2 schreef Michael DeHaan:
Reply all
Reply to author
Forward
0 new messages