Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ansible 2.8 Roles - using the vars/main directory

I am trying to split my Ansible role variables into multiple files - as per this answer, it should be possible to create a vars/main directory, and all the .yml files in that directory should be automatically loaded.

However, this does not seem to happen in my case.

My directory structure:

vars
└── main
    ├── gce_settings.yml
    ├── vsphere_settings.yml
    └── vsphere_zone.yml

However, when I try to use a variable defined inside vsphere_settings.yml, Ansible complains that the variable is undefined: {"msg": "The task includes an option with an undefined variable. The error was: 'vsphere_user' is undefined

If I move the variable declaration into vars/main.yml, everything works as expected. But, of course, I would prefer to separate my variables into multiple files.

I was unable to find any reference to this "feature" in the official Ansible documentation, and I do not know how I could troubleshoot it. Can anyone point me in the right direction?

My ansible version: ansible 2.8.5 on Ubuntu 16.04

And before you ask: yes, I did make sure that main.yml was not present when trying to load vars/main/*.yml...

like image 652
Bogd Avatar asked Sep 17 '25 07:09

Bogd


2 Answers

The example below

$ cat play.yml 
- hosts: localhost
  roles:
    - role1

$ cat roles/role1/tasks/main.yml 
- debug:
    var: var1

$ cat roles/role1/vars/main/var1.yml 
var1: test_var1

gives

"var1": "test_var1"
like image 188
Vladimir Botka Avatar answered Sep 19 '25 15:09

Vladimir Botka


TL;DR version: it is a bug in ansible, caused by the presence of empty .yml files in vars/main. There is a PR out for it already. See here .

The actual result (as mentioned in the comments) actually depends on the order the files are processed (by default, it looks like my Ansible processes them in alphabetical order - but this might depend on the version, or the underlying OS):

  • If the empty file is processed first, you get an error message: ERROR! failed to combine variables, expected dicts but got a 'NoneType' and a 'AnsibleMapping'
  • If the empty file is processed after other files, there is no error message, but all the variables that have been set up to this point are destroyed

More details: since I have no idea how to troubleshoot this in Ansible itself, I went to the code and started to add print statements to see what is happening.

In my case, I had some empty .yml files in the vars/main directory (files that I was planning to populate later on. Well... it looks like when the code encounters such an empty file, it destroys the entire dictionary that it has built so far.

Either I'm missing something very important, or this is a bug... Steps to reproduce:

  • create a role
  • create the vars/main directory, and populate it with some .yml files
  • add an empty .yml file (named so that it is processed after the other files)
  • try to print the variables from the first files
    ansible# tree roles 
    roles
    +-- test
        +-- tasks
        ¦   +-- main.yml
        +-- vars
            +-- main
                +-- correct_vars.yml

    4 directories, 2 files

    ansible# cat roles/test/vars/main/correct_vars.yml  myname: bogd

    ansible# ansible-playbook -i inventory.yml test.yml 
    ... 
    ok: [localhost] => {
        "myname": "bogd" } 
    ...

    ansible# echo > roles/test/vars/main/emptyfile.yml

    ansible# ansible-playbook -i inventory.yml test.yml 
    ... ok: [localhost] => {
        "myname": "VARIABLE IS NOT DEFINED!" } 
    ...

Later edit: yep, it's a bug... See here.

like image 20
Bogd Avatar answered Sep 19 '25 16:09

Bogd



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!