From 01ef4469d992c883f99751fa1d6dccac4986a621 Mon Sep 17 00:00:00 2001 From: Diptanu Choudhury Date: Tue, 17 Nov 2015 01:37:09 -0500 Subject: [PATCH] Added the parsling logic for service blocks --- command/init.go | 5 ++-- jobspec/parse.go | 64 ++++++++++++++++++++++++++++++++++++++++ nomad/structs/structs.go | 18 +++++++++++ 3 files changed, 84 insertions(+), 3 deletions(-) diff --git a/command/init.go b/command/init.go index 668b33b26..6bff4990e 100644 --- a/command/init.go +++ b/command/init.go @@ -128,12 +128,11 @@ job "example" { } } - service { + service "id-redis-check" { # name = redis tags = ["global", "cache"] port = "db" - check { - id = "id-alive-check" + check "id-alive-check" { name = "alive" type = "tcp" interval = "10s" diff --git a/jobspec/parse.go b/jobspec/parse.go index 24772364f..de7d9314c 100644 --- a/jobspec/parse.go +++ b/jobspec/parse.go @@ -378,6 +378,7 @@ func parseTasks(result *[]*structs.Task, list *ast.ObjectList) error { delete(m, "config") delete(m, "env") delete(m, "constraint") + delete(m, "service") delete(m, "meta") delete(m, "resources") @@ -401,6 +402,69 @@ func parseTasks(result *[]*structs.Task, list *ast.ObjectList) error { } } + if o := listVal.Filter("service"); len(o.Items) > 0 { + t.Services = make([]structs.Service, len(o.Items)) + for idx, o := range o.Items { + var service structs.Service + label := o.Keys[0].Token.Value().(string) + service.Id = label + + var m map[string]interface{} + if err := hcl.DecodeObject(&m, o.Val); err != nil { + return err + } + + delete(m, "check") + + if err := mapstructure.WeakDecode(m, &service); err != nil { + return err + } + + if service.Name == "" { + service.Name = service.Id + } + + // Fileter checks + var checkList *ast.ObjectList + if ot, ok := o.Val.(*ast.ObjectType); ok { + checkList = ot.List + } else { + return fmt.Errorf("service '%s': should be an object", label) + } + + if co := checkList.Filter("check"); len(co.Items) > 0 { + service.Checks = make([]structs.ServiceCheck, len(co.Items)) + for idx, co := range co.Items { + var check structs.ServiceCheck + label := o.Keys[0].Token.Value().(string) + var cm map[string]interface{} + if err := hcl.DecodeObject(&cm, co.Val); err != nil { + return err + } + dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + DecodeHook: mapstructure.StringToTimeDurationHookFunc(), + WeaklyTypedInput: true, + Result: &check, + }) + if err != nil { + return err + } + if err := dec.Decode(cm); err != nil { + return err + } + + check.Id = label + if check.Name == "" { + check.Name = label + } + service.Checks[idx] = check + } + } + + t.Services[idx] = service + } + } + // If we have config, then parse that if o := listVal.Filter("config"); len(o.Items) > 0 { for _, o := range o.Elem().Items { diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index 746b9b6c8..f021525fb 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -906,6 +906,22 @@ func NewRestartPolicy(jobType string) *RestartPolicy { return nil } +type ServiceCheck struct { + Id string + Name string + Type string + Interval time.Duration + Timeout time.Duration +} + +type Service struct { + Id string + Name string + Tags []string + PortLabel string `mapstructure:"port"` + Checks []ServiceCheck +} + // TaskGroup is an atomic unit of placement. Each task group belongs to // a job and may contain any number of tasks. A task group support running // in many replicas using the same configuration.. @@ -1009,6 +1025,8 @@ type Task struct { // Map of environment variables to be used by the driver Env map[string]string + Services []Service + // Constraints can be specified at a task level and apply only to // the particular task. Constraints []*Constraint