Writing file templates

BundleWrap uses Mako for file templating by default (Jinja2 is also available). This enables you to dynamically contruct your config files. Templates reside in the files subdirectory of a bundle and are bound to a file item using the source attribute. This page explains how to get started with Mako.

The most basic example would be:

Hello, this is ${node.name}!

After template rendering, it would look like this:

Hello, this is myexamplenodename!

As you can see, ${...} can be used to insert the value of a context variable into the rendered file. By default, you have access to two variables in every template: node and repo. They are bundlewrap.node.Node and bundlewrap.repo.Repository objects, respectively. You can learn more about the attributes and methods of these objects in the API docs, but here are a few examples:


inserts the DNS hostname of the current node

${node.hostname}

a list of all nodes in your repo

% for node in repo.nodes:
${node.name}
% endfor

make exceptions for certain nodes

% if node.name == "node1":
option = foo
% elif node.name in ("node2", "node3"):
option = bar
% else:
option = baz
% endif

check for group membership

% if node.in_group("sparkle"):
enable_sparkles = 1
% endif

check for membership in any of several groups

% if node.in_any_group(("sparkle", "shiny")):
enable_fancy = 1
% endif

check for bundle

% if node.has_bundle("sparkle"):
enable_sparkles = 1
% endif

check for any of several bundles

% if node.has_any_bundle(("sparkle", "shiny")):
enable_fancy = 1
% endif

list all nodes in a group

% for gnode in repo.get_group("mygroup").nodes:
${gnode.name}
% endfor

Working with node metadata

Quite often you will attach custom metadata to your nodes in nodes.py, e.g.:

nodes = {
        "node1": {
                "metadata": {
                        "interfaces": {
                                "eth0": "10.1.1.47",
                                "eth1": "10.1.2.47",
                        },
                },
        },
}

You can easily access this information in templates:

% for interface, ip in node.metadata["interfaces"].items():
interface ${interface}
        ip = ${ip}
% endfor

This template will render to:

interface eth0
        ip = 10.1.1.47
interface eth1
        ip = 10.1.2.47