4

I would like to insert an IP address in to a J2 template which is used by an Ansible playbook. That IP adress is not the address of the host which is being provisioned, but the IP of the host from which the provisioning is done. Everything I have found so far covers using variables/facts related to the hosts being provisioned. In other words: the IP I’d like to insert is the one in ['ansible_default_ipv4']['address'] when executing ansible -m setup 127.0.0.1.

I think that I could use a local playbook to write a dynamically generated template file containing the IP, but I was hoping that this might be possible “the Ansible way”.

techraf
  • 64,883
  • 27
  • 193
  • 198
BlueM
  • 3,658
  • 21
  • 34
  • Did you ever find an answer to this? I'm running into the same issue and curious what you ended up doing. – Cory Jan 02 '16 at 16:08
  • No, unfortunately not yet. – BlueM Jan 03 '16 at 18:02
  • see my answer at http://stackoverflow.com/questions/34560622/best-way-to-get-the-ip-address-of-the-ansible-control-machine/39336170#39336170 – Suire Sep 06 '16 at 17:26

3 Answers3

3

Just use this:

{{ ansible_env["SSH_CLIENT"].split()[0] }}
udondan
  • 57,263
  • 20
  • 190
  • 175
  • When using this in the J2 template with Ansible 1.9.4, I get a fatal error with message “AnsibleUndefinedVariable: One or more undefined variables: 'dict object' has no attribute 'SSH_CLIENT'” – BlueM Nov 30 '15 at 09:17
2

You can force Ansible to fetch facts about the control host by running the setup module locally by using either a local_action or delegate_to. You can then either register that output and parse it or simply use set_fact to give it a useful name to use later in your template.

An example play might look something like:

   tasks:
    - name: setup
      setup:
      delegate_to: 127.0.0.1

    - name: set ansible control host IP fact
      set_fact:
        ansible_control_host_address: "{{ hostvars[inventory_hostname]['ansible_eth0']['ipv4']['address'] }}"
      delegate_to: 127.0.0.1

    - name: template file with ansible control host IP
      template:
        src: /path/to/template.j2
        dest: /path/to/destination/file

And then use the ansible_control_host_address variable in your template as normal:

...
Ansible control host IP: {{ ansible_control_host_address }}
...
ydaetskcoR
  • 53,225
  • 8
  • 158
  • 177
  • If I skip the `setup` task, provisioning works, but `ansible_control_host_address` contains the primary IPv4 of the VM which is being provisioned, not that of the Mac on which Ansible (BTW: v1.9.3) is installed. If I include the `setup` task, I get an error with message “unsupported parameter for module: delegate_to” – BlueM Nov 30 '15 at 09:12
  • @BlueM Just noticed your comment - I'm sure you solved it by now but it sounds like your issue with the setup task is just indentation. If you indented `delegate_to` inside the `setup:` block then it is seen as a parameter to the setup module rather than a parameter to the task which is what it should be. – ydaetskcoR Jun 21 '17 at 07:53
  • Thanks, @ydaetskcoR, for your comment – especially, as I did not solve the issue (but I stopped working on the project for which I needed this a short time after my question). I just tried it (Ansible 2.3.1.0 on OS X 10.12) with the changed indentation, but again: `Unsupported parameters for (setup) module: delegate_to. Supported parameters include: fact_path,filter,gather_subset,gather_timeout"}`. The fact that Ansible speaks of the “setup” module apperas as if the nesting as you intend it to be. – BlueM Jun 22 '17 at 20:32
1

This is how I solved the same problem (Ansible 2.7):

- name: Get local IP address
  setup:
  delegate_to: 127.0.0.1
  delegate_facts: yes

- name: Add to hosts file
  become: yes
  lineinfile:
    line: "{{ hostvars['127.0.0.1']['ansible_default_ipv4']['address'] }}   myhost"
    path: /etc/hosts

Seems to work like a charm. :-)

Bart Van Loon
  • 1,430
  • 8
  • 18
  • Trying this, I get `FAILED! => {"changed": false, "msg": "AnsibleUndefinedVariable: 'ansible.vars.hostvars.HostVarsVars object' has no attribute 'ansible_default_ipv4'"}`. I have hardly used Ansible in the last 2 years, so it may be I’m just missing something obvious … BTW, it’s Ansible 2.7.5 on macOS, and I tried to provision a local Debian Stretch in VirtualBox. – BlueM Jan 19 '19 at 14:31
  • My example runs on ansible 2.7.5 on Arch Linux. I can imagine that macOS perhaps doesn't have the "ansible_default_ipv4" fact, but with a little debug message it should be pretty easy to figure out the correct key. Hope this helps! – Bart Van Loon Jan 19 '19 at 14:41
  • 1
    Using this proposed solution because it works even after `become`. Also added a `run_once` and `when: 'hostvars["127.0.0.1"]["ansible_default_ipv4"] is not defined'` condition to `setup` to avoid multiple collections. – Stephan Mar 24 '23 at 11:05