Files
bkl/README.md
2023-07-03 22:12:04 +01:00

5.4 KiB

bkl

bkl (short for Baklava, because it has layers) is a templating configuration language without the templates. It's designed to be simple to read and write with obvious behavior.

Write your configuration in your favorite format: JSON, YAML, or TOML. Layer configurations on top of each other, even in different formats. Use filenames to define the inheritance. Have as many layers as you like. bkl merges your layers together with sane default behavior that you can override. Export your results in any supported format for human or machine consumption. Use the CLI directly or in scripts, or automate with the library.

No template tags. No schemas. No new formats to learn.

Example

service.yaml

name: myService
addr: 127.0.0.1
port: 8080

service.test.toml

port = 8081

Run it!

$ bkl service.test.toml
{"addr":"127.0.0.1","name":"myService","port":8081}

bkl knows that service.test.toml inherits from service.yaml by the filename pattern, and uses filename extensions to determine formats.

Output Formats

Output defaults to machine-friendly JSON (you can make that explicit with -f json).

YAML

$ bkl -f yaml service.test.toml
addr: 127.0.0.1
name: myService
port: 8081

TOML

$ bkl -f toml service.test.toml
addr = "127.0.0.1"
name = "myService"
port = 8081

Pretty JSON

$ bkl -f json-pretty service.test.toml
{
  "addr": "127.0.0.1",
  "name": "myService",
  "port": 8081
}

Output Locations

Output goes to stdout by default. Errors always go to stderr.

File Output

$ bkl -o out.yaml service.test.toml

Output format is autodetected from output filename.

Advanced Inputs

Multiple Files

Specifying multiple input files evaluates them as normal, then merges them onto each other in order.

$ bkl a.b.yaml c.d.yaml   # (a.yaml + a.b.yaml) + (c.yaml + c.d.yaml)

bkl follows symbolic links and evaluates the inherited layers on the other side of the symlink.

$ ln -s a.b.yaml c.yaml
$ bkl c.d.yaml   # a.yaml + a.b.yaml (c.yaml) + c.d.yaml

Streams

bkl understands input streams (multi-document YAML files delimited with ---). To layer them, it has to match up sections between files. It tries the following strategies, in order:

  • $match: specify match fields in the document:
$match:
  kind: Service
  metadata:
    name: myService
  • K8s paths: If kind and metadata.name are present, they are used as match keys.
  • Ordering: Stream position is used to match documents.

Merge Behavior

By default, lists and maps are merged. To change that, use $patch syntax.

Maps

a: 1

+

b: 2

a: 1
b: 2
a: 1

+

b: 2
$patch: replace

b: 2
a: 1
b: 2

+

c: 3
b: null

a: 1
c: 3

Lists

- 1

+

- 2

- 1
- 2
- 1

+

- 2
 $patch: replace

- 2
- x: 1
- x: 2

+

- x: 3
- x: 2
  $patch: delete

- x: 1
- x: 3

Advanced Keys & Values

$required

Use $required in lower layers to force upper layers to replace the value.

a: 1
b: $required

+

c: 3

Error

a: 1
b: $required

+

b: 2
c: 3

a: 1
b: 2
c: 3

$merge

Merges in another subtree.

foo:
  bar:
    a: 1
zig:
  b: 2
  $merge: foo.bar

foo:
  bar:
    a: 1
zig:
  a: 1
  b: 2

$replace

Replaces a subtree with one from another location.

foo:
  bar:
    a: 1
zig:
  b: 2
  $replace: foo.bar

foo:
  bar:
    a: 1
zig:
  a: 1

$output

Selects a subtree for output.

foo:
  bar:
    $output: true
    a: 1
    b: 2

a: 1
b: 2

Multiple instances of $output in a document will generate multiple output documents (delimited with ---). If the $output key has a numeric value, that value is used as the output document index.

Combine $output with $replace or $merge to have hidden "template" subtrees that don't appear in the output but can be copied in as needed.