Home:ALL Converter>Explanation of behaviour of Ansible Playbook variables defined in vars

Explanation of behaviour of Ansible Playbook variables defined in vars

Ask Time:2018-04-13T23:59:28         Author:Etzeitet

Json Formatter

I am fairly new to Ansible and today while writing a new playbook I came across some behaviour I can't explain. I have been through the documentation and done my best Google-Fu, but I can't seem to find the answer.

The behaviour relates to variables defined in a playbook's "var" section and their lack of expansion into proper values when using other variables or arithmetic.

Take an example playbook with "static" values in vars:

--- # Test playbook vars
- hosts: 'all'
connection: ssh
gather_facts: false
vars:
    - max_size_bytes: 10240

tasks:
- name: debug!
  debug:
      msg: |
         "max_size_bytes: {{max_size_bytes}}"
         "vars:           {{vars['max_size_bytes']}}"

This outputs:

# ansible-playbook -i host1, test_vars.yml

PLAY [all] *************************************************************************************************************************

TASK [debug!] **********************************************************************************************************************
ok: [host1] => {}

MSG:

"max_size_bytes: 10240"
"vars:           10240"

Which is exactly what I would expect.

However, let's say I want to calculate that 10240 number dynamically:

--- # Test playbook vars
- hosts: 'all'
connection: ssh
gather_facts: false
vars:
    - max_size_bytes: "{{10 * 1024}}"

tasks:
- name: debug!
  debug:
      msg: |
         "max_size_bytes: {{max_size_bytes}}"
         "vars:           {{vars['max_size_bytes']}}"

And the new result is:

# ansible-playbook -i host1, test_vars.yml

PLAY [all] *************************************************************************************************************************

TASK [debug!] **********************************************************************************************************************
ok: [host1] => {}

MSG:

"max_size_bytes: 10240"
"vars:           {{10 * 1024}}"

I get a similar output if I try to use another variable within the assignment. I came across this issue when I wanted to allow a playbook user to quick change some settings, without requiring them to calculate anything. For example:

vars:
    - max_size_in_megabytes: 100 #change me if required
    - max_size_bytes: "{{max_size_in_megabytes * 1024 * 1024}}"

But this didn't work as I expected, as above.

In some places the variable is expanded correctly and gives the result I would expect (i.e. the calculated value). At other times, it seems the variable is not expanded and is treated as a string as per the output for vars['max_size_bytes'].

  • What is the reason for this behaviour? Variable expansion and calculated values seem to work elsewhere in a playbook - why not for pre-defined variables?
  • If this behaviour is considered normal, what is the proper way of creating global/reusable variables that may need to be calculated on the fly?

UPDATE

I realise there may be some confusion as to what my issue actually is. That's my fault.

To try and explain better, take a look at another example:

--- # Test playbook vars
 - hosts: 'localhost'
   connection: local
   gather_facts: false
   vars:
       - multiplier: 10 #change me as required
       - some_value: 300
       - max_size_dynamic: "{{10 * 20}}"
       - max_size_static: 200

   tasks:
   - set_fact:
       is_bigger_dynamic: "{{some_value > max_size_dynamic}}"
       is_bigger_static: "{{some_value > max_size_static}}"

   - name: debug!
     debug:
         msg: |
            multiplier:          {{multiplier}}
            some_value           {{some_value}}

            Is {{some_value}} bigger than {{max_size_static}}?
            is_bigger_static:   {{is_bigger_static}}     <-- hooray

            Is {{some_value}} bigger than {{max_size_dynamic}}?
            is_bigger_dynamic:   {{is_bigger_dynamic}}   <-- woops!

When running this playbook, you can see that the value of the conditional clauses in the set_fact task differs based on how a variable is created in vars.

Output:

PLAY [localhost] **********************************************************************************************************************

TASK [set_fact] ***********************************************************************************************************************
ok: [localhost]

TASK [debug!] *************************************************************************************************************************
ok: [localhost] => {}

MSG:

multiplier:          10
some_value           300

Is 300 bigger than 200?
is_bigger_static:   True     <-- hooray

Is 300 bigger than 200?
is_bigger_dynamic:   False   <-- woops!

The conditionals are checking the same expression: 300 > 200, but if the value 200 is derived from another expression in vars the condition is wrong.

I suspect in the case of {{some_value > max_size_dynamic}} the variable isn't being expanded (much like using vars['name\] as mentioned in the comments). So it looks like the conditional ends up being {{some_value > "{{10 * 20}}"}}.

Is this expected behaviour with set_fact? Is there anything I can do to allow expressions in vars which can be further used in set_fact tasks?

This is running the latest version of Ansible on MacOS High Sierra:

# ansible --version
ansible 2.5.0
  config file = /Users/xxx/.ansible.cfg
  configured module search path = [u'/Users/xxx/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/Cellar/ansible/2.5.0/libexec/lib/python2.7/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 2.7.14 (default, Apr  9 2018, 16:44:39) [GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.1)]

Author:Etzeitet,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/49821025/explanation-of-behaviour-of-ansible-playbook-variables-defined-in-vars
yy