Ansible recursive checks in playbooks - ansible

We need to go through this structure
Zone spec
https://gist.github.com/git001/9230f041aaa34d22ec82eb17d444550c
I was able to run the following snipplet but now I'm stucked at the error checking.
playbook
--
- hosts: all
gather_facts: no
vars_files:
- "../doc/application-zone-spec.yml"
roles:
- { role: ingress_add, customers: "{{ application_zone_spec }}" }
role
- name: check if router exists
shell: "oc get dc -n default {{ customers.zone_name }}-{{ item.type }}"
with_items: "{{ customers.ingress }}"
ignore_errors: True
register: check_router
- name: Print ingress hostnames
debug: var=check_router
- name: create new router
shell: "echo 'I will create a router'"
with_items: "{{ customers.ingress }}"
when: check_router.rc == 1
Output of a ansible run
https://gist.github.com/git001/dab97d7d12a53edfcf2a69647ad543b7
The problem is that I need to go through the ingress items and I need to map the error of the differnt types from the "check_router" register.
It would be nice to make something like.
Pseudo code.
Iterate through the "customers.ingress"
check in "check_router" if the rc is ! 0
execute command.
We use.
ansible-playbook --version
ansible-playbook 2.1.0.0
config file = /etc/ansible/ansible.cfg
configured module search path = Default w/o overrides

You can replace the second loop with:
- name: create new router
shell: "echo 'I will create a router with type {{ item.item }}'"
with_items: "{{ check_router.results }}"
when: item.rc == 1
This will iterate over every step of check_route loop and you can access original items via item.item.

Related

How to pass variable value from command parameter and use it in with_items:?

For me the below code is working -
with_items: "{{ groups['mlpoc'] }}" but instead of hardcoded mlpoc I want to pass it in a variable as a parameter.
Say the command parameter is mlhosts=mlpoc and I want to use the variable instead of hardcoded value, something like -
with_items: "{{ groups['{{ mlhosts }}'] }}" but it throws error. Is it even possible to pass a dynamic value to groups ?
Here is my code -
- hosts: dbsrd3510
user: '{{ mluser }}'
gather_facts: no
no_log: false
tasks:
- name: Fetch source list from clients
with_items: "{{ groups['mlpoc'] }}"
shell: rsync -av /MLbackup/{{ pkg }} {{ mluser }}#{{ item }}:/tmp/
Try something like this,
---
- hosts: all
gather_facts: no
tasks:
- name: Add a line to a file if the file does not exist, without passing regexp
debug:
msg: "{{ item }}"
with_items: " {{ groups[group_name] }} "
And you can test the above changes using,
ansible-playbook -i hosts main.yml -e group_name="all"

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.

Iterate over a array in with_items loop

Based on this question
Ansible recursive checks in playbooks
I have another one.
We need to go through this structure
Zone spec https://gist.github.com/git001/9230f041aaa34d22ec82eb17d444550c
Now I can adress the hostnames via the array index but can I also iterate over the array "hosts"?
playbook
--
- hosts: all
gather_facts: no
vars_files:
- "../doc/application-zone-spec.yml"
roles:
- { role: ingress_add, customers: "{{ application_zone_spec }}" }
role
- name: Print ingress hostnames
debug: msg="{{ item.hosts.0.hostname }} {{ item.hosts.1.hostname }}"
with_items: "{{ customers.ingress }}"
We use.
ansible-playbook --version
ansible-playbook 2.1.0.0
config file = /etc/ansible/ansible.cfg
configured module search path = Default w/o overrides
Use with_subelements:
- name: Print ingress hostnames
debug: msg="{{ item.0.type }} {{ item.1.hostname }}"
with_subelements:
- "{{ customers.ingress }}"
- "hosts"
There is quite a bit of examples for different loops in the Loops section of the documentation.

Ansible script is executing but loop is failing

I am trying to write a script (adduser.yml) to create users in a linux machine which imports users list from userlist.csv file. When I executed adduser.yml, the loop failed creating only 1st user. Can someone help me understand what mistake I am doing and how to correct it?
userlist.csv:
id,username,password,sudo
1,ansible1,ansible#123,yes
2,ansible2,ansible#123,no
3,ansible3,ansible#123,yes
4,ansible4,ansible#123,yes
adduser.yml:
---
## executed but until loop failed; check
- hosts: 192.168.0.3
vars:
count: "{{COUNT}}"
x: "1"
uname: "{{ lookup('csvfile', '{{x}} file=userlist.csv delimiter=, col=1') }}"
password: "{{ lookup('csvfile', '{{x}} file=userlist.csv delimiter=, col=2') }}"
sudo: "{{ lookup('csvfile', '{{x}} file=userlist.csv delimiter=, col=3') }}"
tasks:
name: "user add"
action:
- user:
x: "x+=1"
name: "{{ uname }}"
password: "{{ password }}"
state: present
register: x
until: "{{x > count}}"
name: "add to sudoers"
when: sudo == "yes"
lineinfile:
dest: /etc/sudoers
There are quite some things that will not work as you expected them. First thing, your loop is defined for your first task. That means only the user task will be repeated. Neither the sudo task nor the vars definition at the top will be looped. But don't try to re-define your loop, this is not going to work with vars.
Ansible has no build-in way to read vars from a csv file other than the csv lookup which will read exactly one line. But as said, you can not combine that with a loop.
I see two options you have:
Do not use csv. Ansible is mostly bound to yaml. If you'd had a yaml definition of your users, you simply could use the include_vars module to load these vars.
If you are bound to csv, you could try to use this includecsv module. (I have no experience with it and can not tell if it actually works)
Now, let's assume you have loaded your users into a list either from yaml or from csv with mentioned module. Then you'd simply loop with with_items:
tasks:
- name: "user add"
user:
name: "{{ item['uname'] }}"
password: "{{ item['password'] }}"
state: present
with_items: users_you_loaded
- name: "add to sudoers"
when: "{{ item['sudo'] }} == 'yes'"
...
with_items: users_you_loaded

Resources