Ansible Get Host Name and IP for Inventory Host groups
10,770
Solution 1
I would use a jinja template for this :
# hosts_file.j2
{% for server in groups['Servers'] %}
{{hostvars[server]['ansible_facts']['hostname']}}:{{hostvars[server]['ansible_facts']['default_ipv4']['address']}}
{% endfor %}
- hosts: localhost
tasks:
- name: create hosts file from template
template:
src: hosts_file.j2
dest: {{store_files_path}}/{{ansible_date_time.date}}/{{ansible_date_time.time}}/hosts.txt
Solution 2
You are making this extremely complicated for yourself.
- You don't have to go via the
hostvars
in order to achieve what you want, the special variables are mostly giving you information on the host Ansible is currently acting on. This is the same for the facts Ansible gathered for the hosts. - For the matter at hand, you can use another special variable
group_names
that will allow you to get the groups the host you are currently acting on is, in the form of a list. So getting the hosts that are part of a group is as simple as doingwhen: "'group_that_interest_you' in group_names"
So given the inventory:
all:
vars:
ansible_python_interpreter: /usr/bin/python3
children:
local:
hosts:
localhost:
Servers:
hosts:
foo.example.org:
ansible_host: 172.17.0.2
And the playbook:
- hosts: all
gather_facts: yes
tasks:
- debug:
msg: "{{ ansible_hostname }}:{{ ansible_default_ipv4.address }}"
when: "'Servers' in group_names"
This yields the recap:
PLAY [all] **********************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************
ok: [localhost]
ok: [foo.example.org]
TASK [debug] ********************************************************************************************************
skipping: [localhost]
ok: [foo.example.org] => {
"msg": "8088bc73d8cf:172.17.0.2"
}
PLAY RECAP **********************************************************************************************************
foo.example.org : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Now if you adapt that in your own playbook you should be good to go:
- name: Create File with hosts and IP address.
lineinfile:
dest: "{{ store_files_path }}/{{ ansible_date_time.date }}/{{ ansible_date_time.time }}/hosts.txt"
create: yes
line: "{{ ansible_hostname }}:{{ ansible_default_ipv4.address }}"
when: "'Servers' in group_names"
delegate_to: localhost
Related videos on Youtube
Author by
n00b
Updated on June 04, 2022Comments
-
n00b almost 2 years
I am trying to get host name and IP address of hosts and save them to a file.
I have this solution working;
- name: Create File with hosts and IP address. when: inventory_hostname in groups['local'] lineinfile: dest: "{{store_files_path}}/{{ansible_date_time.date}}/{{ansible_date_time.time}}/hosts.txt" create: yes line: "{{hostvars[inventory_hostname].ansible_hostname}}:{{hostvars[inventory_hostname].ansible_default_ipv4.address}}"
But the issue is in my hosts file, I have two groups,
local
andServers
. I want to get theServers
only and not thelocal
group which is thelocalhost
only.I have tried the below line but it doesn't work, it gives me an error.
line: "{{ hostvars[ groups['Servers'][0] ].ansible_hostname }} :{{ hostvars[ groups['Servers'][0] ].ansible_default_ipv4.address }}"
I have searched around and that's what I found, how should I do this?
-
gary lopez over 3 yearsWhat is the error?
-
n00b over 3 yearsHere is the error: "The task includes an option with an undefined variable. The error was: 'ansible.vars.hostvars.HostVarsVars object' has no attribute 'ansible_hostname
-
gary lopez over 3 yearsI guess you change
hosts: all
tohosts: local
. is it correct? -
n00b over 3 yearsI am not using such, I am using when: inventory_hostname in groups['local']
-
gary lopez over 3 yearsI have. how are you using hosts? Write your entire playbook.
-
β.εηοιτ.βε over 3 years@n00b please note that an Ansible playbook is not
sh
, an Ansible is a YAML file. -
n00b over 3 yearsHey, I had placed it as an yaml file but someone edited it. Really don't know how this thing work where someone edits your question as if you don't know what you are asking nor doing.
-
β.εηοιτ.βε over 3 yearsOh, indeed, I didn't look in the edit history properly, my bad.
-
-
n00b over 3 yearsHey, I don't know about templates/jinja templates so could you kindly elaborate on your solution and place it as a task.
-
n00b over 3 yearsShould I place the hosts_file.j2 in the templates folder?
-
Marc Salvetti over 3 yearsI added the task call below. Basically paste the first bloc in a file called hosts_file.j2 which is your template. Then add the second bloc (the task) to your playbook. That's all there is to it. The second block call the "template" module which will render the hosts_file.j2 template into your target file. Yes, the templates folder is a good place to store the template, ansible will look for it there.
-
n00b over 3 yearsOkay, let me give it a try.
-
n00b over 3 yearsFacing some issues.. an Error: fatal: [localhost]: FAILED! => {"changed": false, "msg": "AnsibleUndefinedVariable: 'ansible.vars.hostvars.HostVarsVars object' has no attribute 'ansible_host'"} fatal: [192.168.1.14]: FAILED! => {"changed": false, "msg": "AnsibleUndefinedVariable: 'ansible.vars.hostvars.HostVarsVars object' has no attribute 'ansible_host'"}
-
Marc Salvetti over 3 yearsin your original code, you were calling ansible_hostname not ansible_host so that might be the reason but I thought ansible_host was available on every host. You can eventually display the whole content of hostvars[server] in a debug task to see which exact variable name you are looking for
-
Marc Salvetti over 3 yearsto debug you can add a task like this to your playbook - debug: var: hostvars['yourExampleHost']
-
Marc Salvetti over 3 yearsLet us continue this discussion in chat.
-
n00b over 3 yearsBut I want to get the hostname of the server... not the hostname you have assigned in the hosts file. In my hosts file I have just placed the [group-name] then IP that's it. So this way seems too complicated also.
-
n00b over 3 yearsI have found the solution and would love to edit your answer the template bit, how do I go on about it??
-
β.εηοιτ.βε over 3 yearsHave you tried it? Have you looked at the recap in my answer?
foo.example.org
is the name in my host file,"msg": "8088bc73d8cf:172.17.0.2"
is Ansible recap output.inventory_hostname
would indeed have yield mefoo.example.org
, but here I am usingansible_hostname
, which is, for my host,8088bc73d8cf
. -
n00b over 3 yearsTried it but it saves the output to the server and not the localhost because of the when ...
-
n00b over 3 yearsbut this is also a good way of doing it, so how would I make the data to be saved on localhost
-
β.εηοιτ.βε over 3 yearsAh, yes, you pointed at that requirement in your first question, but forgot to mention it in this one. Still, the answer you got there is the correct one, you should actually add a
delegate_to: localhost
. Answer corrected in that sense. -
β.εηοιτ.βε over 3 yearsThe
when
have nothing to do with where a task is executed.when
allows you to skip hosts based on some conditions, see in the recap: of this answer:skipping: [localhost]
-
n00b over 3 yearsThanks you have taught me the difference between those two. I was actually getting confused, between those two.