Reputation: 4249
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?
Upvotes: 83
Views: 204133
Reputation: 4144
I would like the variable to remain undefined if the condition does not resolve to true.
Then I would do that this way
- name: assign value to variable only if condition is met
set_fact:
my_var: 'foo'
when: my_condition
example:
- name: if 'substring' is contained in my_string, then set my_var to '*'
set_fact:
my_var: '*'
when: 'substring' in my_string
This is something I find useful when I want to reassign the value of a variable contained in a vars_files
script.
I could not do it by simply defining the variable again, because ansible would complain about the not-unique variable name:
my_var: "{% if 'substring' in my_string %}*{% else %}{{ my_var }}{% endif %}"
# but my_var is already declared, so this task fails.
Upvotes: 1
Reputation: 351
- 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 }}"
- 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 }}"
Upvotes: 4
Reputation: 3028
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:
{{ variable }}
are required in the user: groups:
definition above.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.Upvotes: 23
Reputation: 714
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
.
Upvotes: 30
Reputation: 580
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"
Upvotes: 16
Reputation: 1202
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.
Upvotes: 106