Skip to content

Instantly share code, notes, and snippets.

@rothgar
Last active September 10, 2024 09:53
Show Gist options
  • Save rothgar/8793800 to your computer and use it in GitHub Desktop.
Save rothgar/8793800 to your computer and use it in GitHub Desktop.
Generate /etc/hosts with Ansible
# Idempotent way to build a /etc/hosts file with Ansible using your Ansible hosts inventory for a source.
# Will include all hosts the playbook is run on.
# Inspired from http://xmeblog.blogspot.com/2013/06/ansible-dynamicaly-update-etchosts.html
- name: "Build hosts file"
lineinfile: dest=/etc/hosts regexp='.*{{ item }}$' line="{{ hostvars[item].ansible_default_ipv4.address }} {{item}}" state=present
when: hostvars[item].ansible_default_ipv4.address is defined
with_items: groups['all']
@rwngallego
Copy link

It works in Ansible 2.7.6:

  - name: Add the inventory into /etc/hosts
    lineinfile:
      dest: /etc/hosts
      regexp: '.*{{ item }}$'
      line: "{{ hostvars[item]['ansible_default_ipv4']['address'] }} {{item}}"
      state: present
    when: hostvars[item]['ansible_facts']['default_ipv4'] is defined
    with_items:
      - "{{ groups['all'] }}"

@zx1986
Copy link

zx1986 commented Aug 26, 2019

I got:

"msg": "The conditional check 'hostvars[item].ansible_default_ipv4.address is defined' failed. 
The error was: 
error while evaluating conditional (hostvars[item].ansible_default_ipv4.address is defined): 
u\"hostvars['groups['all']']\" is undefined\n\n

The error appears to be in '/var/lib/awx/projects/_16__openpoint_ansible/playbooks/hostname.yml': line 12, column 7, 
but may\n
be elsewhere in the file depending on the exact syntax problem.
\n\n

The offending line appears to be:
\n\n  
post_tasks:
\n    - name: Build hosts file
\n      ^ here
\n",

And I fix it with @rwngallego 's codes.


https://serverfault.com/questions/832799/ansible-add-ip-of-all-hosts-to-etc-hosts-of-all-other-hosts

@ilyesAj
Copy link

ilyesAj commented Jan 9, 2020

this works for ansible 2.2.1

  tasks:
          - name: "generate hosts file from inventory "
            copy:
              src: "{{inventory_for_bastion}}"
              dest: /etc/ansible/hosts
              mode: 766
          - name: "Build hosts file"
            lineinfile: dest=/etc/hosts regexp='.*{{ item }}$' line="{{ hostvars[item].ansible_host}} {{item}}" state=present
            with_items: "{{ groups['internal'] }}"

make sur that the group internal is defined in your inventory located in /etc/ansible/hosts and looks like that :

[internal]
terraform-controller-0   ansible_host=10.240.0.4

@smareti
Copy link

smareti commented Jan 24, 2020

It works in ansible 2.9.2
Screen Shot 2020-01-23 at 7 38 14 PM

@soliverprofesional
Copy link

Hi there, sorry for refloating. I'm sharing my update just in the case helps someone else.

Based on the solutions already posted, I've got the issue where I had hosts with multiple NICs/IPs that I wanted to add to the /etc/hosts.
e.g.:

192.168.10.11 10.0.2.15 10.10.10.11       ha-1      ha-1
192.168.10.12 10.0.2.15 10.10.10.12       ha-2      ha-2

So I changed the variable {{ hostvars[item].ansible_facts.default_ipv4.address }} for {{ hostvars[item].ansible_facts.all_ipv4_addresses | join(" ") }} that is basically the list of IP address in the host gather from the ansible facts, converted to a list of strings separated by space.

Thank you guys for adding your solutions. Were extremely helpful for me.

@dywanik
Copy link

dywanik commented Mar 30, 2020

Hi, I was wondering if anybody was able to test this solution using Molecule?

@iamenr0s
Copy link

iamenr0s commented Jun 26, 2020

@dywanik After some research, I could confirm there's no way to manipulate /etc/hosts with Molecule using docker platform. The /etc/hosts file is crucial for Docker's linking system and it should only be manipulated manually at the image level, rather than the container level.
See:
https://docs.docker.com/network/links/#updating-the-etchosts-file

William-Yeh/docker-ansible#4 (comment)

@iamenr0s
Copy link

Anyway the solution proposed here works fine.
I have simply added this code in my molecule.yml

...
provisioner:
  name: ansible
  inventory:
    group_vars:
      all:
        run_not_in_container: False
...

and then modified my tasks/main.yml

- name: Generate /etc/hosts file
  template:
    src: etc/hosts.j2
    dest: /etc/hosts
    owner: root
    group: root
    mode: 0644
  when: run_not_in_container

when you test your role remember to set the variable

[all:vars]
run_not_in_container=True

@gardar
Copy link

gardar commented Aug 5, 2021

@enr0s, you can also use the tag/variable molecule-notest that's already set by molecule, so you don't have to define your own.

tasks/main.yml

---
- name: Generate /etc/hosts file
  template:
    src: etc/hosts.j2
    dest: /etc/hosts
    owner: root
    group: root
    mode: 0644
  tags:
    - molecule-notest

or
tasks/main.yml

---
- name: Generate /etc/hosts file
  template:
    src: etc/hosts.j2
    dest: /etc/hosts
    owner: root
    group: root
    mode: 0644
  when: molecule-notest not in ansible_skip_tags

Another solution to this issue would be to use a "dummy" hosts file with molecule, which is not a perfect solution but is better than skipping the task in my opinion because you can then confirm that the hosts file is generated correctly.
The way to achieve that would be something like:

defaults/main.yml

---
etc_hosts_file: /etc/hosts

molecule.yml

provisioner:
  name: ansible
  inventory:
    group_vars:
      all:
        etc_hosts_file: /tmp/molecule_etc_hosts

tasks/main.yml

---
- name: Generate /etc/hosts file
  template:
    src: etc/hosts.j2
    dest: "{{ etc_hosts_file }}"
    owner: root
    group: root
    mode: 0644

@irigon
Copy link

irigon commented Dec 9, 2021

@dywanik , I am not sure if that is what you are searching for... in my case, I wanted simply to add an entry to /etc/hosts.
The following worked for me:

molecule.yml:

---
...
platforms:
  - name: "myplatformname"
    etc_hosts:
      "repo": "8.8.8.8"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment