Im trying to set a global variable within a jinja2 template so i can set variables inside and outside of a loop. I've used this before and its worked but in this case it doesnt and i'm struggling to find out why.
This is my j2 template.
{% set found = namespace() %}
{% set vrf = namespace() %}
{% for group_item in site_master_list -%}
{% for host_item in site.list -%}
{% if group_item.ip_addr != host_item.ip_addr %}
none match {{ group_item.ip_addr }} none match {{ host_item.ip_addr }}
{% set found.tracker = false %}
does it have vrf {{ host_item.vrf }}
{% if host_item.vrf != "" %}
{% set vrf = namespace(id=host_item.vrf) %}
vrf {{ vrf }}
vrf.id {{ vrf.id }}
{% endif %}
{% endif %}
{% endfor %}
bottom vrf {{ vrf }}
{%- endfor %}
This is the output
bottom vrf <Namespace {}>none match 10.180.193.235 none match 10.112.208.11
does it have vrf management
vrf <Namespace {'id': 'management'}>
vrf.id management
bottom vrf <Namespace {}>
As you can see i'm setting host_item.vrf to the namespace vrf so i can use vrf.id outside of the loop further down the template.
Where i've got bottom vrf {{ vrf }} you can see in the output the empty namespace where it shows
bottom vrf <namespace {}>
Returning vrf.id within the loop returns management the correct value and all is good.
Anyone got any suggestions why i cant return vrf.id outside of the inner loop? I was returning vrf.id but Ansible returns the below which is correct because 'id' doesn't exist at that stage in the template.
''jinja2.utils.Namespace object'' has no attribute ''id'''
Thanks
I've fixed this by replacing
{% set vrf = namespace(id=host_item.vrf) %}
With
{% set vrf.value = host_item.vrf %}
Not sure why this worked previously but the latter works.
Related
I want to display the value of a specific product tag in my shopify store.
The product tag always starts with Color_ followed by the color Color_Green
I want to display only green. (I can use split or slice for that part)
But I can't figure out to only display the tag that starts with Color_ because I have multiple tags added to my products.
This is my code for now:
{%- for tag in product.tags -%} {%- assign tag_prefix = tag %} {%- if tag_prefix == "Color_" -%} {%- endif -%} {%- endfor -%}
Try this snippet
{% for tag in product.tags %}
{% assign tag_prefix = tag %}
{% if tag_prefix contains "Color_" %}
{% assign tagValue = tag_prefix | replace: "Color_", "" %}
{{ tagValue }}
{% endif %}
{% endfor %}
I want to use the n values in the next for statement and I expect output as router_0, router_1. But any optisons like router_[n], router_{{ n }}, router_(n) etc didnt work. How can we do this?
{% for n in range(0, 2) %}
{% for rtr in web.router_[n] %}
{% if rtr.interface.type == 'lacp' %}
interface Port-Channel{{ rtr.interface.id }}
.
{% endif %}
{% endfor %}
{% endfor %}
In vars.yaml, there are variables for paired routers, router_0 and router_1. I want to generate the config template for both routers at the same time.
Thanks,
Concatenate the name of the attribute
{% for rtr in web['router_' ~ n] %}
I have the below jinja code to conditionally concatenate strings depending on two variables. Whilst it (probably) works it looks unwieldy, but I'd have thought this was a common thing to do when rendering.
{% if item.route %}
{% if item.route_follow and item.route_external %} {% set route_rel = 'external' %}
{% elif not item.route_follow and not item.route_external %} {% set route_rel = 'nofollow' %}
{% elif not item.route_follow and item.route_external %} {% set route_rel = 'nofollow external' %}
{% else %} {% set route_rel = '' %}
{% endif %}
{% endif %}
Is there a better way, maybe a one-liner?
When I got to the end of this I realised the answer:
{% if item.route %}
{% set route_rel = ['' if item.route_follow else 'nofollow', 'external' if item.route_external else '']|reject('==','')|join(' ') %}
{% endif %}
Sometimes, you just have to look at it again...
This question already has an answer here:
Pushing items to a var while looping over another var in Ansible Jinja2 template
(1 answer)
Closed 4 years ago.
I'm trying to calculate the needed space based on the longest word in a dictionary.
It seems though that the variable num doesn't transfer it's value to the second inner loop.
I'm basically trying to caculate the amount of spaces to align the columns correctly.
{% for module in modules %}
module "{{ module.name }}" {
source = "{{ module.source }}"
{% set num = 1 %}
{% for n in module.vars.keys() %}
{% if num < n|length %}
{% set num = n|length %}
{% endif %}
{{ num }}: {{ n }}
{% endfor %}
{% for m in module.vars %}
{{ num }}
{{ m }} {{ '= "' + module.vars[m]|indent(width=num) }}"
{% endfor %}
}
You're right, you can't get variables out of loops this way. See "Scoping behavior" in the docs.
One option is to use what they suggest and create a namespace:
{% set ns = namespace(num=0) %}
{% for n in module.vars.keys() %}
{% if ns.num < n|length %}
{% set ns.num = n|length %}
{% endif %}
{{ ns.num }}: {{ n }}
{% endfor %}
In your case, there is an easier and cleaner solution though: you can calculate the maximum width in an expression. Use map() to get a list of lengths, and use max filter to get the biggest one:
{% set indent_width = module.vars.keys() | map("length") | max %}
{% for m in module.vars %}
{{ m }} {{ '= "' + module.vars[m]|indent(width=indent_width) }}"
{% endfor %}
I am trying to generate some config using Jinja2 templating and Ansible variables. The framework under which I am currently working does not allow me to perform the following operation in Ansible and thus I was hoping to achieve the same results in Jinja2.
My Ansible variables are as follows:
---
Top:
inner:
type: type1
other_random_variable:
- random: 1
inner2:
type: type2
inner3:
type: type1
The above structure works well when I am iterating over a loop and forming a configuration file as follows:
{% if Top is defined %}
{% for inner_vars in Top %}
# perform substitution here
{% endfor %}
{% endif %}
What I would like to do is to form a set of types such that I can generate another configuration for each unique type.
Is there any way for me to iterate through Top and add an item to a set?
I think I have a solution that could work:
{% set types = [] %}
{% if Top is defined%}
{% for inner_var in Top %}
{% if types.append(Top[inner_var].type) %}{% endif %}
{% endfor %}
{% endif %}
{{ types|unique }}