If condition is true run some include yml files - ansible

I have some playbook for ubuntu and centos and I want to use main.yml to check when: ansible_os_family == 'RedHat' or ansible_distribution == 'Centos', run playbooks ( as some ans many :-) ).
When I run just:
-include: centos-xxx.yml
-include: centos-xaa.yml
-include: centos-xsss.yml
It will run all of them
Basically I want that the playbook will run if meet condition.
I didn't find any doc that say how to run include: more then one i am trying to not make task per include if possible.

You can use the when conditional to include files. This is somewhat common, in fact.
- include: centos-xxx.yml
when: ansible_os_family == 'RedHat' or ansible_distribution == 'Centos'
- include: debian-xxx.yml
when: ansible_distribution == 'Debian'
Per your comment- if you want to run them in order, you have two options. Here's the straightforward:
- include: centos-a.yml
when: ansible_os_family == 'RedHat' or ansible_distribution == 'Centos'
- include: centos-b.yml
when: ansible_os_family == 'RedHat' or ansible_distribution == 'Centos'
- include: centos-c.yml
when: ansible_os_family == 'RedHat' or ansible_distribution == 'Centos'
- include: centos-d.yml
when: ansible_os_family == 'RedHat' or ansible_distribution == 'Centos'
Or, you can do this:
- include: centos.yml
when: ansible_os_family == 'RedHat' or ansible_distribution == 'Centos'
and inside centos.yml:
- include: centos-a.yml
- include: centos-b.yml
- include: centos-c.yml
- include: centos-d.yml

Related

Ansible: Task control

I am working with Ansible and familiarizing myself with task control in a playbook. I am struggling with the fail module and fail_when statement. Here is a lab I worked on, which seems to work, but I would like to see how this could be handled using the fail module or fail_when, IF it is needed.
Here is the task I struggled with:
Install packages only if the current operating system is CentOS or RHEL version 8 or later. If that is not the case, the playbook should fail with the error message "Host hostname does not meet the minimal requirements", where hostname is replaced with the current host name.
Here are my issues:
Using ansible_facts in the fail module does not workout well it seems
I do not understand how I would use fail_when on this task
Here is my solution:
---
- name: Install packages
hosts: all
vars_files:
vars/pack.yml
tasks:
- name: Install packages
block:
- name: Install packages and loop
yum:
name: "{{ item.package }}"
state: "{{ item.state }}"
loop: "{{ packages }}"
when:
( ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_version'] == "8" )
or
( ansible_facts['distribution'] == "RedHat" and ansible_facts['distribution_version'] >= "8.1" )
- name: Copy file to /tmp
copy:
content: "Welcome to my webserver"
dest: /tmp/index.html
notify: restart web
- name: Check for firewalld
yum:
name: firewalld
state: latest
- name: verify firewalld is started
service:
name: firewalld
state: started
- name: open firewall ports for http and https
firewalld:
service: "{{ item.service }}"
state: "{{ item.state }}"
immediate: yes
permanent: yes
loop: "{{ firewall }}"
rescue:
- name: fail if any task fail
fail:
msg: did not meet the requirements
handlers:
- name: restart web
service:
name: httpd
state: restarted
I am using the RHCE exam book by Sander Van Vugt btw. This is lab 7-1. His Github is a bit lacking on the labs.
Here is the better optimized playbook:
---
- name: End of chapter lab 7 final
hosts: all
become: true
vars_files:
- vars/pack.yml
tasks:
- name: Install httpd and mod_ssl packages
yum:
name: "{{ item.package }}"
state: "{{ item.state }}"
loop: "{{ packages }}"
when:
( ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_version'] <= "8" )
or
( ansible_facts['distribution'] == "RedHat" and ansible_facts['distribution_version'] <= "8" )
- name: Fail if the following is not met
fail:
msg: "Host {{ ansible_facts['hostname'] }} does not meet the minimal requirements"
when:
not (( ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_version'] <= "8" )
or
( ansible_facts['distribution'] == "RedHat" and ansible_facts['distribution_version'] <= "8" ))
- name: Copy tmp file
copy:
content: "Welcome to my webserver"
dest: /tmp/index.html
- name: Configure Firewalld for http and https rules
firewalld:
service: "{{ item.service }}"
state: "{{ item.state }}"
immediate: yes
permanent: yes
loop: "{{ firewall }}"
Use the fail module to stop the script with a custom error message. In your case you could use it like this:
- name: fail if wrong OS
fail:
msg: "Wrong OS: {{ansible_facts['distribution']}}"
when: not (( ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_version'] == "8" )
or
( ansible_facts['distribution'] == "RedHat" and ansible_facts['distribution_version'] >= "8.1" ))
Whereas the failed_when can be used to define when some behaviour is to be considered a failure. No custom error message possible. Use it like this:
- name: check if file exists and fail if it does
stat:
path: /etc/hosts
register: result
failed_when: result.stat.exists
In your above script you used when. This one executes the task if the when expression is true, or it skips the task if the when expression is false. But it would not stop the script execution.

skip the ansible role and move to next one if that server joined to AD already otherwise execute current role

If my ansible task reports the server join the domain already,it should move to next role and if not it should move with the domain join role.
root#ghepoc:/home/hasabd# wbinfo -t
checking the trust secret for domain TESTDEV via RPC calls succeeded
If the above command shows succeeded then should move to next role otherwise execute the current role.
---
- name: "Check domain status"
command: "wbinfo -t"
register: "domain"
ignore_errors: True
- name: AD join status
debug:
msg: "{{ domain.stdout }}"
when: "domain.rc == 0"
- name: Include OS-specific variables.
include_vars: "{{ ansible_os_family }}.yml"
- include: setup-RedHat.yml
when: ansible_os_family == 'RedHat'
- include: setup-Debian.yml
when: ansible_os_family == 'Debian'
- include: config-RedHat.yml
when:
- ad_create_config | bool
- ansible_os_family == 'RedHat'
- include: config-Debian.yml
when:
- ad_create_config | bool
- ansible_os_family == 'Debian'
I can see "failed_when" option. Is there anyway we can mention, if we domain.rc = o skip this role or otherwise

Run Ansible task on SUSE machines only

I want to execute my Ansible task only on a specific SUSE version. But this task gets executed for all Linux OS flavors. Which is not expected. Can someone help me with this? Why is the when condition not working? What I am doing wrong?
Code:
# Action 146: addlink ld-lsb.so.3->ld-2.11.1.so in /lib on sles11.x,12.x for lmutil in cct2000739233
- name: Addlink ld-lsb.so.3->ld-2.11.1.so in /lib on sles11.x,12.x for lmutil
shell: "ls ld-*.so|grep -v lsb|head -n 1"
args:
chdir: /lib
register: ldso
- stat:
path: /lib64/ld-lsb-x86-64.so.3
register: lib64_result
- stat:
path: /lib/ld-lsb.so.3
register: lib_result
- block:
- file:
src: "/lib/{{ ldso.stdout }}"
dest: /lib/ld-lsb.so.3
state: link
force: true
- file:
src: /lib64/ld-linux-x86-64.so.2
dest: /lib64/ld-lsb-x86-64.so.3
state: link
force: true
when:
# Check the OS level. Make sure it runs only on SLES-11 SP4,SLES-12SP0/1/2/3
- ansible_distribution == 'Suse'
- ansible_distribution_major_version == "11"
- ansible_distribution_release == "4"
- ansible_distribution_version == "11.4"
- ansible_distribution == 'SLES'
- ansible_distribution_major_version == "12"
- ansible_distribution_release == "0" or "1" or "2" or "3"
- ansible_distribution_version == "12.0" or "12.1" or "12.2" or "12.3"
- not lib64_result.stat.exists|bool or not lib_result.stat.exists|bool
- ldso.stdout != ''
- debug:
msg: "{{ ldso.stdout }}"
Cannot do or like that. Has to be like this:
- ansible_distribution_release == "0" or ansible_distribution_release == "1" or ansible_distribution_release == "2" or ansible_distribution_release == "3"
- ansible_distribution_version == "12.0" or ansible_distribution_version == "12.1" or ansible_distribution_version == "12.2" or ansible_distribution_version == "12.3"
The way you have it, ansible_distribution_release == "0" or "1", ansible_distribution_release == "0" evaluates to false, that's fine, but then "1" evaluates to true. false or true then evaluates to true.

Invoke multiple roles in Ansible with where condition

Is there a possibility to invoke roles depends on the when condition OR may be use Ansible handlers?
I have a below playbook which gets the current status of deployment on remote host and if and only required then perform the next steps. Below is the validation.yml from validations role (1st one to invoke) which does the validations -
---
- name: Getting the status of current deployment
stat:
path: "{{ tomcat_symlink_path }}"
register: p
- set_fact:
current_release: "{{ p.stat.lnk_target.split('/')[4] | regex_replace('^Release(.*)$', '\\1') }}"
- debug:
msg: "The currently deployed release is : {{ p.stat.lnk_target.split('/')[4] | regex_replace('^Release(.*)$', '\\1') }}"
- name: Copying Application Configuration files and get the checksum
template:
src: "{{ item }}"
dest: "{{config_location}}/{{ item | basename | regex_replace('.j2$', '') }}"
mode: 0755
with_fileglob:
- /temp/env/*.j2
register: config_var
- block:
- name: "Exit the deployment if no changes required...."
debug:
msg: "Target Release and currently deployed release is same OR no configuration changed required.. so Exiting the Deployment!!!!"
- meta: end_play
when: myvm_release_version == current_release and config_var.changed == false
Now depends on the above 2 variables. I need to invoke roles. For example -
if config_var.changed == true and myvm_release_version == current_release then invoke only roles stoptomcat and starttomcat and exit the deployment because it is just the config change so only restart tomcat is required.
if only config_var.changed == false and myvm_release_version != current_release then continue with the playbook which will execute everything and all the roles
This may be a weird requirement but may be someone expert can throw some light on it.
It's a common requirement
You can include role with when condition as simple as following..
Solution: 1
you can not refer two of more than two task with when condition, only one task is allowed,
simple hack can be include a external playbook In that conditional task.
Solution: 2
Your Ansible code till "register: config_var"
- name: include conditional role
include_role: "{{item}}"
when: config_var.changed == true and myvm_release_version == current_release
with_items:
- "stoptomcat"
- 'starttomcat"
- name: block of code
block:
// conditional ansible tasks
when: config_var.changed == false and myvm_release_version != current_release
I was able to find a solution as below using meta
- block:
- name: "Doing Configuration Changes...."
include_role:
name: '{{ roleinputvar }}'
loop:
- stoptomcat
- starttomcat
loop_control:
loop_var: roleinputvar
- meta: end_play
when: config_var.changed == true and myvm_release_version == current_release
Just posting so it might help others.

Ansible to register to a dictionary or dynamic variable for several tasks

In Ansible I have two separate tasks to get the list of existing services for redhat 6 and 7, they register to a variable, then I have another task that stops those services, if I use the same variable it gets overwritten by the last task, so it does not stop anything.
Is there a way of distinguishing between the two results? and yet only use one task to stop the services? I tried dynamic var names or creating a dictionary, but none work.
thanks
- name: Get registered services
command: bash -c "chkconfig --list | awk '{print $1}'"
register: loaded_services_{{ansible_distribution_major_version}}
when: (( ansible_os_family == "RedHat" ) and ( ansible_distribution_major_version == "6" ))
changed_when: False
tags: test
- name: Get registered services
command: bash -c "systemctl list-unit-files | grep enabled | cut -d. -f1"
register: loaded_services_{{ansible_distribution_major_version}}
when: (( ansible_os_family == "RedHat" ) and ( ansible_distribution_major_version == "7" ))
changed_when: False
tags: test
- name: shutdown unnecessary services
service: name={{ item }} enabled=no state=stopped
with_items: "{{ disable_services | intersect(loaded_services_{{ansible_distribution_major_version}}.stdout_lines)}}"
when: ansible_os_family == "RedHat" and ansible_distribution_major_version == "6"
tags:
- harden
- test
ignore_errors: yes
Try with blocks, first in this way:
- block:
- name: Get registered services
command: bash -c "chkconfig --list | awk '{print $1}'"
register: loaded_services
changed_when: False
tags: test
when: (( ansible_os_family == "RedHat" ) and ( ansible_distribution_major_version == "6" ))
- block:
- name: Get registered services
command: bash -c "systemctl list-unit-files | grep enabled | cut -d. -f1"
register: loaded_services
changed_when: False
tags: test
when: (( ansible_os_family == "RedHat" ) and ( ansible_distribution_major_version == "7" ))
- name: shutdown unnecessary services
service: name={{ item }} enabled=no state=stopped
with_items: "{{ disable_services | intersect(loaded_services.stdout_lines)}}"
when: ansible_os_family == "RedHat" and ansible_distribution_major_version == "6"
tags:
- harden
- test
ignore_errors: yes
And if doesn´t work, try in this other way:
- block:
- name: Get registered services
command: bash -c "chkconfig --list | awk '{print $1}'"
register: loaded_services
changed_when: False
tags: test
- name: shutdown unnecessary services
service: name={{ item }} enabled=no state=stopped
with_items: "{{ disable_services | intersect(loaded_services.stdout_lines)}}"
tags:
- harden
- test
ignore_errors: yes
when: (( ansible_os_family == "RedHat" ) and ( ansible_distribution_major_version == "6" ))
- block:
- name: Get registered services
command: bash -c "systemctl list-unit-files | grep enabled | cut -d. -f1"
register: loaded_services
changed_when: False
tags: test
- name: shutdown unnecessary services
service: name={{ item }} enabled=no state=stopped
with_items: "{{ disable_services | intersect(loaded_services.stdout_lines)}}"
tags:
- harden
- test
ignore_errors: yes
when: (( ansible_os_family == "RedHat" ) and ( ansible_distribution_major_version == "7" ))

Resources