github.com/ryanslade/nomad@v0.2.4-0.20160128061903-fc95782f2089/api/jobs_test.go (about) 1 package api 2 3 import ( 4 "reflect" 5 "sort" 6 "strings" 7 "testing" 8 9 "github.com/hashicorp/nomad/testutil" 10 ) 11 12 func TestJobs_Register(t *testing.T) { 13 c, s := makeClient(t, nil, nil) 14 defer s.Stop() 15 jobs := c.Jobs() 16 17 // Listing jobs before registering returns nothing 18 resp, qm, err := jobs.List(nil) 19 if err != nil { 20 t.Fatalf("err: %s", err) 21 } 22 if qm.LastIndex != 0 { 23 t.Fatalf("bad index: %d", qm.LastIndex) 24 } 25 if n := len(resp); n != 0 { 26 t.Fatalf("expected 0 jobs, got: %d", n) 27 } 28 29 // Create a job and attempt to register it 30 job := testJob() 31 eval, wm, err := jobs.Register(job, nil) 32 if err != nil { 33 t.Fatalf("err: %s", err) 34 } 35 if eval == "" { 36 t.Fatalf("missing eval id") 37 } 38 assertWriteMeta(t, wm) 39 40 // Query the jobs back out again 41 resp, qm, err = jobs.List(nil) 42 if err != nil { 43 t.Fatalf("err: %s", err) 44 } 45 assertQueryMeta(t, qm) 46 47 // Check that we got the expected response 48 if len(resp) != 1 || resp[0].ID != job.ID { 49 t.Fatalf("bad: %#v", resp[0]) 50 } 51 } 52 53 func TestJobs_Info(t *testing.T) { 54 c, s := makeClient(t, nil, nil) 55 defer s.Stop() 56 jobs := c.Jobs() 57 58 // Trying to retrieve a job by ID before it exists 59 // returns an error 60 _, _, err := jobs.Info("job1", nil) 61 if err == nil || !strings.Contains(err.Error(), "not found") { 62 t.Fatalf("expected not found error, got: %#v", err) 63 } 64 65 // Register the job 66 job := testJob() 67 _, wm, err := jobs.Register(job, nil) 68 if err != nil { 69 t.Fatalf("err: %s", err) 70 } 71 assertWriteMeta(t, wm) 72 73 // Query the job again and ensure it exists 74 result, qm, err := jobs.Info("job1", nil) 75 if err != nil { 76 t.Fatalf("err: %s", err) 77 } 78 assertQueryMeta(t, qm) 79 80 // Check that the result is what we expect 81 if result == nil || result.ID != job.ID { 82 t.Fatalf("expect: %#v, got: %#v", job, result) 83 } 84 } 85 86 func TestJobs_PrefixList(t *testing.T) { 87 c, s := makeClient(t, nil, nil) 88 defer s.Stop() 89 jobs := c.Jobs() 90 91 // Listing when nothing exists returns empty 92 results, qm, err := jobs.PrefixList("dummy") 93 if err != nil { 94 t.Fatalf("err: %s", err) 95 } 96 if qm.LastIndex != 0 { 97 t.Fatalf("bad index: %d", qm.LastIndex) 98 } 99 if n := len(results); n != 0 { 100 t.Fatalf("expected 0 jobs, got: %d", n) 101 } 102 103 // Register the job 104 job := testJob() 105 _, wm, err := jobs.Register(job, nil) 106 if err != nil { 107 t.Fatalf("err: %s", err) 108 } 109 assertWriteMeta(t, wm) 110 111 // Query the job again and ensure it exists 112 // Listing when nothing exists returns empty 113 results, qm, err = jobs.PrefixList(job.ID[:1]) 114 if err != nil { 115 t.Fatalf("err: %s", err) 116 } 117 118 // Check if we have the right list 119 if len(results) != 1 || results[0].ID != job.ID { 120 t.Fatalf("bad: %#v", results) 121 } 122 } 123 124 func TestJobs_List(t *testing.T) { 125 c, s := makeClient(t, nil, nil) 126 defer s.Stop() 127 jobs := c.Jobs() 128 129 // Listing when nothing exists returns empty 130 results, qm, err := jobs.List(nil) 131 if err != nil { 132 t.Fatalf("err: %s", err) 133 } 134 if qm.LastIndex != 0 { 135 t.Fatalf("bad index: %d", qm.LastIndex) 136 } 137 if n := len(results); n != 0 { 138 t.Fatalf("expected 0 jobs, got: %d", n) 139 } 140 141 // Register the job 142 job := testJob() 143 _, wm, err := jobs.Register(job, nil) 144 if err != nil { 145 t.Fatalf("err: %s", err) 146 } 147 assertWriteMeta(t, wm) 148 149 // Query the job again and ensure it exists 150 // Listing when nothing exists returns empty 151 results, qm, err = jobs.List(nil) 152 if err != nil { 153 t.Fatalf("err: %s", err) 154 } 155 156 // Check if we have the right list 157 if len(results) != 1 || results[0].ID != job.ID { 158 t.Fatalf("bad: %#v", results) 159 } 160 } 161 162 func TestJobs_Allocations(t *testing.T) { 163 c, s := makeClient(t, nil, nil) 164 defer s.Stop() 165 jobs := c.Jobs() 166 167 // Looking up by a non-existent job returns nothing 168 allocs, qm, err := jobs.Allocations("job1", nil) 169 if err != nil { 170 t.Fatalf("err: %s", err) 171 } 172 if qm.LastIndex != 0 { 173 t.Fatalf("bad index: %d", qm.LastIndex) 174 } 175 if n := len(allocs); n != 0 { 176 t.Fatalf("expected 0 allocs, got: %d", n) 177 } 178 179 // TODO: do something here to create some allocations for 180 // an existing job, lookup again. 181 } 182 183 func TestJobs_Evaluations(t *testing.T) { 184 c, s := makeClient(t, nil, nil) 185 defer s.Stop() 186 jobs := c.Jobs() 187 188 // Looking up by a non-existent job ID returns nothing 189 evals, qm, err := jobs.Evaluations("job1", nil) 190 if err != nil { 191 t.Fatalf("err: %s", err) 192 } 193 if qm.LastIndex != 0 { 194 t.Fatalf("bad index: %d", qm.LastIndex) 195 } 196 if n := len(evals); n != 0 { 197 t.Fatalf("expected 0 evals, got: %d", n) 198 } 199 200 // Insert a job. This also creates an evaluation so we should 201 // be able to query that out after. 202 job := testJob() 203 evalID, wm, err := jobs.Register(job, nil) 204 if err != nil { 205 t.Fatalf("err: %s", err) 206 } 207 assertWriteMeta(t, wm) 208 209 // Look up the evaluations again. 210 evals, qm, err = jobs.Evaluations("job1", nil) 211 if err != nil { 212 t.Fatalf("err: %s", err) 213 } 214 assertQueryMeta(t, qm) 215 216 // Check that we got the evals back 217 if n := len(evals); n == 0 || evals[0].ID != evalID { 218 t.Fatalf("expected 1 eval (%s), got: %#v", evalID, evals) 219 } 220 } 221 222 func TestJobs_Deregister(t *testing.T) { 223 c, s := makeClient(t, nil, nil) 224 defer s.Stop() 225 jobs := c.Jobs() 226 227 // Register a new job 228 job := testJob() 229 _, wm, err := jobs.Register(job, nil) 230 if err != nil { 231 t.Fatalf("err: %s", err) 232 } 233 assertWriteMeta(t, wm) 234 235 // Attempting delete on non-existing job returns an error 236 if _, _, err = jobs.Deregister("nope", nil); err == nil { 237 t.Fatalf("expected error deregistering job") 238 } 239 240 // Deleting an existing job works 241 evalID, wm3, err := jobs.Deregister("job1", nil) 242 if err != nil { 243 t.Fatalf("err: %s", err) 244 } 245 assertWriteMeta(t, wm3) 246 if evalID == "" { 247 t.Fatalf("missing eval ID") 248 } 249 250 // Check that the job is really gone 251 result, qm, err := jobs.List(nil) 252 if err != nil { 253 t.Fatalf("err: %s", err) 254 } 255 assertQueryMeta(t, qm) 256 if n := len(result); n != 0 { 257 t.Fatalf("expected 0 jobs, got: %d", n) 258 } 259 } 260 261 func TestJobs_ForceEvaluate(t *testing.T) { 262 c, s := makeClient(t, nil, nil) 263 defer s.Stop() 264 jobs := c.Jobs() 265 266 // Force-eval on a non-existent job fails 267 _, _, err := jobs.ForceEvaluate("job1", nil) 268 if err == nil || !strings.Contains(err.Error(), "not found") { 269 t.Fatalf("expected not found error, got: %#v", err) 270 } 271 272 // Create a new job 273 _, wm, err := jobs.Register(testJob(), nil) 274 if err != nil { 275 t.Fatalf("err: %s", err) 276 } 277 assertWriteMeta(t, wm) 278 279 // Try force-eval again 280 evalID, wm, err := jobs.ForceEvaluate("job1", nil) 281 if err != nil { 282 t.Fatalf("err: %s", err) 283 } 284 assertWriteMeta(t, wm) 285 286 // Retrieve the evals and see if we get a matching one 287 evals, qm, err := jobs.Evaluations("job1", nil) 288 if err != nil { 289 t.Fatalf("err: %s", err) 290 } 291 assertQueryMeta(t, qm) 292 for _, eval := range evals { 293 if eval.ID == evalID { 294 return 295 } 296 } 297 t.Fatalf("evaluation %q missing", evalID) 298 } 299 300 func TestJobs_PeriodicForce(t *testing.T) { 301 c, s := makeClient(t, nil, nil) 302 defer s.Stop() 303 jobs := c.Jobs() 304 305 // Force-eval on a non-existent job fails 306 _, _, err := jobs.PeriodicForce("job1", nil) 307 if err == nil || !strings.Contains(err.Error(), "not found") { 308 t.Fatalf("expected not found error, got: %#v", err) 309 } 310 311 // Create a new job 312 job := testPeriodicJob() 313 _, _, err = jobs.Register(job, nil) 314 if err != nil { 315 t.Fatalf("err: %s", err) 316 } 317 318 testutil.WaitForResult(func() (bool, error) { 319 out, _, err := jobs.Info(job.ID, nil) 320 if err != nil || out == nil || out.ID != job.ID { 321 return false, err 322 } 323 return true, nil 324 }, func(err error) { 325 t.Fatalf("err: %s", err) 326 }) 327 328 // Try force again 329 evalID, wm, err := jobs.PeriodicForce(job.ID, nil) 330 if err != nil { 331 t.Fatalf("err: %s", err) 332 } 333 assertWriteMeta(t, wm) 334 335 if evalID == "" { 336 t.Fatalf("empty evalID") 337 } 338 339 // Retrieve the eval 340 evals := c.Evaluations() 341 eval, qm, err := evals.Info(evalID, nil) 342 if err != nil { 343 t.Fatalf("err: %s", err) 344 } 345 assertQueryMeta(t, qm) 346 if eval.ID == evalID { 347 return 348 } 349 t.Fatalf("evaluation %q missing", evalID) 350 } 351 352 func TestJobs_NewBatchJob(t *testing.T) { 353 job := NewBatchJob("job1", "myjob", "region1", 5) 354 expect := &Job{ 355 Region: "region1", 356 ID: "job1", 357 Name: "myjob", 358 Type: JobTypeBatch, 359 Priority: 5, 360 } 361 if !reflect.DeepEqual(job, expect) { 362 t.Fatalf("expect: %#v, got: %#v", expect, job) 363 } 364 } 365 366 func TestJobs_NewServiceJob(t *testing.T) { 367 job := NewServiceJob("job1", "myjob", "region1", 5) 368 expect := &Job{ 369 Region: "region1", 370 ID: "job1", 371 Name: "myjob", 372 Type: JobTypeService, 373 Priority: 5, 374 } 375 if !reflect.DeepEqual(job, expect) { 376 t.Fatalf("expect: %#v, got: %#v", expect, job) 377 } 378 } 379 380 func TestJobs_SetMeta(t *testing.T) { 381 job := &Job{Meta: nil} 382 383 // Initializes a nil map 384 out := job.SetMeta("foo", "bar") 385 if job.Meta == nil { 386 t.Fatalf("should initialize metadata") 387 } 388 389 // Check that the job was returned 390 if job != out { 391 t.Fatalf("expect: %#v, got: %#v", job, out) 392 } 393 394 // Setting another pair is additive 395 job.SetMeta("baz", "zip") 396 expect := map[string]string{"foo": "bar", "baz": "zip"} 397 if !reflect.DeepEqual(job.Meta, expect) { 398 t.Fatalf("expect: %#v, got: %#v", expect, job.Meta) 399 } 400 } 401 402 func TestJobs_Constrain(t *testing.T) { 403 job := &Job{Constraints: nil} 404 405 // Create and add a constraint 406 out := job.Constrain(NewConstraint("kernel.name", "=", "darwin")) 407 if n := len(job.Constraints); n != 1 { 408 t.Fatalf("expected 1 constraint, got: %d", n) 409 } 410 411 // Check that the job was returned 412 if job != out { 413 t.Fatalf("expect: %#v, got: %#v", job, out) 414 } 415 416 // Adding another constraint preserves the original 417 job.Constrain(NewConstraint("memory.totalbytes", ">=", "128000000")) 418 expect := []*Constraint{ 419 &Constraint{ 420 LTarget: "kernel.name", 421 RTarget: "darwin", 422 Operand: "=", 423 }, 424 &Constraint{ 425 LTarget: "memory.totalbytes", 426 RTarget: "128000000", 427 Operand: ">=", 428 }, 429 } 430 if !reflect.DeepEqual(job.Constraints, expect) { 431 t.Fatalf("expect: %#v, got: %#v", expect, job.Constraints) 432 } 433 } 434 435 func TestJobs_Sort(t *testing.T) { 436 jobs := []*JobListStub{ 437 &JobListStub{ID: "job2"}, 438 &JobListStub{ID: "job0"}, 439 &JobListStub{ID: "job1"}, 440 } 441 sort.Sort(JobIDSort(jobs)) 442 443 expect := []*JobListStub{ 444 &JobListStub{ID: "job0"}, 445 &JobListStub{ID: "job1"}, 446 &JobListStub{ID: "job2"}, 447 } 448 if !reflect.DeepEqual(jobs, expect) { 449 t.Fatalf("\n\n%#v\n\n%#v", jobs, expect) 450 } 451 }