I'm looking to migrate app config from one host to another. The tasks to be ran on either host differ significantly that they warrant their own roles. Ideally, I'm looking for the target host to be determined dynamically from a web call rather than supplied to the playbook.
Unfortunately, delegate_to has been restricted due to company policy, so that's not an option. Instead, I'm looking to provide the target host as a variable to hosts: but either it doesn't match or it complaints that the variable is undefined.
Simplified playbook
- hosts: all
tasks:
- name: Get target host
uri:
url: http://url_link.com/get_gateways.cgi?name={{ target_gateway }}
timeout: 5
return_content: true
register: connection_string
- name: store target host as fact
set_fact:
target_host: "{{ connection_string.content }}"
- name: debug connection string
debug:
var: target_host
- debug:
var=hostvars[inventory_hostname]["connection_string"].content
- hosts: target_host # Case 1
- hosts: "{{ hostvars[inventory_hostname]['connection_string'].content }}" #Case 2
tasks:
- import_role:
name: gateway_migration
Output when using target_host:
PLAY [all] ************************************************************************************************************************************************************************************************************************************************************************************************************************************************
TASK [Initialising the host specific facts only.] *********************************************************************************************************************************************************************************************************************************************************************************************************
ok: [myhost]
TASK [Get target host] ************************************************************************************************************************************************************************************************************************************************************************************************************************************
ok: [myhost]
TASK [store target host as fact] **************************************************************************************************************************************************************************************************************************************************************************************************************************
ok: [myhost]
TASK [debug] **********************************************************************************************************************************************************************************************************************************************************************************************************************************************
ok: [myhost] => {
"target_host": [
"target-1"
]
}
TASK [debug] **********************************************************************************************************************************************************************************************************************************************************************************************************************************************
ok: [sd-a6l1-kupa.nam.nsroot.net] => {
"hostvars[inventory_hostname][\"connection_string\"].content": "target-1"
}
[WARNING]: Could not match supplied host pattern, ignoring: target_host
PLAY [target_host] ****************************************************************************************************************************************************************************************************************************************************************************************************************************************
skipping: no hosts matched
And for case 2 (It's pretty much the same error msg when substituting the hostvars dictionary with target_host). In both cases it claims the variable is undefined:
ERROR! The field 'hosts' has an invalid value, which includes an undefined variable. The error was: 'inventory_hostname' is undefined. 'inventory_hostname' is undefined
In reality I'm running a regex on the returned string from the url, and when trying without the "jinja syntax", so removing the quotes and curly braces I get the following:
[WARNING]: Could not match supplied host pattern, ignoring: hostvars[inventory_hostname]['connection_string'].content | regex_search('(.*?)~(.*?)~(.*?)~(.*?)'
[WARNING]: Could not match supplied host pattern, ignoring: '\\1')
Q: "... looking for the target host to be determined dynamically from a web call ..."
For an inventory example.ini
[roles:children]
control
managed
[control]
controlnode.example.com
[managed]
remotenode.example.com
managednode.example.com
a minimal example playbook example.yml
---
- hosts: control
become: false
gather_facts: false
tasks:
- name: Get target host
uri:
url: "{{ URL }}"
return_content: true
register: response
vars:
URL: http://www.example.com
- name: Determined dynamically from a web call
add_host:
hostname: "{{ response.content | regex_search('www(.*?)org') }}"
group: managed
- hosts: managed
become: false
gather_facts: false
tasks:
- name: Target hosts
debug:
msg: "{{ inventory_hostname }}"
called via
ansible-playbook --inventory example.ini example.yml
will result into an output of
PLAY [control] **********************************
TASK [Get target host] **************************
ok: [controlnode.example.com]
TASK [Determined dynamically from a web call] ***
changed: [controlnode.example.com]
PLAY [managed] **********************************
TASK [Target hosts] *****************************
ok: [remotenode.example.com] =>
msg: remotenode.example.com
ok: [managednode.example.com] =>
msg: managednode.example.com
ok: [www.iana.org] =>
msg: www.iana.org