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
just do {{ city }}, if it is the ‘current host’, to access vars of other hosts {{ hostvars[‘server3’].city }}
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 }} }}
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
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
`
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
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?
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.
Yep, typo on my part.
I can’t keep 100% of this program in my head but only 97.2%
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.
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 }}
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.
Can we see the host_vars file contents?
Of course:
ansible-vault edit /etc/ansible/host_vars/ansible-test
`
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 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!