Is Ansible declarative or imperative?
There is a lot of discussion about this topic. And the question implies that it is either one or the other. I think that is the wrong question. This Blog post will describe why.
Writing something like that is declarative for sure.
- name: Webservers
apt:
pkg:
- apache2
- nginx
state: present
But we could get the same result with that task as well.
- name: Install Webservers
shell: apt-get install "{{item}}"
loop:
- apache2
- nginx
The latter is the one that seems natural to a sysadmin who starts using Config Management. So it is not uncommon that we find those things in playbooks. And sometimes it gets even more complicated:
- name: Check if Apache is installed
shell: dpkg -l apache2
register: apache_installed
- name: Install Apache
shell: apt-get install apache2
when: apache_installed.rc !=0
- name: Check if Nginx is installed
shell: dpkg -l nginx
register: nginx_installed
- name: Install Nginx
shell: apt-get install nginx
when: nginx_installed.rc !=0
A simple apt-get install apache2 nginx
in a bash script (imperative approach) would do the same job. We are not forced to make things more complicated than they have to be. Ansible (as most other config management tools) allows us to use declarative and imperative methods. But it is not Ansible itself that is declarative or imperative. It is how we use it.
There is nothing wrong with using loops and conditions occasionally. But if more than 50% of our tasks have a when condition attached there is probably a better way. We can not solve everything with declarative code. Sometimes we need more flexibility. Instead of creating complicated contructs and flow control in Ansible we can write a simple bash script that does the same job. We can still call that from an Ansible task.
“Simlicity is the ultimate sophistication” - Leonardo da Vinci