Skip to content

Nested templates and include function #399

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ e75a60548dc9 = 1 # a key can be either container name (nginx) or ID

The templates used by docker-gen are written using the Go [text/template](http://golang.org/pkg/text/template/) language. In addition to the [built-in functions](http://golang.org/pkg/text/template/#hdr-Functions) supplied by Go, docker-gen uses [sprig](https://masterminds.github.io/sprig/) and some additional functions to make it simpler (or possible) to generate your desired output.

For parsing several templates, split path with `;` (for example `template = "nginx.tmpl;header.tmpl"`). This makes possible to use go nested templates through standard `template` function.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should mention that the "main" template should be first in the list.


#### Emit Structure

Within the templates, the object emitted by docker-gen will be a structure consisting of following Go structs:
Expand Down Expand Up @@ -365,6 +367,7 @@ For example, this is a JSON version of an emitted RuntimeContainer struct:
* *`groupByKeys $containers $fieldPath`*: Returns the same as `groupBy` but only returns the keys of the map.
* *`groupByMulti $containers $fieldPath $sep`*: Like `groupBy`, but the string value specified by `$fieldPath` is first split by `$sep` into a list of strings. A container whose `$fieldPath` value contains a list of strings will show up in the map output under each of those strings.
* *`groupByLabel $containers $label`*: Returns the same as `groupBy` but grouping by the given label's value.
* *`include $file`*: Returns content of `$file`, and empty string if file reading error.
* *`intersect $slice1 $slice2`*: Returns the strings that exist in both string slices.
* *`json $value`*: Returns the JSON representation of `$value` as a `string`.
* *`keys $map`*: Returns the keys from `$map`. If `$map` is `nil`, a `nil` is returned. If `$map` is not a `map`, an error will be thrown.
Expand Down
9 changes: 9 additions & 0 deletions internal/template/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"io"
"io/ioutil"
"log"
"os"
"reflect"
"strings"
)
Expand All @@ -31,6 +32,14 @@ func keys(input interface{}) (interface{}, error) {
return k, nil
}

func include(file string) string {
data, err := os.ReadFile(file)
if err != nil {
return ""
}
return string(data)
}

func intersect(l1, l2 []string) []string {
m := make(map[string]bool)
m2 := make(map[string]bool)
Expand Down
10 changes: 10 additions & 0 deletions internal/template/functions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@ func TestKeysNil(t *testing.T) {
}
}

func TestInclude(t *testing.T) {
data := include("some_random_file")
assert.Equal(t, "", data)

_ = os.WriteFile("/tmp/docker-gen-test-temp-file", []byte("some string"), 0o777)
data = include("/tmp/docker-gen-test-temp-file")
assert.Equal(t, "some string", data)
_ = os.Remove("/tmp/docker-gen-test-temp-file")
}

func TestIntersect(t *testing.T) {
i := intersect([]string{"foo.fo.com", "bar.com"}, []string{"foo.bar.com"})
assert.Len(t, i, 0, "Expected no match")
Expand Down
6 changes: 4 additions & 2 deletions internal/template/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func newTemplate(name string) *template.Template {
"groupByMulti": groupByMulti,
"groupByLabel": groupByLabel,
"json": marshalJson,
"include": include,
"intersect": intersect,
"keys": keys,
"replace": strings.Replace,
Expand Down Expand Up @@ -207,13 +208,14 @@ func GenerateFile(config config.Config, containers context.Context) bool {
}

func executeTemplate(templatePath string, containers context.Context) []byte {
tmpl, err := newTemplate(filepath.Base(templatePath)).ParseFiles(templatePath)
templatePathList := strings.Split(templatePath, ";")
tmpl, err := newTemplate(filepath.Base(templatePath)).ParseFiles(templatePathList...)
if err != nil {
log.Fatalf("Unable to parse template: %s", err)
}

buf := new(bytes.Buffer)
err = tmpl.ExecuteTemplate(buf, filepath.Base(templatePath), &containers)
err = tmpl.ExecuteTemplate(buf, filepath.Base(templatePathList[0]), &containers)
if err != nil {
log.Fatalf("Template error: %s\n", err)
}
Expand Down