ansible variables usage - ansible_hostname or {{ ansible_hostname }} - ansible

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.

Related

Ansible search sublists for value

A webhook triggers an AWX job and I want to run the deployment on a certain host depending on the service, since they run on different servers. I need to know which server uses that service to set is as a var so it can be used as a host in the following play.
My variable inside vars.yaml looks like this:
staging_hosts:
server1: ['service1', 'service2', 'service3']
server2: ['service4', 'service5', 'service6']
server3: ['service7', 'service8', 'service9']
Playbook:
- name: write deployment hosts
hosts: localhost
vars:
deployment_hosts: absent
vars_files:
- ./group_vars/vars.yaml
tasks:
- set_fact:
modified_repos: (small regex filter to find modified repository)
- set_fact:
deployment_hosts: "{{ item }}"
when: '{{ modified_repos }} in {{ item }}'
with_list:
- "{{ staging_hosts }}"
- name: connect to Cluster
hosts: "{{ hostvars['localhost']['deployment_hosts'] }}"
What can I do against this warning and error?
[WARNING]: conditional statements should not include jinja2 templating
delimiters such as {{ }} or {% %}. Found: {{ modified_repos }} in {{ item }}
fatal: [localhost]: FAILED! => {"msg": "The conditional check '{{ modified_repos }} in {{ item }}' failed. True {% else %} False {% endif %}): unhashable type: 'list'
Oh I forgot to mention. It is important, that deployment_hosts could also contain two hosts if modified repos include for example service1 and service4.
Q: "deployment_hosts could also contain two hosts if modified repos include for example service1 and service4."
A: Use intersect filter. For example, the playbook
- hosts: localhost
vars:
staging_hosts:
server1: ['service1', 'service2', 'service3']
server2: ['service4', 'service5', 'service6']
server3: ['service7', 'service8', 'service9']
modified_repos: ['service1', 'service4']
tasks:
- set_fact:
deployment_hosts: "{{ deployment_hosts|default([]) + [item.key] }}"
loop: "{{ staging_hosts|dict2items }}"
when: modified_repos|intersect(item.value)|length > 0
- debug:
var: deployment_hosts
gives
deployment_hosts:
- server1
- server2

Ansible condtional statement with stdout and variable

I am trying to use a condition to verify the MD5_hash value from the std output with the stored value in the host file.
- block:
- name: Install OS
nxos_install_os:
provider: "{{ creds }}"
system_image_file: "{{bin}}"
issu: no
timeout: 500
when: md5_result.stdout[0] == "{{ MD5_Hash }}"
[WARNING]: conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found:
md5_result.stdout[0] == "{{ MD5_bin5 }}"
I found a suggestion of using [] instead of {{}}, but I am just getting the condition result is FALSE.
Please suggest.

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

How to dynamically create an ansible list out of hostvars?

I have a few variables defined for every host. Like...
hosts:
- hostA:
vars:
self_ip: "192.168.1.10"
self_port: "8001"
- hostB:
vars:
self_ip: "192.168.1.11"
self_port: "8002"
Inside one of the roles, I want to define a variable, which is a combination of few host variables. For example...
all_endpoints: 192.168.1.10:8001,192.168.1.11:8002
How can I do this?
I tried using Jinja2 for loops like below:
rs_members:
"{% for host in groups['all_hosts'] %}
- {{hostvars[host]['self_ip']}}:{{hostvars[host]['self_port']}}
{% endfor %}"
This seems to be creating a string. Not a list.
Can someone tell me what is wrong? And is there a way to use ansible filters to achieve this?
- set_fact:
all_endpoints: "{{ hosts|json_query('[].vars.[self_ip, self_port]') }}"
- set_fact:
touples: "{{ touples|default([]) + [ item.0 + ':' + item.1 ] }}"
loop: "{{ all_endpoints }}"
- debug:
var: touples
gives
"touples": [
"192.168.1.10:8001",
"192.168.1.11:8002"
]

How to reference a variable in ansible playbook?

I'm new to ansible. I can't get the answer in ansible website.
How to reference a variable in ansible playbook? eg:
- name: Set schedulability
hosts: oo_first_master
vars:
install_nodes: "{{ hostvars
| oo_select_keys(groups['oo_nodes_to_config'])
| oo_collect('open.common.hostname') }}"
install_node_vars: "{{ hostvars | oo_select_keys(groups['oo_nodes_to_config']) }}"
Seen "install_nodes" refered to like this:
- name: Wait for Node Registration
command: >
{{ install.common.client_binary }} get node {{ item | lower }}
register: omd_get_node
until: omd_get_node.rc == 0
retries: 20
delay: 5
changed_when: false
with_items: install_nodes
I think reference a variable should be involed with "{{ }}" in ansible playbook. But it's referenced directly. How many way to reference variables in ansible?
Regards
when, failed_when, changed_when, with_items, with_dict, etc expect a variable, so you don't have to use {{ }}, in all other cases use the double curly brackets.

Resources