Minimizing Conditionals in Ansible
2017-08-25
Ansible gives you conditionals to use when you want to check if something meets a certain criteria. However conditionals can become annoying if you need many include statements or repeat tasks based on facts. Here’s a way to minimize the need for them in the tasks themselves.
Let’s take Apache for example:
- name: install apache package: name: httpd state: installed when: ansible_distribution == 'CentOS'- name: install apache package: name: apache2 state: installed when: ansible_distribution == 'Ubuntu'
- name: install apache package: name: httpd state: installed when: ansible_distribution == 'CentOS'- name: install apache package: name: apache2 state: installed when: ansible_distribution == 'Ubuntu'
This can become annoying and hard to read when it’s all in one file. If you have a lot of these you can separate out specific .yml files to include a conditional:
- include: centos.yml when: ansible_distribution == 'CentOS'- include: ubuntu.yml when: ansible_distribution == 'Ubuntu'
- include: centos.yml when: ansible_distribution == 'CentOS'- include: ubuntu.yml when: ansible_distribution == 'Ubuntu'
However sometimes a cleaner way (in my opinion) is to use a variable to minimize the use of conditional statements. Using the same example with Apache:
- name: install apache package: name: "{{ apache_package }}" state: installed
- name: install apache package: name: "{{ apache_package }}" state: installed
Then in your variables file set this dictionary and variable:
dist_dict: "RedHat": apache: 'httpd' "Fedora": apache: 'httpd' "CentOS": apache: 'httpd' "Ubunu": apache: 'apache2'apache_package: "{{ dist_dict[ansible_distribution]['apache'] }}"
dist_dict: "RedHat": apache: 'httpd' "Fedora": apache: 'httpd' "CentOS": apache: 'httpd' "Ubunu": apache: 'apache2'apache_package: "{{ dist_dict[ansible_distribution]['apache'] }}"
You can take this one step further and utilize that same dictionary for services (and other things) as well.
dist_dict: "RedHat": apache_package: 'httpd' apache_service: 'httpd' "Fedora": apache_package: 'httpd' apache_service: 'httpd' "CentOS": apache_package: 'httpd' apache_service: 'httpd' "Ubunu": apache_package: 'apache2' apache_service: 'apache2'apache_package: "{{ dist_dict[ansible_distribution]['apache_package'] }}"apache_service: "{{ dist_dict[ansible_distribution]['service_service'] }}"
dist_dict: "RedHat": apache_package: 'httpd' apache_service: 'httpd' "Fedora": apache_package: 'httpd' apache_service: 'httpd' "CentOS": apache_package: 'httpd' apache_service: 'httpd' "Ubunu": apache_package: 'apache2' apache_service: 'apache2'apache_package: "{{ dist_dict[ansible_distribution]['apache_package'] }}"apache_service: "{{ dist_dict[ansible_distribution]['service_service'] }}"
Then your tasks could simply be:
- name: install apache package: name: "{{ apache_package }}" state: installed- name: start apache service: name: "{{ apache_service }}" state: started enabled: true
- name: install apache package: name: "{{ apache_package }}" state: installed- name: start apache service: name: "{{ apache_service }}" state: started enabled: true
This gives you the power to utilize these variables in other places without including whole .yml files or using a bunch of conditional statements.