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.

  1. 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.
  2. 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 doing when: "'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
Share:
10,770

Related videos on Youtube

n00b
Author by

n00b

Updated on June 04, 2022

Comments

  • n00b
    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 and Servers. I want to get the Servers only and not the local group which is the localhost 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
      gary lopez over 3 years
      What is the error?
    • n00b
      n00b over 3 years
      Here 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
      gary lopez over 3 years
      I guess you change hosts: all to hosts: local. is it correct?
    • n00b
      n00b over 3 years
      I am not using such, I am using when: inventory_hostname in groups['local']
    • gary lopez
      gary lopez over 3 years
      I 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
      n00b over 3 years
      Hey, 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 years
      Oh, indeed, I didn't look in the edit history properly, my bad.
  • n00b
    n00b over 3 years
    Hey, I don't know about templates/jinja templates so could you kindly elaborate on your solution and place it as a task.
  • n00b
    n00b over 3 years
    Should I place the hosts_file.j2 in the templates folder?
  • Marc Salvetti
    Marc Salvetti over 3 years
    I 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
    n00b over 3 years
    Okay, let me give it a try.
  • n00b
    n00b over 3 years
    Facing 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
    Marc Salvetti over 3 years
    in 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
    Marc Salvetti over 3 years
    to debug you can add a task like this to your playbook - debug: var: hostvars['yourExampleHost']
  • Marc Salvetti
    Marc Salvetti over 3 years
  • n00b
    n00b over 3 years
    But 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
    n00b over 3 years
    I have found the solution and would love to edit your answer the template bit, how do I go on about it??
  • β.εηοιτ.βε
    β.εηοιτ.βε over 3 years
    Have 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 me foo.example.org, but here I am using ansible_hostname, which is, for my host, 8088bc73d8cf.
  • n00b
    n00b over 3 years
    Tried it but it saves the output to the server and not the localhost because of the when ...
  • n00b
    n00b over 3 years
    but this is also a good way of doing it, so how would I make the data to be saved on localhost
  • β.εηοιτ.βε
    β.εηοιτ.βε over 3 years
    Ah, 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 years
    The 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
    n00b over 3 years
    Thanks you have taught me the difference between those two. I was actually getting confused, between those two.