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.
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:
ip command line tool on the controller.---
- 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 }}"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With