When writing automation scripts I tend to use a local Ansible configuration file. This has certain advantages for me, such as including it in a version control system (VCS). It also is a valid option for developers without access to the global configuration file installed by the package manager. And more convenient to use than setting environment variables.
Until now I haven’t spent a lot of time thinking about configuration variables and the order of precedence, but that is exactly what I’d like to do in this post.
When putting this short article together I used Ansible 2.7.6 on Oracle Linux 7.6
What does the documentation have to say?
The official documentation does a really good job explaining the configuration settings. You have the choice of:
- Environment variable
- configuration file (ansible.cfg) in your local directory
- A playbook-independent configuration file in ~/.ansible.cfg
- The global settings in /etc/ansible/ansible.cfg
Let’s try this
This is an example of a very minimalist project folder in my lab, deliberately omitting a local configuration file.
[vagrant@server1 ansible]$ ls -la total 16 drwxrwxr-x. 3 vagrant vagrant 53 Feb 14 09:09 . drwx------. 5 vagrant vagrant 4096 Feb 14 08:40 .. drwxrwxr-x. 7 vagrant vagrant 4096 Feb 14 09:09 .git -rw-rw-r--. 1 vagrant vagrant 17 Feb 14 09:09 .gitignore -rw-rw-r--. 1 vagrant vagrant 94 Feb 14 08:40 hello.yml
The example is kept super-short on purpose.
Without a local configuration file (~/.ansible.cfg or $(pwd)/ansible.cfg) and/or defined environment variables, the settings made by your friendly system administrator in /etc/ansible/ansible.cfg govern every execution. You can use ansible-config to view the non-default values:
[vagrant@server1 ansible]$ ansible-config dump --only-changed ANSIBLE_NOCOWS(/etc/ansible/ansible.cfg) = True [vagrant@server1 ansible]$
As you can see, the global configuration file prevents the use of cowsay.
Now if I as an automation developer wanted to override a certain setting, I could use an environment variable. The documentation tricked me for a moment – when you see “DEFAULT_LOG_PATH” for example, exporting that variable does not have any effect. What you need to use is shown in the same section, but further down, with the Environment: label. To set the default log path on your shell, use ANSIBLE_LOG_PATH as in this example:
[vagrant@server1 ansible]$ export ANSIBLE_LOG_PATH=/home/vagrant/ansible/logs/my_ansible.log [vagrant@server1 ansible]$ ansible-config dump --only-changed ANSIBLE_NOCOWS(/etc/ansible/ansible.cfg) = True DEFAULT_LOG_PATH(env: ANSIBLE_LOG_PATH) = /home/vagrant/ansible/logs/my_ansible.log
Thankfully ansible-config shows me the origin for each setting.
Using a local configuration file
Now how does a local configuration file play into this? Let’s try! I keep the global configuration file as it is, but I unset the environment variable. Here is the result:
[vagrant@server1 ansible]$ unset ANSIBLE_LOG_PATH [vagrant@server1 ansible]$ cat ansible.cfg [defaults] stdout_callback = debug log_path = /home/vagrant/ansible/logs/ansible_blogpost.log [vagrant@server1 ansible]$ ansible-config dump --only-changed DEFAULT_LOG_PATH(/home/vagrant/ansible/ansible.cfg) = /home/vagrant/ansible/logs/ansible_blogpost.log DEFAULT_STDOUT_CALLBACK(/home/vagrant/ansible/ansible.cfg) = debug [vagrant@server1 ansible]$
What’s interesting is that my “nocows” setting from the global configuration file in /etc/ansible/ansible.cfg isn’t merged into the configuration. Without the use of environment variables, the only settings coming into play are those of the local configuration file. The same seems to apply if a local configuration file exists in addition to ~/.ansible.cfg. The file in the current working directory always took precedence in my testing.This did not affect environment variables, they have always been considered by ansible-config. If for example I wanted to temporarily save the logfile to a different place and was too lazy to fire up vim, I could use this approach
[vagrant@server1 ansible]$ ANSIBLE_LOG_PATH=/home/vagrant/ansible/logs/overriding.log ansible-config dump --only-changed DEFAULT_LOG_PATH(env: ANSIBLE_LOG_PATH) = /home/vagrant/ansible/logs/overriding.log DEFAULT_STDOUT_CALLBACK(/home/vagrant/ansible/ansible.cfg) = debug [vagrant@server1 ansible]$Happy scripting!