What is the equivalent of Ansible's "when" clause in SaltStack? - ansible

For the given below Ansible code, how can I implement a similar functionality in SaltStack (specifically when clause)?
---
- include: install-redhat.yml
when: ansible_os_family == "RedHat"
- include: install-debian.yml
when: ansible_os_family == "Debian"
Do I have to use Jinja2 templates for this? It looks like unless and onlyif can only test return codes of shell commands.

Yes, you have to use jinja for this.
Something like
{% if grains['os'] == 'Redhat' %}
include:
- install-redhat
{% endif %}
But I would rather include the states in top file
for example, in top.sls, you can do
'os:Redhat':
- match: grain
- state1_redhat
- state2_redhat
'os:FreeBSD':
- match: grain
- freebsd1
- freebsd2

Related

ansible variables usage - ansible_hostname or {{ ansible_hostname }}

I am new to ansible. What is the correct to call ansible variables? Here are the 3 playbooks, playbook 1 uses "{{ ansible_hostname }}", however, playbook 2 and 3 uses "ansible_hostname" directly. What are the differences? Thanks!
Playbook 1:
tasks:
- name: Jinja2 template
template:
src: template.j2
dest: "/tmp/{{ ansible_hostname }}_template.out"
trim_blocks: true
mode: 0644
Playbook 2:
tasks:
- name: Ansible Jinja2 if
debug:
msg: >
--== Ansible Jinja2 if statement ==--
{# If the hostname is ubuntu-c, include a message -#}
{% if ansible_hostname == "ubuntu-c" -%}
This is ubuntu-c
{% endif %}
Playbook 3:
tasks:
- name: Exploring register
command: hostname -s
when:
- ansible_distribution == "CentOS"
- ansible_distribution_major_version | int >= 8
register: command_register
playbook 1 uses "{{ ansible_hostname }}", however, playbook 2 uses "ansible_hostname"
That's not entirely correct. Both playbooks use the variable name ansible_hostname inside a Jinja templating context.
In the first playbook, it's simple variable substitution, so we use the {{ ... }} markers.
In the second playbook, it's being used in a control expression, so we use the {% ... %} markers.
In the third playbook, you're looking at the clauses of a when expression. From the documentation:
The when clause is a raw Jinja2 expression without double curly braces...
You can read more about Jinja syntax here.

ansible jinja2 template delimiters failed if using 'when'

I have this code, where the first task fails and the second task produces the following warning:
[WARNING]: conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: {{ VRF }} == 17
I am assuming this warning and the failure of the first task are happening for the same reason. From what I understand, the variables are different types. How do I fix this?
---
- name: PE_CE
hosts: localhost
tasks:
- include_vars: /opt/netsec/ansible/orchestration/capabilities/PE_CE/PE_CE_1.yml
- name: Build PE config Cisco
template:
src=/opt/netsec/ansible/orchestration/cisco_templates/PE_CE_CISCO_config_PE.j2
dest=/opt/netsec/ansible/orchestration/config_outputs/new/{{PE_HOSTNAME}}
when: "{{ PX_HOSTNAME }} == None"
- name: Build CE config Cisco
template:
src=/opt/netsec/ansible/orchestration/cisco_templates/PE_CE_CISCO_config_CE.j2
dest=/opt/netsec/ansible/orchestration/config_outputs/new/{{CE_HOSTNAME}}
when: "{{ VRF }} == 17"
What I really want to do is when: "{{ VRF }} == 17" and "{{ PX_HOSTNAME }} == None", or something like {{ PX_HOSTNAME }}|length < 1"
You do not need {{ and }} with when. Do it like this:
when: PX_HOSTNAME == "None" and when: VRF == "17"
Here is some documentation
when: PX_HOSTNAME == "None" will check if PX_HOSTNAME contains the string "None".
If you want to run the task if it is empty, do when: not PX_HOSTNAME or if you want to run the task it it is not empty, do when: PX_HOSTNAME.
You can use the length as well: when: PX_HOSTNAME|length > 0

Ansible: conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}

Can someone help me in understanding and resolving it
- name: Copying file to sever2
fetch:
src: /tmp/
dest: /u0/test/
when:
"{{ inventory_hostname == 'testdb' }}"
In your case, you should use when condition without Jinja delimiters.
Example:
when: inventory_hostname == 'testdb'
Detailed explanation:
Jinja template delimiters are used when variable interpolation is required in context of text and templates. This tells Ansible to use the value of the variable instead of the variable name.
Consider everything as text unless told otherwise (with delimiters)
Example:
vars:
fav_tool: Ansible
tasks:
- debug:
msg: "I like fav_tool"
This will output:
"msg": "I like fav_tool"
This is not what I wanted, I wanted to display "I like Ansible". So then I have to "tell" ansible to use the value of fav_tool.
- debug:
msg: "I like {{ fav_tool }}"
Similarly we use Jinja template delimiters in templates. Where we want to separate the variable, and expressions from text.
Example template such as below:
if fav_tool == 'Ansible'
I like Ansible
endif
... will result in exactly the same text without evaluating:
if fav_tool == 'Ansible'
I like Ansible
endif
However, when we use Jinja delimiters:
{% if fav_tool == 'Ansible' %}
I like Ansible
{% endif %}
It will result in:
I like Ansible
When we use conditions such as when:, we don't need delimiters as the conditionals will automatically interpolate the variable to value.
Consider everything as variables and expressions unless told otherwise (with '')
Example:
The case is reversed here and whatever is not enclosed in single-quotes is automatically evaluated. Only 'Ansible' is considered as text here (not evaluated).
vars:
fav_tool: Ansible
tasks:
- debug:
msg: "Ansible rocks!"
when: fav_tool == 'Ansible'
It worked for me with
when:
(inventory_hostname in groups['testdb'])

ansible if else construct

Heres my if else Ansible logic ..
- name: Check certs exist
stat: path=/etc/letsencrypt/live/{{ rootDomain }}/fullchain.pem
register: st
- include: ./_common/check-certs-renewable.yaml
when: st.stat.exists
- include: ./_common/create-certs.yaml
when: not st.stat.exists
This code boils down to:
IF certs exist
renew certs
ELSE
create certs
END IF
Is this the correct approach or is there a better approach to the IF ELSE construct in ansible?
What you have there should work and is one way of doing it.
Alternatively, you could use a Jinja query to reduce it to 2 tasks, such that:
- name: Check certs exist
stat: path=/etc/letsencrypt/live/{{ rootDomain }}/fullchain.pem
register: st
- include: "{{ './_common/check-certs-renewable.yaml' if st.stat.exists else './_common/create-certs.yaml' }}"
However, it's more a matter of personal preference than anything else, and your way is more readable, so I would just stick with that IMHO.
What about the following
condition_arg: >-
{%- if ansible_distribution == 'Ubuntu' -%}
'param for ubuntu'
{%- elif ansible_distribution == "Debian" -%}
'params for debian'
{%- else -%}
'what else'
{%- end %-}
kind of if-else statement.. ? They have been used in some projects with ansible.
This form isn't available from the official docs, but from an active thread on stackexchange
The following can be used if you want to search if a register is empty. The msg Unavailable is printed if php -version info is not found.If it is found, it prints the output of the command.
- name: Check php
shell: php -version
register: result
- name: Print register
debug:
msg: '{{ (result.stdout) | ternary( (result.stdout),"Unavailable") }}'

Ansible Using --extra-vars for conditional includes

I am using Ansible to deploy an environment that may have services distributed or not. I would like to conditionally include playbooks based on arguments I pass to ansible-playbook.
create_server.yml
---
- include: launch_ec2_instance.yml
- include install_postgres.yml
when {{db}} == "Y"
- include install_redis.yml
when {{redis}} == "Y"
Here is how I am calling create_server.yml
ansible-playbook create_server.yml -i local --extra-vars "db=Y redis=N"
Is it possible to do this and if so, how?
Yes. It's possible. You are missing a colon(:) on your when statement.
---
- include: launch_ec2_instance.yml
- include install_postgres.yml
when: {{ db }} == "Y"
- include install_redis.yml
when: {{ redis }} == "Y"
You can also omit the braces ({{ }}):
---
- include: launch_ec2_instance.yml
- include install_postgres.yml
when: db == "Y"
- include install_redis.yml
when: redis == "Y"
#Rico's answer is correct except that it only applies when your include statement is part of a task.
Eg.
---
tasks:
- include install_postgres.yml
when: db == "Y"
If your playbook is just a bunch of includes as your 'create_server.yml' seems to be then 'when' wont work.

Resources