4

I want an Ansible 2.6.2 task to use the value of variable var1 if it's set, otherwise a string containing variable var2. Only one of these will be set, however. If I use a simple {{ var1 | default(var2) }} it works, but when I try to append a string to var2 Ansible gives an error when var2 is undefined, even though var1 is:

FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'var2' is undefined\n\nThe error appears to have been in 'test.yml': line 13, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n msg: \"Simple default: {{ var1 | default(var2) }}\"\n - debug:\n ^ here\n"}

Playbook:

- hosts: all
  gather_facts: false
  connection: local
  vars:
    var1: "one"
#    var2: "two"
  tasks:
    - debug:
        # This works
        msg: "Simple default: {{ var1 | default(var2) }}"
    - debug:
        # This fails when var2 is undefined, even though var1 is
        msg: "Default with concatenation: {{ var1 | default(var2 + '?') }}"
techraf
  • 64,883
  • 27
  • 193
  • 198
EM0
  • 5,369
  • 7
  • 51
  • 85

3 Answers3

6

The error message is clear: parser requires a variable to be defined.

You can use the same default filter to provide default value instead of the var2:

msg: "Default with concatenation: {{ var1 | default(var2|default('') + '?') }}"
techraf
  • 64,883
  • 27
  • 193
  • 198
  • Thanks, this works, but is there a way to still get an error if both var1 and var2 are undefined? (Even better if it also gives an error if both are defined.) – EM0 Aug 16 '18 at 08:27
  • Check `assert` module. – techraf Aug 16 '18 at 08:40
  • Sure, I could add an explicit assert, but I was hoping there was some way to do that in the templating language, like `var1 | default(var2)` would do, except that I want to add extra stuff to `var2` – EM0 Aug 16 '18 at 08:42
1

OK, I found a way that works, thanks to another answer by techraf:

{{ var1 if var1 is defined else var2 + '?' }}

This works if either var1 or var2 is defined, but if both are undefined throws an error:

The task includes an option with an undefined variable. The error was: 'var2' is undefined...

I can add a third variable to this, too:

{{ var1 if var1 is defined else (var2 + '?' if var2 is defined else var3 + '!' ) }}

Dictionary version:

{{ mydict.key1 if mydict.get('key1') else mydict.key2 }}

(if mydict.key1 raises an error if key1 is not in mydict)

EM0
  • 5,369
  • 7
  • 51
  • 85
0

Both doing the same (don't know which is more efficient)

Variables:

repo: hththt
file_name: file.txt

Templates:

url: "{{ url if url is defined else repo + '/files/' + file_name }}"

url: "{{ url | default(repo + '/files/'' + file_name) }}"   
jackaaxc
  • 21
  • 5