Skip to content

Input Type | Jinja2

This input type is probably the most simple input type to use: it is very versatile and is commonly used to create scripts and documentation files.

It renders jinja2 templates.

Example configuration

Here's some configuration from the nginx example

examples/kubernetes/inventory/classes/component/nginx-common.yml

  templates: #(1)!
    - docs/nginx/README.md
    - components/nginx-deploy.sh

  kapitan:
    compile:
      - output_path: . #(2)!
        input_type: jinja2
        input_paths: ${templates} #(3)!
  1. We define a list with all the templates we want to compile with this input type
  2. Then input type will render the files a the root of the target compiled folder e.g. compiled/${target_name}
  3. We pass the list as input_paths

Notice how make use of variable interpolation to use the convenience of a list to add all the files we want to compile. You can now simply add to that list from any other place in the inventory that calls that class.

  • input_paths can either be a file, or a directory: in case of a directory, all the templates in the directory will be rendered.
  • input_params (optional) can be used to pass extra parameters, helpful when needing to use a similar template for multiple components in the same target.

Documentation

We usually store documentation templates under the templates/docs directory.

examples/kubernetes/docs/nginx/README.md

{% set i = inventory.parameters %}

# Welcome to the README!

Target *{{ i.target_name }}* is running:

* {{ i.nginx.replicas }} replicas of *nginx* running nginx image {{ i.nginx.image }}
* on cluster {{ i.cluster.name }}

Compiled result

# Welcome to the README!

Target *minikube-nginx-jsonnet* is running:

* 1 replicas of *nginx* running nginx image nginx:1:15.8
* on cluster minikube

Scripts

When we use Jinja to render scripts, we tend to call them "canned scripts" to indicate that these scripts have everything needed to run without extra parameters.

We usually store script templates under the templates/scripts directory.

examples/kubernetes/components/nginx-deploy.sh

#!/bin/bash -e
DIR=$(dirname ${BASH_SOURCE[0]})
{% set i = inventory.parameters %} #(1)!

KUBECTL="kubectl -n {{i.namespace}}" #(2)!

# Create namespace before anything else
${KUBECTL} apply -f ${DIR}/pre-deploy/namespace.yml

for SECTION in manifests
do
  echo "## run kubectl apply for ${SECTION}"
  ${KUBECTL} apply -f ${DIR}/${SECTION}/ | column -t
done
  1. We import the inventory as a Jinja variable
  2. We use to set the namespace explicitly

Compiled result

#!/bin/bash -e
DIR=$(dirname ${BASH_SOURCE[0]})
 #(1)!

KUBECTL="kubectl -n minikube-nginx-jsonnet" #(2)!

# Create namespace before anything else
${KUBECTL} apply -f ${DIR}/pre-deploy/namespace.yml

for SECTION in manifests
do
  echo "## run kubectl apply for ${SECTION}"
  ${KUBECTL} apply -f ${DIR}/${SECTION}/ | column -t
done
  1. The script is now a "canned script" and ready to be used for this specif target.
  2. You can see that the namespace has been replaced with the target's one.

Accessing the inventory

Templates will be provided at runtime with 3 variables:

  • inventory: To access the inventory for that specific target.
  • inventory_global: To access the inventory of all targets.
  • input_params: To access the optional dictionary provided to the input type.

Use of inventory_global

inventory_global can be used to generate a "global" README.md that contains a link to all generated targets.

| *Target*                                                               |
|------------------------------------------------------------------------|
{% for target in inventory_global | sort() %}
{% set p = inventory_global[target].parameters %}
|[{{target}}](../{{target}}/docs/README.md)                              |
{% endfor %}

Compiled result

| *Target*                                                               |
|------------------------------------------------------------------------|
| [argocd](../argocd/docs/README.md)                                     |
| [dev-sockshop](../dev-sockshop/docs/README.md)                         |
| [echo-server](../echo-server/docs/README.md)                           |
| [examples](../examples/docs/README.md)                                 |
| [gke-pvm-killer](../gke-pvm-killer/docs/README.md)                     |
| [global](../global/docs/README.md)                                     |
| [guestbook-argocd](../guestbook-argocd/docs/README.md)                 |
| [kapicorp-demo-march](../kapicorp-demo-march/docs/README.md)           |
| [kapicorp-project-123](../kapicorp-project-123/docs/README.md)         |
| [kapicorp-terraform-admin](../kapicorp-terraform-admin/docs/README.md) |
| [mysql](../mysql/docs/README.md)                                       |
| [postgres-proxy](../postgres-proxy/docs/README.md)                     |
| [pritunl](../pritunl/docs/README.md)                                   |
| [prod-sockshop](../prod-sockshop/docs/README.md)                       |
| [sock-shop](../sock-shop/docs/README.md)                               |
| [tesoro](../tesoro/docs/README.md)                                     |
| [tutorial](../tutorial/docs/README.md)                                 |
| [vault](../vault/docs/README.md)                                       |

Jinja2 custom filters

We support the following custom filters for use in Jinja2 templates:

SHA256 hashing of text

{{ text | sha256 }}

Dump text as YAML

{{ text | yaml }}

Dump text as TOML

{{ text | toml }}

base64 encode text

{{ text | b64encode }}

base64 decode text

{{ text | b64decode }}

return datetime object for string

{{ "2019-03-07 13:37:00" | to_datetime }}

return current date string for format

{{ "%a, %d %b %Y %H:%M" | strftime }}

perform a re.sub returning a string

{{ hello world | regex_replace(pattern="world", replacement="kapitan")}}

escape all regular expressions special characters from string

{{ "+s[a-z].*" | regex_escape}}

perform re.search and return the list of matches or a backref

{{ hello world | regex_search("world.*")}}

perform re.findall and return the list of matches as array

{{ hello world | regex_findall("world.*")}}

return list of matched regular files for glob

{{ ./path/file* | fileglob }}

return the bool for value

{{ yes | bool }}

value ? true_val : false_val

{{ condition | ternary("yes", "no")}}

randomly shuffle elements of a list

{{ [1, 2, 3, 4, 5] | shuffle }}

reveal ref/secret tag only if compile --reveal flag is set

{{ "?{base64:my_ref}" | reveal_maybe}}

Tip

You can also provide path to your custom filter modules in CLI. By default, you can put your filters in lib/jinja2_filters.py and they will automatically get loaded.