Ansible hostname and IP address - variables

How I can use the value of hostname and IP address from hosts inventory file?
For example, I have only one host in the hosts file with name as FQDN, but this is registered on the DNS server.
I tried with some vars, but always get the hostname. But, need both of them :(
Output of request to DNS server:
nslookup host1.dinamarca.com
Server: 10.10.1.1
Address: 10.10.1.1#53
Name: host1.dinamarca.com
Address: 192.168.1.10
Example host file: (only have one host)
host1.dinamarca.com
I call the service ansible with the command:
ansible-playbook --ask-pass -i hosts test.yml
My test.yml file:
---
- name: test1
hosts: host1.dinamarca.com
remote_user: usertest
tasks:
- name: show ansible_ssh_host
debug:
msg: "{{ ansible_ssh_host }}"
- name: show inventary_hostname
debug: var=inventory_hostname
- name: show ansible_hostname
debug: var=ansible_hostname
...
Output is:
TASK [show ansible_ssh_host] ****************************************************************************************************************************************
ok: [host1.dinamarca.com] => {
"msg": "host1.dinamarca.com"
}
TASK [show inventary_hostname] **************************************************************************************************************************************
ok: [host1.dinamarca.com] => {
"inventory_hostname": "host1.dinamarca.com"
}
TASK [show ansible_hostname] ****************************************************************************************************************************************
ok: [host1.dinamarca.com] => {
"ansible_hostname": "host1"
}
PLAY RECAP ************************************************************************************************ *************************************************************
host1.dinamarca.com : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

There is an Ansible fact called ansible_fqdn. If you need both the hostname and FQDN, you can have tasks like this:
tasks:
- name: show ansible_ssh_host
debug:
msg: "{{ ansible_ssh_host }}"
- name: show inventory_hostname
debug:
msg: "{{ inventory_hostname }}"
- name: show ansible_hostname
debug:
msg: "{{ ansible_fqdn }}"

Related

Overwrite vars_prompt variable in playbook with host variable from inventory in Ansible

I want to overwrite some variables in my playbook file from the inventory file for a host that are defined as "vars_prompt". If I understand it correctly, Ansible shouldn't prompt for the variables if they were already set before, however, it still prompts for the variables when I try to execute the playbook.
How can I overwrite the "vars_prompt" variables from the inventory or is this not possible because of the variable precedence definition of Ansible?
Example:
playbook.yml
---
- name: Install Gateway
hosts: all
become: yes
vars_prompt:
- name: "hostname"
prompt: "Hostname"
private: no
...
inventory.yml
---
all:
children:
gateways:
hosts:
gateway:
ansible_host: 192.168.1.10
ansible_user: user
hostname: "gateway-name"
...
Q: "If I understand it correctly, Ansible shouldn't prompt for the variables if they were already set before, however, it still prompts for the variables when I try to execute the playbook."
A: You're wrong. Ansible won't prompt for variables defined by the command line --extra-vars. Quoting from Interactive input: prompts:
Prompts for individual vars_prompt variables will be skipped for any variable that is already defined through the command line --extra-vars option, ...
You can't overwrite vars_prompt variables from the inventory. See Understanding variable precedence. Inventory variables (3.-9.) is lower precedence compared to play vars_prompt (13.). The precedence of extra vars is 22.
Use the module pause to ask for the hostname if any variable is not defined. For example, the inventory
shell> cat hosts
host_1
host_2
and the playbook
hosts: all
gather_facts: false
vars:
hostnames: "{{ ansible_play_hosts_all|
map('extract', hostvars, 'hostname')|
list }}"
hostnames_undef: "{{ hostnames|from_yaml|
select('eq', 'AnsibleUndefined')|
length > 0 }}"
tasks:
- debug:
msg: |
hostnames: {{ hostnames }}
hostnames_undef: {{ hostnames_undef }}
run_once: true
- pause:
prompt: "Hostname"
register: out
when: hostnames_undef
run_once: true
- set_fact:
hostname: "{{ out.user_input }}"
when: hostname is not defined
- debug:
var: hostname
gives
shell> ansible-playbook pb.yml
PLAY [all] ************************************************************************************
TASK [debug] **********************************************************************************
ok: [host_1] =>
msg: |-
hostnames: [AnsibleUndefined, AnsibleUndefined]
hostnames_undef: True
TASK [pause] **********************************************************************************
[pause]
Hostname:
gw.example.com^Mok: [host_1]
TASK [set_fact] *******************************************************************************
ok: [host_1]
ok: [host_2]
TASK [debug] **********************************************************************************
ok: [host_1] =>
hostname: gw.example.com
ok: [host_2] =>
hostname: gw.example.com
PLAY RECAP ************************************************************************************
host_1: ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host_2: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
The playbook won't ovewrite variables defined in the inventory. For example
shell> cat hosts
host_1
host_2 hostname=gw2.example.com
gives
TASK [debug] **********************************************************************************
ok: [host_1] =>
hostname: gw.example.com
ok: [host_2] =>
hostname: gw2.example.com
I don't know if you can stop the prompts but you can se a default value directly in vars_prompts. In this way you do not need to type "gateway-name" every time.
vars_prompt:
- name: "hostname"
prompt: "Hostname"
private: no
default: "gateway-name"
Source: https://docs.ansible.com/ansible/latest/user_guide/playbooks_prompts.html

Is there a way in Ansible to retrieve a variable located on a different host, to get it on the localhost

I have the following playbook:
- name: Some action on the workers
hosts: workers
gather_facts: false
run_once: true
tasks:
- name: Set var for server information
set_fact:
server_info:
"name": "winserver"
"os": "Microsoft Windows Server 2019 Datacenter"
- name: Some action on the localhost
hosts: localhost
gather_facts: false
run_once: true
tasks:
- name: Show script stdout
debug:
msg:
- "{{ server_info }}"
The hosts is actually a group of servers put in a group named workers (for example server1, server2 and server3), where just one is chosen (arbitrary) to run this task. Now I need to retrieve the information from this variable on the localhost, but as I don't know on which server the first task runs, I cannot explicitly reference it by using:
"{{ hostvars['server2']['server_info'] }}"
Does someone know if there is a way to retrieve this variable on the localhost?
Q: "I don't know on which server the first task runs."
A: It's irrelevant which server the first task runs on. The variable server_info will be declared on all of them. For example, given the inventory
shell> cat hosts
[workers]
server1
server2
server3
The playbook
- hosts: workers
gather_facts: false
run_once: true
tasks:
- set_fact:
server_info: winserver
- debug:
var: hostvars[item]['server_info']
loop: "{{ ansible_play_hosts_all }}"
gives
TASK [debug] *********************************************************
ok: [server1] => (item=server1) =>
ansible_loop_var: item
hostvars[item]['server_info']: winserver
item: server1
ok: [server1] => (item=server2) =>
ansible_loop_var: item
hostvars[item]['server_info']: winserver
item: server2
ok: [server1] => (item=server3) =>
ansible_loop_var: item
hostvars[item]['server_info']: winserver
item: server
You can pick any host you like. For example,
- hosts: localhost
gather_facts: false
run_once: true
tasks:
- debug:
var: hostvars.server2.server_info
gives
TASK [debug] ************************************************************
ok: [localhost] =>
hostvars.server2.server_info: winserver
I just found the answer to this question myself: through the use of
delegate_to: localhost
delegate_facts: true
This way the variable gets stored on the localhost.
- name: Some action on the workers
hosts: workers
gather_facts: false
run_once: true
tasks:
- name: Set var for server information
set_fact:
server_info:
"name": "winserver"
"os": "Microsoft Windows Server 2019 Datacenter"
delegate_to: localhost
delegate_facts: true
- name: Some action on the localhost
hosts: localhost
gather_facts: false
run_once: true
tasks:
- name: Show script stdout
debug:
msg:
- "{{ server_info }}"

How to detect unreachable target hosts in ansible

I wish to grab in a variable sshreachable if a target hosts all_hosts are reachable or not.
I wrote the below playbook for the same.
- name: Play 3- check telnet nodes
hosts: localhost
ignore_unreachable: yes
- name: Check all port numbers are accessible from current host
include_tasks: innertelnet.yml
with_items: "{{ groups['all_hosts'] }}"
cat innertelnet.yml
---
- name: Check ssh connectivity
block:
- raw: "ssh -o BatchMode=yes root#{{ item }} echo success"
ignore_errors: yes
register: sshcheck
- debug:
msg: "SSHCHECK variable:{{ sshcheck }}"
- set_fact:
sshreachable: 'SSH SUCCESS'
when: sshcheck.unreachable == 'false'
- set_fact:
sshreachable: 'SSH FAILED'
when: sshcheck.unreachable == 'true'
- debug:
msg: "INNERSSH1: {{ sshreachable }}"
Unfortunately, i get error like below:
Output:
TASK [raw] *********************************************************************
fatal: [localhost]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Shared connection to 10.9.9.126 closed.", "skip_reason": "Host localhost is unreachable", "unreachable": true}
TASK [debug] ***********************************************************************************************************************************************************
task path:
ok: [localhost] => {
"msg": "SSHCHECK variable:{'msg': u'Failed to connect to the host via ssh: Shared connection to 10.9.9.126 closed.', 'unreachable': True, 'changed': False}"
}
TASK [set_fact] ****************************************************************
skipping: [localhost]
TASK [set_fact] ****************************************************************
skipping: [localhost]
TASK [debug] *******************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'sshreachable' is undefined\n\nThe error appears to be in '/app/playbook/checkssh/innertelnet.yml': line 45, column 10, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - debug:\n ^ here\n"}
PLAY RECAP *********************************************************************
10.0.116.194 : ok=101 changed=1 unreachable=9 failed=0 skipped=12 rescued=0 ignored=95
localhost : ok=5 changed=0 unreachable=1 failed=1 skipped=4 rescued=0 ignored=0
Can you please suggest changes to my code to get this to work?
The error seems to indicate that sshreachable variable is not getting set as the when: condition does not match. I.e. sshcheck.unreachable might not be something returned by raw.
For this purpose, command module should be enough, and we can evaluate the return code of the command to set_fact.
You could do something like:
- block:
- command: ssh -o BatchMode=yes user#host1 echo success
ignore_errors: yes
register: sshcheck
- set_fact:
sshreachable: "{{ sshcheck is success }}"
- debug:
msg: "Host1 reachable: {{ sshreachable | string }}"
Update:
raw module seems to work the same way. Example (including #mdaniel's valuable input):
- block:
- raw: ssh -o BatchMode=yes user#host1 echo success
ignore_errors: yes
register: sshcheck
- set_fact:
sshreachable: SSH SUCCESS
when: sshcheck is success
- set_fact:
sshreachable: SSH FAILED
when: sshcheck is failed
- debug:
msg: "Host1 reachable: {{ sshreachable }}"

Ansible variable interpolation not working in brackets

I'm using Ansible to grab an VIP from InfoBlox and running into an issue when trying to build my exclude list. I need to exclude the first 3 IP's as they are reserved, however the CIDR range is a dynamic variable so I need to build this exclude list on the fly. Here's a representation of what I have so far:
---
- name: Assign VIP to FQDN in Grid Manager
hosts: all
connection: local
gather_facts: false
vars:
CIDR: 10.0.0.
tasks:
- set_fact:
EXCLUDES: "{{ EXCLUDES | default([]) + [item] }}"
with_sequence: start=1 end=3 format=''{{ CIDR }}%d''
- set_fact:
formated_excludes: "{{ EXCLUDES |join(', ') }}"
- debug:
msg: "{{ formated_excludes }}"
- set_fact:
VIP: "{{ lookup('nios_next_ip', '10.0.0.0/25', exclude=[formated_excludes]) | first }}"
- name: Print next IP address
debug:
msg: "The next available IP is {{ VIP }}"
Here are the results of the play:
PLAY [Assign VIP to FQDN in Grid Manager] *****************************************************************************************************************
TASK [set_fact] *******************************************************************************************************************************************
ok: [localhost] => (item='10.0.0.1')
ok: [localhost] => (item='10.0.0.2')
ok: [localhost] => (item='10.0.0.3')
TASK [set_fact] *******************************************************************************************************************************************
ok: [localhost]
TASK [debug] **********************************************************************************************************************************************
ok: [localhost] => {
"msg": "'10.0.0.1', '10.0.0.2', '10.0.0.3'"
}
TASK [set_fact] *******************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "An unhandled exception occurred while running the lookup plugin 'nios_next_ip'. Error was a <class 'ansible.errors.AnsibleError'>, original message: Invalid value for exclude: \"'10.0.0.1', '10.0.0.2', '10.0.0.3'\": Invalid IPv4 address"}
PLAY RECAP ************************************************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
The formatting appears to be fine, however the lookup won't accept it. For comparison, using the following works fine:
- set_fact:
VIP: "{{ lookup('nios_next_ip', '10.0.0.0/25', exclude=['10.0.0.1', '10.0.0.2', '10.0.0.3']) | first }}"
Here are the results:
PLAY [Assign VIP to FQDN in Grid Manager] *****************************************************************************************************************
TASK [set_fact] *******************************************************************************************************************************************
ok: [localhost]
TASK [Print next IP address] ******************************************************************************************************************************
ok: [localhost] => {
"msg": "The next available IP is 10.0.0.4"
}
PLAY RECAP ************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Any thoughts on why this variable isn't working would be much appreciated!
Parameter exclude is "List of IP's ...", but the filter join makes a string from the list
- set_fact:
formated_excludes: "{{ EXCLUDES |join(', ') }}"
Use the list EXCLUDES in the parameter
- set_fact:
VIP: "{{ lookup('nios_next_ip', '10.0.0.0/25', exclude=EXCLUDES) | first }}"

Unable to get value of a variable from another Play in Ansible

I wish to obtain the value of "fdet_APP" variable of Play 2 into Play 3.
Below is my playbook which case be used as a testcase:
- name: "Play 1"
hosts: localhost
tasks:
- add_host: name={{ item }}
groups=dest_nodes
ansible_user={{ USER }}
with_items: "{{ Dest_IP.split(',') }}"
- name: "Play 2"
hosts: dest_nodes
user: "{{ USER }}"
tasks:
- set_fact:
fdet_APP: "Yellow"
- name: "Play 3"
hosts: localhost
user: "{{ USER }}"
vars:
dbfiledet: "{{ hostvars['dest_nodes']['fdet_APP'] }}"
tasks:
- debug: msg="{{ dbfiledet.stdout }}"
I get the below error for my attempt:
playbook RUN command:
ansible-playbook variabletest.yml -e "USER=user1 Dest_IP=10.17.44.26,10.17.54.26"
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [Play 1]
TASK [Gathering Facts]
************************************************************************************************************************************** ok: [localhost]
TASK [add_host]
********************************************************************************************************************************************* changed: [localhost] => (item=10.17.44.26) changed: [localhost] =>
(item=10.17.54.26)
PLAY [Play 2]
TASK [Gathering Facts]
************************************************************************************************************************************** ok: [10.17.54.26] ok: [10.17.44.26]
TASK [set_fact]
********************************************************************************************************************************************* ok: [10.17.44.26] ok: [10.17.54.26]
PLAY [Play 3]
TASK [Gathering Facts]
************************************************************************************************************************************** ok: [localhost]
TASK [debug]
************************************************************************************************************************************************ fatal: [localhost]: FAILED! => {"msg": "The task includes an option
with an undefined variable. The error was: \"hostvars['dest_nodes']\"
is undefined\n\nThe error appears to be in 'variabletest.yml': line
36, column 6, but may\nbe elsewhere in the file depending on the exact
syntax problem.\n\nThe offending line appears to be:\n\n\n - debug:
msg=\"{{ dbfiledet.stdout }}\"\n ^ here\nWe could be wrong, but
this one looks like it might be an issue with\nmissing quotes. Always
quote template expression brackets when they\nstart a value. For
instance:\n\n with_items:\n - {{ foo }}\n\nShould be written
as:\n\n with_items:\n - \"{{ foo }}\"\n"}
PLAY RECAP
10.17.44.26 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.17.54.26 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 localhost
: ok=3 changed=1 unreachable=0 failed=1 skipped=0
rescued=0 ignored=0
I'm on the latest version of ansible and python 2.7.5
Can someone suggest what is wrong and how can i get the value for the variable in Play 3 please ?
hostvars are tied to a single Ansible managed host, not an inventory group. Try running debug: var=hostvars to see what I mean. In your case dest_nodes is an inventory group, not a host.
If just want to pull the variable from any host in the group, try:
- debug:
msg: "{{ hostvars[groups.dest_nodes|first]['fdet_APP'] }}"
If you are looking to parse the value for all hosts in the group, then you'll need to implement either a loop or a json_query filter