From fca2becaa55b16fde498a1d9f77b9a3d95757a22 Mon Sep 17 00:00:00 2001 From: Alex Dadgar Date: Mon, 26 Sep 2016 15:23:26 -0700 Subject: [PATCH] Parse --- jobspec/parse.go | 49 +++++++++++++++++++++++++++++++++ jobspec/parse_test.go | 30 ++++++++++++++++---- jobspec/test-fixtures/basic.hcl | 14 ++++++++++ nomad/structs/structs.go | 9 ++++++ 4 files changed, 96 insertions(+), 6 deletions(-) diff --git a/jobspec/parse.go b/jobspec/parse.go index 90a678e3d..08fdef05c 100644 --- a/jobspec/parse.go +++ b/jobspec/parse.go @@ -550,6 +550,7 @@ func parseTasks(jobName string, taskGroupName string, result *[]*structs.Task, l "meta", "resources", "service", + "template", "user", "vault", } @@ -569,6 +570,7 @@ func parseTasks(jobName string, taskGroupName string, result *[]*structs.Task, l delete(m, "meta") delete(m, "resources") delete(m, "service") + delete(m, "template") delete(m, "vault") // Build the task @@ -705,6 +707,13 @@ func parseTasks(jobName string, taskGroupName string, result *[]*structs.Task, l } } + // Parse templates + if o := listVal.Filter("template"); len(o.Items) > 0 { + if err := parseTemplates(&t.Templates, o); err != nil { + return multierror.Prefix(err, fmt.Sprintf("'%s', template ->", n)) + } + } + // If we have a vault block, then parse that if o := listVal.Filter("vault"); len(o.Items) > 0 { var v structs.Vault @@ -792,6 +801,46 @@ func parseArtifactOption(result map[string]string, list *ast.ObjectList) error { return nil } +func parseTemplates(result *[]*structs.Template, list *ast.ObjectList) error { + for _, o := range list.Elem().Items { + // Check for invalid keys + valid := []string{ + "source", + "destination", + "data", + "change_mode", + "restart_signal", + "splay", + "once", + } + if err := checkHCLKeys(o.Val, valid); err != nil { + return err + } + + var m map[string]interface{} + if err := hcl.DecodeObject(&m, o.Val); err != nil { + return err + } + + templ := structs.DefaultTemplate() + dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + DecodeHook: mapstructure.StringToTimeDurationHookFunc(), + WeaklyTypedInput: true, + Result: templ, + }) + if err != nil { + return err + } + if err := dec.Decode(m); err != nil { + return err + } + + *result = append(*result, templ) + } + + return nil +} + func parseServices(jobName string, taskGroupName string, task *structs.Task, serviceObjs *ast.ObjectList) error { task.Services = make([]*structs.Service, len(serviceObjs.Items)) var defaultServiceName bool diff --git a/jobspec/parse_test.go b/jobspec/parse_test.go index 1831366b6..22ed87667 100644 --- a/jobspec/parse_test.go +++ b/jobspec/parse_test.go @@ -162,6 +162,24 @@ func TestParse(t *testing.T) { Policies: []string{"foo", "bar"}, Env: true, }, + Templates: []*structs.Template{ + { + SourcePath: "foo", + DestPath: "foo", + ChangeMode: "foo", + RestartSignal: "foo", + Splay: 10 * time.Second, + Once: true, + }, + { + SourcePath: "bar", + DestPath: "bar", + ChangeMode: structs.TemplateChangeModeRestart, + RestartSignal: "", + Splay: 5 * time.Second, + Once: false, + }, + }, }, &structs.Task{ Name: "storagelocker", @@ -451,9 +469,9 @@ func TestParse(t *testing.T) { Region: "global", TaskGroups: []*structs.TaskGroup{ &structs.TaskGroup{ - Name: "cache", - Count: 1, - LocalDisk: structs.DefaultLocalDisk(), + Name: "cache", + Count: 1, + EphemeralDisk: structs.DefaultEphemeralDisk(), Tasks: []*structs.Task{ &structs.Task{ Name: "redis", @@ -474,9 +492,9 @@ func TestParse(t *testing.T) { }, }, &structs.TaskGroup{ - Name: "cache2", - Count: 1, - LocalDisk: structs.DefaultLocalDisk(), + Name: "cache2", + Count: 1, + EphemeralDisk: structs.DefaultEphemeralDisk(), Tasks: []*structs.Task{ &structs.Task{ Name: "redis", diff --git a/jobspec/test-fixtures/basic.hcl b/jobspec/test-fixtures/basic.hcl index 1c01d6802..8591b8ba0 100644 --- a/jobspec/test-fixtures/basic.hcl +++ b/jobspec/test-fixtures/basic.hcl @@ -133,6 +133,20 @@ job "binstore-storagelocker" { vault { policies = ["foo", "bar"] } + + template { + source = "foo" + destination = "foo" + change_mode = "foo" + restart_signal = "foo" + splay = "10s" + once = true + } + + template { + source = "bar" + destination = "bar" + } } task "storagelocker" { diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index 4a2052c90..fb783dc4a 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -2242,6 +2242,15 @@ type Template struct { Once bool `mapstructure:"once"` } +// DefaultTemplate returns a default template. +func DefaultTemplate() *Template { + return &Template{ + ChangeMode: TemplateChangeModeRestart, + Splay: 5 * time.Second, + Once: false, + } +} + func (t *Template) Copy() *Template { if t == nil { return nil