iterate over the hostname stored in var_files - ansible

I have two type of server host names added in the ansible main.yml var file:
main.yml file:
foo_server1: 10.10.1.1
foo_server2: 10.10.1.2
bar_server1: 192.168.1.3
bar_server2: 192.168.1.4
bar_server3: 192.168.1.5
I am having an ansible playbook which essentially runs on foo_server1 and initializes/formats all other servers in the list one at a time - starting with foo_server2 then bar_server1, bar_server2 and so on...
---
- name: Reading variables from var files
hosts: localhost
connection: local
vars_files:
- main.yml
tasks:
- name: Initialize foo server2
command: initialize --host1 {{foo_server1}} to --host2 {{foo_server2}}
- name: Initialize bar server1
command: initialize --host1 {{foo_server1}} to --host2 {{bar_server1}}
- name: Initialize bar server2
command: initialize --host1 {{foo_server1}} to --host2 {{bar_server2}}
- name: Initialize bar server3
command: initialize --host1 {{foo_server1}} to --host2 {{bar_server3}}
I dont want to add multiple lines in the playbook for each server rather wants to loop over the host names from the variable file. I am not sure how i would get this done..i am trying to loop over the hostname.. tried something below but no luck as i am getting undefined variable name..
---
server_list:
foo_server1: 10.10.1.1
foo_server2: 10.10.1.2
bar_server1: 192.168.1.3
bar_server2: 192.168.1.4
bar_server3: 192.168.1.5
Ansible playbook...
---
- hosts: localhost
gather_facts: no
vars_files:
- input.yml
tasks:
- name: Enable replication
local_action: shell initialize --host1 {{item.foo_server1}} --host2 {{item.foo_server2}}
with_items:
- "{{ server_list }}"
Can some one please suggest how can i run the same command on multiple servers. Would appreciate any help offered..

Here is an example for you:
---
- hosts: localhost
gather_facts: no
vars:
servers:
foo_server1: 10.10.1.1
foo_server2: 10.10.1.2
bar_server1: 192.168.1.3
bar_server2: 192.168.1.4
bar_server3: 192.168.1.5
tasks:
- debug:
msg: shell initialize --host1 {{ servers.foo_server1 }} --host2 {{ item.value }}
when: item.key != 'foo_server1'
with_dict: "{{ servers }}"

Related

ansible playbook: print custom message if hosts variable is not defined

The simple playbook
---
- name: NTP client
# hosts: all:!ntpserver
hosts: "{{ target_hosts }}"
roles:
- ntp_client
can be executed using
ansible-playbook -i hosts.yml -e target_hosts=<target host> <path to playbook> --ask-become-pass
This works just fine when target_hosts is set. In case target_hosts isn't set it obviously fails with
ERROR! The field 'hosts' has an invalid value, which includes an undefined variable. The error was: 'target_hosts' is undefined
How do I print a custom message such as
The variable 'target_hosts' is not set, use e.g. '-e target_hosts=all:!ntpserver'.
Note, I am aware that a default can be set via a hosts line like
hosts: "{{ target_hosts | default('all:!ntpserver') }}"
Add a localhost play for validating input arguments as given below. This will fail with a custom message if the 'target_hosts' var is not defined.
---
- name: Validate target_host variable
hosts: localhost
tasks:
- fail:
msg: The variable 'target_hosts' is not set, use e.g. '-e target_hosts=all:!ntpserver'.
when: target_hosts is not defined
- name: NTP client
# hosts: all:!ntpserver
hosts: "{{ target_hosts }}"
roles:
- ntp_client
Use the filter mandatory. For example,
- hosts: "{{ target_hosts|mandatory('The variable target_hosts is mandatory') }}"
Example of a complete playbook
shell> cat pb.yml
- hosts: "{{ target_hosts|mandatory(err001) }}"
vars:
err001: >-
The variable 'target_hosts' is not set,
use e.g. '-e target_hosts=all:!ntpserver'
tasks:
- debug:
msg: hello
gives
shell> ansible-playbook pb.yml
ERROR! The variable 'target_hosts' is not set, use e.g. '-e target_hosts=all:!ntpserver'

How to check the OS version of host which in dynamically added to inventory

I'm trying to get server name as user input and if the server OS is RHEL7 it will proceed for further tasks. I'm trying with hostvars but it is not helping, kindly help me to find the OS version with when condition:
---
- name: Add hosts
hosts: localhost
vars:
- username: test
password: test
vars_prompt:
- name: server1
prompt: Server_1 IP or hostname
private: no
- name: server2
prompt: Server_2 IP or hostname
private: no
tasks:
- add_host:
name: "{{ server1 }}"
groups:
- cluster_nodes
- primary
- management
ansible_user: "{{ username }}"
ansible_password: "{{ password}}"
- add_host:
name: "{{ server2 }}"
groups:
- cluster_nodes
- secondary
ansible_user: "{{ username }}"
ansible_password: "{{ password}}"
- debug:
msg: "{{ hostvars['server1'].ansible_distribution_major_version }}"
When I execute the playbook, I'm getting below error:
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: \"hostvars['server1']\" is undefined\n\nThe error appears to be in '/var/lib/awx/projects/pacemaker_RHEL_7_ST/main_2.yml': line 33, column 7, 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"}
You need to gather_facts on the newly added host before you consume the variable. As an example, this will do it with automatic facts gathering.
---
- name: Add hosts
hosts: localhost
vars:
- username: test
password: test
vars_prompt:
- name: server1
prompt: Server_1 IP or hostname
private: no
- name: server2
prompt: Server_2 IP or hostname
private: no
tasks:
- add_host:
name: "{{ server1 }}"
groups:
- cluster_nodes
- primary
- management
ansible_user: "{{ username }}"
ansible_password: "{{ password}}"
- add_host:
name: "{{ server2 }}"
groups:
- cluster_nodes
- secondary
ansible_user: "{{ username }}"
ansible_password: "{{ password}}"
- name: Gather facts for newly added targets
hosts: cluster_nodes
# gather_facts: true <= this is the default
- name: Do <whatever> targeting localhost again
hosts: localhost
gather_facts: false # already gathered in play1
tasks:
# Warning!! bad practice. Looping on a group usually
# shows you should have a play targeting that specific group
- debug:
msg: "OS version for {{ item }} is 7"
when: hostvars[item].ansible_distribution_major_version | int == 7
loop: "{{ groups['cluster_nodes'] }}"
If you don't want to rely on automatic gathering, you can manually play the setup module, e.g. for the second play:
- name: Gather facts for newly added targets
hosts: cluster_nodes
gather_facts: false
tasks:
- name: get facts from targets
setup:

Ansible vars_prompt for host list into Import_playbook

I want to use a specific host / host list for an imported playbook which I get from a vars_prompt input. How can I do this? So far I wasn´t able to get this running.
I have two playbooks which I need to run separately and ios_check_routerports.yaml is the parent playbook:
ios_check_routerports.yaml
---
- hosts: '{{ branch_number }}'
connection: network_cli
gather_facts: False
any_errors_fatal: no
throttle: 75
vars_prompt:
- name: "branch_number"
prompt: "Which branch do you want to check?"
default: all
private: no
tasks:
- name: Check facts
ios_facts:
gather_subset: hardware
- name: Create directory
file:
path: /root/ansible/pb-outputs/ios_check_routerports/
state: directory
delegate_to: 127.0.0.1
- name: Run playbook
import_playbook: ios_check_routerports_main.yaml
ios_check_routerports_main.yaml
---
- hosts: '{{ branch_number }}'
connection: network_cli
gather_facts: False
any_errors_fatal: no
throttle: 75
tasks:
- name: Check default-gateway
ios_command:
commands: sh run | i default-gateway
register: default_gateway
I tried to set a fact for the var {{ branch_number }} like this:
ios_check_routerports.yaml
- set_fact:
devices: "{{ branch_number }}"
ios_check_routerports_main.yaml
---
- hosts: '{{ devices }}'
connection: network_cli
The playbook always runs into an error because the hosts var is not defined. What am I doing wrong here?
try this: no need to create a new variable devices but a dummy host
in ios_check_routerports.yaml add a task:
- name: Register dummy host with variable
add_host:
name: "DUMMY_HOST"
DEVICES: "{{ branch_number }}"
then :
- hosts: "{{ hostvars['DUMMY_HOST']['DEVICES'] }}"
connection: network_cli
as you create a new host, i suggest you to delete it if you havent need the variable branch_number so remove_host doesnt exit:
either you do a first task - meta: refresh_inventory
or you modify your host like this:
- hosts: "{{ hostvars['DUMMY_HOST']['DEVICES'] }},!DUMMY_HOST"

How to use variables defined through vars_prompt of one host in another host vars?

I am having 2 plays in a playbook. One of them prompts for input from user and I want to use that variable in another play. Please suggest me how to do that
---
- hosts: workers
gather_facts: false
sudo: true
vars_prompt:
- name: "server_ip"
prompt: "Enter the Server IP"
private: no
roles:
- client-setup-worker
- hosts: master
gather_facts: false
sudo: true
vars:
server: "{{ hostvars['workers']['server_ip'] }}"
roles:
- client-setup-master
In the above playbook I want to use server_ip defined in workers hosts to be used in master hosts.
I am facing the error "The error was: \"hostvars['workers']\" is undefined" while doing so
I am facing the error "The error was: \"hostvars['workers']\" is undefined" while doing so
That's because workers is evidently a group, and not a host, which is the only thing one will find declared in hostvars
You'll need to grab one of the hosts at random from the workers group, and then extract its fact; I believe this will do that:
update after seeing the mostly correct answer by #VladimirBotka
- hosts: workers
vars_prompt:
# as before ...
pre_tasks:
- name: re-export the vars_prompt for cross playbook visibility
set_fact:
server_ip: '{{ server_ip }}'
roles:
# as before
- hosts: masters
vars:
server: '{{ hostvars[(groups.workers|first)].server_ip }}'
The scope of variables declared in vars_prompt is the play.
Such variable may be put into the hostvars by set_facts "to use that variable in another play". For example the play below
- hosts: test_01
gather_facts: false
vars_prompt:
- name: "server_ip"
prompt: "Enter the Server IP"
private: no
tasks:
- set_fact:
stored_server_ip: "{{ server_ip }}"
- debug:
var: stored_server_ip
- hosts: test_02
gather_facts: false
vars:
server: "{{ hostvars.test_01.stored_server_ip }}"
tasks:
- debug:
var: server
gives (abridged):
ok: [test_01] => {
"stored_server_ip": "10.1.0.10"
}
ok: [test_02] => {
"server": "10.1.0.10"
}

ansible does not read in variables when connected to another host

I have a playbook which reads in a list of variables:
vars_files:
- vars/myvariables.yml
tasks:
- name: Debug Variable List
debug:
msg: "An item: {{item}}"
with_list: "{{ myvariables }}"
This prints out the list of "myvariables" from a file variables.yml, which contains:
---
myvariables:
- variable1
- variable2
I get the following as expected.
"msg": "An item: variable1"
"msg": "An item: variable2"
However, when I connect to another host, and run the same Debug statement, it throws an error:
vars_files:
- vars/myvariables.yml
tasks:
- name: Configure instance(s)
hosts: launched
become: True
remote_user: ubuntu
port: 22
gather_facts: False
tasks:
- name: Wait for SSH to come up
delegate_to: ***
remote_user: ubuntu
connection: ssh
register: item
- name: Debug Variable List
debug:
msg: "An item: {{item}}"
with_list: "{{ myvariables }}"
OUTPUT:
"msg": "'myvariables' is undefined"
How do I define the variables file when connecting to another host that is not localhost?
Any help on this would be greatly appreciated.
With "hosts: launched" you started new playbook. Put the vars_files: into the scope of this playbook (see below).
- name: Configure instance(s)
hosts: launched
become: True
remote_user: ubuntu
port: 22
gather_facts: False
vars_files:
- vars/myvariables.yml
tasks:
Review the Scoping variables.

Resources