Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get Ansible client IP from target host?

Tags:

ansible

On an isolated network (without internet access to do public IP address lookups), I want to run a playbook from a controller against a number of target hosts where one of the tasks is to download a file via HTTP/HTTPS from the controller without hard-coding the controller IP as part of the task. E.g.

Controller: 192.168.0.5
Target 1: 192.168.0.10
Target 2: 192.168.0.11
Target 3: 192.168.0.12

The controller can have different IPs configured via DHCP, and there could be multiple network interfaces listed in ansible_all_ipv4_addresses (some of which may not be available to the target hosts) so it may not be straight forward to determine which network interface the target hosts should use from ansible_facts on localhost without exploring the idea of looping through them with a timeout until the file has been downloaded. It seems as though the most robust way to determine the public IP of the controller (assuming the web server is listening on 0.0.0.0) would be to determine the originating IP of the established connection (192.168.0.5) from the target host - is there a way to do this?

The motivation for downloading the file from the controller rather than sending it to remote hosts is that some of the target hosts are running Windows and the win_copy module is incredibly slow via WinRM so the Ansible documentation includes the following note:

Because win_copy runs over WinRM, it is not a very efficient transfer mechanism. If sending large files consider hosting them on a web service and using ansible.windows.win_get_url instead.

like image 804
gratz Avatar asked Jan 16 '26 18:01

gratz


1 Answers

Limited test on my machine which has a single ip and with a single target. But I don't see why it would not work in your scenario.

Given the following inventories/default/hosts.yml

all:
  hosts:
    target1:
      ansible_host: 192.168.0.10
    target2:
      ansible_host: 192.168.0.11
    target3:
      ansible_host: 192.168.0.12

The following test playbook should do what you expect. Replace the dummy debug task with get_url/uri to initiate the download.

Notes:

  • this playbook infers you have access to the ip command line tool on the controller.
  • I took for granted that the controller IP used to connect to target is the one that the target has access to in the other direction. If this isn't the case then the below will not work in your situation.
---
- hosts: all
  gather_facts: false

  tasks:
    - name: Check route on controller for each target destination
      ansible.builtin.command: ip route get {{ ansible_host }}
      register: route_cmd
      delegate_to: localhost

    - name: Register the controller outgoing ip for each target
      ansible.builtin.set_fact:
        controller_ip: "{{ route_cmd.stdout_lines[0] | regex_replace('^.* src (\\d*(\\.\\d*){3}).*$', '\\1') }}"

    - name: Show result
      ansible.builtin.debug:
        msg: "I would connect from target {{ inventory_hostname }} ({{ ansible_host }}) 
          to controller using ip {{ controller_ip }}"
like image 135
Zeitounator Avatar answered Jan 19 '26 18:01

Zeitounator



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!