how to run multiple items using variables - ansible

I am trying to call port. But it is taking as array as two values instead of one.
Example:
cmd: nc -z msgq0003.svc.ops.wd5.wd ['2181', '5674']
Instead of:
nc -z servername 2181
This is my ansible palybook:
become: true
gather_facts: false
name: "Check all port numbers are accessible from current host"
hosts: ops-mgmt-aod,ops-mgmt-ots
vars:
server: "{{ groups['mgmt-server'] }}"
port: "{{ groups['mgmt-port'] }}"
tasks:
- name: network connection for zookeeper
shell: "nc -z {{ item }} {{ port }}"
with_items:
- "{{ server }}"
register: network_reachable_zoo
- debug: msg={{network_reachable_zoo}}

Related

Create Local File With Ansible Template From Variables

I'm running an ansible playbook against a number of ec2 instances to check if a directory exists.
---
- hosts: all
become: true
tasks:
- name: Check if foo is installed
stat:
path:
/etc/foo
register: path
- debug: msg="{{path.stat.exists}}"
And I would like to generate a localfile that lists the private IP addresses of the ec2 instances and states whether or not the directory foo does exist.
I can get the private IP addresses of the instances with this task
- name: Get info from remote
shell: curl http://169.254.169.254/latest/meta-data/local-ipv4
register: bar
- debug: msg="{{bar.stdout}}"
How do I create a local file with content
IP address: 10.100.0.151 directory foo - false
IP address: 10.100.0.152 directory foo - true
I've tried adding a block for this as such
- hosts: localhost
become: false
vars:
installed: "{{bar.stdout}}"
status: "{{path.stat.exists}}"
local_file: "./Report.txt"
tasks:
- name: Create local file with info
copy:
dest: "{{ local_file }}"
content: |
"IP address {{ installed }} foo - {{ status }}"
But it doesn't look like I can read values of variables from earlier steps.
What am I doing wrong please?
A similar question has been answered here.
Basically what you want is to reference it through the host var variable.
This should work.
- hosts: localhost
become: false
vars:
local_file: "./Report.txt"
tasks:
- name: Create local file with info
lineinfile:
path: "{{ local_file }}"
line:
"IP Address: {{ hostvars[item]['bar'].stdout }} - Installed: {{ hostvars[item]['path'].stat.exists }}"
with_items: "{{ query('inventory_hostnames', 'all') }}"
And this should populate your local ./Report.txt file, with the info you need.
I've used the ec2_metadata_facts module to get the IP address us ingansible_ec2_local_ipv4
I've also created the directory /tmp/testdir on the second host.
- hosts: test_hosts
gather_facts: no
vars:
directory_name: /tmp/testdir
tasks:
- ec2_metadata_facts:
- name: check if directory '{{ directory_name }}' exsists
stat:
path: "{{ directory_name }}"
register: path
# I make the outputfile empty
# because the module lineinfile(as I know) can't overwrite a file
# but appends line to the old content
- name: create empty output file
copy:
content: ""
dest: outputfile
delegate_to: localhost
- name: write output to outputfile
lineinfile:
dest: outputfile
line: "IP Address: {{ ansible_ec2_local_ipv4 }} {{ directory_name }} - {{ path.stat.exists }}"
state: present
with_items: "{{ groups.all }}"
# with_items: "{{ ansible_play_hosts }}" can also be used here
delegate_to: localhost
The outputfile looks like:
IP Address: xxx.xx.x.133 /tmp/testdir - False
IP Address: xxx.xx.x.45 /tmp/testdir - True

Ansible playbook to check connectivity to windows host and report status

I am trying to put together a playbook that will connect to hosts and report back if the connection was successful or not. The result of the connection check should be stored in a variable. I had a crack at this by using the ansible facts, however I cannot workout how to handle unsuccessful connections to hosts.
---
- name: Set Facts variables
set_fact:
server_domain: "{{ ansible_domain}}"
server_ip: "{{ ansible_ip_addresses[1] }}"
- name: Set PowerShell parameters
set_fact:
ps_params: '-server_ip "{{ ansible_ip_addresses[1] }}" -server_domain "{{ ansible_domain }}"'
- name: Execute Script
win_shell: "powershell.exe -file \\PSfile.ps1 {{ps_params}}"
Try this:
---
- hosts: all
gather_facts: yes
ignore_errors: true
ignore_unreachable: true
vars:
# email_file The filename to attach to the email
# email_recipient email address to send the email to
# email_subject text to appear in the subject line
email_subject: "Windows Server Connection Report for {{ awx_inventory_name }}"
email_file: ./failed_connect_report.csv
ansible_port: 5985
tasks:
- name: Write header and ensure the email file exists
lineinfile:
path: "{{ email_file }}"
line: 'VM Name,IP Address,Distribution,Port,Note,Port,Note'
state: present
mode: '0774'
create: yes
insertafter: EOF
become: no
delegate_to: localhost
run_once: True
when: email_recipient != ''
- name: Test connectivity to port {{ ansible_port }}
win_ping:
register: result
- name: Did we fail to talk to this host?
block:
- set_fact:
ip_addresses: "unknown"
- set_fact:
distribution: "unknown"
- name: Did we fail to talk to this host?
set_fact:
line1: "{{ inventory_hostname }},{{ ip_addresses }},{{ distribution }},{{ ansible_port }},FAILED - {{ result.msg | replace(',',' ') }}"
delegate_to: localhost
- set_fact:
failed1: "True"
when: ((result.unreachable is defined and
result.unreachable == True) or
(result.failed is defined and
result.failed == True)) and
email_recipient != ''
- name: Log the success
set_fact:
line1: "{{ inventory_hostname }},{{ ansible_facts.ip_addresses.0 }},{{ ansible_facts.distribution }},{{ ansible_port }},SUCCESS"
delegate_to: localhost
when: (failed1 is not defined) and
email_recipient != ''

How to change and use a global variable for each host in Ansible?

I am trying to write a playbook to setup mysql master-slave replication with multiple slave servers. For each slave server, I need access to a variable called next_id that should be incremented before use for each host. For example, for the first slave server, next_id should be 2 and for the second slave server it should be 3 and so on. What is the way to achieve this in Ansible?
This is the yaml file I use to run my role.
- name: Setup the environment
hosts: master , slave_hosts
serial: 1
roles:
- setup-master-slave
vars:
master_ip_address : "188.66.192.11"
slave_ip_list :
- "188.66.192.17"
- "188.66.192.22"
This is the yaml file where I use the variable.
- name: Replace conf file with template
template:
src: masterslave.j2
dest: /etc/mysql/mariadb.conf.d/50-server.cnf
when: inventory_hostname != 'master'
vars:
- ip_address : "{{ master_ip_address }}"
- server_id : "{{ next_id }}"
I can suggest a way which will work according to you requirement for any number of slave servers but it is not based on any any module but self conscience.
Here my master_ip_address is 10.x.x.x and input is any value of next_id you want to increment for every slave server
- hosts: master,slave1,slave2,slave3,slave4
serial: 1
gather_facts: no
tasks:
- shell: echo "{{ input }}" > yes.txt
delegate_to: localhost
when: inventory_hostname == '10.x.x.x'
- shell: cat yes.txt
register: var
delegate_to: localhost
when: inventory_hostname != '10.x.x.x'
- shell: echo "$(({{var.stdout}}+1))"
register: next_id
delegate_to: localhost
when: inventory_hostname != '10.x.x.x'
- shell: echo "{{ next_id.stdout }}" > yes.txt
delegate_to: localhost
when: inventory_hostname != '10.x.x.x'
- name: Replace conf file with template
template:
src: masterslave.j2
dest: 50-server.cnf
when: inventory_hostname != '10.x.x.x'
vars:
- ip_address : "{{ master_ip_address }}"
- server_id : "{{ next_id.stdout }}"
[ansibleserver#172 test_increment]$ cat masterslave.j2
- {{ ip_address }}
- {{ server_id }}
Now, if you run
ansible-playbook increment.yml -e 'master_ip_address=10.x.x.x input=1'
slave1 server
[root#slave1 ~]# cat 50-server.cnf
- 10.x.x.x
- 2
slave2 server
[root#slave2 ~]# cat 50-server.cnf
- 10.x.x.x
- 3
slave3 server
[root#slave3 ~]# cat 50-server.cnf
- 10.x.x.x
- 4
and so on
"serial" is available in a playbooks only and not working in roles
therefore, for fully automatic generation of server_id for MySQL in Ansible roles, you can use the following:
roles/my_role/defaults/main.yml
---
cluster_alias: test_cluster
mysql_server_id_config: "settings/mysql/{{ cluster_alias }}/server_id.ini"
roles/my_role/tasks/server-id.yml
---
- name: Ensures '{{ mysql_server_id_config | dirname }}' dir exists
file:
path: '{{ mysql_server_id_config | dirname }}'
state: directory
owner: root
group: root
mode: 0755
delegate_to: localhost
- name: Ensure mysql server id config file exists
copy:
content: "0"
dest: "{{ mysql_server_id_config }}"
force: no
owner: root
mode: '0755'
delegate_to: localhost
- name: server-id
include_tasks: server-id-tasks.yml
when: inventory_hostname == item
with_items: "{{ ansible_play_hosts }}"
tags:
- server-id
roles/my_role/tasks/server-id-tasks.yml
# tasks file
---
- name: get last server id
shell: >
cat "{{ mysql_server_id_config }}"
register: _last_mysql_server_id
check_mode: no
delegate_to: localhost
tags:
- server-id
- name: get new server id
shell: >
echo "$(({{_last_mysql_server_id.stdout}}+1))"
register: _new_mysql_server_id
check_mode: no
delegate_to: localhost
tags:
- server-id
- name: save new server id
shell: >
echo -n "{{ _new_mysql_server_id.stdout }}" > "{{ mysql_server_id_config }}"
check_mode: no
delegate_to: localhost
tags:
- server-id
- debug:
var: _new_mysql_server_id.stdout
tags:
- server-id
- name: Replace conf file with template
template:
src: server-id.j2
dest: server-id.cnf

How to set fact witch is visible on all hosts in Ansible role

I'm setting fact in a role:
- name: Check if manager already configured
shell: >
docker info | perl -ne 'print "$1" if /Swarm: (\w+)/'
register: swarm_status
- name: Init cluster
shell: >-
docker swarm init
--advertise-addr "{{ ansible_default_ipv4.address }}"
when: "'active' not in swarm_status.stdout_lines"
- name: Get worker token
shell: docker swarm join-token -q worker
register: worker_token_result
- set_fact:
worker_token: "{{ worker_token_result.stdout }}"
Then I want to access worker_token on another hosts. Here's my main playbook, the fact is defined in the swarm-master role
- hosts: swarm_cluster
become: yes
roles:
- docker
- hosts: swarm_cluster:&manager
become: yes
roles:
- swarm-master
- hosts: swarm_cluster:&node
become: yes
tasks:
- debug:
msg: "{{ worker_token }}"
I'm getting undefined variable. How to make it visible globally?
Of course it works perfectly if I run debug on the same host.
if your goal is just to access worker_token from on another host, you can use hostvars variable and iterate through the group where you've defined your variable like this:
- hosts: swarm_cluster:&node
tasks:
- debug:
msg: "{{ hostvars[item]['worker_token'] }}"
with_items: "{{ groups['manager'] }}"
If your goal is to define the variable globally, you can add a step to define a variable on all hosts like this:
- hosts: all
tasks:
- set_fact:
worker_token_global: "{{ hostvars[item]['worker_token'] }}"
with_items: "{{ groups['manager'] }}"
- hosts: swarm_cluster:&node
tasks:
- debug:
var: worker_token_global

item from list of nodes depend on current index of host from hostgroup

I am having below setup,
groups_var/all.yml
---
cassandra_restore:
nodes:
- 192.168.0.1
- 192.168.0.2
- 192.168.0.3
inventory contains,
[just_created]
192.168.0.4
192.168.0.5
192.168.0.6
main.yml
---
# playbook
- name: setup
hosts: just_created
remote_user: ubuntu
become: true
become_method: sudo
gather_facts: yes
vars:
current_index: "{{ ansible_play_batch.index(inventory_hostname) }}"
tasks:
- debug:
msg: "current host index: {{ ansible_play_batch.index(inventory_hostname) }} : {{ current_index }}"
- debug:
msg: "first target host: {{ cassandra_restore.nodes.0 }}"
- name: get mapped value
debug:
msg: "current target host: {{ cassandra_restore.nodes.current_index }} "
I want to access item from list of nodes depend on current index of host from hostgroup just_created.
So when the host is 192.168.0.4 it should print 192.168.0.1 and when host is 192.168.0.5 it should print 192.168.0.2 and so on.
How can I achieve this?
You have to use the map form to access with a dynamic index or key:
- name: get mapped value
debug:
msg: "current target host: {{ cassandra_restore.nodes[current_index] }} "
But I'm not sure the order of the hosts is deterministic.
---
# playbook for creating cassandra setup
- name: setup cassnadra
hosts: just_created
remote_user: ubuntu
become: true
become_method: sudo
gather_facts: yes
vars:
current_index: "{{ ansible_play_batch.index(inventory_hostname) }}"
tasks:
- name: get mapped value
debug:
msg: "current_index current target host: {{ item.index }} : {{ item.host }} : {{ current_index }} "
when: current_index == item.index
with_items:
- "{{ cassandra_restore }}"
I got this working with following variables,
cassandra_restore:
- { index: "0", host: 192.168.0.1 }
- { index: "1", host: 192.168.0.2 }
- { index: "2", host: 192.168.0.3 }

Resources