RBMS Template Engine
The RBMS Template Engine is an execution engine for templates. A folder in the filesystem serves as template storage for the engine. The content of the folder follows a convention.
Template Folder structure
templates
|-- includes
| |-- <include-template>.gojson
|-- <template name>
|-- config.yaml
|-- <include-template>.gojson
|-- <main-template>.gojson
The template engine uses one templates folder where all the templates are stored.
Each template resides in his own folder, the folder name is the template name.
The config.yaml
file inside a template folder indicates that this folder is a template.
In this file also other configurations for the template engine can be made.
The template folder contains one main-template
and can contain multiple `include-templates.
The include-templates can be included into the main template.
Folders that don’t contain a config.yaml
are not treated as templates.
This folders can be used as containers for other include-template files.
Template config
This section describes the config.yaml
file.
Image this folder structure for the next examples.
templates
|-- includes
| |-- global_include.gojson
|-- sample
|-- config.yaml
|-- local_include.gojson
|-- main.gojson
Here there is a main-template which includes the local_include-template and the global_include-template.
The config.yaml
is used by the template engine to parse the right files, so that the include-directives work.
engine: golang
main_template: "main.gojson"
main_pattern: "*.gojson"
include_pattern: "includes/*.gojson"
post_processors:
- removeTrailingCommas
- prettyJSON
Attribute | Default | Description |
---|---|---|
engine |
golang |
selects the template engine, at the moment only golang is supported |
main_template |
none |
points to the entrypoint of the rendering process, this template is used as the top most, it hast to be included in the main pattern. |
main_pattern |
none |
describes which files the engine should parse from the template folder. |
include_pattern |
none |
describes which files the engine should additionally parse relative to the templates folder. |
post_processors |
none |
allows to specify post processors that are used in that order on top of the generated output. |
Attribute | Description |
---|---|
removeTrailingCommas |
removes in json files the commas which are not valid, this makes the template much easier |
removeEmptyLines |
removes empty lines |
prettyJSON |
Pretty converts the input json into a more human readable format where each element is on it’s own line with clear indentation |
uglyJSON |
Ugly removes insignificant space characters from the input json byte slice and returns the compacted result. |
GO Lang Template Engine
The default engine is the golang template engine. This gives some links to more detailed information.
The GO Lange template engine is based on:
-
GoLang test template
The golang text template engine. This allows evaluating arguments, execute actions and include other templates. -
sprig functions
Beside of the default functions golang already provides, the sprig function library is added to the engine.
Example
This section shows a simple example, that covers a lot of functionality of the templates.
The example uses the following folder structure. Each file will be described in more detail.
templates
|-- includes
| |-- global_include.gojson
|-- sample
|-- config.yaml
|-- example_variables.json
|-- local_include.gojson
|-- main.gojson
The template is called sample, because there is a config.yaml in the folder sample.
engine: golang
main_template: "main.gojson"
main_pattern: "*.gojson"
include_pattern: "includes/*.gojson"
post_processors:
- removeTrailingCommas
- prettyJSON
The config.yaml
file states that the main_template
is called main.gojson
, so thats the entrypoint for the generation.
The main_pattern
defines this files templates/sample/*.gojson
should be parsed into the template engine, so also the main_pattern
is included.
The include_patterns
defines this files templates/includes/*.gojson
should be parsed into the template engine.
The post_processors
are used to remove the trailing commas and make the JSON output more readable.
Let’s expect the following example variables structure.
{
"description": "sample",
"interfaces": [
{
"name": "ifp_0/0/1",
"ipv4": "127.0.0.1",
"x": 5,
"y": 3
}, {
"name": "ifp_0/0/2",
"ipv4": "127.0.0.2",
"x": 4,
"y": 4
}
]
}
The this variables can be used to fill a template.
{{define "t1"}}
"hostname": "static",
{{end}}
{
{{template "t1"}}
"description": "{{.description}}",
"interfaces": {
{{template "local_include.gojson" .interfaces}}
},
"list": {{template "global_include.gojson" .}}
}
This templates starts with a definition of a new template t1
that will be used in this template.
This template t1
is included immediately after {
.
Then the description is added, the selection from the variable is done via the .description
.
For the interfaces we use the local template local_include.gojson
, the variables that are forwarded to the template are the .interfaces
so only the array of the original variable set.
To render the list we include the global_include.gojson
template and forward the original variable set.
{{range .}}
"{{.name}}": {
"ip": "{{.ipv4}}",
"1000/x*y": {{div 10000 (mul .x .y) }},
},
{{end}}
The local_include.gojson
iterates over the interfaces list and prints the name and ip-address of the interface.
Also a simple computation is done by using the sprig functions div
and mul
.
[
{{range .interfaces}}"{{.name}}",{{end}}
]
The global_include.gojson
iterates over the interfaces list and prints in an array.
This json template does not create a valid json. The commas are not set correct. The document is not well formatted. Therefore it is easier to create the templates. To create a syntactically correct and well formatted document we use post processors. The syntax is corrected by removeTrailingCommas` post processor. The format is corrected by the prettyJSON post processor. |
The next source block shows the expected outcome when applying the variables from above to the template.
{
"description": "sample",
"hostname": "static",
"interfaces": {
"ifp_0/0/1": {
"1000/x*y": 666,
"ip": "127.0.0.1"
},
"ifp_0/0/2": {
"1000/x*y": 625,
"ip": "127.0.0.2"
}
},
"list": [
"ifp_0/0/1",
"ifp_0/0/2"
]
}
TestKit
In order to do a fast template prototyping we developed a test kit. The test kit allows to execute a template with a given variable set and validate the outcome against an expected result.
To execute we have to specify:
-
templatePath: Template main folder (default ".")
-
template: Template name
-
format: File format [txt, json, json5] (default "txt")
So for example if we execute template-engine-test -template sample -test example -format json
inside the templates folder, this command will execute the sample
template with the content of the example_variables.json
file as input variables.
After execution the outcome is stored in the example_got.json
file, and validated against the example_result.json
file.
The format not only specifies the file endings, it also specifies how the validation is done.
So for example the json format does not care about ordering of whitespace differences.