Skip to content

Month: January 2021

Where to place Ansible variables?

In this post, I want to discuss a couple of the choices one can have when it comes to placing Ansible variables. The docs for variable precedence state 22 where variables can be defined and the order of precedence that the program applies.

Does that mean you should use all of them? Nope. Although each of one of them has its own use case, I usually vouch for implementation simplicity: less is better.

Here is the list I’d recommend:

  • role defaults
  • inventory group_vars
  • inventory host_vars
  • role vars

I usually do not use other types of variables and I’d not recommend doing so. I reiterate that they can all be useful, but, in my opinion, relying mostly on your inventory variables, reduces the complexity significantly. Which leads to time savings when it comes to troubleshooting and other things.

I remember many times where I spent days working on a bug that was introduced due to a misplaced.

Think of it this way: For every additional layer, you are adding more opportunity for the system to break. For example, one time when we writing playbooks for upgrading OS on a networking device we stipulated that some tasks of the playbook should use a different password, and we thus hardcoded those variables as task vars. For some reason, in production someone was inputting the password variables with more precedence and thus breaking the code. Now, I could argue that the person inputting the password was making a mistake. But in hindsight I’d say the mistake was allowing this complexity to take place at all.

So if you have N layers, you can have O(N^2) possible conflicts. Which means that troubleshooting this can be a nightmare. Ansible developers have experience with this and know how to navigate it, but still why even bother if you could prevent it.

Again, let’s say you wrote your code so that it uses block variables. But then the user wants to overwrite some behavior by setting variables using include_vars? That could mean that you are in uncharted territory, meaning that the code wasn’t tested for this use case…

Role defaults vs Role vars

One pattern that I’ve been using when writing roles using role defaults as an example of how to configure your role. Similar to what is used here:

---
# defaults file for ansible-frr
frr_daemons:
  bgpd: false
  isisd: false
  ldpd: false
  nhrpd: false
  ospf6d: false
  ospfd: false
  pimd: false
  ripd: false
  ripngd: false
  zebra: true

I like to use Role vars when something must be hardcoded. Such as your data model schema. Let’s say the dictionary frr_daemons, must have entries for bgpd. Then I like to put an entry in vars that explicitly defines that and I also add a task on the beginning of my role to check if the inputs are given.

---
# Must have children in variables
Children:
  frr_daemons_: [ 'bgpd' ]

This can get out of hand quick, but usually it works out

Conclusion

In summary, I believe you can place your Ansible variables in the 4 locations listed below. And if you avoid placing variables in any other place you’ll save yourself a lot of troubleshooting time. I’d love to hear if you can think of a usecase to which this example doesn’t suffice.

  • role defaults
  • inventory group_vars
  • inventory host_vars
  • role vars

Please comment below, or PM me on the slack channel from the networktocode folks, my username is castroflavio.

Leave a Comment