Set Ansible role defaults conditionally - ansible

Pseudocode:
If env is de, set variable name to hello else if env is prod, set variable name to bye.
I tried https://serverfault.com/questions/715769/ansible-change-default-value-according-to-a-condition
- name: setting variable
set_fact: name="hello"
when: "{{ env }}" == "de"
- name: setting variable
set_fact: name="bye"
when: "{{ env }}" == "prod"
ERROR! The default/main.yml file for role 'trial' must contain a
dictionary of variables

As per my requirement, it needs to be done in role.So it is done as follows:
name: "{% if env == 'de' %}hello{% elif env == 'prod' %}bye{% endif %}"

Related

Add a command flag based on a condition in Ansible

I have a command written like below in Ansible,
- set_fact:
user_arg: true
some_arg: "--with some-ver=1.0.0 if {{ user_arg is defined else '' }}"
path: "path/to/file"
- command: "some-command {{ some_arg }} {{ path }}"
Please note, I am adding argument name (--with) and its value (some-var=1.0.0) if user argument is defined.
I want to use args and switch it to look something like
- set_fact:
user_arg: true
some_arg: "--with some-ver=1.0.0 if {{ user_arg is defined else '' }}"
path: "path/to/file"
- command: "some-command {{ path }}"
args:
some_arg: "{{ some_arg }}"
But this adds some_arg with empty value, I do not want it to be added at all if user_arg is undefined. Could any one help me with this.
You cannot use set_fact to set a variable and use it in the same set_fact.
You have to break them up:
- set_fact:
user_arg: true
path: "path/to/file"
- set_fact:
some_arg: "{% if user_arg is defined %}--with some-ver=1.0.0{% endif %}"
Now, what I think you actually want is to set some_arg if user_arg is set and true. If so...
- set_fact:
some_arg: "{% if user_arg is defined and user_arg %}--with some-ver=1.0.0{% endif %}"
You should use the default filter with the omit variable for that.
This will set the argument some_arg if user_arg is defined, otherwise, no argument at all will be sent to the command.
- command: "some-command {{ path }}"
vars:
path: "path/to/file"
args:
some_arg: "{{ user_arg|default(omit) if user_arg is not defined else '--with some-ver=1.0.0' }}"

In ansible, how can I assign values to variable based on conditions?

I want to assign a value to a variable based on my env name. If env=e1, some variable name "var" should get the value as "x". If env=e2, "var" should get the value as "y".
Let me know your suggestions!
Say you have an env var called FOO.
- hosts: localhost
gather_facts: "False"
vars:
my_env_var: "{{ lookup('env','FOO') }}"
tasks:
- name: "set e1"
set_fact:
my_ansible_var: "x"
when: my_env_var == "e1"
- name: "set e2"
set_fact:
my_ansible_var: "y"
when: my_env_var == "e2"
You can now reference the {{ my_ansible_var }} value anywhere it is needed.

Conditional ansible to set variable

Tried all luck but doesnot work. I would require to set the environment variable check with a condition and then run a play or task on the main.yml while doing includes and using 2 tasks.
main.yml
- include: createnonprod.yml
when: "{{ environment }}" == 'dev' or "{{ environment }}" == 'qa' or "
{{ environment }}" == 'preprod'
- include: createprod.yml
when: "{{ environment }}" == 'prod'
The environment is set on groups_vars variable file "all"
environment:
"{{ lookup('env','ENVIRONMENT') }}"
But this logic to check fails
(Or)
I need to run this logic so that it calls the task with a condition to check the variable
create.yml
- name: Install all users from IAM of the AWS Account.
shell: "{{ scriptdir }}/install.sh -i {{ iamgroup }},{{ sudogroup }} -s {{ sudogroup }}"
when: "{{ environment }}" == 'dev' or "{{ environment }}" == 'qa' or "{{ environment }}" == 'preprod'
- name: Install all users from IAM of the AWS Account.
shell: "{{ scriptdir }}/install.sh -i {{ iamgroup }},{{ sudogroup }} -s {{ sudogroup }}"
when: "{{ environment }}" == 'prod'
Please help me with a logic that works. I get this error:
fatal: [localhost]: FAILED! => {"failed": true, "reason": "ERROR!
Syntax Error while loading YAML.\n\n\nThe error appears to have been in
'/tmp/ansible/roles/provision/users/tasks/create.yml': line 18, column
22, but may\nbe elsewhere in the file depending on the exact syntax
problem.\n\nThe offending line appears to be:\n\n when:\n - {{
env_type }} == 'dev'\n ^ here\nWe could be wrong,
but this one looks like it might be an issue with\nmissing quotes.
Always quote template expression brackets when they\nstart a value. For
instance:\n\n with_items:\n - {{ foo }}\n\nShould be written
as:\n\n with_items:\n - \"{{ foo }}\"\n"}
The When Statement
The when clause, which contains a raw Jinja2 expression without
double curly braces
when: environment == 'dev' or environment == 'qa' or environment == 'preprod'
when: environment == 'prod'
What if you try this way.
Define a variable to handle the lookup of your environment:
vars:
env_value: "{{ lookup('env', 'ENVIRONMENT') }}"
and then use this variable in the when condition:
when: env_value == "dev"
Simple example:
- hosts: "localhost"
vars:
env_value: "{{ lookup('env', 'ENVIRONMENT') }}"
tasks:
- shell: echo "I've got {{ env_value }} and am not afraid to use it!"
when: env_value == "prd"
Example in your code:
- name: Install all users from IAM of the AWS Account.
shell: "{{ scriptdir }}/install.sh -i {{ iamgroup }},{{ sudogroup }} -s {{ sudogroup }}"
when: env_value == 'dev' or env_value == 'qa' or env_value == 'preprod'
Please, also look at this link about Ansible environment variable name being reserved.

Variable interpolation with ansible filters and environment variables

I've got a role that bootstraps a user's OSX workstation. In it, I need to ensure that xdg variables are set properly, using the following precedence:
defaults/main.yml
user's environment variable
any other value (set in vars, host_vars, command line, etc)
I've tried a couple different approaches, but the basic problem I'm having is that I can't nest variable interpolation, so approach one (and all the others I could think of to try) in defaults/main.yml have failed:
# if the env var doesn't exist, it'll set it to an empty string, doesn't look
# like there is a way to specify the 'default' string that should be used
# xdg_cache_home: "{{ lookup('env','XDG_CACHE_HOME') }}"
# this is just bad syntax, can't have nested '{{ }}'
# xdg_config_home: "{{ lookup('env','XDG_CACHE_HOME') | default("{{ home }}/.cache", true) }}"
# this simply fails to define the variable, i'm not sure why
# xdg_cache_home: "{{ default( lookup('env','XDG_CACHE_HOME'), join(lookup('env', 'HOME', '.cache'))) }}"
The next approach I tried was to just set the defaults using the first method (empty string if empty) and then inspect and set a default value in the roles/myrole/tasks/main.yml:
- name: set default xdg_cache_home
set_fact: xdg_cache_home="{{ join(lookup('env', 'HOME', '/.cache')) }}"
when: "{{ xdg_cache_home }}" == ""
But I can't get that to work either. Any suggestions or advice?
Found the answer in the jinja documentation - using the jinja string concatenation operator (~):
xdg_cache_home: "{{ lookup('env', 'XDG_CACHE_HOME') | default(ansible_user_dir ~ '/.cache', true) }}"
xdg_config_home: "{{ lookup('env', 'XDG_CONFIG_HOME') | default(ansible_user_dir ~ '/.config', true) }}"
xdg_data_home: "{{ lookup('env', 'XDG_DATA_HOME') | default(ansible_user_dir ~ '/.local/share', true) }}"

Conditionally define variable in Ansible

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?
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.
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.
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.
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"
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 }}"

Resources