Ansible - Loop Variable - ansible

i'am trying to start application with a ansible playbook.
the variable inst got all the required software id's:
WEB
TS3
SQL
....
how can i create a loop for all the software id's and run the same command on all of them?
---
- name: "start sw"
become: yes
command: "swstart {{ inst }}"
retries: 3
failed_when: ( instance_start.rc not in [ 0 ] )

You should first of all define your list as a variable on your playbook .
After that you can use
with_items
Like that:
---
- hosts: all
remote_user: root
vars:
softwares:
- WEB
- TS3
- SQL
vars_files:
- /softwares.yml # if you need to import data from file
tasks:
- name: display your softwares using debug module
debug:
msg: "An item: {{ item }}"
with_items: "{{ softwares }}"
I hope that this can help you to fix your issue.

Use with_items as below
---
- name: "start sw"
become: yes
command: "swstart {{ item }}"
with_items: "{{ inst }}"
Documentation:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#with-items

Related

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

loop using with_sequence over with_subelement in ansible

I am trying to loop over a subelement variables using the a loop like with_sequence,
For the moment I have :
---
- hosts: corosync
gather_facts: no
vars:
host_list:
- node_one
- node_two
list_services:
- group: ALPHA
services:
- name: DHCP
directory: /etc/dhcp
- name: DNS
directory : /etc/dns
- group: BETA
services:
- name: SSH
directory: /etc/ssh
- name: FTP
directory: /ztc/ftp
tasks:
- name: create group-services
debug:
msg: "the service name is {{ item.0.group}}-{{ item.1.name}} , directory is {{ item.1.directory }}"
with_subelements:
- "{{ list_services }}"
- services
Since I have 2 nodes in my cluster
node_one
node_two
I want to deplucate each service like below :
{{ item.0.group}}-{{host_id}}-{{ item.1.name}}
with {{ host_id }} a list that equal ['0','1'] since I have 2 nodes
and the with_subelement function loop over the {{ host_id }} twice since we have two nodes, what gives :
ALPHA-0-DHCP
ALPHA-0-DNS
ALPHA-1-DHCP
ALPHA-1-DNS
BETA-0-SSH
BETA-0-FTP
BETA-1-SSH
BETA-1-FTP
I want to use something like with_sequence function beside with_subelement like
with_sequence: start=0, end={{ groups['host_list']|length}}
Any suggestions please
The loop declaration introduced in Ansible 2.5 makes it pretty straightforward ー you just need to combine the two patterns replacing legacy with_sequence and legacy with_subelements:
- name: create group-services
debug:
msg: "{{item.1.0.group}}-{{item.0}}-{{item.1.1.name}}"
loop: "{{ range(0, host_list|length) | product(list_services|subelements('services')) | list }}"

How to pass results back from include_tasks

Started to learn ansible yesterday, so I believe I may risk XY problem here, but still…
The main yml:
- hosts: localhost
vars_files:
[ "users.yml" ]
tasks:
- name: manage instances
#include_tasks: create_instance.yml
include_tasks: inhabit_instance.yml
with_dict: "{{users}}"
register: res
- name: print
debug: msg="{{res.results}}"
inhabit_instance.yml:
- name: Get instance info for {{ item.key }}
ec2_instance_facts:
profile: henryaws
filters:
"tag:name": "{{item.key}}"
instance-state-name: running
register: ec2
- name: print
debug:
msg: "IP: {{ec2.instances.0.public_ip_address}}"
So that's that IP that I'd like to have on the top level. Haven't found anything right away about return values of the include block…
Well, I've found some way that suits me, maybe it's even canonical?
main.yml:
- hosts: localhost
vars_files:
[ "users.yml" ]
vars:
ec_results: {}
tasks:
- name: manage instances
#include_tasks: create_instance.yml
include_tasks: inhabit_instance.yml
with_dict: "{{users}}"
register: res
inhabit_instance.yml:
- name: Get instance info for {{ item.key }}
ec2_instance_facts:
profile: henryaws
filters:
"tag:name": "{{item.key}}"
instance-state-name: running
register: ec2
- name: update
set_fact:
ec_results: "{{ ec_results|combine({ item.key: ec2.instances.0.public_ip_address }) }}"
Thanks for you answer - this helped me to find an answer to my issue when my task was called in a loop - my solution was just to use lists so for your example above, the solution would be:
The main yml:
- hosts: localhost
vars_files:
[ "users.yml" ]
vars:
ec_results: []
tasks:
- name: manage instances
#include_tasks: create_instance.yml
include_tasks: inhabit_instance.yml
with_dict: "{{users}}"
- name: print
debug: msg="{{ec_results}}"
inhabit_instance.yml:
- name: Get instance info for {{ item.key }}
ec2_instance_facts:
profile: henryaws
filters:
"tag:name": "{{item.key}}"
instance-state-name: running
register: ec2
- name: Add IP to results
set_fact:
ec_results: "{{ ec_results + [ec2.instances.0.public_ip_address] }}"
In my code, include_tasks was in a loop so then ec_results contained a list of the results from each iteration of the loop

Assign item to a var with_items in ansible

I am trying to create a playbook to find out on which openstack server vm is running on. I have created a list of openstack servers in vars and used delegate_to with with_items to iterate through until find vm. I am using wc -l at the end of command and 1 will be success. The aim is, once os-server is found, store servername into a var so this can be used for rest of tasks in playbook. I am unable to get the os server name in a var from the list. I am not an ansible expert. Can anyone help to achieve this? Thanks
- hosts: localhost
vars:
openstack:
- reg1
- reg2
- reg3
- reg4
tasks:
- name: Command to find os server where vm exists
shell: somecommand-to-check-if-vm-exist | wc -l
delegate_to: "{{ item }}"
with_items: "{{ openstack }}"
register: found_server
retries: 1
delay: 1
until: found_server.stdout != "1"
- debug: var=found_server
- name: set fact
set_fact: os-server = "{{ item.item }}"
when: item.stdout == "1"
with_items: "{{ found_server.results }}"
register: var2
- name: debug var
debug: var=var2
- debug: var=os-server
There's no need to retry/until here and for the second loop as well.
Try this:
- hosts: localhost
vars:
openstack: [reg1, reg2, reg3, reg4]
tasks:
- name: Command to find os server where vm exists
shell: somecommand-to-check-if-vm-exist | wc -l
delegate_to: "{{ item }}"
with_items: "{{ openstack }}"
register: vm_check
- name: set fact
set_fact:
os_server: "{{ (vm_check.results | selectattr('stdout','equalto','1') | list | first).item }}"
- name: debug var
debug:
msg: "{{ os_server }}"
This will register results from every server into vm_check.results, and then just select elements with stdout set to 1, take first element of it it (I suppose you always have one server with VM), and get .item of this element which contains the item of original loop (in our case it is server's name).

Return Variable from Included Ansible Playbook

I have seen how to register variables within tasks in an ansible playbook and then use those variables elsewhere in the same playbook, but can you register a variable in an included playbook and then access those variables back in the original playbook?
Here is what I am trying to accomplish:
This is my main playbook:
- include: sub-playbook.yml job_url="http://some-jenkins-job"
- hosts: localhost
roles:
- some_role
sub-playbook.yml:
---
- hosts: localhost
tasks:
- name: Collect info from Jenkins Job
script: whatever.py --url "{{ job_url }}"
register: jenkins_artifacts
I'd like to be able to access the jenkins_artifacts results back in main_playbook if possible. I know you can access it from other hosts in the same playbook like this: "{{ hostvars['localhost']['jenkins_artifacts'].stdout_lines }}"
Is it the same idea for sharing across playbooks?
I'm confused what this question is about. Just use the variable name jenkins_artifacts:
- include: sub-playbook.yml job_url="http://some-jenkins-job"
- hosts: localhost
debug:
var: jenkins_artifacts
This might seem complicated but I love doing this in my Playbooks:
rc defines the name of the variable which contains the return value
ar gives the arguments to the include tasks
master.yml:
- name: verify_os
include_tasks: "verify_os/main.yml"
vars:
verify_os:
rc: "isos_present"
ar:
image: "{{ os.ar.to_os }}"
verify_os/main.yml:
---
- name: check image on device
ios_command:
commands:
- "sh bootflash: | inc {{ verify_os.ar.image }}"
register: image_check
- name: check if available
shell: "printf '{{ image_check.stdout_lines[0][0] }}\n' | grep {{ verify_os.ar.image }} | wc -l"
register: image_available
delegate_to: localhost
- set_fact: { "{{ verify_os.rc }}": "{{ true if image_available.stdout == '1' else false }}" }
...
I can now use the isos_present variable anywhere in the master.yml to access the returned value.

Resources