Ansible template adds 'u' to array in template - ansible

I have the following vars inside of my ansible playbook I got the following structure
domains:
- { main: 'local1.com', sans: ['test.local1.com', 'test2.local.com'] }
- { main: 'local3.com' }
- { main: 'local4.com' }
And have the following inside of the my conf.j2
{% for domain in domains %}
[[acme.domains]]
{% for key, value in domain.iteritems() %}
{% if value is string %}
{{ key }} = "{{ value }}"
{% else %}
{{ key }} = {{ value }}
{% endif %}
{% endfor %}
{% endfor %}
Now when I go in the VM and see the file I get the following:
Output
[[acme.domains]]
main = "local1.com
sans = [u'test.local1.com', u'test2.local.com']
[[acme.domains]]
main = "local3.com"
[[acme.domains]]
main = "local4.com"
Notice the u inside of the sans array.
Excpeted output
[[acme.domains]]
main = "local1.com"
sans = ["test.local1.com", "test2.local.com"]
[[acme.domains]]
main = "local3.com"
[[acme.domains]]
main = "local4.com"
Why is this happening and how can I fix it?

You get u' ' because you print the object containing the Unicode strings and this is how Python renders it by default.
You can filter it with list | join filters:
{% for domain in domains %}
[[acme.domains]]
{% for key, value in domain.iteritems() %}
{% if value is string %}
{{ key }} = "{{ value }}"
{% else %}
{{ key }} = ["{{ value | list | join ('\',\'') }}"]
{% endif %}
{% endfor %}
{% endfor %}
Or you can rely on the fact, that the string output after sans = is a JSON and render it with to_json filter:
{{ key }} = {{ value | to_json }}
Either will get you:
[[acme.domains]]
main = "local1.com"
sans = ["test.local1.com", "test2.local.com"]
[[acme.domains]]
main = "local3.com"
[[acme.domains]]
main = "local4.com"
But the first one is more versatile.

Related

How can I output social url's in JSON+LD from a yaml data file?

My code will capture items from the data file. I need those to be comma separated. I've had no luck!
Data File socialmedia.yml
facebook:
id: 'dpcgco'
href: 'https://www.facebook.com/'
title: 'Facebook'
fa-icon: 'fa-facebook-square'
twitter:
id: 'DenverProphitJr'
href: 'https://www.twitter.com/'
title: 'Twitter'
fa-icon: 'fa-twitter-square'
I have tried this. It doesn't comma separate them, though:
"sameAs":[
{% if site.data.socialmedia %}
{% assign sm = site.data.socialmedia %}
{% for entry in sm %}
{% assign key = entry | first | split%}
{% if sm[key].id %}
{% capture social %}{{ sm[key].href }}{{ sm[key].id }}{% endcapture %}
{{ social | replace: " ", "," | jsonify }}
{% endif %}
{% endfor %}
{% endif %}
],
Desired Output Format:
"sameAs": [
"http://www.facebook.com/your-profile",
"http://instagram.com/yourProfile",
"http://www.linkedin.com/in/yourprofile",
"http://plus.google.com/your_profile"
]
Actual Invalid Output:
"sameAs":[ "https://www.facebook.com/dpcgco" "https://www.twitter.com/DenverProphitJr" ],
You have to check if an item is the last in the forloop.last.
{% if site.data.socialmedia %}
{% assign sm = site.data.socialmedia %}
"sameAs":[
{% for entry in sm %}
{% assign key = entry | first %}
{% if sm[key].id %}"{{ sm[key].href }}
{{ sm[key].id }}",
{% if forloop.last %}
"{{ sm[key].href }}{{ sm[key].id }}"
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
],

How do i specify variable as alt attribute in a liquid HTML filter

Im trying to append the name of the variable in img alt attribute,
from the official documentation, they're hard-code the alt text.
is there any working solution?
{% for product in products %}
{{ product | img_tag: 'Picture of {{ product.name }}' }}
{% endfor %}
Thank you
You must do your logic outside and pass it as a variable.
{% for product in products %}
{%- capture image_alt -%}Picture of {{ product.title }}{%- endcapture -%}
{{ product | img_tag: image_alt }}
{% endfor %}
And there is no product.name object but there is product.title.

Ansible loops matching on array/dict_list

I have an array like so
our_domains:
- domain: www.example.com
urls:
- { path: '/' }
- { path: '/test1' }
- domain: www.example2.com
urls:
- { path: '/' }
- { path: '/test2' }
and in a template I want to match on a given domain and then loop over the contents of urls
e.g
{% if item.value.domain == 'www.example2.com' %}
{% for item_url in item.urls %}
service_description http://anotherwebsite.com{{ item_url['path'] }}
{% endfor %}
{% endif %}
Im sure the FOR loop will work ok as its working in a similar context elsewhere in the code.
Im just struggling getting a conditional match on the domain name.
Any help would be appreciated
Thanks
it looks like you want to execute the template task for each of the elements of the our_domains list.
you should just remove the value from the if statement, rest looks fine:
{% if item.domain == 'www.example2.com' %}
{% for item_url in item.urls %}
service_description http://anotherwebsite.com{{ item_url['path'] }}
{% endfor %}
{% endif %}
if on the other hand, your intention was to generate only 1 file, you should use this template (one more for loop added enclosing the previous code):
{% for item in our_domains %}
{% if item.domain == 'www.example2.com' %}
{% for item_url in item.urls %}
service_description http://anotherwebsite.com{{ item_url['path'] }}
{% endfor %}
{% endif %}
{% endfor %}

Ansible jinja block

How to comment a particular line only by using jinja template.
I have my line
/var/log/maillog
I have tried
{% comment %}{{ var }} {% endcomment %}
also
{% if var is defined %}
{{ var }}
{% endif %}
Can you try this:
{# {{ var }} #}

Why doesn't this Jekyll Liquid where filter filter?

I am trying to output a list of blog posts for a certain author. I tried this where Jekyll filter:
{% for post in (site.posts | where:"author", "mike") %}
{{ post.title }}
{% endfor %}
But it outputs every post. I'm not clear what I'm doing wrong.
Supposing that your post author is in your front matter, like this :
---
author: toto
...
---
If you want two last post by author == toto, just do :
{% assign counter = 0 %}
{% assign maxPostCount = 2 %}
<ul>
{% for post in site.posts %}
{% if post.author == 'toto' and counter < maxPostCount %}
{% assign counter=counter | plus:1 %}
<li>{{ counter }} - {{ post.title }}</li>
{% endif %}
{% endfor %}
</ul>
Et hop !
EDIT :
And another solution using the where filter instead of the if clause :
{% assign posts = site.posts | where: "author", "toto" %}
{% assign counter2 = 0 %}
{% assign maxPostCount2 = 3 %}
<ul>
{% for post in posts %}
{% if counter2 < maxPostCount2 %}
{% assign counter2=counter2 | plus:1 %}
<li>{{ counter2 }} - {{ post.title }}</li>
{% endif %}
{% endfor %}
</ul>
RE-EDIT: Justin is right I don't need my two vars (counter2 and maxPostCount2), I can use Liquid for loop limit:n option.
{% assign posts = site.posts | where: "author", "toto" %}
<ul>
{% for post in posts limit:3 %}
<Ol>{{ post.title }}</ol>
{% endfor %}
</ul>
Better !
You need to do an assign first for the filtered items
{% assign posts = site.posts | where:"author", "mike" %}
{% for post in posts %}
{{ post.title }}
{% endfor %}
It seems filters are to be used only inside output tags (those surrounded by {{ and }}. Which mean you could use something like :
{{ site.posts | where "author", "mike" }}
But you can't use it the way you're doing.
Source: liquid documentation on Filters

Resources