github.com/dkerwin/nomad@v0.3.3-0.20160525181927-74554135514b/api/jobs.go (about) 1 package api 2 3 import ( 4 "fmt" 5 "sort" 6 "time" 7 ) 8 9 const ( 10 // JobTypeService indicates a long-running processes 11 JobTypeService = "service" 12 13 // JobTypeBatch indicates a short-lived process 14 JobTypeBatch = "batch" 15 ) 16 17 // Jobs is used to access the job-specific endpoints. 18 type Jobs struct { 19 client *Client 20 } 21 22 // Jobs returns a handle on the jobs endpoints. 23 func (c *Client) Jobs() *Jobs { 24 return &Jobs{client: c} 25 } 26 27 // Register is used to register a new job. It returns the ID 28 // of the evaluation, along with any errors encountered. 29 func (j *Jobs) Register(job *Job, q *WriteOptions) (string, *WriteMeta, error) { 30 var resp registerJobResponse 31 32 req := &RegisterJobRequest{job} 33 wm, err := j.client.write("/v1/jobs", req, &resp, q) 34 if err != nil { 35 return "", nil, err 36 } 37 return resp.EvalID, wm, nil 38 } 39 40 // List is used to list all of the existing jobs. 41 func (j *Jobs) List(q *QueryOptions) ([]*JobListStub, *QueryMeta, error) { 42 var resp []*JobListStub 43 qm, err := j.client.query("/v1/jobs", &resp, q) 44 if err != nil { 45 return nil, qm, err 46 } 47 sort.Sort(JobIDSort(resp)) 48 return resp, qm, nil 49 } 50 51 // PrefixList is used to list all existing jobs that match the prefix. 52 func (j *Jobs) PrefixList(prefix string) ([]*JobListStub, *QueryMeta, error) { 53 return j.List(&QueryOptions{Prefix: prefix}) 54 } 55 56 // Info is used to retrieve information about a particular 57 // job given its unique ID. 58 func (j *Jobs) Info(jobID string, q *QueryOptions) (*Job, *QueryMeta, error) { 59 var resp Job 60 qm, err := j.client.query("/v1/job/"+jobID, &resp, q) 61 if err != nil { 62 return nil, nil, err 63 } 64 return &resp, qm, nil 65 } 66 67 // Allocations is used to return the allocs for a given job ID. 68 func (j *Jobs) Allocations(jobID string, q *QueryOptions) ([]*AllocationListStub, *QueryMeta, error) { 69 var resp []*AllocationListStub 70 qm, err := j.client.query("/v1/job/"+jobID+"/allocations", &resp, q) 71 if err != nil { 72 return nil, nil, err 73 } 74 sort.Sort(AllocIndexSort(resp)) 75 return resp, qm, nil 76 } 77 78 // Evaluations is used to query the evaluations associated with 79 // the given job ID. 80 func (j *Jobs) Evaluations(jobID string, q *QueryOptions) ([]*Evaluation, *QueryMeta, error) { 81 var resp []*Evaluation 82 qm, err := j.client.query("/v1/job/"+jobID+"/evaluations", &resp, q) 83 if err != nil { 84 return nil, nil, err 85 } 86 sort.Sort(EvalIndexSort(resp)) 87 return resp, qm, nil 88 } 89 90 // Deregister is used to remove an existing job. 91 func (j *Jobs) Deregister(jobID string, q *WriteOptions) (string, *WriteMeta, error) { 92 var resp deregisterJobResponse 93 wm, err := j.client.delete("/v1/job/"+jobID, &resp, q) 94 if err != nil { 95 return "", nil, err 96 } 97 return resp.EvalID, wm, nil 98 } 99 100 // ForceEvaluate is used to force-evaluate an existing job. 101 func (j *Jobs) ForceEvaluate(jobID string, q *WriteOptions) (string, *WriteMeta, error) { 102 var resp registerJobResponse 103 wm, err := j.client.write("/v1/job/"+jobID+"/evaluate", nil, &resp, q) 104 if err != nil { 105 return "", nil, err 106 } 107 return resp.EvalID, wm, nil 108 } 109 110 // PeriodicForce spawns a new instance of the periodic job and returns the eval ID 111 func (j *Jobs) PeriodicForce(jobID string, q *WriteOptions) (string, *WriteMeta, error) { 112 var resp periodicForceResponse 113 wm, err := j.client.write("/v1/job/"+jobID+"/periodic/force", nil, &resp, q) 114 if err != nil { 115 return "", nil, err 116 } 117 return resp.EvalID, wm, nil 118 } 119 120 func (j *Jobs) Plan(job *Job, diff bool, q *WriteOptions) (*JobPlanResponse, *WriteMeta, error) { 121 if job == nil { 122 return nil, nil, fmt.Errorf("must pass non-nil job") 123 } 124 125 var resp JobPlanResponse 126 req := &JobPlanRequest{ 127 Job: job, 128 Diff: diff, 129 } 130 wm, err := j.client.write("/v1/job/"+job.ID+"/plan", req, &resp, q) 131 if err != nil { 132 return nil, nil, err 133 } 134 135 return &resp, wm, nil 136 } 137 138 // periodicForceResponse is used to deserialize a force response 139 type periodicForceResponse struct { 140 EvalID string 141 } 142 143 // UpdateStrategy is for serializing update strategy for a job. 144 type UpdateStrategy struct { 145 Stagger time.Duration 146 MaxParallel int 147 } 148 149 // PeriodicConfig is for serializing periodic config for a job. 150 type PeriodicConfig struct { 151 Enabled bool 152 Spec string 153 SpecType string 154 ProhibitOverlap bool 155 } 156 157 // Job is used to serialize a job. 158 type Job struct { 159 Region string 160 ID string 161 Name string 162 Type string 163 Priority int 164 AllAtOnce bool 165 Datacenters []string 166 Constraints []*Constraint 167 TaskGroups []*TaskGroup 168 Update *UpdateStrategy 169 Periodic *PeriodicConfig 170 Meta map[string]string 171 Status string 172 StatusDescription string 173 CreateIndex uint64 174 ModifyIndex uint64 175 } 176 177 // JobListStub is used to return a subset of information about 178 // jobs during list operations. 179 type JobListStub struct { 180 ID string 181 ParentID string 182 Name string 183 Type string 184 Priority int 185 Status string 186 StatusDescription string 187 CreateIndex uint64 188 ModifyIndex uint64 189 } 190 191 // JobIDSort is used to sort jobs by their job ID's. 192 type JobIDSort []*JobListStub 193 194 func (j JobIDSort) Len() int { 195 return len(j) 196 } 197 198 func (j JobIDSort) Less(a, b int) bool { 199 return j[a].ID < j[b].ID 200 } 201 202 func (j JobIDSort) Swap(a, b int) { 203 j[a], j[b] = j[b], j[a] 204 } 205 206 // NewServiceJob creates and returns a new service-style job 207 // for long-lived processes using the provided name, ID, and 208 // relative job priority. 209 func NewServiceJob(id, name, region string, pri int) *Job { 210 return newJob(id, name, region, JobTypeService, pri) 211 } 212 213 // NewBatchJob creates and returns a new batch-style job for 214 // short-lived processes using the provided name and ID along 215 // with the relative job priority. 216 func NewBatchJob(id, name, region string, pri int) *Job { 217 return newJob(id, name, region, JobTypeBatch, pri) 218 } 219 220 // newJob is used to create a new Job struct. 221 func newJob(id, name, region, typ string, pri int) *Job { 222 return &Job{ 223 Region: region, 224 ID: id, 225 Name: name, 226 Type: typ, 227 Priority: pri, 228 } 229 } 230 231 // SetMeta is used to set arbitrary k/v pairs of metadata on a job. 232 func (j *Job) SetMeta(key, val string) *Job { 233 if j.Meta == nil { 234 j.Meta = make(map[string]string) 235 } 236 j.Meta[key] = val 237 return j 238 } 239 240 // AddDatacenter is used to add a datacenter to a job. 241 func (j *Job) AddDatacenter(dc string) *Job { 242 j.Datacenters = append(j.Datacenters, dc) 243 return j 244 } 245 246 // Constrain is used to add a constraint to a job. 247 func (j *Job) Constrain(c *Constraint) *Job { 248 j.Constraints = append(j.Constraints, c) 249 return j 250 } 251 252 // AddTaskGroup adds a task group to an existing job. 253 func (j *Job) AddTaskGroup(grp *TaskGroup) *Job { 254 j.TaskGroups = append(j.TaskGroups, grp) 255 return j 256 } 257 258 // AddPeriodicConfig adds a periodic config to an existing job. 259 func (j *Job) AddPeriodicConfig(cfg *PeriodicConfig) *Job { 260 j.Periodic = cfg 261 return j 262 } 263 264 // RegisterJobRequest is used to serialize a job registration 265 type RegisterJobRequest struct { 266 Job *Job 267 } 268 269 // registerJobResponse is used to deserialize a job response 270 type registerJobResponse struct { 271 EvalID string 272 } 273 274 // deregisterJobResponse is used to decode a deregister response 275 type deregisterJobResponse struct { 276 EvalID string 277 } 278 279 type JobPlanRequest struct { 280 Job *Job 281 Diff bool 282 } 283 284 type JobPlanResponse struct { 285 JobModifyIndex uint64 286 CreatedEvals []*Evaluation 287 Diff *JobDiff 288 Annotations *PlanAnnotations 289 } 290 291 type JobDiff struct { 292 Type string 293 ID string 294 Fields []*FieldDiff 295 Objects []*ObjectDiff 296 TaskGroups []*TaskGroupDiff 297 } 298 299 type TaskGroupDiff struct { 300 Type string 301 Name string 302 Fields []*FieldDiff 303 Objects []*ObjectDiff 304 Tasks []*TaskDiff 305 Updates map[string]uint64 306 } 307 308 type TaskDiff struct { 309 Type string 310 Name string 311 Fields []*FieldDiff 312 Objects []*ObjectDiff 313 Annotations []string 314 } 315 316 type FieldDiff struct { 317 Type string 318 Name string 319 Old, New string 320 Annotations []string 321 } 322 323 type ObjectDiff struct { 324 Type string 325 Name string 326 Fields []*FieldDiff 327 Objects []*ObjectDiff 328 } 329 330 type PlanAnnotations struct { 331 DesiredTGUpdates map[string]*DesiredUpdates 332 } 333 334 type DesiredUpdates struct { 335 Ignore uint64 336 Place uint64 337 Migrate uint64 338 Stop uint64 339 InPlaceUpdate uint64 340 DestructiveUpdate uint64 341 }