set interface name in a variable with jinja loop on ansible - 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 -%}

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.

Jina2 template, Nested Ansible Condition

- 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']})

Ansible jinjia2 template whitespaces control

Question
How do I get the desired output?
Code
yaml
nodeStatusUpdateFrequency:
{% if nodeStatusUpdateFrequency is defined -%}
{{ nodeStatusUpdateFrequency }}
{% else -%}
{%- if nodeStatusUpdate == 'Fast' -%}
4s
{%- elif nodeStatusUpdate == 'Medium' -%}
20s
{%- elif nodeStatusUpdate == 'Low' -%}
1m
{% else -%}
10s
{% endif %}
{%- endif %}
oomScoreAdj: -999
Output:
My current output is:
nodeStatusUpdateFrequency: $x
oomScoreAdj: -999
Desired Output:
My expected output is:
nodeStatusUpdateFrequency: $xoomScoreAdj: -999
Your template is OK. The play below with copy&paste of your template
vars:
nodeStatusUpdateFrequency: "$x"
nodeStatusUpdate: "NONE"
tasks:
- template:
src: test-template.j2
dest: /scratch/test.txt
gives:
# cat /scratch/test.txt
nodeStatusUpdateFrequency: $x
oomScoreAdj: -999
You are simply missing the minus (-) signs on some of your endif control structures. This is doing the job as you expect:
nodeStatusUpdateFrequency:
{%- if nodeStatusUpdateFrequency is defined -%}
{{ nodeStatusUpdateFrequency }}
{%- else -%}
{%- if nodeStatusUpdate == 'Fast' -%}
4s
{%- elif nodeStatusUpdate == 'Medium' -%}
20s
{%- elif nodeStatusUpdate == 'Low' -%}
1m
{%- else -%}
10s
{%- endif -%}
{%- endif -%}
oomScoreAdj: -999

Creating a comma separated string from a dictionary in Ansible

I want to write an Ansible role to be able to alter a given Kafka topic. I am using a dictionary of key/value pairs.
The command module is then used to execute a Kafka script that take a string of comma separated values. For instance, use app_kafka_topic list:
---
app_kafka_topic:
cleanup.policy :
- "delete"
retention.ms :
- "146800000"
partitions :
- "6"
replication-factor :
- "2"
and create the string:
"cleanup.policy=delete,retention.ms=146800000,partitions=6,replication-factor=2"
This is what I have so far.
- name: Reading the Default Topic Properties
set_fact:
app_kafka_topic_properties_dicts: |
{% set res = [] -%}
{% for key in app_kafka_topic.keys() -%}
{% for value in app_kafka_topic[key] -%}
{% set ignored = res.extend([{'topic_property': key, 'value':value}]) -%}
{%- endfor %}
{%- endfor %}
{{ res }}
- name: Create Topic with Default Properties
command: "{{ kafka_bin_dir }}/{{ kafka_config_script }}
--zookeeper {{ prefix }}-kafka-{{ Kafka_node }}.{{ DNSDomain}}:{{ zookeeper_port }}
--entity-type topics
--alter
--entity-name {{ kafka_topic }}
--add-config
{{ properties }}"
with_items: "{{ app_kafka_topic_properties_dicts }}"
register: createdTopic
vars:
properties: |-
{% for key in app_kafka_topic.keys() %}
{% for value in app_kafka_topic[key] %}
"{{ key }}={{ value }}"
{%- endfor %}
{%- endfor %}
However, the properties variable is not concatenating the values to the end of a string. Is there a way to append the values to a string and separate them by a comma?
Is this the code that you're looking for?
play.yml
- hosts: localhost
gather_facts: no
vars:
string: ""
app_kafka_topic:
cleanup.policy :
- "delete"
retention_ms :
- "146800000"
partitions :
- "6"
replication_factor :
- "2"
tasks:
- set_fact:
string: "{{ string }}{{ (index > 0)|ternary(',','') }}{{ item.key }}={{ item.value[0] }}"
loop: "{{ app_kafka_topic|dict2items }}"
loop_control:
index_var: index
- debug:
var: string
$ ansible-playbook play.yml | grep string
"string": "retention_ms=146800000,cleanup.policy=delete,replication_factor=2,partitions=6"

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