hosts
[mesosSandbox]
mesos1-01d.chalybs.net zoo_id=1
mesos1-02d.chalybs.net zoo_id=2
mesos1-03d.chalybs.net zoo_id=3
mesos1-04d.chalybs.net
mesos1-05d.chalybs.net
I have a template that generates the zookeeper zoo.cfg
{% for server in groups[cluster] %}
server.{{loop.index}}={{server}}:2888:3888
{% endfor %}
Is there a way to add an if zoo_id is defined to this loop or can I generate a list via a task in the playbook?
Ansible's if var is defined syntax is derived from jinja. You should be able to check for zoo id right in the loop:
{% for server in groups[cluster] %}
{% if zoo_id is defined %}
server.{{loop.index}}={{server}}:2888:3888
{% endif %}
{% endfor %}
I can't say whether this will compile/run without seeing more of your playbook, but assuming the loop in your question works as is, this will allow you to filter on whether zoo_id is defined.
Ansible's template syntax is Jinja2, so you can use it right away.
Also, you need to access zoo_id for the target host using hostvars array.
{% for server in groups[cluster] %}
{% if hostvars[server].zoo_id is defined %}
server.{{loop.index}}={{server}}:2888:3888
{% endif %}
{% endfor %}
You may need to load delegate facts before being able to access hostvars, but I believe it's not needed if you need to access anything defined directly in the inventory.
Related
I want to loop over all of the collections in my Jekyll site, and within that I want to sort and list all of the pages in that collection.
Based on this stackoverflow answer, I can loop through all the collections and items:
{% for collection in site.collections %}
<h2>Items from {{ collection.label }}</h2>
<ul>
{% assign pages = site[collection.label] %}
{% for item in pages %}
<li>{{ item.title }}</li>
{% endfor %}
</ul>
{% endfor %}
For a specific collection, I can also sort the update field from the frontmatter:
{% assign sorted = site.programming | sort: 'update' %}
But if I try to apply this to the 1st example, it fails:
{% assign pages = site[collection.label] | sort: 'update' %}
This gives a rather generically useless error:
Liquid Exception: Liquid error (line 30): comparison of Array with Array failed in index.md
Error: Liquid error (line 30): comparison of Array with Array failed
Error: Run jekyll build --trace for more information.
I'm guessing that somehow site[collection.label] returns something different than site.programming, but I'm not sure what, or how to solve this.
EDIT: I tried using collection.docs instead of site[collection.label] and got the same error.
The cause of this error turned out not to be the difference between collection.docs and site[collection.label]. Rather, in one of the collections, there was an item where the frontmatter did not contain the update field. As a result, it couldn't sort by this field because not all items had it. Similarly, you get the same error if the types are not comparable in all cases. In this case, they were all supposed to be dates; if one was not a valid date format, it failed.
I still think this is a terribly ambiguous error message.
I want something like:
---
my_var: "foo.bar.baz"
---
{{- site.data.header[page.my_var] -}}
Unfortunately, it doesn't work…
I know that I can use site.data.header.foo.bar.bazor site.data.header["foo"]["bar"]["baz"], but it's not that.
Also I know that I can split page.my_var to substrings and use them then as site.data.header["foo"]["bar"]["baz"]. But this increases Jekyll build time.
I guess I need some Ruby plugin, but don't know one and I don't know Ruby to write one.
If you know such plugin or can help me write one or know some native workaround, this would be sooo great!
Help :)
Also I know that I can split page.my_var to substrings and use them then as site.data["foo"]["bar"]["baz"]. But this increases Jekyll build time.
I'm not sure you can do this. And even if you can, I'm not sure that there is a real performance impact.
But you can do this :
_data/foo.yml
bar:
baz: 1
biz: 2
buz: 3
beer:
baz: 1
biz: 2
buz: 3
Then :
---
my_var: "foo.bar.baz"
---
{% assign keys = page.my_var | split: "." %}
{% assign object = site.data %}
{% for key in keys %}
{% assign object = object[key] %}
{% endfor %}
{{ object }}
What are hoping to do has been blocked by design.
site.data["foo.bar.baz"] implies that you need to have a data file named foo.bar.baz.yml or foo.bar.baz.json, ... etc.
But Jekyll sanitizes data files' names and therefore the resulting object would only have a key named "foobarbaz"
A plugin that purposely removes this sanitization can written but it wouldn't appear to be a benign or safe to end-users. So the chances of finding such a plugin in the wild is slim..
I have a nested yaml data file for my jekyll blog like so:
Nickname1:
name: John
address: Johnstreet 1
Nickname2:
name: Rudolf
address: Rudolfstreet 1
I use this to print additional information after each post, which I specify in the front matter. This works fine.
I now wish to create a site that lists all entries of this data file. This should in theory be easy:
{% for nickname in site.data.NAMEOFFILE %}
<li> {{ nickname.address }} </li>
{% endfor %}
However, this does not work because the YAML data is nested. The data has to remain nested, and each entry needs to have a different nickname. The problem with that is of course that I am unable to loop over all entries, because they are all differently named.
Can you folks help me out here? Is there any way in which I can achieve this without changing the nested structure of my data file? Changing the nested structure would break large parts of my site.
Jekyll data files can be set up in two formats: list or dictionary (not the official terminology, but that's what I call them and what helps me understand them).
Lists are used for iteration. Dictionaries are used for looking up an individual item and shouldn't be used in iteration.
// list.yml
- nickname: Nickname1
name: John
address: Johnstreet 1
- nickname: Nickname2
name: Rudolf
address: Rudolfstreet 1
...
// usage
{% for person in site.data.list %}
<li> {{ person.address }} </li>
{% endfor %}
// dictionary.yml
Nickname1:
name: John
address: Johnstreet 1
Nickname2:
name: Rudolf
address: Rudolfstreet 1
...
// usage
{% assign person = site.data.dictionary['Nickname1'] %}
<ul>
<li> {{ person.address }} </li>
</ul>
I have the same data in two different files: one in a list format and one in a dictionary format. That lets me iterate or do specific lookups whenever I need. Drawbacks are that you have duplicated data across two different files and need to maintain consistency whenever you make changes.
To solve your specific problem, I would make another data file with the data formatted into a list so that you can iterate through the data. This means you don't need to change the file with the nested structure and can avoid breaking the site.
Jekyll docs example on 'dictionary' usage
Jekyll docs example on 'list' usage
When you iterate over an object, the iteration variable is a two-element array with the key at index 0 and the value at index 1:
<ul>
{% for nickname in site.data.people -%}
<li>
{{ nickname[0] }}: name {{ nickname[1].name }},
address {{ nickname[1].address }}
</li>
{% endfor %}
</ul>
renders (after whitespace cleanup) as
<ul>
<li>Nickname1: name John, address Johnstreet 1</li>
<li>Nickname2: name Rudolf, address Rudolfstreet 1</li>
</ul>
Weirdly, I can't find this described anywhere in the Liquid docs, neither on the Jekyll site nor in the official documentation. The only reference I've seen is on the platformOS documentation page.
I really want to use datatable for big data with runtime custom query .I have tried django-datatable but seem , it have only static custom query. thanks
I took a quick look at django-datatable; the only thing it seems to do if provide a template tag to render entire DB tables to HTML responses.
{% load table_tags %}
...
{% render_table people %}
If you want custom DB queries in django, the normal way is to use the ORM, i.e.
#!/usr/bin/env python
from models import Person
from django.shortcuts import render_to_response
...
def some_view(...):
a_people = Person.objects.filter(name__startswith="A")
return render_to_response(<template>, context={"people":a_people})
// HTML template
...
{% for person in people %}
<tr><td>{{ person.id }}</td><td>{{ person.name }</td></tr>
{% endfor %}
...
This allows you all freedom to define a dynamic DB query in your python code.
I'm trying to use a sandboxed Jinja2 environment to handle template customizations.
I've tried using both a DictLoader and FunctionLoader, but keep running into similar issues... I'm mostly concerned with FunctionLoader now.
I can't manage to include or import another template (which contains macros). The FuctionLoader's specified "load" function is never called for the referenced templates.
I've tried with no luck:
just expecting an import would hit the loader using basic 'import' and 'include' syntax
passing the loader into the context , seeing if it might pull in that way
passing a dict of templates into the context, also hoping it might pull in
a few more things , all of which I forgot
I'm sure there's got to be a way to support this - can someone point me in the right direction ?
The import syntax must use quoted strings.
Bad:
{% import utils %}
{% import utils.macros as macros %}
{% from utils.macros import macro_1 , macro_2 %}
Good:
{% import "utils" as utils %}
{% import "utils.macros" as macros %}
{% from "utils.macros" import macro_1 , macro_2 %}
The quoted string is passed into the FunctionLoader or used as the key with the DictLoader