looking for ways to map replsetB to a hostname/ipaddress in the /etc/ansible/hosts inventory file? Goal is to be able to use the hosts in inventory files in playbooks as variables
Please read: How To Access Information About Other Hosts.
- debug:
msg: "This is replsetB ip {{ hostvars['replsetB'].ansible_host }}"
Related
In my playbook I use var group[inventory_group]. And I need to use my dynamic inventory script. In the documentation I found:
Like above, it is possible to pass an additional inventory file (or
even dynamic inventory script), using the hosts key. Ansible will
automatically merge this inventory with the one generated by molecule.
This can be useful if you want to define extra hosts that are not
managed by Molecule.
But I didn't find any examples.
So, how do I "pass an additional inventory file (or even dynamic inventory script), using the hosts key" ?
Perhaps you could execute the dynamic inventory script in create or prepare steps in the molecule scenario, and then use the add_host module to add the hosts to the in memory inventory?
So something like:
- command:
cmd: /path/to/your_dynamic_inventory_scri.pt
delegate_to: localhost
register: dynamic_inventory
- add_host:
name: "{{ item }}"
loop: "{{ dynamic_inventory.stdout_lines }}"
I am running a shell command, this command runs for all hosts listed in my inventory file. I am then using register to define the variable, when i retrieve these values for debug messages i see register variable for all hosts printed for all IP in my inventory but i want to store them in a list so that i can use them in templates. How can we achieve it?
- name: Command
shell: hostname -f
register: fqdn_name
For your specific question, you are doing more work than you need to. Each time Ansible runs against a host, it collects a series of 'facts' about the host and stores them in a dictionary available during your plays. Therefore, replace your existing Command task with the following, to see what I mean:
- name: Display the Ansible FQDN fact
debug:
var: ansible_fqdn
Running ansible -m setup <hostname taken from inventory file> will show you all the variables that get collected.
The variables for all your hosts are made available through a special dictionary called 'hostvars', therefore in your template you can do something like this:
{% for host in groups.all %}
{{ hostvars[host]['ansible_fqdn'] }}
{% endfor %}
You could replace groups.all with groups.<some inventory groupname> to limit the matched hosts to a particular group.
One possible gotcha here, is that these facts will only have been collected if Ansible has already targeted a host, therefore one strategy for more complex playbooks is:
# This play simply connects to all your hosts and gathers facts
- hosts: all
gather_facts: yes
# Now all subsequent plays have access to facts for all hosts
- hosts: <all or some group>
tasks: ...
I'm working on putting together a playbook that will deploy local facts scripts to various groups in my Ansible inventory, and I would to be able to utilize the group name being worked on as a variable in the tasks themselves. Assume for this example that I have the traditional Ansible roles directory structure on my Ansible machine, and I have subdirectories under the "files" directory called "apache", "web", and "db". I'll now illustrate by example, ...
---
- hosts: apache:web:db
tasks:
- name: Set facts for facts directories
set_fact:
facts_dir_local: "files/{{ group_name }}"
facts_dir_remote: "/etc/ansible/facts.d"
- name: Deploy local facts
copy:
src: "{{ item }}"
dest: "{{ facts_dir_remote }}"
owner: ansible
group: ansible
mode: 0750
with_fileglob:
- "{{ facts_dir_local }}/*.fact"
The goal is to have {{ group_name }} above take on the value of "apache" for the hosts in the apache group, "web" for the hosts in the web group, and "db" for the hosts in the db group. This way I don't have to copy and paste this task and assign custom variables for each group. Any suggestions for how to accomplish this would be greatly appreciated.
While there is no group_name variable in ansible, there is a group_names (plural). That is because any host may be part of one or more groups.
It is described in the official documentation as
group_names
List of groups the current host is part of
In the most common case each host would only be part of one group and so you could simply say group_names[0] to get what you want.
TLDR;
Use group_names[0].
You can use group variables to achieve this, either specified in the inventory file or in separate group_vars/<group> files - see https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html
Note though that these group variables are squashed into host variables when you run the playbook. Hosts that are listed in multiple groups will end up with variables based on a precedence order
I have two VMs one as ansible control machine and running playbook to perform action on second vm.
Following are files on ansible control machine
/etc/ansible/ansible.cfg
inventory = /etc/ansible/hosts
/etc/ansible/hosts
# My nodes
[my-group]
my1-node ansible_user=imran DB_SERVER=10.136.10.49 DB_USER=mydbusr
I tried following two ways to access variables but no success, but if i provide with command line like -e DB_SERVER=10.136.10.49. its working
myplaybook
---
- hosts: all
tasks:
- debug:
msg:
- "Database server {{DB_SERVER}}"
- "Database Username {{ hostvars['DB_USER'] }}"
Above is producing error
Update:
I also run with verbose and its saying so its pointing to correct config, as i read due to vagrant sometime configuration is not pointed correctly.
Using /etc/ansible/ansible.cfg as config file
if you want to use the hostvars magic variables array, you should use the below syntax:
---
- hosts: all
tasks:
- debug:
msg:
- "Database server {{DB_SERVER}}"
- "Database Username {{ hostvars[inventory_hostname]['DB_USER'] }}"
{{DB_SERVER}} should work, ansible knows how to resolve it to the value you defined in the inventory file.
hope it helps.
I am trying to get a list of the IP's of all the hosts in my inventory file from a playbook that only runs in a single group.
Assume the following inventory file:
[dbservers]
db1.example.com
db2.example.com
[webservers]
www1.example.com
www2.example.com
And the playbook:
---
- hosts: dbservers
roles:
- dosomething
And the dosomething role:
- name: print all host ips
template: src=hosts.j2 dest=/tmp/hosts.txt
And the hosts.j2 template:
{% for host in hostvars %}
{{ hostvars[host].ansible_eth0.ipv4.address }}
{% endfor %}
Problem:
When running this, I only ever get the dbserver ip's listed, not all ip's
Question:
How can I gain access to the entire inventory from within this playbook? Changing the hosts to all in the playbook works, but then the dosomething playbook also runs on all hosts, which is not what I want. I only want the list on the dbservers.
In order to gain access to all the hosts in hostvars, you first have to create a task for all hosts. I created a simple role that would simple echo something on all hosts. This role then forces gather facts on all hosts and add each to the hostvars group.
Please note that if you then run the playbook with a tag limit, the hostvars group is again effected.
I got the tip here: https://groups.google.com/forum/#!msg/Ansible-project/f90Y4T4SJfQ/L1YomumcPEQJ
The special variable groups is probably what you want to do this, in your case the value of groups will be:
"groups" : {
"dbservers": [
"db1.example.com",
"db2.example.com"
],
"webservers": [
"www1.example.com",
"www2.example.com"
]
}
which you can loop over in your jinja template.