github.com/diptanu/nomad@v0.5.7-0.20170516172507-d72e86cbe3d9/api/tasks.go (about) 1 package api 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 "github.com/hashicorp/nomad/helper" 9 ) 10 11 // MemoryStats holds memory usage related stats 12 type MemoryStats struct { 13 RSS uint64 14 Cache uint64 15 Swap uint64 16 MaxUsage uint64 17 KernelUsage uint64 18 KernelMaxUsage uint64 19 Measured []string 20 } 21 22 // CpuStats holds cpu usage related stats 23 type CpuStats struct { 24 SystemMode float64 25 UserMode float64 26 TotalTicks float64 27 ThrottledPeriods uint64 28 ThrottledTime uint64 29 Percent float64 30 Measured []string 31 } 32 33 // ResourceUsage holds information related to cpu and memory stats 34 type ResourceUsage struct { 35 MemoryStats *MemoryStats 36 CpuStats *CpuStats 37 } 38 39 // TaskResourceUsage holds aggregated resource usage of all processes in a Task 40 // and the resource usage of the individual pids 41 type TaskResourceUsage struct { 42 ResourceUsage *ResourceUsage 43 Timestamp int64 44 Pids map[string]*ResourceUsage 45 } 46 47 // AllocResourceUsage holds the aggregated task resource usage of the 48 // allocation. 49 type AllocResourceUsage struct { 50 ResourceUsage *ResourceUsage 51 Tasks map[string]*TaskResourceUsage 52 Timestamp int64 53 } 54 55 // RestartPolicy defines how the Nomad client restarts 56 // tasks in a taskgroup when they fail 57 type RestartPolicy struct { 58 Interval *time.Duration 59 Attempts *int 60 Delay *time.Duration 61 Mode *string 62 } 63 64 func (r *RestartPolicy) Merge(rp *RestartPolicy) { 65 if rp.Interval != nil { 66 r.Interval = rp.Interval 67 } 68 if rp.Attempts != nil { 69 r.Attempts = rp.Attempts 70 } 71 if rp.Delay != nil { 72 r.Delay = rp.Delay 73 } 74 if rp.Mode != nil { 75 r.Mode = rp.Mode 76 } 77 } 78 79 // The ServiceCheck data model represents the consul health check that 80 // Nomad registers for a Task 81 type ServiceCheck struct { 82 Id string 83 Name string 84 Type string 85 Command string 86 Args []string 87 Path string 88 Protocol string 89 PortLabel string `mapstructure:"port"` 90 Interval time.Duration 91 Timeout time.Duration 92 InitialStatus string `mapstructure:"initial_status"` 93 TLSSkipVerify bool `mapstructure:"tls_skip_verify"` 94 } 95 96 // The Service model represents a Consul service definition 97 type Service struct { 98 Id string 99 Name string 100 Tags []string 101 PortLabel string `mapstructure:"port"` 102 Checks []ServiceCheck 103 } 104 105 func (s *Service) Canonicalize(t *Task, tg *TaskGroup, job *Job) { 106 if s.Name == "" { 107 s.Name = fmt.Sprintf("%s-%s-%s", *job.Name, *tg.Name, t.Name) 108 } 109 } 110 111 // EphemeralDisk is an ephemeral disk object 112 type EphemeralDisk struct { 113 Sticky *bool 114 Migrate *bool 115 SizeMB *int `mapstructure:"size"` 116 } 117 118 func DefaultEphemeralDisk() *EphemeralDisk { 119 return &EphemeralDisk{ 120 Sticky: helper.BoolToPtr(false), 121 Migrate: helper.BoolToPtr(false), 122 SizeMB: helper.IntToPtr(300), 123 } 124 } 125 126 func (e *EphemeralDisk) Canonicalize() { 127 if e.Sticky == nil { 128 e.Sticky = helper.BoolToPtr(false) 129 } 130 if e.Migrate == nil { 131 e.Migrate = helper.BoolToPtr(false) 132 } 133 if e.SizeMB == nil { 134 e.SizeMB = helper.IntToPtr(300) 135 } 136 } 137 138 // TaskGroup is the unit of scheduling. 139 type TaskGroup struct { 140 Name *string 141 Count *int 142 Constraints []*Constraint 143 Tasks []*Task 144 RestartPolicy *RestartPolicy 145 EphemeralDisk *EphemeralDisk 146 Meta map[string]string 147 } 148 149 // NewTaskGroup creates a new TaskGroup. 150 func NewTaskGroup(name string, count int) *TaskGroup { 151 return &TaskGroup{ 152 Name: helper.StringToPtr(name), 153 Count: helper.IntToPtr(count), 154 } 155 } 156 157 func (g *TaskGroup) Canonicalize(job *Job) { 158 if g.Name == nil { 159 g.Name = helper.StringToPtr("") 160 } 161 if g.Count == nil { 162 g.Count = helper.IntToPtr(1) 163 } 164 for _, t := range g.Tasks { 165 t.Canonicalize(g, job) 166 } 167 if g.EphemeralDisk == nil { 168 g.EphemeralDisk = DefaultEphemeralDisk() 169 } else { 170 g.EphemeralDisk.Canonicalize() 171 } 172 173 var defaultRestartPolicy *RestartPolicy 174 switch *job.Type { 175 case "service", "system": 176 defaultRestartPolicy = &RestartPolicy{ 177 Delay: helper.TimeToPtr(15 * time.Second), 178 Attempts: helper.IntToPtr(2), 179 Interval: helper.TimeToPtr(1 * time.Minute), 180 Mode: helper.StringToPtr("delay"), 181 } 182 default: 183 defaultRestartPolicy = &RestartPolicy{ 184 Delay: helper.TimeToPtr(15 * time.Second), 185 Attempts: helper.IntToPtr(15), 186 Interval: helper.TimeToPtr(7 * 24 * time.Hour), 187 Mode: helper.StringToPtr("delay"), 188 } 189 } 190 191 if g.RestartPolicy != nil { 192 defaultRestartPolicy.Merge(g.RestartPolicy) 193 } 194 g.RestartPolicy = defaultRestartPolicy 195 } 196 197 // Constrain is used to add a constraint to a task group. 198 func (g *TaskGroup) Constrain(c *Constraint) *TaskGroup { 199 g.Constraints = append(g.Constraints, c) 200 return g 201 } 202 203 // AddMeta is used to add a meta k/v pair to a task group 204 func (g *TaskGroup) SetMeta(key, val string) *TaskGroup { 205 if g.Meta == nil { 206 g.Meta = make(map[string]string) 207 } 208 g.Meta[key] = val 209 return g 210 } 211 212 // AddTask is used to add a new task to a task group. 213 func (g *TaskGroup) AddTask(t *Task) *TaskGroup { 214 g.Tasks = append(g.Tasks, t) 215 return g 216 } 217 218 // RequireDisk adds a ephemeral disk to the task group 219 func (g *TaskGroup) RequireDisk(disk *EphemeralDisk) *TaskGroup { 220 g.EphemeralDisk = disk 221 return g 222 } 223 224 // LogConfig provides configuration for log rotation 225 type LogConfig struct { 226 MaxFiles *int `mapstructure:"max_files"` 227 MaxFileSizeMB *int `mapstructure:"max_file_size"` 228 } 229 230 func DefaultLogConfig() *LogConfig { 231 return &LogConfig{ 232 MaxFiles: helper.IntToPtr(10), 233 MaxFileSizeMB: helper.IntToPtr(10), 234 } 235 } 236 237 func (l *LogConfig) Canonicalize() { 238 if l.MaxFiles == nil { 239 l.MaxFiles = helper.IntToPtr(10) 240 } 241 if l.MaxFileSizeMB == nil { 242 l.MaxFileSizeMB = helper.IntToPtr(10) 243 } 244 } 245 246 // DispatchPayloadConfig configures how a task gets its input from a job dispatch 247 type DispatchPayloadConfig struct { 248 File string 249 } 250 251 // Task is a single process in a task group. 252 type Task struct { 253 Name string 254 Driver string 255 User string 256 Config map[string]interface{} 257 Constraints []*Constraint 258 Env map[string]string 259 Services []*Service 260 Resources *Resources 261 Meta map[string]string 262 KillTimeout *time.Duration `mapstructure:"kill_timeout"` 263 LogConfig *LogConfig `mapstructure:"logs"` 264 Artifacts []*TaskArtifact 265 Vault *Vault 266 Templates []*Template 267 DispatchPayload *DispatchPayloadConfig 268 Leader bool 269 } 270 271 func (t *Task) Canonicalize(tg *TaskGroup, job *Job) { 272 min := MinResources() 273 min.Merge(t.Resources) 274 min.Canonicalize() 275 t.Resources = min 276 277 if t.KillTimeout == nil { 278 t.KillTimeout = helper.TimeToPtr(5 * time.Second) 279 } 280 if t.LogConfig == nil { 281 t.LogConfig = DefaultLogConfig() 282 } else { 283 t.LogConfig.Canonicalize() 284 } 285 for _, artifact := range t.Artifacts { 286 artifact.Canonicalize() 287 } 288 if t.Vault != nil { 289 t.Vault.Canonicalize() 290 } 291 for _, tmpl := range t.Templates { 292 tmpl.Canonicalize() 293 } 294 for _, s := range t.Services { 295 s.Canonicalize(t, tg, job) 296 } 297 } 298 299 // TaskArtifact is used to download artifacts before running a task. 300 type TaskArtifact struct { 301 GetterSource *string `mapstructure:"source"` 302 GetterOptions map[string]string `mapstructure:"options"` 303 RelativeDest *string `mapstructure:"destination"` 304 } 305 306 func (a *TaskArtifact) Canonicalize() { 307 if a.RelativeDest == nil { 308 a.RelativeDest = helper.StringToPtr("local/") 309 } 310 } 311 312 type Template struct { 313 SourcePath *string `mapstructure:"source"` 314 DestPath *string `mapstructure:"destination"` 315 EmbeddedTmpl *string `mapstructure:"data"` 316 ChangeMode *string `mapstructure:"change_mode"` 317 ChangeSignal *string `mapstructure:"change_signal"` 318 Splay *time.Duration `mapstructure:"splay"` 319 Perms *string `mapstructure:"perms"` 320 LeftDelim *string `mapstructure:"left_delimiter"` 321 RightDelim *string `mapstructure:"right_delimiter"` 322 } 323 324 func (tmpl *Template) Canonicalize() { 325 if tmpl.SourcePath == nil { 326 tmpl.SourcePath = helper.StringToPtr("") 327 } 328 if tmpl.DestPath == nil { 329 tmpl.DestPath = helper.StringToPtr("") 330 } 331 if tmpl.EmbeddedTmpl == nil { 332 tmpl.EmbeddedTmpl = helper.StringToPtr("") 333 } 334 if tmpl.ChangeMode == nil { 335 tmpl.ChangeMode = helper.StringToPtr("restart") 336 } 337 if tmpl.ChangeSignal == nil { 338 if *tmpl.ChangeMode == "signal" { 339 tmpl.ChangeSignal = helper.StringToPtr("SIGHUP") 340 } else { 341 tmpl.ChangeSignal = helper.StringToPtr("") 342 } 343 } else { 344 sig := *tmpl.ChangeSignal 345 tmpl.ChangeSignal = helper.StringToPtr(strings.ToUpper(sig)) 346 } 347 if tmpl.Splay == nil { 348 tmpl.Splay = helper.TimeToPtr(5 * time.Second) 349 } 350 if tmpl.Perms == nil { 351 tmpl.Perms = helper.StringToPtr("0644") 352 } 353 if tmpl.LeftDelim == nil { 354 tmpl.LeftDelim = helper.StringToPtr("{{") 355 } 356 if tmpl.RightDelim == nil { 357 tmpl.RightDelim = helper.StringToPtr("}}") 358 } 359 } 360 361 type Vault struct { 362 Policies []string 363 Env *bool 364 ChangeMode *string `mapstructure:"change_mode"` 365 ChangeSignal *string `mapstructure:"change_signal"` 366 } 367 368 func (v *Vault) Canonicalize() { 369 if v.Env == nil { 370 v.Env = helper.BoolToPtr(true) 371 } 372 if v.ChangeMode == nil { 373 v.ChangeMode = helper.StringToPtr("restart") 374 } 375 if v.ChangeSignal == nil { 376 v.ChangeSignal = helper.StringToPtr("SIGHUP") 377 } 378 } 379 380 // NewTask creates and initializes a new Task. 381 func NewTask(name, driver string) *Task { 382 return &Task{ 383 Name: name, 384 Driver: driver, 385 } 386 } 387 388 // Configure is used to configure a single k/v pair on 389 // the task. 390 func (t *Task) SetConfig(key string, val interface{}) *Task { 391 if t.Config == nil { 392 t.Config = make(map[string]interface{}) 393 } 394 t.Config[key] = val 395 return t 396 } 397 398 // SetMeta is used to add metadata k/v pairs to the task. 399 func (t *Task) SetMeta(key, val string) *Task { 400 if t.Meta == nil { 401 t.Meta = make(map[string]string) 402 } 403 t.Meta[key] = val 404 return t 405 } 406 407 // Require is used to add resource requirements to a task. 408 func (t *Task) Require(r *Resources) *Task { 409 t.Resources = r 410 return t 411 } 412 413 // Constraint adds a new constraints to a single task. 414 func (t *Task) Constrain(c *Constraint) *Task { 415 t.Constraints = append(t.Constraints, c) 416 return t 417 } 418 419 // SetLogConfig sets a log config to a task 420 func (t *Task) SetLogConfig(l *LogConfig) *Task { 421 t.LogConfig = l 422 return t 423 } 424 425 // TaskState tracks the current state of a task and events that caused state 426 // transitions. 427 type TaskState struct { 428 State string 429 Failed bool 430 StartedAt time.Time 431 FinishedAt time.Time 432 Events []*TaskEvent 433 } 434 435 const ( 436 TaskSetup = "Task Setup" 437 TaskSetupFailure = "Setup Failure" 438 TaskDriverFailure = "Driver Failure" 439 TaskDriverMessage = "Driver" 440 TaskReceived = "Received" 441 TaskFailedValidation = "Failed Validation" 442 TaskStarted = "Started" 443 TaskTerminated = "Terminated" 444 TaskKilling = "Killing" 445 TaskKilled = "Killed" 446 TaskRestarting = "Restarting" 447 TaskNotRestarting = "Not Restarting" 448 TaskDownloadingArtifacts = "Downloading Artifacts" 449 TaskArtifactDownloadFailed = "Failed Artifact Download" 450 TaskSiblingFailed = "Sibling Task Failed" 451 TaskSignaling = "Signaling" 452 TaskRestartSignal = "Restart Signaled" 453 TaskLeaderDead = "Leader Task Dead" 454 ) 455 456 // TaskEvent is an event that effects the state of a task and contains meta-data 457 // appropriate to the events type. 458 type TaskEvent struct { 459 Type string 460 Time int64 461 FailsTask bool 462 RestartReason string 463 SetupError string 464 DriverError string 465 DriverMessage string 466 ExitCode int 467 Signal int 468 Message string 469 KillReason string 470 KillTimeout time.Duration 471 KillError string 472 StartDelay int64 473 DownloadError string 474 ValidationError string 475 DiskLimit int64 476 DiskSize int64 477 FailedSibling string 478 VaultError string 479 TaskSignalReason string 480 TaskSignal string 481 }