Ansible: list all hosts to add it to 'hosts' file - ansible

I set up group of test VMs (with pure Debian) to play with, all of them are on test network so it is self-contained group of VM. These VMs be destroyed soon so I don't want to add its names to DNS while I need to have them communicate oven hostnames.
Is there any way I can form /etc/hosts files on these VMs based on hosts IPs from Ansible hosts file?
I can set hostnames like that
192.168.0.5 myhostname=host01.local
192.168.0.6 myhostname=host02.local
so I think I can somehow form /etc/hosts like that:
{{ ip }} {{ myhostname }}
but can archive that. I think I can iterate over group['all'] and use lineinfile to add lines to /etc/hosts, but it won't work for me so far.

You can use the inventory_file variable to get the path filename of the hosts file:
Also available, inventory_dir is the pathname of the directory holding Ansible’s inventory host file, inventory_file is the pathname and the filename pointing to the Ansible’s inventory host file.
Reference
You can read its variables with something like:
tasks:
- local_action: shell cat {{ inventory_file }}
register: result
As recommended here. More on local actions here.
You can then use jinja filters and loops to use the variable.

Related

How can I limit the hosts in a Template on AWX?

The hosts which I address in the Playbook maint-change.yml belong to two Groups (instancegroup1 & instancegroup2 with sveral hosts in each group) like this:
- hosts: "{{ server | default('instancegroup1 instancegroup2') }}"
So if I just want to run the Playbook against one host I will limit with (-e EXTRA_VARS) the variable server and the hostname from the instance:
ansible-playbook maint-change.yml -e server=test.instance2
In that Case the "test.instance2" is listet in the inventory file of instancegroup2 and the playbook will only run against the host "test.instance2" successfully.
But how is is that possible with awx? If I have created the template with the same Playbook "maint-change.yml" which is using the variable server as I mentioned above, it's not possible to paste the "server=test.instance2" in the EXTRA VARIABLES field of the Template. Is there any Solution to set the specific variable server from the Playbook in the EXTRA VARIABLES field from awx's Template?
I believe you are using AWX Job templates. You can use the limit check option in your templates. Here's a screenshot of that -

Ansible fetch host IP from another group based on defined variable

I would like to fetch IP of a host from another group in inventory file based on variable name.
Example inventory file:
[master]
master-0.example.io
master-1.example.io
master-2.example.io
[replica]
replica-0.example.io master_host=master-0.example.io
replica-1.example.io master_host=master-1.example.io
replica-2.example.io master_host=master-2.example.io
Later in playbook I want to run a command, but for that one I require IP of master (FQDN does not work). I have tried following, but this is not working:
- name: Test run
shell: "echo {{ ansible_default_ipv4.address }}:{{ port }} {{ hostvars['master_host']['ansible_default_ipv4', 'address'] }}:{{ port }}"
Any idea if there is a way to get this covered? Or if there is any other way to do this - basically what I need is to match master-0 with replica-0 etc. and I do not want to put IPs into inventory file.
hostvars is a hash. Each top entry in the hash is the name of your host in the inventory. To address that hash, your are using the string 'master_host' which does not exist. What you want, is to use the value of the variable master_host for the particular host your are executing the command on.
The 2 possible correct syntaxes are:
{{ hostvars[master_host].ansbible_default_ipv4.address }}
{{ hostvars[master_host]['ansbible_default_ipv4']['address'] }}
... or any mix between the dot or bracket syntax.

Ansible get hostname as defined in inventory

In my inventory I define hosts like this:
[server1]
141.151.176.223
I am looking for a variable which keeps the server1 name, as I am using it to define server hostname.
inventory_hostname is set to 141.151.176.223
ansible_hostname as well as inventory_hostname_short is set to 148.
To workaround this problem I am setting my own variable like this:
[server1]
141.151.176.223 hostname=server1
but I am not satisfied with this approach.
Any ideas?
Explanation
If the inventory file was defined this way:
[server1_group]
server1 ansible_host=141.151.176.223
Then you can access:
server1 with the inventory_hostname fact;
141.151.176.223 with the ansible_host fact;
server1_group with group_names|first (group_names fact contains a list of all groups server belongs to, first selects the first element from that list).
Regardless of the above, ansible_hostname fact contains the host name as defined on the host itself (the value is set during facts gathering).
Solution
You should use a standard ansible_host declaration to point to the target's IP address and set the inventory hostname to however you want to refer to the server in Ansible playbooks.
In particular you can skip groups definition altogether and define just:
server1 ansible_host=141.151.176.223
The [server1] declaration is the name of a group, not a host (even if you only assign a single host to that group).
As ansible allows a host to be placed in multiple groups, you can only get the names as an array: http://docs.ansible.com/ansible/latest/playbooks_variables.html#magic-variables-and-how-to-access-information-about-other-hosts
So I think the workaround that you found is the way to go, unless you can use real host names instead of IP addresses (using DNS or just static hosts file).

ansible playbook on multiple servers with different vars

I'm running an ansible playbook on a list of hosts with a host file:
[consul]
${HOST1} ansible_ssh_host=${HOST1} ansible_ssh_user=devops ansible_ssh_pass=blabla
${HOST2} ansible_ssh_host=${HOST2} ansible_ssh_user=devops ansible_ssh_pass=blabla
.......so on...
The thing is that I need to pass a different variable for each host.
I know of the flag -e that allows me to send a variable with the ansible-playbook command but it's not for each of the hosts.
I'm running the playbook with this:
ansible-playbook -vvvv site.yml
How can I pass a different var for each host?
Thanks!
Note: I'm using ansible 1.7.1
Two ways you should be able to do this:
1) Include the variable in your host file:
[consul]
${HOST1} ansible_ssh_host=${HOST1} .... myvar=x
${HOST2} ansible_ssh_host=${HOST2} .... myvar=y
2) Or use the include_vars task to load a file based on the host name
include_vars: "{{ ansible_ssh_host }}.yml"
The second method is good if you have a lot of variables to load for a host.
For more complex cases the lookups module might help:
http://docs.ansible.com/ansible/playbooks_lookups.html

Defining host as variable in Ansible hosts file

I have a rather simple hosts file
[clients]
qas0062
[dbs_server]
qas0063
For the users of the project we don't want them to modify hosts file but rather we have a separate user.config.yml file that contain various user-configurable parameters. There we have entry such as
dbs_server: qas0065
So the question is: is it possible to use a variable in the hosts file that would use a value defined in user.config.yml? And what would be the format?
Pretty sure you can't templatize the actual host key entry in the inventory, but you can templatize the value of its ansible_host connection var to achieve roughly the same effect, eg:
[clients]
clienthost ansible_host="{{ clienthost_var }}"
[dbs_server]
dbsserver ansible_host="{{ dbsserver_var }}"
then set the value of those vars from external vars before the play starts executing (eg, with the vars_files directive or -e).
There is another way to do the same thing. We can simply refer to values in the hosts (inventory) file by using the following syntax in our playbook
host={{ groups['dbs_server'][0] }}
This works well when you have one entry in the group (db_server in this specific case)

Resources