2015-09-09 20:02:39 +00:00
|
|
|
package api
|
|
|
|
|
2015-10-30 23:32:05 +00:00
|
|
|
import (
|
2017-02-22 20:30:05 +00:00
|
|
|
"fmt"
|
2017-07-06 03:44:49 +00:00
|
|
|
"path"
|
|
|
|
"path/filepath"
|
2017-02-13 23:18:17 +00:00
|
|
|
"strings"
|
2015-10-30 23:32:05 +00:00
|
|
|
"time"
|
2017-02-06 19:48:28 +00:00
|
|
|
|
|
|
|
"github.com/hashicorp/nomad/helper"
|
2018-01-18 20:49:01 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
2015-10-30 23:32:05 +00:00
|
|
|
)
|
|
|
|
|
2016-05-27 22:24:22 +00:00
|
|
|
// MemoryStats holds memory usage related stats
|
2016-04-29 20:03:02 +00:00
|
|
|
type MemoryStats struct {
|
|
|
|
RSS uint64
|
|
|
|
Cache uint64
|
|
|
|
Swap uint64
|
|
|
|
MaxUsage uint64
|
|
|
|
KernelUsage uint64
|
|
|
|
KernelMaxUsage uint64
|
2016-06-10 02:45:41 +00:00
|
|
|
Measured []string
|
2016-04-29 20:03:02 +00:00
|
|
|
}
|
|
|
|
|
2016-05-27 22:24:22 +00:00
|
|
|
// CpuStats holds cpu usage related stats
|
2016-05-21 07:49:17 +00:00
|
|
|
type CpuStats struct {
|
2016-05-19 21:06:19 +00:00
|
|
|
SystemMode float64
|
|
|
|
UserMode float64
|
2016-06-10 21:32:45 +00:00
|
|
|
TotalTicks float64
|
2016-04-29 20:03:02 +00:00
|
|
|
ThrottledPeriods uint64
|
|
|
|
ThrottledTime uint64
|
2016-05-19 21:06:19 +00:00
|
|
|
Percent float64
|
2016-06-10 02:45:41 +00:00
|
|
|
Measured []string
|
2016-04-29 20:03:02 +00:00
|
|
|
}
|
|
|
|
|
2016-05-27 22:24:22 +00:00
|
|
|
// ResourceUsage holds information related to cpu and memory stats
|
2016-05-21 09:05:08 +00:00
|
|
|
type ResourceUsage struct {
|
2016-04-29 20:03:02 +00:00
|
|
|
MemoryStats *MemoryStats
|
2016-05-21 07:49:17 +00:00
|
|
|
CpuStats *CpuStats
|
2016-05-21 09:05:08 +00:00
|
|
|
}
|
|
|
|
|
2016-05-27 22:24:22 +00:00
|
|
|
// TaskResourceUsage holds aggregated resource usage of all processes in a Task
|
|
|
|
// and the resource usage of the individual pids
|
2016-05-21 09:05:08 +00:00
|
|
|
type TaskResourceUsage struct {
|
|
|
|
ResourceUsage *ResourceUsage
|
2016-05-27 22:24:22 +00:00
|
|
|
Timestamp int64
|
2016-05-21 09:05:08 +00:00
|
|
|
Pids map[string]*ResourceUsage
|
2016-04-29 20:03:02 +00:00
|
|
|
}
|
|
|
|
|
2016-06-12 03:15:50 +00:00
|
|
|
// AllocResourceUsage holds the aggregated task resource usage of the
|
|
|
|
// allocation.
|
|
|
|
type AllocResourceUsage struct {
|
|
|
|
ResourceUsage *ResourceUsage
|
|
|
|
Tasks map[string]*TaskResourceUsage
|
|
|
|
Timestamp int64
|
|
|
|
}
|
|
|
|
|
2015-11-02 21:24:59 +00:00
|
|
|
// RestartPolicy defines how the Nomad client restarts
|
|
|
|
// tasks in a taskgroup when they fail
|
2015-10-30 23:32:05 +00:00
|
|
|
type RestartPolicy struct {
|
2017-02-13 23:18:17 +00:00
|
|
|
Interval *time.Duration
|
|
|
|
Attempts *int
|
|
|
|
Delay *time.Duration
|
|
|
|
Mode *string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *RestartPolicy) Merge(rp *RestartPolicy) {
|
|
|
|
if rp.Interval != nil {
|
|
|
|
r.Interval = rp.Interval
|
|
|
|
}
|
|
|
|
if rp.Attempts != nil {
|
|
|
|
r.Attempts = rp.Attempts
|
|
|
|
}
|
|
|
|
if rp.Delay != nil {
|
|
|
|
r.Delay = rp.Delay
|
|
|
|
}
|
|
|
|
if rp.Mode != nil {
|
|
|
|
r.Mode = rp.Mode
|
|
|
|
}
|
2015-10-31 04:28:56 +00:00
|
|
|
}
|
|
|
|
|
2018-01-18 20:49:01 +00:00
|
|
|
// Reschedule configures how Tasks are rescheduled when they crash or fail.
|
|
|
|
type ReschedulePolicy struct {
|
|
|
|
// Attempts limits the number of rescheduling attempts that can occur in an interval.
|
|
|
|
Attempts *int `mapstructure:"attempts"`
|
|
|
|
|
|
|
|
// Interval is a duration in which we can limit the number of reschedule attempts.
|
|
|
|
Interval *time.Duration `mapstructure:"interval"`
|
2018-02-23 16:23:32 +00:00
|
|
|
|
|
|
|
// Delay is a minimum duration to wait between reschedule attempts.
|
|
|
|
// The delay function determines how much subsequent reschedule attempts are delayed by.
|
|
|
|
Delay *time.Duration `mapstructure:"delay"`
|
|
|
|
|
|
|
|
// DelayFunction determines how the delay progressively changes on subsequent reschedule
|
|
|
|
// attempts. Valid values are "exponential", "linear", and "fibonacci".
|
|
|
|
DelayFunction *string `mapstructure:"delay_function"`
|
|
|
|
|
2018-03-13 15:06:26 +00:00
|
|
|
// MaxDelay is an upper bound on the delay.
|
|
|
|
MaxDelay *time.Duration `mapstructure:"max_delay"`
|
2018-02-23 16:23:32 +00:00
|
|
|
|
|
|
|
// Unlimited allows rescheduling attempts until they succeed
|
|
|
|
Unlimited *bool `mapstructure:"unlimited"`
|
2018-01-18 20:49:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *ReschedulePolicy) Merge(rp *ReschedulePolicy) {
|
|
|
|
if rp.Interval != nil {
|
|
|
|
r.Interval = rp.Interval
|
|
|
|
}
|
|
|
|
if rp.Attempts != nil {
|
|
|
|
r.Attempts = rp.Attempts
|
|
|
|
}
|
2018-02-23 16:23:32 +00:00
|
|
|
if rp.Delay != nil {
|
|
|
|
r.Delay = rp.Delay
|
|
|
|
}
|
|
|
|
if rp.DelayFunction != nil {
|
|
|
|
r.DelayFunction = rp.DelayFunction
|
|
|
|
}
|
2018-03-13 15:06:26 +00:00
|
|
|
if rp.MaxDelay != nil {
|
|
|
|
r.MaxDelay = rp.MaxDelay
|
2018-02-23 16:23:32 +00:00
|
|
|
}
|
|
|
|
if rp.Unlimited != nil {
|
|
|
|
r.Unlimited = rp.Unlimited
|
|
|
|
}
|
2018-01-18 20:49:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *ReschedulePolicy) Copy() *ReschedulePolicy {
|
|
|
|
if r == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
nrp := new(ReschedulePolicy)
|
|
|
|
*nrp = *r
|
|
|
|
return nrp
|
|
|
|
}
|
|
|
|
|
2017-08-25 00:18:06 +00:00
|
|
|
// CheckRestart describes if and when a task should be restarted based on
|
|
|
|
// failing health checks.
|
|
|
|
type CheckRestart struct {
|
2017-09-11 00:31:55 +00:00
|
|
|
Limit int `mapstructure:"limit"`
|
2017-09-26 17:21:35 +00:00
|
|
|
Grace *time.Duration `mapstructure:"grace"`
|
2017-09-11 00:31:55 +00:00
|
|
|
IgnoreWarnings bool `mapstructure:"ignore_warnings"`
|
2017-08-25 00:18:06 +00:00
|
|
|
}
|
|
|
|
|
2017-09-14 00:27:08 +00:00
|
|
|
// Canonicalize CheckRestart fields if not nil.
|
|
|
|
func (c *CheckRestart) Canonicalize() {
|
|
|
|
if c == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.Grace == nil {
|
|
|
|
c.Grace = helper.TimeToPtr(1 * time.Second)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy returns a copy of CheckRestart or nil if unset.
|
|
|
|
func (c *CheckRestart) Copy() *CheckRestart {
|
|
|
|
if c == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
nc := new(CheckRestart)
|
|
|
|
nc.Limit = c.Limit
|
|
|
|
if c.Grace != nil {
|
|
|
|
g := *c.Grace
|
|
|
|
nc.Grace = &g
|
|
|
|
}
|
|
|
|
nc.IgnoreWarnings = c.IgnoreWarnings
|
|
|
|
return nc
|
|
|
|
}
|
|
|
|
|
|
|
|
// Merge values from other CheckRestart over default values on this
|
|
|
|
// CheckRestart and return merged copy.
|
|
|
|
func (c *CheckRestart) Merge(o *CheckRestart) *CheckRestart {
|
|
|
|
if c == nil {
|
|
|
|
// Just return other
|
|
|
|
return o
|
|
|
|
}
|
|
|
|
|
|
|
|
nc := c.Copy()
|
|
|
|
|
|
|
|
if o == nil {
|
|
|
|
// Nothing to merge
|
|
|
|
return nc
|
|
|
|
}
|
|
|
|
|
2018-01-09 22:53:34 +00:00
|
|
|
if o.Limit > 0 {
|
2017-09-14 00:27:08 +00:00
|
|
|
nc.Limit = o.Limit
|
|
|
|
}
|
|
|
|
|
2018-01-09 22:53:34 +00:00
|
|
|
if o.Grace != nil {
|
2017-09-14 00:27:08 +00:00
|
|
|
nc.Grace = o.Grace
|
|
|
|
}
|
|
|
|
|
2018-01-09 22:53:34 +00:00
|
|
|
if o.IgnoreWarnings {
|
2017-09-14 00:27:08 +00:00
|
|
|
nc.IgnoreWarnings = o.IgnoreWarnings
|
|
|
|
}
|
|
|
|
|
|
|
|
return nc
|
|
|
|
}
|
|
|
|
|
2015-11-17 07:20:35 +00:00
|
|
|
// The ServiceCheck data model represents the consul health check that
|
|
|
|
// Nomad registers for a Task
|
|
|
|
type ServiceCheck struct {
|
2017-08-25 00:18:06 +00:00
|
|
|
Id string
|
|
|
|
Name string
|
|
|
|
Type string
|
|
|
|
Command string
|
|
|
|
Args []string
|
|
|
|
Path string
|
|
|
|
Protocol string
|
|
|
|
PortLabel string `mapstructure:"port"`
|
2017-12-05 19:39:42 +00:00
|
|
|
AddressMode string `mapstructure:"address_mode"`
|
2017-08-25 00:18:06 +00:00
|
|
|
Interval time.Duration
|
|
|
|
Timeout time.Duration
|
|
|
|
InitialStatus string `mapstructure:"initial_status"`
|
|
|
|
TLSSkipVerify bool `mapstructure:"tls_skip_verify"`
|
|
|
|
Header map[string][]string
|
|
|
|
Method string
|
|
|
|
CheckRestart *CheckRestart `mapstructure:"check_restart"`
|
2015-11-17 07:20:35 +00:00
|
|
|
}
|
|
|
|
|
2016-05-15 16:41:34 +00:00
|
|
|
// The Service model represents a Consul service definition
|
2015-11-17 07:20:35 +00:00
|
|
|
type Service struct {
|
2017-08-25 00:18:06 +00:00
|
|
|
Id string
|
|
|
|
Name string
|
|
|
|
Tags []string
|
|
|
|
PortLabel string `mapstructure:"port"`
|
|
|
|
AddressMode string `mapstructure:"address_mode"`
|
|
|
|
Checks []ServiceCheck
|
|
|
|
CheckRestart *CheckRestart `mapstructure:"check_restart"`
|
2015-11-17 07:20:35 +00:00
|
|
|
}
|
|
|
|
|
2017-02-22 20:30:05 +00:00
|
|
|
func (s *Service) Canonicalize(t *Task, tg *TaskGroup, job *Job) {
|
|
|
|
if s.Name == "" {
|
|
|
|
s.Name = fmt.Sprintf("%s-%s-%s", *job.Name, *tg.Name, t.Name)
|
|
|
|
}
|
2017-06-21 22:28:51 +00:00
|
|
|
|
|
|
|
// Default to AddressModeAuto
|
|
|
|
if s.AddressMode == "" {
|
|
|
|
s.AddressMode = "auto"
|
|
|
|
}
|
2017-09-11 00:31:55 +00:00
|
|
|
|
2018-03-11 17:46:20 +00:00
|
|
|
// Canonicalize CheckRestart on Checks and merge Service.CheckRestart
|
2017-09-15 21:34:36 +00:00
|
|
|
// into each check.
|
2018-01-09 22:53:34 +00:00
|
|
|
for i, check := range s.Checks {
|
|
|
|
s.Checks[i].CheckRestart = s.CheckRestart.Merge(check.CheckRestart)
|
|
|
|
s.Checks[i].CheckRestart.Canonicalize()
|
2017-09-11 00:31:55 +00:00
|
|
|
}
|
2017-02-22 20:30:05 +00:00
|
|
|
}
|
|
|
|
|
2016-09-14 22:43:42 +00:00
|
|
|
// EphemeralDisk is an ephemeral disk object
|
|
|
|
type EphemeralDisk struct {
|
2017-02-06 19:48:28 +00:00
|
|
|
Sticky *bool
|
|
|
|
Migrate *bool
|
|
|
|
SizeMB *int `mapstructure:"size"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func DefaultEphemeralDisk() *EphemeralDisk {
|
|
|
|
return &EphemeralDisk{
|
|
|
|
Sticky: helper.BoolToPtr(false),
|
|
|
|
Migrate: helper.BoolToPtr(false),
|
|
|
|
SizeMB: helper.IntToPtr(300),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *EphemeralDisk) Canonicalize() {
|
|
|
|
if e.Sticky == nil {
|
|
|
|
e.Sticky = helper.BoolToPtr(false)
|
|
|
|
}
|
|
|
|
if e.Migrate == nil {
|
|
|
|
e.Migrate = helper.BoolToPtr(false)
|
|
|
|
}
|
|
|
|
if e.SizeMB == nil {
|
|
|
|
e.SizeMB = helper.IntToPtr(300)
|
|
|
|
}
|
2016-08-24 18:51:15 +00:00
|
|
|
}
|
|
|
|
|
2015-09-09 20:02:39 +00:00
|
|
|
// TaskGroup is the unit of scheduling.
|
|
|
|
type TaskGroup struct {
|
2018-01-18 20:49:01 +00:00
|
|
|
Name *string
|
|
|
|
Count *int
|
|
|
|
Constraints []*Constraint
|
|
|
|
Tasks []*Task
|
|
|
|
RestartPolicy *RestartPolicy
|
|
|
|
ReschedulePolicy *ReschedulePolicy
|
|
|
|
EphemeralDisk *EphemeralDisk
|
|
|
|
Update *UpdateStrategy
|
|
|
|
Meta map[string]string
|
2015-09-09 20:02:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewTaskGroup creates a new TaskGroup.
|
2015-09-10 00:59:18 +00:00
|
|
|
func NewTaskGroup(name string, count int) *TaskGroup {
|
2015-09-09 20:02:39 +00:00
|
|
|
return &TaskGroup{
|
2017-02-06 19:48:28 +00:00
|
|
|
Name: helper.StringToPtr(name),
|
|
|
|
Count: helper.IntToPtr(count),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-22 20:30:05 +00:00
|
|
|
func (g *TaskGroup) Canonicalize(job *Job) {
|
2017-02-06 19:48:28 +00:00
|
|
|
if g.Name == nil {
|
|
|
|
g.Name = helper.StringToPtr("")
|
|
|
|
}
|
|
|
|
if g.Count == nil {
|
|
|
|
g.Count = helper.IntToPtr(1)
|
|
|
|
}
|
|
|
|
for _, t := range g.Tasks {
|
2017-02-22 20:30:05 +00:00
|
|
|
t.Canonicalize(g, job)
|
2017-02-06 19:48:28 +00:00
|
|
|
}
|
|
|
|
if g.EphemeralDisk == nil {
|
|
|
|
g.EphemeralDisk = DefaultEphemeralDisk()
|
|
|
|
} else {
|
|
|
|
g.EphemeralDisk.Canonicalize()
|
|
|
|
}
|
2017-02-13 23:18:17 +00:00
|
|
|
|
2017-05-09 00:44:26 +00:00
|
|
|
// Merge the update policy from the job
|
|
|
|
if ju, tu := job.Update != nil, g.Update != nil; ju && tu {
|
|
|
|
// Merge the jobs and task groups definition of the update strategy
|
|
|
|
jc := job.Update.Copy()
|
|
|
|
jc.Merge(g.Update)
|
|
|
|
g.Update = jc
|
2017-08-30 18:35:19 +00:00
|
|
|
} else if ju && !job.Update.Empty() {
|
|
|
|
// Inherit the jobs as long as it is non-empty.
|
2017-05-09 00:44:26 +00:00
|
|
|
jc := job.Update.Copy()
|
|
|
|
g.Update = jc
|
|
|
|
}
|
|
|
|
|
|
|
|
if g.Update != nil {
|
|
|
|
g.Update.Canonicalize()
|
|
|
|
}
|
|
|
|
|
2018-01-18 20:49:01 +00:00
|
|
|
// Merge the reschedule policy from the job
|
|
|
|
if jr, tr := job.Reschedule != nil, g.ReschedulePolicy != nil; jr && tr {
|
|
|
|
jobReschedule := job.Reschedule.Copy()
|
|
|
|
jobReschedule.Merge(g.ReschedulePolicy)
|
|
|
|
g.ReschedulePolicy = jobReschedule
|
2018-01-23 01:58:23 +00:00
|
|
|
} else if jr {
|
2018-01-18 20:49:01 +00:00
|
|
|
jobReschedule := job.Reschedule.Copy()
|
|
|
|
g.ReschedulePolicy = jobReschedule
|
|
|
|
}
|
|
|
|
|
|
|
|
// Merge with default reschedule policy
|
|
|
|
var defaultReschedulePolicy *ReschedulePolicy
|
|
|
|
switch *job.Type {
|
|
|
|
case "service":
|
|
|
|
defaultReschedulePolicy = &ReschedulePolicy{
|
2018-02-23 16:23:32 +00:00
|
|
|
Attempts: helper.IntToPtr(structs.DefaultServiceJobReschedulePolicy.Attempts),
|
|
|
|
Interval: helper.TimeToPtr(structs.DefaultServiceJobReschedulePolicy.Interval),
|
|
|
|
Delay: helper.TimeToPtr(structs.DefaultServiceJobReschedulePolicy.Delay),
|
|
|
|
DelayFunction: helper.StringToPtr(structs.DefaultServiceJobReschedulePolicy.DelayFunction),
|
2018-03-13 15:06:26 +00:00
|
|
|
MaxDelay: helper.TimeToPtr(structs.DefaultServiceJobReschedulePolicy.MaxDelay),
|
2018-02-23 16:23:32 +00:00
|
|
|
Unlimited: helper.BoolToPtr(structs.DefaultServiceJobReschedulePolicy.Unlimited),
|
2018-01-18 20:49:01 +00:00
|
|
|
}
|
|
|
|
case "batch":
|
|
|
|
defaultReschedulePolicy = &ReschedulePolicy{
|
2018-02-23 16:23:32 +00:00
|
|
|
Attempts: helper.IntToPtr(structs.DefaultBatchJobReschedulePolicy.Attempts),
|
|
|
|
Interval: helper.TimeToPtr(structs.DefaultBatchJobReschedulePolicy.Interval),
|
|
|
|
Delay: helper.TimeToPtr(structs.DefaultBatchJobReschedulePolicy.Delay),
|
|
|
|
DelayFunction: helper.StringToPtr(structs.DefaultBatchJobReschedulePolicy.DelayFunction),
|
2018-03-13 15:06:26 +00:00
|
|
|
MaxDelay: helper.TimeToPtr(structs.DefaultBatchJobReschedulePolicy.MaxDelay),
|
2018-02-23 16:23:32 +00:00
|
|
|
Unlimited: helper.BoolToPtr(structs.DefaultBatchJobReschedulePolicy.Unlimited),
|
2018-01-18 20:49:01 +00:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
defaultReschedulePolicy = &ReschedulePolicy{
|
|
|
|
Attempts: helper.IntToPtr(0),
|
|
|
|
Interval: helper.TimeToPtr(0 * time.Second),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if g.ReschedulePolicy != nil {
|
|
|
|
defaultReschedulePolicy.Merge(g.ReschedulePolicy)
|
|
|
|
}
|
|
|
|
g.ReschedulePolicy = defaultReschedulePolicy
|
|
|
|
|
2017-02-13 23:18:17 +00:00
|
|
|
var defaultRestartPolicy *RestartPolicy
|
2017-02-22 20:30:05 +00:00
|
|
|
switch *job.Type {
|
2017-02-13 23:18:17 +00:00
|
|
|
case "service", "system":
|
|
|
|
defaultRestartPolicy = &RestartPolicy{
|
2018-01-31 22:33:00 +00:00
|
|
|
Delay: helper.TimeToPtr(structs.DefaultServiceJobRestartPolicy.Delay),
|
|
|
|
Attempts: helper.IntToPtr(structs.DefaultServiceJobRestartPolicy.Attempts),
|
|
|
|
Interval: helper.TimeToPtr(structs.DefaultServiceJobRestartPolicy.Interval),
|
|
|
|
Mode: helper.StringToPtr(structs.DefaultServiceJobRestartPolicy.Mode),
|
2017-02-06 19:48:28 +00:00
|
|
|
}
|
2017-02-13 23:18:17 +00:00
|
|
|
default:
|
|
|
|
defaultRestartPolicy = &RestartPolicy{
|
2018-01-31 22:33:00 +00:00
|
|
|
Delay: helper.TimeToPtr(structs.DefaultBatchJobRestartPolicy.Delay),
|
|
|
|
Attempts: helper.IntToPtr(structs.DefaultBatchJobRestartPolicy.Attempts),
|
|
|
|
Interval: helper.TimeToPtr(structs.DefaultBatchJobRestartPolicy.Interval),
|
|
|
|
Mode: helper.StringToPtr(structs.DefaultBatchJobRestartPolicy.Mode),
|
2017-02-13 23:18:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if g.RestartPolicy != nil {
|
|
|
|
defaultRestartPolicy.Merge(g.RestartPolicy)
|
2015-09-09 20:02:39 +00:00
|
|
|
}
|
2017-02-13 23:18:17 +00:00
|
|
|
g.RestartPolicy = defaultRestartPolicy
|
2015-09-09 20:02:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Constrain is used to add a constraint to a task group.
|
|
|
|
func (g *TaskGroup) Constrain(c *Constraint) *TaskGroup {
|
|
|
|
g.Constraints = append(g.Constraints, c)
|
|
|
|
return g
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddMeta is used to add a meta k/v pair to a task group
|
|
|
|
func (g *TaskGroup) SetMeta(key, val string) *TaskGroup {
|
|
|
|
if g.Meta == nil {
|
|
|
|
g.Meta = make(map[string]string)
|
|
|
|
}
|
|
|
|
g.Meta[key] = val
|
|
|
|
return g
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddTask is used to add a new task to a task group.
|
|
|
|
func (g *TaskGroup) AddTask(t *Task) *TaskGroup {
|
|
|
|
g.Tasks = append(g.Tasks, t)
|
|
|
|
return g
|
|
|
|
}
|
|
|
|
|
2016-09-14 22:43:42 +00:00
|
|
|
// RequireDisk adds a ephemeral disk to the task group
|
|
|
|
func (g *TaskGroup) RequireDisk(disk *EphemeralDisk) *TaskGroup {
|
|
|
|
g.EphemeralDisk = disk
|
2016-08-26 03:10:25 +00:00
|
|
|
return g
|
|
|
|
}
|
|
|
|
|
2016-02-05 07:54:15 +00:00
|
|
|
// LogConfig provides configuration for log rotation
|
|
|
|
type LogConfig struct {
|
2017-02-22 20:30:05 +00:00
|
|
|
MaxFiles *int `mapstructure:"max_files"`
|
|
|
|
MaxFileSizeMB *int `mapstructure:"max_file_size"`
|
2017-02-06 19:48:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func DefaultLogConfig() *LogConfig {
|
|
|
|
return &LogConfig{
|
|
|
|
MaxFiles: helper.IntToPtr(10),
|
|
|
|
MaxFileSizeMB: helper.IntToPtr(10),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *LogConfig) Canonicalize() {
|
|
|
|
if l.MaxFiles == nil {
|
|
|
|
l.MaxFiles = helper.IntToPtr(10)
|
|
|
|
}
|
|
|
|
if l.MaxFileSizeMB == nil {
|
|
|
|
l.MaxFileSizeMB = helper.IntToPtr(10)
|
|
|
|
}
|
2016-02-05 07:54:15 +00:00
|
|
|
}
|
|
|
|
|
2017-01-26 05:06:16 +00:00
|
|
|
// DispatchPayloadConfig configures how a task gets its input from a job dispatch
|
|
|
|
type DispatchPayloadConfig struct {
|
2016-12-14 20:50:08 +00:00
|
|
|
File string
|
2016-11-23 22:56:50 +00:00
|
|
|
}
|
|
|
|
|
2015-09-09 20:02:39 +00:00
|
|
|
// Task is a single process in a task group.
|
|
|
|
type Task struct {
|
2017-01-26 05:06:16 +00:00
|
|
|
Name string
|
|
|
|
Driver string
|
|
|
|
User string
|
|
|
|
Config map[string]interface{}
|
|
|
|
Constraints []*Constraint
|
|
|
|
Env map[string]string
|
2017-03-01 23:30:01 +00:00
|
|
|
Services []*Service
|
2017-01-26 05:06:16 +00:00
|
|
|
Resources *Resources
|
|
|
|
Meta map[string]string
|
2017-02-22 20:30:05 +00:00
|
|
|
KillTimeout *time.Duration `mapstructure:"kill_timeout"`
|
|
|
|
LogConfig *LogConfig `mapstructure:"logs"`
|
2017-01-26 05:06:16 +00:00
|
|
|
Artifacts []*TaskArtifact
|
|
|
|
Vault *Vault
|
|
|
|
Templates []*Template
|
|
|
|
DispatchPayload *DispatchPayloadConfig
|
2017-02-21 00:36:41 +00:00
|
|
|
Leader bool
|
2017-08-17 00:54:11 +00:00
|
|
|
ShutdownDelay time.Duration `mapstructure:"shutdown_delay"`
|
2017-12-06 21:23:24 +00:00
|
|
|
KillSignal string `mapstructure:"kill_signal"`
|
2016-03-14 22:46:06 +00:00
|
|
|
}
|
|
|
|
|
2017-02-22 20:30:05 +00:00
|
|
|
func (t *Task) Canonicalize(tg *TaskGroup, job *Job) {
|
2017-11-09 15:57:57 +00:00
|
|
|
if t.Resources == nil {
|
2017-11-10 01:09:37 +00:00
|
|
|
t.Resources = &Resources{}
|
2017-11-09 15:57:57 +00:00
|
|
|
}
|
2017-11-10 01:09:37 +00:00
|
|
|
t.Resources.Canonicalize()
|
2017-02-24 20:08:31 +00:00
|
|
|
if t.KillTimeout == nil {
|
|
|
|
t.KillTimeout = helper.TimeToPtr(5 * time.Second)
|
|
|
|
}
|
2017-02-06 19:48:28 +00:00
|
|
|
if t.LogConfig == nil {
|
|
|
|
t.LogConfig = DefaultLogConfig()
|
|
|
|
} else {
|
|
|
|
t.LogConfig.Canonicalize()
|
|
|
|
}
|
|
|
|
for _, artifact := range t.Artifacts {
|
|
|
|
artifact.Canonicalize()
|
|
|
|
}
|
2017-02-24 20:08:31 +00:00
|
|
|
if t.Vault != nil {
|
|
|
|
t.Vault.Canonicalize()
|
|
|
|
}
|
2017-02-06 19:48:28 +00:00
|
|
|
for _, tmpl := range t.Templates {
|
|
|
|
tmpl.Canonicalize()
|
|
|
|
}
|
2017-03-01 23:30:01 +00:00
|
|
|
for _, s := range t.Services {
|
|
|
|
s.Canonicalize(t, tg, job)
|
|
|
|
}
|
2017-02-06 19:48:28 +00:00
|
|
|
}
|
|
|
|
|
2016-03-16 03:21:52 +00:00
|
|
|
// TaskArtifact is used to download artifacts before running a task.
|
2016-03-14 22:46:06 +00:00
|
|
|
type TaskArtifact struct {
|
2017-02-22 20:30:05 +00:00
|
|
|
GetterSource *string `mapstructure:"source"`
|
|
|
|
GetterOptions map[string]string `mapstructure:"options"`
|
2017-07-06 03:44:49 +00:00
|
|
|
GetterMode *string `mapstructure:"mode"`
|
2017-02-22 20:30:05 +00:00
|
|
|
RelativeDest *string `mapstructure:"destination"`
|
2017-02-06 19:48:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (a *TaskArtifact) Canonicalize() {
|
2017-07-06 03:44:49 +00:00
|
|
|
if a.GetterMode == nil {
|
|
|
|
a.GetterMode = helper.StringToPtr("any")
|
|
|
|
}
|
|
|
|
if a.GetterSource == nil {
|
|
|
|
// Shouldn't be possible, but we don't want to panic
|
|
|
|
a.GetterSource = helper.StringToPtr("")
|
|
|
|
}
|
2017-02-06 19:48:28 +00:00
|
|
|
if a.RelativeDest == nil {
|
2017-07-06 03:44:49 +00:00
|
|
|
switch *a.GetterMode {
|
|
|
|
case "file":
|
|
|
|
// File mode should default to local/filename
|
|
|
|
dest := *a.GetterSource
|
|
|
|
dest = path.Base(dest)
|
|
|
|
dest = filepath.Join("local", dest)
|
|
|
|
a.RelativeDest = &dest
|
|
|
|
default:
|
|
|
|
// Default to a directory
|
|
|
|
a.RelativeDest = helper.StringToPtr("local/")
|
|
|
|
}
|
2017-02-06 19:48:28 +00:00
|
|
|
}
|
2015-09-09 20:02:39 +00:00
|
|
|
}
|
|
|
|
|
2016-09-23 22:39:52 +00:00
|
|
|
type Template struct {
|
2017-02-22 20:30:05 +00:00
|
|
|
SourcePath *string `mapstructure:"source"`
|
|
|
|
DestPath *string `mapstructure:"destination"`
|
|
|
|
EmbeddedTmpl *string `mapstructure:"data"`
|
|
|
|
ChangeMode *string `mapstructure:"change_mode"`
|
|
|
|
ChangeSignal *string `mapstructure:"change_signal"`
|
|
|
|
Splay *time.Duration `mapstructure:"splay"`
|
|
|
|
Perms *string `mapstructure:"perms"`
|
|
|
|
LeftDelim *string `mapstructure:"left_delimiter"`
|
|
|
|
RightDelim *string `mapstructure:"right_delimiter"`
|
2017-05-13 00:07:54 +00:00
|
|
|
Envvars *bool `mapstructure:"env"`
|
2017-08-01 21:14:08 +00:00
|
|
|
VaultGrace *time.Duration `mapstructure:"vault_grace"`
|
2017-02-06 19:48:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (tmpl *Template) Canonicalize() {
|
2017-02-24 18:31:05 +00:00
|
|
|
if tmpl.SourcePath == nil {
|
|
|
|
tmpl.SourcePath = helper.StringToPtr("")
|
2017-02-06 19:48:28 +00:00
|
|
|
}
|
2017-02-24 18:31:05 +00:00
|
|
|
if tmpl.DestPath == nil {
|
|
|
|
tmpl.DestPath = helper.StringToPtr("")
|
2017-02-06 19:48:28 +00:00
|
|
|
}
|
2017-02-24 18:31:05 +00:00
|
|
|
if tmpl.EmbeddedTmpl == nil {
|
|
|
|
tmpl.EmbeddedTmpl = helper.StringToPtr("")
|
|
|
|
}
|
|
|
|
if tmpl.ChangeMode == nil {
|
|
|
|
tmpl.ChangeMode = helper.StringToPtr("restart")
|
2017-02-06 19:48:28 +00:00
|
|
|
}
|
2017-02-24 18:47:50 +00:00
|
|
|
if tmpl.ChangeSignal == nil {
|
|
|
|
if *tmpl.ChangeMode == "signal" {
|
|
|
|
tmpl.ChangeSignal = helper.StringToPtr("SIGHUP")
|
|
|
|
} else {
|
|
|
|
tmpl.ChangeSignal = helper.StringToPtr("")
|
|
|
|
}
|
|
|
|
} else {
|
2017-02-13 23:18:17 +00:00
|
|
|
sig := *tmpl.ChangeSignal
|
|
|
|
tmpl.ChangeSignal = helper.StringToPtr(strings.ToUpper(sig))
|
|
|
|
}
|
2017-02-24 18:31:05 +00:00
|
|
|
if tmpl.Splay == nil {
|
|
|
|
tmpl.Splay = helper.TimeToPtr(5 * time.Second)
|
|
|
|
}
|
|
|
|
if tmpl.Perms == nil {
|
|
|
|
tmpl.Perms = helper.StringToPtr("0644")
|
|
|
|
}
|
2017-02-21 00:43:28 +00:00
|
|
|
if tmpl.LeftDelim == nil {
|
|
|
|
tmpl.LeftDelim = helper.StringToPtr("{{")
|
|
|
|
}
|
|
|
|
if tmpl.RightDelim == nil {
|
|
|
|
tmpl.RightDelim = helper.StringToPtr("}}")
|
|
|
|
}
|
2017-05-13 00:07:54 +00:00
|
|
|
if tmpl.Envvars == nil {
|
|
|
|
tmpl.Envvars = helper.BoolToPtr(false)
|
|
|
|
}
|
2017-08-01 21:14:08 +00:00
|
|
|
if tmpl.VaultGrace == nil {
|
2017-10-12 00:20:12 +00:00
|
|
|
tmpl.VaultGrace = helper.TimeToPtr(15 * time.Second)
|
2017-08-01 21:14:08 +00:00
|
|
|
}
|
2016-09-23 22:39:52 +00:00
|
|
|
}
|
|
|
|
|
2016-08-17 04:32:25 +00:00
|
|
|
type Vault struct {
|
2016-10-17 18:41:22 +00:00
|
|
|
Policies []string
|
2017-02-06 19:48:28 +00:00
|
|
|
Env *bool
|
2017-02-22 20:30:05 +00:00
|
|
|
ChangeMode *string `mapstructure:"change_mode"`
|
|
|
|
ChangeSignal *string `mapstructure:"change_signal"`
|
2017-02-06 19:48:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (v *Vault) Canonicalize() {
|
|
|
|
if v.Env == nil {
|
|
|
|
v.Env = helper.BoolToPtr(true)
|
|
|
|
}
|
|
|
|
if v.ChangeMode == nil {
|
|
|
|
v.ChangeMode = helper.StringToPtr("restart")
|
|
|
|
}
|
|
|
|
if v.ChangeSignal == nil {
|
2017-02-13 23:18:17 +00:00
|
|
|
v.ChangeSignal = helper.StringToPtr("SIGHUP")
|
2017-02-06 19:48:28 +00:00
|
|
|
}
|
2016-08-17 04:32:25 +00:00
|
|
|
}
|
|
|
|
|
2015-09-09 20:02:39 +00:00
|
|
|
// NewTask creates and initializes a new Task.
|
|
|
|
func NewTask(name, driver string) *Task {
|
|
|
|
return &Task{
|
|
|
|
Name: name,
|
|
|
|
Driver: driver,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Configure is used to configure a single k/v pair on
|
|
|
|
// the task.
|
2016-08-22 16:35:25 +00:00
|
|
|
func (t *Task) SetConfig(key string, val interface{}) *Task {
|
2015-09-09 20:02:39 +00:00
|
|
|
if t.Config == nil {
|
2015-11-14 04:51:30 +00:00
|
|
|
t.Config = make(map[string]interface{})
|
2015-09-09 20:02:39 +00:00
|
|
|
}
|
|
|
|
t.Config[key] = val
|
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetMeta is used to add metadata k/v pairs to the task.
|
|
|
|
func (t *Task) SetMeta(key, val string) *Task {
|
|
|
|
if t.Meta == nil {
|
|
|
|
t.Meta = make(map[string]string)
|
|
|
|
}
|
|
|
|
t.Meta[key] = val
|
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
|
|
|
// Require is used to add resource requirements to a task.
|
|
|
|
func (t *Task) Require(r *Resources) *Task {
|
|
|
|
t.Resources = r
|
|
|
|
return t
|
|
|
|
}
|
2015-09-10 00:29:43 +00:00
|
|
|
|
|
|
|
// Constraint adds a new constraints to a single task.
|
|
|
|
func (t *Task) Constrain(c *Constraint) *Task {
|
|
|
|
t.Constraints = append(t.Constraints, c)
|
|
|
|
return t
|
|
|
|
}
|
2015-11-12 23:28:22 +00:00
|
|
|
|
2016-02-10 21:36:47 +00:00
|
|
|
// SetLogConfig sets a log config to a task
|
|
|
|
func (t *Task) SetLogConfig(l *LogConfig) *Task {
|
|
|
|
t.LogConfig = l
|
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2015-11-12 23:28:22 +00:00
|
|
|
// TaskState tracks the current state of a task and events that caused state
|
2016-05-15 16:41:34 +00:00
|
|
|
// transitions.
|
2015-11-12 23:28:22 +00:00
|
|
|
type TaskState struct {
|
2017-07-07 06:04:32 +00:00
|
|
|
State string
|
|
|
|
Failed bool
|
|
|
|
Restarts uint64
|
|
|
|
LastRestart time.Time
|
|
|
|
StartedAt time.Time
|
|
|
|
FinishedAt time.Time
|
|
|
|
Events []*TaskEvent
|
2015-11-12 23:28:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
2017-02-10 01:40:13 +00:00
|
|
|
TaskSetup = "Task Setup"
|
2016-10-10 21:49:37 +00:00
|
|
|
TaskSetupFailure = "Setup Failure"
|
2016-03-15 17:53:20 +00:00
|
|
|
TaskDriverFailure = "Driver Failure"
|
2016-12-20 19:51:09 +00:00
|
|
|
TaskDriverMessage = "Driver"
|
2016-03-15 17:53:20 +00:00
|
|
|
TaskReceived = "Received"
|
2016-03-24 17:55:14 +00:00
|
|
|
TaskFailedValidation = "Failed Validation"
|
2016-03-15 17:53:20 +00:00
|
|
|
TaskStarted = "Started"
|
|
|
|
TaskTerminated = "Terminated"
|
2016-07-21 22:49:54 +00:00
|
|
|
TaskKilling = "Killing"
|
2016-03-15 17:53:20 +00:00
|
|
|
TaskKilled = "Killed"
|
|
|
|
TaskRestarting = "Restarting"
|
2016-03-24 22:43:55 +00:00
|
|
|
TaskNotRestarting = "Not Restarting"
|
2016-03-15 17:53:20 +00:00
|
|
|
TaskDownloadingArtifacts = "Downloading Artifacts"
|
|
|
|
TaskArtifactDownloadFailed = "Failed Artifact Download"
|
2017-02-11 01:55:19 +00:00
|
|
|
TaskSiblingFailed = "Sibling Task Failed"
|
2016-10-05 20:41:29 +00:00
|
|
|
TaskSignaling = "Signaling"
|
2016-10-05 22:11:09 +00:00
|
|
|
TaskRestartSignal = "Restart Signaled"
|
2017-02-11 01:55:19 +00:00
|
|
|
TaskLeaderDead = "Leader Task Dead"
|
2017-07-07 06:04:42 +00:00
|
|
|
TaskBuildingTaskDir = "Building Task Directory"
|
2015-11-12 23:28:22 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// TaskEvent is an event that effects the state of a task and contains meta-data
|
|
|
|
// appropriate to the events type.
|
|
|
|
type TaskEvent struct {
|
2017-11-03 17:48:55 +00:00
|
|
|
Type string
|
|
|
|
Time int64
|
|
|
|
DisplayMessage string
|
|
|
|
Details map[string]string
|
2017-11-03 15:12:37 +00:00
|
|
|
// DEPRECATION NOTICE: The following fields are all deprecated. see TaskEvent struct in structs.go for details.
|
2016-12-20 19:51:09 +00:00
|
|
|
FailsTask bool
|
|
|
|
RestartReason string
|
|
|
|
SetupError string
|
|
|
|
DriverError string
|
|
|
|
DriverMessage string
|
|
|
|
ExitCode int
|
|
|
|
Signal int
|
|
|
|
Message string
|
|
|
|
KillReason string
|
|
|
|
KillTimeout time.Duration
|
|
|
|
KillError string
|
|
|
|
StartDelay int64
|
|
|
|
DownloadError string
|
|
|
|
ValidationError string
|
|
|
|
DiskLimit int64
|
|
|
|
DiskSize int64
|
|
|
|
FailedSibling string
|
|
|
|
VaultError string
|
|
|
|
TaskSignalReason string
|
|
|
|
TaskSignal string
|
2017-08-08 04:26:04 +00:00
|
|
|
GenericSource string
|
2015-11-12 23:28:22 +00:00
|
|
|
}
|