Add support for loading templates without using files.

This commit is contained in:
Mariano Cano 2020-02-20 15:48:48 -08:00
parent 8e882faf44
commit 914636668a
2 changed files with 33 additions and 12 deletions

View file

@ -106,6 +106,7 @@ type Template struct {
TemplatePath string `json:"template"`
Path string `json:"path"`
Comment string `json:"comment"`
Content []byte `json:"-"`
}
// Validate returns an error if the template is not valid.
@ -117,10 +118,12 @@ func (t *Template) Validate() error {
return errors.New("template name cannot be empty")
case t.Type != Snippet && t.Type != File && t.Type != Directory:
return errors.Errorf("invalid template type %s, it must be %s, %s, or %s", t.Type, Snippet, File, Directory)
case t.TemplatePath == "" && t.Type != Directory:
case t.TemplatePath == "" && t.Type != Directory && len(t.Content) == 0:
return errors.New("template template cannot be empty")
case t.TemplatePath != "" && t.Type == Directory:
return errors.New("template template must be empty with directory type")
case t.TemplatePath != "" && len(t.Content) > 0:
return errors.New("template template must be empty with content")
case t.Path == "":
return errors.New("template path cannot be empty")
}
@ -148,17 +151,27 @@ func (t *Template) Validate() error {
// template fails.
func (t *Template) Load() error {
if t.Template == nil && t.Type != Directory {
switch {
case t.TemplatePath != "":
filename := config.StepAbs(t.TemplatePath)
b, err := ioutil.ReadFile(filename)
if err != nil {
return errors.Wrapf(err, "error reading %s", filename)
}
return t.LoadBytes(b)
default:
return t.LoadBytes(t.Content)
}
}
return nil
}
func (t *Template) LoadBytes(b []byte) error {
tmpl, err := template.New(t.Name).Funcs(sprig.TxtFuncMap()).Parse(string(b))
if err != nil {
return errors.Wrapf(err, "error parsing %s", filename)
return errors.Wrapf(err, "error parsing template %s", t.Name)
}
t.Template = tmpl
}
return nil
}

View file

@ -62,6 +62,12 @@ func TestSSHTemplates_Validate(t *testing.T) {
host := []Template{
{Name: "ca.tpl", Type: File, TemplatePath: "../authority/testdata/templates/ca.tpl", Path: "/etc/ssh/ca.pub", Comment: "#"},
}
content := []Template{
{Name: "test.tpl", Type: File, Content: []byte("some content"), Path: "/test.pub", Comment: "#"},
}
badContent := []Template{
{Name: "ca.tpl", Type: File, TemplatePath: "../authority/testdata/templates/ca.tpl", Content: []byte("some content"), Path: "/etc/ssh/ca.pub", Comment: "#"},
}
type fields struct {
User []Template
@ -75,8 +81,10 @@ func TestSSHTemplates_Validate(t *testing.T) {
{"ok", fields{user, host}, false},
{"user", fields{user, nil}, false},
{"host", fields{nil, host}, false},
{"content", fields{content, nil}, false},
{"badUser", fields{[]Template{{}}, nil}, true},
{"badHost", fields{nil, []Template{{}}}, true},
{"badContent", fields{badContent, nil}, true},
}
var nilValue *SSHTemplates
assert.NoError(t, nilValue.Validate())
@ -163,8 +171,8 @@ func TestLoadAll(t *testing.T) {
{"ok", args{tmpl}, false},
{"empty", args{&Templates{}}, false},
{"nil", args{nil}, false},
{"badUser", args{&Templates{SSH: &SSHTemplates{User: []Template{{}}}}}, true},
{"badHost", args{&Templates{SSH: &SSHTemplates{Host: []Template{{}}}}}, true},
{"badUser", args{&Templates{SSH: &SSHTemplates{User: []Template{{TemplatePath: "missing"}}}}}, true},
{"badHost", args{&Templates{SSH: &SSHTemplates{Host: []Template{{TemplatePath: "missing"}}}}}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {