Syntax overview
Jsonnet is the data templating language Tanka uses for expressing what shall be deployed to your Kubernetes cluster. Understanding Jsonnet is crucial to using Tanka effectively.
This page covers the Jsonnet language itself. For more information on how to use Jsonnet with Kubernetes, see the tutorial. There’s also the official Jsonnet tutorial that provides a more detailed review of language features.
Syntax
Being a superset of JSON, the syntax is very similar:
// Line comment/* Block comment */
// a local variable (not exported)local greeting = "hello world!";
// the exported/returned object{ foo: "bar", // string bar: 5, // int baz: false, // bool list: [1,2,3], // array // object dict: { nested: greeting, // using the local }, hidden:: "incognito!" // an unexported field}
Abstraction
Jsonnet has rich abstraction features, which makes it interesting for configuring Kubernetes, as it allows to keep configurations concise, yet readable.
Imports
Just as other languages, Jsonnet allows code to be imported from other files:
local secret = import "./secret.libsonnet";
The exported object (the only non-local one) of secret.libsonnet
is now
available as a local
variable called secret
.
When using Tanka, it is also possible to directly import .json
files, as if
they were a .libsonnet
.
Make sure to also take a look at the libraries documentation to learn how to use import
and re-use code.
The documentation on Tanka import paths and vendoring are useful to understand how imports work in Tanka’s context.
Merging
Deep merging allows you to change parts of an object without touching all of it. Consider the following example:
local secret = { kind: Secret, metadata: { name: "mySecret", namespace: "default", // need to change that }, data: { foo: std.base64("foo") }};
To change the namespace only, we can use the special merge key +:
like so:
// define the patch:local patch = { metadata+: { namespace: "myApp" }}
The difference between :
and +:
is that the former replaces the original
data at that key, while the latter applies the new object as a patch on top,
meaning that values will be updated if possible but all other stay like they
are.
To merge those two, just add (+
) the patch to the original:
secret + patch
The output of this is the following JSON object:
{ "kind": "Secret", "metadata": { "name": "mySecret", "namespace": "myApp" }, "data": { "foo": "Zm9vCg==" }}
Functions
Jsonnet supports functions, similar to how Python does. They can be defined in two different ways:
local add(x,y) = x + y;local mul = (function(x, y) x * y);
Objects can have methods:
{ greet(who): "hello " + who,}
Default values, keyword-args and more examples can be found at jsonnet.org.
Standard library
The Jsonnet standard library includes many helper methods ranging from object and array mutation, over string utils to computation helpers.
Documentation is available at jsonnet.org.
Conditionals
Jsonnet supports a conditionals in a fashion similar to a ternary operator:
local tag = if prod then "v1.0" else "latest";
More on jsonnet.org.
References
Jsonnet has multiple options to refer to parts of an object:
{ // this is $ junk: "foo", nested: { // this is self app: "Tanka", msg: self.app + " rocks!" // "Tanka rocks!" }, children: { // this is also self baz: "bar", junk: $.junk + self.baz, // "foobar" }}
For more information take a look at jsonnet.org