Conditionally define variable in Ansible

Ansible

Ansible Problem Overview


I want to conditionally define a variable in an Ansible playbook like this:

my_var: "{{ 'foo' if my_condition}}"

I would like the variable to remain undefined if the condition does not resolve to true.

Ansible gives the following error if I try to execute the code:

fatal: [foo.local] => {'msg': 'AnsibleUndefinedVariable: One or more undefined
                       variables: the inline if-expression on line 1 evaluated
                       to false and no else section was defined.', 'failed': True}

Why is this an error anyway?

The complete case looks like this:

{role: foo, my_var: "foo"}

If my_var is defined, the role does something special. In some cases, I don't want the role to do this. I could use when: condition, but then I would have to copy the whole role block. I could also use an extra bool variable, but I would like a solution without having to change the "interface" to the role.

Any ideas?

Ansible Solutions


Solution 1 - Ansible

You could use something like this:

my_var: "{{ 'foo' if my_condition else '' }}"

The 'else' will happen if condition not match, and in this case will set a empty value for the variable. I think this is a short, readable and elegant solution.

Solution 2 - Ansible

This code may help you to define a variable with condition.

- hosts: node1
  gather_facts: yes
  tasks:
   - name: Check File
     shell: ls -ld /etc/postfix/post-install
     register: result
     ignore_errors: yes

   - name: Define Variable
     set_fact:
         exists: "{{ result.stdout }}"
     when: result|success

   - name: Display Variable
     debug: msg="{{ exists }}"
     ignore_errors: yes

So here the exists will display only if the condition is true.

Solution 3 - Ansible

My example, after https://stackoverflow.com/a/43403229/5025060:

vars:
    sudoGroup: "{{ 'sudo' if ansible_distribution == 'Ubuntu' else 'wheel' }}"

Because of the different sudo conventions used by Ubuntu versus other platforms, here I am telling Ansible to set a variable named sudoGroup to sudo if the platform is Ubuntu, otherwise set it to wheel.

Later in my playbook, I combine the variable with Ansible's user module to add either sudo or wheel to an account's secondary groups depending on the OS Ansible is running on:

- name: Add or update bob account
  user:
    name: bob
    uid: 3205
    groups: "{{ sudoGroup }}"
    append: yes

NOTES:

  • Double quotes around the {{ variable }} are required in the user: groups: definition above.
  • Once I define sudoGroup as above in my playbook's global vars: section, Ansible configures it at run time (based on ansible_distribution) for each target I define in my hosts: section.

Solution 4 - Ansible

I believe you're after the default(omit) filter. (Reference).

As per the example, mode will behave like it wasn't set at all for the first two items in the loop.

- name: touch files with an optional mode
  file:
    dest: "{{item.path}}"
    state: touch
    mode: "{{item.mode|default(omit)}}"
  loop:
    - path: /tmp/foo
    - path: /tmp/bar
    - path: /tmp/baz
      mode: "0444"

Solution 5 - Ansible

This can be set as with bool:
- name: Conditional (true and false)
  set_fact: 
      my_boolean_set_to_be: "{{ 'true' if my_var == 'foo' else 'false' }}"  

- name: Display Variable
  debug: msg="{{ my_boolean_set_to_be }}"
This can be set as for more conditionals like 'if-ifelse-else' statements:
- name: Conditional for 'my_var' (2 options and one default)
  set_fact: 
      my_var_set_to_be: "{{ 'breakfast' if my_var == 'morning' else 'lunch' if my_var == 'afternoon' else 'dinner' }}"  

- name: Display Variable
  debug: msg="{{ my_var_set_to_be }}"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChristianView Question on Stackoverflow
Solution 1 - AnsiblemhalanoView Answer on Stackoverflow
Solution 2 - AnsibleSPMView Answer on Stackoverflow
Solution 3 - AnsibleCODE-REaDView Answer on Stackoverflow
Solution 4 - AnsibleLucidObscurityView Answer on Stackoverflow
Solution 5 - AnsibleO.CaliariView Answer on Stackoverflow