Skip to content
This repository has been archived by the owner on Jan 21, 2020. It is now read-only.

Commit

Permalink
New template improvements (#388)
Browse files Browse the repository at this point in the history
Signed-off-by: David Chung <david.chung@docker.com>
  • Loading branch information
David Chung authored Feb 6, 2017
1 parent d4de67a commit 908e9fb
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 1 deletion.
7 changes: 7 additions & 0 deletions dockerfiles/Dockerfile.bundle
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,11 @@ FROM alpine:3.5

RUN apk add --update ca-certificates

RUN mkdir -p /infrakit/plugins /infrakit/configs /infrakit/logs

VOLUME /infrakit

ENV INFRAKIT_HOME /infrakit
ENV INFRAKIT_PLUGINS_DIR /infrakit/plugins

ADD build/* /usr/local/bin/
38 changes: 37 additions & 1 deletion pkg/template/funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,40 @@ func IndexOf(srch interface{}, array interface{}, strictOptional ...bool) int {
// DefaultFuncs returns a list of default functions for binding in the template
func (t *Template) DefaultFuncs() []Function {
return []Function{
{
Name: "source",
Description: []string{
"Source / evaluate the template at the input location (as URL).",
"This will make all of the global variables declared there visible in this template's context.",
},
Func: func(p string) (string, error) {
loc := p
if strings.Index(loc, "str://") == -1 {
buff, err := getURL(t.url, p)
if err != nil {
return "", err
}
loc = buff
}
sourced, err := NewTemplate(loc, t.options)
if err != nil {
return "", err
}
// copy the binds in the parent scope into the child
for k, v := range t.binds {
sourced.binds[k] = v
}
// inherit the functions defined for this template
for k, v := range t.funcs {
sourced.AddFunc(k, v)
}
// set this as the parent of the sourced template so its global can mutate the globals in this
sourced.parent = t

// TODO(chungers) -- let the sourced template define new functions that can be called in the parent.
return sourced.Render(nil)
},
},
{
Name: "include",
Description: []string{
Expand Down Expand Up @@ -187,7 +221,9 @@ func (t *Template) DefaultFuncs() []Function {
"Global variables are propagated to all templates that are rendered via the 'include' function.",
},
Func: func(name string, v interface{}) interface{} {
t.binds[name] = v
for here := t; here != nil; here = here.parent {
here.updateGlobal(name, v)
}
return ""
},
},
Expand Down
10 changes: 10 additions & 0 deletions pkg/template/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,13 @@ func TestAddDef(t *testing.T) {
require.NoError(t, err)
require.Equal(t, "hello: x + y = 125", view)
}

func TestSourceAndGlobal(t *testing.T) {
r := `{{ global \"foo\" 100 }}`
s := `{{ source "str://` + r + `" }}foo={{ref "foo"}}`
tt, err := NewTemplate("str://"+s, Options{})
require.NoError(t, err)
view, err := tt.Render(nil)
require.NoError(t, err)
require.Equal(t, "foo=100", view)
}
8 changes: 8 additions & 0 deletions pkg/template/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ type Template struct {

registered []Function
lock sync.Mutex

parent *Template
}

// NewTemplate fetches the content at the url and returns a template. If the string begins
Expand Down Expand Up @@ -143,6 +145,12 @@ func (t *Template) AddDef(name string, val interface{}, doc ...string) *Template
return t
}

func (t *Template) updateGlobal(name string, value interface{}) {
t.lock.Lock()
defer t.lock.Unlock()
t.binds[name] = value
}

// Validate parses the template and checks for validity.
func (t *Template) Validate() (*Template, error) {
t.lock.Lock()
Expand Down

0 comments on commit 908e9fb

Please sign in to comment.