
Ansible is one of the most prominent tools among DevOps for managing software configuration because of its ease of use and bare minimum dependencies. The highlight of this tool is Ansible roles which provide a wholesome package of various functionalities that we need for software configuration.
As we know that ansible roles have a wide directory structure that looks something like this.
$ tree -d
.
├── defaults
├── files
├── handlers
├── media
├── meta
├── molecule
│ └── default
│ └── tests
├── tasks
└── templates
10 directories
We can read online about the significance of these directories but often there is some confusion around two of them that always bugs me, which are vars and defaults. Whenever I write a role I often think of whether to put my variables in defaults or the vars.
According to Ansible’s definition, the difference between defaults and vars is:
- defaults mean “default variables for the roles” and vars mean “other variables for the role”.
- The priority of the vars is higher than that of defaults.
For example, consider a variable named ‘version’ defined in the defaults have value ‘5.0.1’ and the same variable defined in vars have value ‘7.1.3’, so the final value that will be taken into account is the value defined in vars i.e., ‘7.1.3’.
Due to my limited understanding of this, I used to define all variables in defaults and whenever needed to override them, I declared those variables in vars.
But there was more to it just than precedence, which motivated me to deep dive into it and finds out that there are two types of variables in terms of content, “static” with constant value and “dynamic” with changing value. According to the ansible definition, the static variables should be placed in default and the dynamic should be placed in vars.
For Example,
Download URL for tomcat is “https://archive.apache.org/dist/tomcat/tomcat-version/”
“https://archive.apache.org/dist/tomcat/tomcat-” -> Fixed Part
“version” -> Varying Part
Here, we can make a variable for the fixed value in the defaults with any name suppose “tomcat_base_url” and varying value should be declared in vars, let it be with any name suppose “tomcat-version”.
So, whenever I have to use the tomcat download url in the role it will be: “{{ tomcat_base_url }}/{{ tomcat-version }}”.
defaults: contain variables which user have to not alter.
vars: contain variables that require input by user.
The reason for the same is user executing the role have to not go to multiple places for configuring the role according to their needs. I think we should follow this convention for variable declaration irrespective of thinking that defining variables in either directory will serve the purpose.
I hope these findings might help with your clarity in defaults and vars directory structure of Ansible roles. Do let me know if I am missing out on some points regarding these. I am open to feedback.
Happy Automating!!
Image Source – https://bit.ly/2UdOoN5
Opstree is an End to End DevOps solution provider
“defaults: contain variables which user have to not alter.
vars: contain variables that require input by user.”
Now that is something that I can work with. Thanks! 🙂
LikeLike
Given some comments else, mostly around role and variable precedence, I’ll reverse the above, and go with:
“vars: contain variables which user have to not alter.
default: contain variables that (may) require (overriding) input by user.”
The difference here (and triggering the reversal) is that role vars actually have a higher precedence than play vars, and are difficult to override (via a -e on the command line!). So the defaults have sensible defaults and can be easily overridden. So consider the var variables as static, and the default vars to be changeable (dynamic).
Hope this clears things up and makes sense.
LikeLike
> default: contain variables that (may) require (overriding) input by user.
Variables from default are always overriden if there are any other out there for example in the following `vars` folder or `host_vars` or `group_vars` or finally in `-e` parameter. But that doesn’t matter that they are dynamic. It proves that they are static. So this takes as to point where defaults because they are on beginning ,they define “static” variables and can be whole variables or just piece of variables that can be appended by other from different directories depends how you wanna organise them. But defaults by default as the name says itself.. they are those that come first and are the static ones.
LikeLike
Why not make tomcat_base_url part of template? Why to store it in a variable?
LikeLike
I think this article is completely wrong. The [Ansible docs](https://docs.ansible.com/ansible/2.9/user_guide/playbooks_variables.html) state about `defaults`:
> If you are writing a redistributable role with reasonable defaults, put those in the roles/x/defaults/main.yml file. This means the role will bring along a default value but ANYTHING in Ansible will override it.
And about `vars`:
> If you are writing a role and want to ensure the value in the role is absolutely used in that role, and is not going to be overridden by inventory, you should put it in roles/x/vars/main.yml
Therefore, the constant (described as “fixed part” in the article) should go in `vars` while the changeable part (described as “varying part” in the article) should go in `defaults`.
LikeLike
Many thanks Tom for pointing this out, really appreciate for pointing this out.
LikeLike