Jina2 template, Nested Ansible Condition - ansible

- set_fact:
{%- for IP in Neighbor_Info.keys() -%}
{%- if item['items']['key'] | string is IP | string -%}
Neighbor_Info[IP]: {{ Neighbor_Info[IP] + item[fetch][0][0] | regex_search(' [0-9]+') }}
{%- endif -%}
{%- endfor -%}
when: fetch in item.keys()
loop: "{{Prefix_Limit1['results']}}"
Error:
fatal: ]: FAILED! =>
msg: 'template error while templating string: Encountered unknown tag ''endif''. Jinja was looking for the following tags: ''endfor'' or ''else''. The innermost block that needs to be closed is ''for''.. String: {% for IP in Neighbor_Info.keys() if item[''items''][''key''] == IP -%} Neighbor_Info[IP]: {{ Neighbor_Info[IP] + item[fetch][0][0] | regex_search('' [0-9]+'') }} {% endif %} {% endfor -%}'
I want to update the value in a dictionary after matching the key value.
Once the match against the key is found, the value is appended in the list.
Dictionary
(item={'key': '192.168.123.9', 'value': ['xxx: 1', 'YYY: 0', 'ABCD']})

Related

List of other hosts in ansible, without the current host

I have these hosts in my hosts.yml file:
all:
hosts:
host1:
name: name1
port: port1
host2:
name: name2
port: port2
host3:
name: name3
port: port3
I want a string with all of my hosts in the hosts.yml file with ports like:
"http://name2:port2, http://name3:port3"
Without the current host (in my example, http://name1:port1).
I want this to be generated for each host when the ansible-playbook is run, and I want to pass it to my app in the startup process like (for host1):
$entrypoint.sh otherUrls="http://name2:port2, http://name3:port3"
I use this code to make the string:
otherUrls: "{%- for host in groups['all'] -%}
{%- if hostvars[host]['name'] is defined -%}
{%- if name != hostvars[host]['name'] -%}http://{{ hostvars[host]['name'] }}:{{ hostvars[host]['port'] }}
{%- if not loop.last -%}\", \"{% endif -%}
{% endif -%}
{% endif -%}
{% endfor -%}"
I made this with jinja2. But I still have an extra ',' at the end of the string for the last host. Are there any ideas to get rid of the problem?
I found a way to my problem without json_query:
{%- set groups_without_this = [] -%}
{% for host in groups['all'] -%}
{% if node_name != hostvars[host]['name'] -%}
{% do groups_without_this.append(host) -%}
{% endif -%}
{% endfor -%}
{%- for host in groups_without_this -%}
{%- if hostvars[host]['nname'] is defined -%}
{%- if name != hostvars[host]['name'] -%}http://{{ hostvars[host]['name'] }}:{{ hostvars[host]['port'] }}
{%- if not loop.last -%}\", \"{% endif -%}
{% endif -%}
{% endif -%}
{% endfor -%}
This code creates a new list without the current node and then constructs the "otherUrls" string.

ansible jinja2: nested dictionary

I'm trying to generate the following list:
list1:127.0.0.1,127.0.0.2
list2:192.168.1.1,192.168.1.254
From this dictionary:
ip_allowed:
list1:
- 127.0.0.1
- 127.0.0.2
list2:
- 192.168.1.1
- 192.168.1.254
Using the following jinja2 Ansible template:
#ZONE HOST(S) OPTIONS
{% for hosts_key, hosts_value in ip_allowed.iteritems() %}
{% set hosts_dict = hosts_value %}
{% for item in hosts_dict %}
{{ hosts_key }} {{ item }}
{%- if loop.first %},{% endif %}
{% endfor %}
{% endfor %}
But I'm getting the following result:
#ZONE HOST(S) OPTIONS
list1 127.0.0.1, list1 127.0.0.2 list2 192.168.1.1, list2 192.168.1.254
I'm not entirely sure I got the exact format you want out of the template but you'll adapt if needed once you get the idea. Just join each ip in the value.
#ZONE HOST(S) OPTIONS
{% for allowed_item in (ip_allowed | dict2items) %}
{{ allowed_item.key }} {{ allowed_item.value | join(',') }}
{% endfor %}

set interface name in a variable with jinja loop on ansible

i want to set inside a variable interface name if is equals to a variable pass on command line so i'm using jinja like this :
- name: Inizializzo la rete
hosts: all
gather_facts: true
become: yes
become_user: root
tasks:
- name: stampo interfacce
set_fact:
privata: "{% for interfacce in ansible_interfaces %} {% set int_tmp = 'ansible_facts.' ~ interfacce ~ '.macaddress' %} {% if {{int_tmp}}==mac_privata %} {{interfacce}} {% endif %} {% endfor %}"
- name: Stampo
debug:
msg: "{{privata}}"
but it doesn't works
i call this :
ansible-playbook test.yml --extra-vars "mac_privata=00:50:56:b7:bc:f1"
i do this because i've more than three interface
where i'm wrong?
EDIT:
#mdaniel
Thanks for your answer but it seems that it doesn't substitute hostvars['ansible_' ~ interfacce ~ '.macaddress'] with content of ansible_ens32.macaddress.
For example i do this :
- name: Stampo
debug:
msg: "{{ ansible_ens32.macaddress }}"
i've this output :
TASK [Stampo] **********************************************************************************************************************************************
ok: [10.150.20.130] => {
"msg": "00:50:56:b7:bb:f1"
}
but if i do this :
- name: stampo interfacce
set_fact:
privata: >-
{%- for interfacce in ansible_interfaces -%}
{%- if interfacce != 'lo' -%}
{%- set int_tmp = hostvars['ansible_' ~ interfacce ~ '.macaddress'] -%}
{%- if int_tmp == mac_privata -%}
{{ interfacce }}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
- name: Stampo
debug:
msg: "{{privata}}"
I'm expecting name of interface with mac_privata macaddress in privata variable if i do this :
ansible-playbook test.yml --extra-vars "mac_privata=00:50:56:b7:bb:f1"
i've ens_32 but it's empty:
TASK [stampo interfacce] ***********************************************************************************************************************************
task path: /mnt/c/Users/francesco.ferraro/ansible_test/test.yml:7
ok: [10.150.20.130] => {
"ansible_facts": {
"privata": ""
},
"changed": false
}
Any time one sees {{ inside another jinja2 context, it's almost certainly not what you what to happen. To dynamically look up a variable, use either vars[""] or hostvars[""], or if you prefer the lookup("vars", "")
privata: >-
{%- for interfacce in ansible_interfaces -%}
{%- set int_tmp = vars['ansible_facts.' ~ interfacce ~ '.macaddress'] -%}
{%- if int_tmp == mac_privata -%}
{{ interfacce }}
{%- endif -%}
{%- endfor -%}
Most cases support the conditional for loop, which can make the snippet a little shorter
privata: >-
{%- for interfacce in ansible_interfaces
if mac_privata == vars['ansible_facts.' ~ interfacce ~ '.macaddress'] -%}
{{ interfacce }}
{%- endfor -%}

Result from Jinja2 template returned as string in Ansible

I try to set a variable on ansible using the jinja2 templates. In my playbook I have this:
- set_fact:
restart: |
{% for host in groups['primary'] %}
{% if hostvars[host].arbiter_host == inventory_hostname_short %}
{{ restart | combine(hostvars[host].restart | dict2items | selectattr('key', 'regex', 'mongod_\d+$') | list | items2dict) }}
{% endif %}
{% endfor %}
- debug:
var: restart
The result is this one
ok: [my_host] => {
"restart": "{u'mongod_01': True}\n{u'mongod_02': True}\n"
}
Which is almost fine, but the data is given as a single string. I need the get an dict as this:
ok: [my_host] => {
"restart": {
"mongod_01": true,
"mongod_02": true,
}
}
I tried almost everything, but noting succeeded. How to transform from string to dict object?
btw, it work fine when the dict object holds only one item but it fails with two or more.
Finally I found a solution:
set_fact:
restart: |
{% set services = {} %}
{% for host in groups['primary'] %}
{% if hostvars[host].arbiter_host == inventory_hostname_short %}
{% set _ = services.update(hostvars[host].restart | dict2items | selectattr('key', 'regex', 'mongod_\d+$') | list | items2dict) %}
{% endif %}
{% endfor %}
{{ restart | combine(services) }}
Gives the desired result.

Ansible concat vars to string

I've spent most of the day trying to solve this problem and have thus far failed. I am building some playbooks to automate functions in Splunk, and am attempting to convert a list of hosts from an inventory group E.G.
[search_head]
1.2.3.4
5.6.7.8
My expected (desired) result from the debug output of the play should be:
https://1.2.3.4:8089, https://5.6.7.8:8089
I am attempting to complete this by running the following playbook against a running host:
---
- name: Build search head list to initialize the captain
hosts: search_head
remote_user: ansible
vars:
inventory_file: ./inventory-ec2-single-site
search_head_uri: "{{ lookup('template', './bootstrap-sh-deployer.j2') }}"
pre_tasks:
- include_vars:
dir: 'group_vars'
extensions:
- yml
- yaml
tasks:
- name: dump array
debug:
msg: "{{ search_head_uri }}"`
With the template bootstrap-sh-deployer.j2:
{%- set search_head_uri = [] %}
{% for host in groups['search_head'] %}
{%- if search_head_uri.append("https://{{ host }}:8089") %}
{%- endif %}
{%- if not loop.last %}, {% endif -%}
{%- endfor %}
However, the current play returns search_head_uri: ", " which tells me that the loop is running, but {{ host }} is not resolving.
Once you open a Jinja2 expression or a statement you should use Jinja2 syntax. You cannot nest them (i.e. you can't use {{ }} inside {% %}).
{%- if search_head_uri.append("https://" + host + ":8089") %}
This worked - Combination of the answer above to fix jinja formatting and using hostvars to get to the ansible_nodename.
{%- set search_head_uri = [] %}
{% for host in groups['search_head'] %}
{{ "https://" + hostvars[host]['ansible_nodename'] + ":8089" }}
{%- if not loop.last %}, {% endif -%}
{%- endfor %}

Resources