Salt jinja2 and trailing lines inside a loop and if statement - jinja2

I can't figure out how to remove the last empty line from the output generated by a for and an if Jinja2 statments on SaltStack. I couldn't find a post pointing out the solution neither, as the solutions on internet that I could find don't involve for and if nested statements.
Any help is welcome, thanks.
This is what I tried so far:
{% for user in list_users -%}
{% if user.enabled == True -%}
{{ user.name }}:{{ user.passwd }}
{%- endif %}
{% endfor %}
user1:encrypted_pass
user2:encrypted_pass
user3:encrypted_pass
I also tried adding - at the beginning of the {endfor}:
{% for user in list_users -%}
{% if user.enabled == True -%}
{{ user.name }}:{{ user.passwd }}
{%- endif %}
{%- endfor %}
user1:encrypted_passuser2:encrypted_passuser3:encrypted_pass
Edit: this is the output that I am trying to achieve:
user1:encrypted_pass
user2:encrypted_pass
user3:encrypted_pass
PS: I had a look to the Jinja's whitespace control without success.

Related

How to dynamically call dbt macros using jinja?

I have a use case where I would like to define the name of a macro and then apply it to one column.
A simplified example could be as follows. I have two macros defined that I want to call dynamically in my model (both take one column as an input):
cast_to_string
convert_empty_string_to_null_value
Now, I want to call them dynamically. See the example below
{%- set macro_names = ["cast_to_string", "convert_empty_string_to_null_value"] -%}
select
{% for macro_name in macro_names %}
-- this should dynamically be evaluated to `{{ cast_to_string(my_column) }}`
-- and `{{ convert_empty_string_to_null_value(my_column) }}`
{{ macro_name(my_column) }}
{% endfor %}
from my_model
However, this will throw an error saying that a string is not callable.
I also tried using {% raw %} {{ {% endraw %} to escape brackets, but that didn’t work either.
So, my question is, if there is a way to dynamically call macros in jinja/dbt?
I think it should work if you remove the quotes :
{%- set macro_names = [cast_to_string, convert_empty_string_to_null_value] -%}
So that jinja doesn't interpret it as string and you can use it as a Callable
I achieve it using this example :
{%- set macro_names = [print_lower, print_upper] -%}
{% for macro_name in macro_names %}
{{ macro_name("test") }}
{% endfor %}
and
{% macro print_lower(string) %}
{{ print(string|lower) }}
{% endmacro %}
{% macro print_upper(string) %}
{{ print(string|upper) }}
{% endmacro %}

jinja2 using {if} within {for}

I'm trying to make a template which iterates over a list to check if a string exists. if it does then something happens, if the string isn't in the list, something else should happen. The issue is the result is repeated for all the lines in the list, which i do not want.
e.g.
The list is some simple yaml
LIST:
- A
- B
- C
Jinja looks like
{% for line in mylist %}
{% if 'A' in line %}
{{ A }} Was found in the list
{% else %}
{{ A }} Was not found
{% endif %}
{% endfor %}
So when 'A' matches i get this
A Was found in the list
A Was not found
A Was not found
And when 'A' does not match i get this:
A Was not found
A Was not found
A Was not found
Basically i need to stop it iterating over the list and just do one thing if it matches or one thing if it doesn't match
So if 'A' matches i need it to just do
A was found
If 'A' doesn't match i need it to just do A was not found
Use some kind of flag variable:
{% set ns = namespace(found=false) %}
{% for line in mylist %}
{% if 'A' in line %}
{% set ns.found=true %}
{% endif %}
{% endfor %}
{% if ns.foo %}
{{ A }} Was found in the list
{% else %}
{{ A }} Was not found
{% endif %}

Listing all the key-value properites in site.pages

On my blog, I have a debug page which lists several things, including all the properties for each page in site.pages, like so:
{%- for page in site.pages -%}
<strong>{{ page.path }}:</strong><br>
<table>
{% for key_value in page %}
{% if key_value[0] == "content" %}
<tr><td>content</td><td>[{{ key_value[1] | size }} characters]</td></tr>
{% else %}
<tr><td>{{ key_value[0] }}</td><td><span>{{ key_value[1] }}</span></td></tr>
{% endif %}
{% endfor %}
</table>
{%- endfor -%}
This produces output like this:
So far, so good.
Now, I want to do the exact same thing with site.posts, but it doesn't work.
In particular, key_value[0] and key_value[1] don't have any value. The iteration does produce something, but it is not a key an value.
For example, the following produces a list of key names:
{%- for pp in site.posts -%}
<strong>{{ pp.path }}:</strong><br>
{% for kv in pp %}
{% capture cap %}{{ kv }}{% endcapture %}
<div>{{ cap }}</div>
{% endfor %}
<br>
{%- endfor -%}
like so:
I can't seem to get the content of the properties in a generic way, however. I guess the type of the things in the site.posts is not the same as sites.pages, in particular not a simple liquid dictionary.
I've tried messing around with to_liquid mentioned here without luck.

Acessing csv in _data folder of Jekyll using an include tag

I am trying to simplify the organization and use of data for a Jekyll website. I am trying to access individual rows or values in the CSV, which is successful using this snippet:
{%- include speclocator.html name="Thing" -%}
Data is located in folders under the _data folder, as below:
_data/FOLDER1/specifications.csv,
_data/FOLDER2/specifications.csv,
_data/FOLDER3/specifications.csv,
etc.
The include to access the CSV by named column:
{%- for spec in site.data.FOLDER1.specifications -%}
{%- if spec.name == include.name -%}
{{ spec.value | strip }}
{% endif %}
{% endfor %}
The snippet in the post:
{%- for specification in site.data.FOLDER1.specifications -%}
<tr>
<td><strong>{{specification.name}}</strong></td>
<td>{{specification.value}}</td>
</tr>
{% endfor %}
How can I use a variable for FOLDER1, so that I can use this for multiple posts?
If you want to reuse your includes for multiple data sources, you can use bracket notation like this :
{%- include speclocator.html name="Thing" data_source="FOLDER1" -%}
or, if you have a page variable like data_source: FOLDER1
{%- include speclocator.html name="Thing" data_source=page.data_source -%}
In your include :
{%- for spec in site.data[include.data_source]["specifications"] -%}
{%- if spec.name == include.name -%}
{{ spec.value | strip }}
{% endif %}
{% endfor %}

Unable to find current post's category jekyll

I want to display keywords and description automatically according to the category of the current post. I've used the following code, but it doesn't worked.
{% if page.categories = "category" %}
{% else %}
{% endif %}
But while using {% page.categories %} it is echoing out the category name correctly. Here are my two doubts:
How can I compare the current post's category?
Are {{ }} and {% %} are same here?
It should look like the following:
{% if page.categories == 'some-name' %}
Hei I am in some-name category
{% else %}
No I am not in some-name category
{% endif %}
2.
No, {{ }} and {% %} are not the same. {{ }} is used for echoing stuff, while {% %} is used for logic expressions and arguments.