1package db_test 2 3import ( 4 "github.com/concourse/concourse/atc" 5 "github.com/concourse/concourse/atc/db" 6 . "github.com/onsi/ginkgo" 7 . "github.com/onsi/gomega" 8 . "github.com/onsi/gomega/gstruct" 9) 10 11var _ = Describe("Job Factory", func() { 12 var jobFactory db.JobFactory 13 14 BeforeEach(func() { 15 jobFactory = db.NewJobFactory(dbConn, lockFactory) 16 }) 17 18 Context("when there are public and private pipelines", func() { 19 var publicPipeline db.Pipeline 20 21 BeforeEach(func() { 22 otherTeam, err := teamFactory.CreateTeam(atc.Team{Name: "other-team"}) 23 Expect(err).NotTo(HaveOccurred()) 24 25 publicPipeline, _, err = otherTeam.SavePipeline("public-pipeline", atc.Config{ 26 Jobs: atc.JobConfigs{ 27 { 28 Name: "public-pipeline-job-1", 29 PlanSequence: []atc.Step{ 30 { 31 Config: &atc.GetStep{ 32 Name: "some-resource", 33 }, 34 }, 35 { 36 Config: &atc.GetStep{ 37 Name: "some-other-resource", 38 }, 39 }, 40 { 41 Config: &atc.PutStep{ 42 Name: "some-resource", 43 }, 44 }, 45 }, 46 }, 47 { 48 Name: "public-pipeline-job-2", 49 PlanSequence: []atc.Step{ 50 { 51 Config: &atc.GetStep{ 52 Name: "some-resource", 53 Passed: []string{"public-pipeline-job-1"}, 54 }, 55 }, 56 { 57 Config: &atc.GetStep{ 58 Name: "some-other-resource", 59 Passed: []string{"public-pipeline-job-1"}, 60 }, 61 }, 62 { 63 Config: &atc.GetStep{ 64 Name: "resource", 65 Resource: "some-resource", 66 }, 67 }, 68 { 69 Config: &atc.PutStep{ 70 Name: "resource", 71 Resource: "some-resource", 72 }, 73 }, 74 { 75 Config: &atc.PutStep{ 76 Name: "some-resource", 77 }, 78 }, 79 }, 80 }, 81 { 82 Name: "public-pipeline-job-3", 83 PlanSequence: []atc.Step{ 84 { 85 Config: &atc.GetStep{ 86 Name: "some-resource", 87 Passed: []string{"public-pipeline-job-1", "public-pipeline-job-2"}, 88 }, 89 }, 90 }, 91 }, 92 }, 93 Resources: atc.ResourceConfigs{ 94 { 95 Name: "some-resource", 96 Type: "some-type", 97 }, 98 { 99 Name: "some-other-resource", 100 Type: "some-type", 101 }, 102 }, 103 }, db.ConfigVersion(0), false) 104 Expect(err).ToNot(HaveOccurred()) 105 Expect(publicPipeline.Expose()).To(Succeed()) 106 107 _, _, err = otherTeam.SavePipeline("private-pipeline", atc.Config{ 108 Jobs: atc.JobConfigs{ 109 { 110 Name: "private-pipeline-job", 111 PlanSequence: []atc.Step{ 112 { 113 Config: &atc.GetStep{ 114 Name: "some-resource", 115 }, 116 }, 117 { 118 Config: &atc.PutStep{ 119 Name: "some-resource", 120 }, 121 }, 122 }, 123 }, 124 }, 125 Resources: atc.ResourceConfigs{ 126 { 127 Name: "some-resource", 128 Type: "some-type", 129 }, 130 }, 131 }, db.ConfigVersion(0), false) 132 Expect(err).ToNot(HaveOccurred()) 133 }) 134 135 Describe("VisibleJobs", func() { 136 It("returns jobs in the provided teams and jobs in public pipelines", func() { 137 visibleJobs, err := jobFactory.VisibleJobs([]string{"default-team"}) 138 Expect(err).ToNot(HaveOccurred()) 139 140 Expect(len(visibleJobs)).To(Equal(4)) 141 Expect(visibleJobs[0].Name).To(Equal("some-job")) 142 Expect(visibleJobs[1].Name).To(Equal("public-pipeline-job-1")) 143 Expect(visibleJobs[2].Name).To(Equal("public-pipeline-job-2")) 144 Expect(visibleJobs[3].Name).To(Equal("public-pipeline-job-3")) 145 146 Expect(visibleJobs[0].Inputs).To(BeNil()) 147 Expect(visibleJobs[1].Inputs).To(Equal([]atc.DashboardJobInput{ 148 atc.DashboardJobInput{ 149 Name: "some-other-resource", 150 Resource: "some-other-resource", 151 }, 152 atc.DashboardJobInput{ 153 Name: "some-resource", 154 Resource: "some-resource", 155 }, 156 })) 157 Expect(visibleJobs[2].Inputs).To(Equal([]atc.DashboardJobInput{ 158 atc.DashboardJobInput{ 159 Name: "resource", 160 Resource: "some-resource", 161 }, 162 atc.DashboardJobInput{ 163 Name: "some-other-resource", 164 Resource: "some-other-resource", 165 Passed: []string{"public-pipeline-job-1"}, 166 }, 167 atc.DashboardJobInput{ 168 Name: "some-resource", 169 Resource: "some-resource", 170 Passed: []string{"public-pipeline-job-1"}, 171 }, 172 })) 173 Expect(visibleJobs[3].Inputs).To(Equal([]atc.DashboardJobInput{ 174 atc.DashboardJobInput{ 175 Name: "some-resource", 176 Resource: "some-resource", 177 Passed: []string{"public-pipeline-job-1", "public-pipeline-job-2"}, 178 }, 179 })) 180 181 Expect(visibleJobs[0].Outputs).To(BeNil()) 182 Expect(visibleJobs[1].Outputs).To(Equal([]atc.JobOutput{ 183 atc.JobOutput{ 184 Name: "some-resource", 185 Resource: "some-resource", 186 }, 187 })) 188 Expect(visibleJobs[2].Outputs).To(Equal([]atc.JobOutput{ 189 atc.JobOutput{ 190 Name: "resource", 191 Resource: "some-resource", 192 }, 193 atc.JobOutput{ 194 Name: "some-resource", 195 Resource: "some-resource", 196 }, 197 })) 198 Expect(visibleJobs[3].Outputs).To(BeNil()) 199 }) 200 201 It("returns next build, latest completed build, and transition build for each job", func() { 202 job, found, err := defaultPipeline.Job("some-job") 203 Expect(err).ToNot(HaveOccurred()) 204 Expect(found).To(BeTrue()) 205 206 transitionBuild, err := job.CreateBuild() 207 Expect(err).ToNot(HaveOccurred()) 208 209 err = transitionBuild.Finish(db.BuildStatusSucceeded) 210 Expect(err).ToNot(HaveOccurred()) 211 212 found, err = transitionBuild.Reload() 213 Expect(err).ToNot(HaveOccurred()) 214 Expect(found).To(BeTrue()) 215 216 finishedBuild, err := job.CreateBuild() 217 Expect(err).ToNot(HaveOccurred()) 218 219 err = finishedBuild.Finish(db.BuildStatusSucceeded) 220 Expect(err).ToNot(HaveOccurred()) 221 222 found, err = finishedBuild.Reload() 223 Expect(err).ToNot(HaveOccurred()) 224 Expect(found).To(BeTrue()) 225 226 nextBuild, err := job.CreateBuild() 227 Expect(err).ToNot(HaveOccurred()) 228 229 visibleJobs, err := jobFactory.VisibleJobs([]string{"default-team"}) 230 Expect(err).ToNot(HaveOccurred()) 231 232 Expect(visibleJobs[0].Name).To(Equal("some-job")) 233 Expect(visibleJobs[0].NextBuild.ID).To(Equal(nextBuild.ID())) 234 Expect(visibleJobs[0].NextBuild.Name).To(Equal(nextBuild.Name())) 235 Expect(visibleJobs[0].NextBuild.JobName).To(Equal(nextBuild.JobName())) 236 Expect(visibleJobs[0].NextBuild.PipelineName).To(Equal(nextBuild.PipelineName())) 237 Expect(visibleJobs[0].NextBuild.TeamName).To(Equal(nextBuild.TeamName())) 238 Expect(visibleJobs[0].NextBuild.Status).To(Equal(string(nextBuild.Status()))) 239 Expect(visibleJobs[0].NextBuild.StartTime).To(Equal(nextBuild.StartTime())) 240 Expect(visibleJobs[0].NextBuild.EndTime).To(Equal(nextBuild.EndTime())) 241 242 Expect(visibleJobs[0].FinishedBuild.ID).To(Equal(finishedBuild.ID())) 243 Expect(visibleJobs[0].FinishedBuild.Name).To(Equal(finishedBuild.Name())) 244 Expect(visibleJobs[0].FinishedBuild.JobName).To(Equal(finishedBuild.JobName())) 245 Expect(visibleJobs[0].FinishedBuild.PipelineName).To(Equal(finishedBuild.PipelineName())) 246 Expect(visibleJobs[0].FinishedBuild.TeamName).To(Equal(finishedBuild.TeamName())) 247 Expect(visibleJobs[0].FinishedBuild.Status).To(Equal(string(finishedBuild.Status()))) 248 Expect(visibleJobs[0].FinishedBuild.StartTime).To(Equal(finishedBuild.StartTime())) 249 Expect(visibleJobs[0].FinishedBuild.EndTime).To(Equal(finishedBuild.EndTime())) 250 251 Expect(visibleJobs[0].TransitionBuild.ID).To(Equal(transitionBuild.ID())) 252 Expect(visibleJobs[0].TransitionBuild.Name).To(Equal(transitionBuild.Name())) 253 Expect(visibleJobs[0].TransitionBuild.JobName).To(Equal(transitionBuild.JobName())) 254 Expect(visibleJobs[0].TransitionBuild.PipelineName).To(Equal(transitionBuild.PipelineName())) 255 Expect(visibleJobs[0].TransitionBuild.TeamName).To(Equal(transitionBuild.TeamName())) 256 Expect(visibleJobs[0].TransitionBuild.Status).To(Equal(string(transitionBuild.Status()))) 257 Expect(visibleJobs[0].TransitionBuild.StartTime).To(Equal(transitionBuild.StartTime())) 258 Expect(visibleJobs[0].TransitionBuild.EndTime).To(Equal(transitionBuild.EndTime())) 259 }) 260 }) 261 262 Describe("AllActiveJobs", func() { 263 It("return all private and public pipelines", func() { 264 allJobs, err := jobFactory.AllActiveJobs() 265 Expect(err).ToNot(HaveOccurred()) 266 267 Expect(len(allJobs)).To(Equal(5)) 268 Expect(allJobs[0].Name).To(Equal("some-job")) 269 Expect(allJobs[1].Name).To(Equal("public-pipeline-job-1")) 270 Expect(allJobs[2].Name).To(Equal("public-pipeline-job-2")) 271 Expect(allJobs[3].Name).To(Equal("public-pipeline-job-3")) 272 Expect(allJobs[4].Name).To(Equal("private-pipeline-job")) 273 274 Expect(allJobs[0].Inputs).To(BeNil()) 275 Expect(allJobs[1].Inputs).To(Equal([]atc.DashboardJobInput{ 276 atc.DashboardJobInput{ 277 Name: "some-other-resource", 278 Resource: "some-other-resource", 279 }, 280 atc.DashboardJobInput{ 281 Name: "some-resource", 282 Resource: "some-resource", 283 }, 284 })) 285 Expect(allJobs[2].Inputs).To(Equal([]atc.DashboardJobInput{ 286 atc.DashboardJobInput{ 287 Name: "resource", 288 Resource: "some-resource", 289 }, 290 atc.DashboardJobInput{ 291 Name: "some-other-resource", 292 Resource: "some-other-resource", 293 Passed: []string{"public-pipeline-job-1"}, 294 }, 295 atc.DashboardJobInput{ 296 Name: "some-resource", 297 Resource: "some-resource", 298 Passed: []string{"public-pipeline-job-1"}, 299 }, 300 })) 301 Expect(allJobs[3].Inputs).To(Equal([]atc.DashboardJobInput{ 302 atc.DashboardJobInput{ 303 Name: "some-resource", 304 Resource: "some-resource", 305 Passed: []string{"public-pipeline-job-1", "public-pipeline-job-2"}, 306 }, 307 })) 308 Expect(allJobs[4].Inputs).To(Equal([]atc.DashboardJobInput{ 309 atc.DashboardJobInput{ 310 Name: "some-resource", 311 Resource: "some-resource", 312 }, 313 })) 314 315 Expect(allJobs[0].Outputs).To(BeNil()) 316 Expect(allJobs[1].Outputs).To(Equal([]atc.JobOutput{ 317 atc.JobOutput{ 318 Name: "some-resource", 319 Resource: "some-resource", 320 }, 321 })) 322 Expect(allJobs[2].Outputs).To(Equal([]atc.JobOutput{ 323 atc.JobOutput{ 324 Name: "resource", 325 Resource: "some-resource", 326 }, 327 atc.JobOutput{ 328 Name: "some-resource", 329 Resource: "some-resource", 330 }, 331 })) 332 Expect(allJobs[3].Outputs).To(BeNil()) 333 Expect(allJobs[4].Outputs).To(Equal([]atc.JobOutput{ 334 atc.JobOutput{ 335 Name: "some-resource", 336 Resource: "some-resource", 337 }, 338 })) 339 }) 340 }) 341 }) 342 343 Describe("JobsToSchedule", func() { 344 var ( 345 job1 db.Job 346 job2 db.Job 347 job3 db.Job 348 ) 349 350 BeforeEach(func() { 351 err := defaultPipeline.Destroy() 352 Expect(err).ToNot(HaveOccurred()) 353 }) 354 355 Context("when the job has a requested schedule time later than the last scheduled", func() { 356 BeforeEach(func() { 357 pipeline1, _, err := defaultTeam.SavePipeline("fake-pipeline", atc.Config{ 358 Jobs: atc.JobConfigs{ 359 {Name: "job-name"}, 360 }, 361 }, db.ConfigVersion(1), false) 362 Expect(err).ToNot(HaveOccurred()) 363 364 var found bool 365 job1, found, err = pipeline1.Job("job-name") 366 Expect(err).ToNot(HaveOccurred()) 367 Expect(found).To(BeTrue()) 368 369 err = job1.RequestSchedule() 370 Expect(err).ToNot(HaveOccurred()) 371 }) 372 373 It("fetches that job", func() { 374 jobs, err := jobFactory.JobsToSchedule() 375 Expect(err).ToNot(HaveOccurred()) 376 Expect(len(jobs)).To(Equal(1)) 377 Expect(jobs[0].Name()).To(Equal(job1.Name())) 378 }) 379 }) 380 381 Context("when the job has a requested schedule time earlier than the last scheduled", func() { 382 BeforeEach(func() { 383 pipeline1, _, err := defaultTeam.SavePipeline("fake-pipeline", atc.Config{ 384 Jobs: atc.JobConfigs{ 385 {Name: "job-name"}, 386 }, 387 }, db.ConfigVersion(1), false) 388 Expect(err).ToNot(HaveOccurred()) 389 390 var found bool 391 job1, found, err = pipeline1.Job("job-name") 392 Expect(err).ToNot(HaveOccurred()) 393 Expect(found).To(BeTrue()) 394 395 _, err = dbConn.Exec("UPDATE jobs SET last_scheduled = now() WHERE id = $1;", job1.ID()) 396 Expect(err).ToNot(HaveOccurred()) 397 }) 398 399 It("does not fetch that job", func() { 400 jobs, err := jobFactory.JobsToSchedule() 401 Expect(err).ToNot(HaveOccurred()) 402 Expect(len(jobs)).To(Equal(0)) 403 }) 404 }) 405 406 Context("when the job has a requested schedule time is the same as the last scheduled", func() { 407 BeforeEach(func() { 408 pipeline1, _, err := defaultTeam.SavePipeline("fake-pipeline", atc.Config{ 409 Jobs: atc.JobConfigs{ 410 {Name: "job-name"}, 411 }, 412 }, db.ConfigVersion(1), false) 413 Expect(err).ToNot(HaveOccurred()) 414 415 var found bool 416 job1, found, err = pipeline1.Job("job-name") 417 Expect(err).ToNot(HaveOccurred()) 418 Expect(found).To(BeTrue()) 419 420 err = job1.RequestSchedule() 421 Expect(err).ToNot(HaveOccurred()) 422 423 found, err = job1.Reload() 424 Expect(err).ToNot(HaveOccurred()) 425 Expect(found).To(BeTrue()) 426 427 err = job1.UpdateLastScheduled(job1.ScheduleRequestedTime()) 428 Expect(err).ToNot(HaveOccurred()) 429 }) 430 431 It("does not fetch that job", func() { 432 jobs, err := jobFactory.JobsToSchedule() 433 Expect(err).ToNot(HaveOccurred()) 434 Expect(len(jobs)).To(Equal(0)) 435 }) 436 }) 437 438 Context("when there are multiple jobs with different times", func() { 439 BeforeEach(func() { 440 pipeline1, _, err := defaultTeam.SavePipeline("fake-pipeline", atc.Config{ 441 Jobs: atc.JobConfigs{ 442 {Name: "job-name"}, 443 }, 444 }, db.ConfigVersion(1), false) 445 Expect(err).ToNot(HaveOccurred()) 446 447 var found bool 448 job1, found, err = pipeline1.Job("job-name") 449 Expect(err).ToNot(HaveOccurred()) 450 Expect(found).To(BeTrue()) 451 452 err = job1.RequestSchedule() 453 Expect(err).ToNot(HaveOccurred()) 454 455 team, err := teamFactory.CreateTeam(atc.Team{Name: "some-team"}) 456 Expect(err).ToNot(HaveOccurred()) 457 458 pipeline2, _, err := team.SavePipeline("fake-pipeline-two", atc.Config{ 459 Jobs: atc.JobConfigs{ 460 {Name: "job-fake"}, 461 }, 462 }, db.ConfigVersion(1), false) 463 Expect(err).ToNot(HaveOccurred()) 464 465 job2, found, err = pipeline2.Job("job-fake") 466 Expect(err).ToNot(HaveOccurred()) 467 Expect(found).To(BeTrue()) 468 469 pipeline3, _, err := team.SavePipeline("fake-pipeline-three", atc.Config{ 470 Jobs: atc.JobConfigs{ 471 {Name: "job-fake-two"}, 472 }, 473 }, db.ConfigVersion(1), false) 474 Expect(err).ToNot(HaveOccurred()) 475 476 job3, found, err = pipeline3.Job("job-fake-two") 477 Expect(err).ToNot(HaveOccurred()) 478 Expect(found).To(BeTrue()) 479 480 _, err = dbConn.Exec("UPDATE jobs SET last_scheduled = now() WHERE id = $1;", job2.ID()) 481 Expect(err).ToNot(HaveOccurred()) 482 483 err = job3.RequestSchedule() 484 Expect(err).ToNot(HaveOccurred()) 485 }) 486 487 It("fetches the jobs that have a requested schedule time later than it's last scheduled", func() { 488 jobs, err := jobFactory.JobsToSchedule() 489 Expect(err).ToNot(HaveOccurred()) 490 Expect(len(jobs)).To(Equal(2)) 491 jobNames := []string{jobs[0].Name(), jobs[1].Name()} 492 Expect(jobNames).To(ConsistOf(job1.Name(), job3.Name())) 493 }) 494 }) 495 496 Context("when the job is paused but has a later schedule requested time", func() { 497 BeforeEach(func() { 498 pipeline1, _, err := defaultTeam.SavePipeline("fake-pipeline", atc.Config{ 499 Jobs: atc.JobConfigs{ 500 {Name: "job-name"}, 501 }, 502 }, db.ConfigVersion(1), false) 503 Expect(err).ToNot(HaveOccurred()) 504 505 var found bool 506 job1, found, err = pipeline1.Job("job-name") 507 Expect(err).ToNot(HaveOccurred()) 508 Expect(found).To(BeTrue()) 509 510 err = job1.RequestSchedule() 511 Expect(err).ToNot(HaveOccurred()) 512 513 err = job1.Pause() 514 Expect(err).ToNot(HaveOccurred()) 515 }) 516 517 It("does not fetch that job", func() { 518 jobs, err := jobFactory.JobsToSchedule() 519 Expect(err).ToNot(HaveOccurred()) 520 Expect(len(jobs)).To(Equal(0)) 521 }) 522 }) 523 524 Context("when the job is inactive but has a later schedule requested time", func() { 525 BeforeEach(func() { 526 pipeline1, _, err := defaultTeam.SavePipeline("fake-pipeline", atc.Config{ 527 Jobs: atc.JobConfigs{ 528 {Name: "job-name"}, 529 }, 530 }, db.ConfigVersion(1), false) 531 Expect(err).ToNot(HaveOccurred()) 532 533 var found bool 534 job1, found, err = pipeline1.Job("job-name") 535 Expect(err).ToNot(HaveOccurred()) 536 Expect(found).To(BeTrue()) 537 538 err = job1.RequestSchedule() 539 Expect(err).ToNot(HaveOccurred()) 540 541 _, _, err = defaultTeam.SavePipeline("fake-pipeline", atc.Config{}, pipeline1.ConfigVersion(), false) 542 Expect(err).ToNot(HaveOccurred()) 543 }) 544 545 It("does not fetch that job", func() { 546 jobs, err := jobFactory.JobsToSchedule() 547 Expect(err).ToNot(HaveOccurred()) 548 Expect(len(jobs)).To(Equal(0)) 549 }) 550 }) 551 552 Context("when the pipeline is paused but it's job has a later schedule requested time", func() { 553 BeforeEach(func() { 554 pipeline1, _, err := defaultTeam.SavePipeline("fake-pipeline", atc.Config{ 555 Jobs: atc.JobConfigs{ 556 {Name: "job-name"}, 557 }, 558 }, db.ConfigVersion(1), false) 559 Expect(err).ToNot(HaveOccurred()) 560 561 var found bool 562 job1, found, err = pipeline1.Job("job-name") 563 Expect(err).ToNot(HaveOccurred()) 564 Expect(found).To(BeTrue()) 565 566 err = job1.RequestSchedule() 567 Expect(err).ToNot(HaveOccurred()) 568 569 err = pipeline1.Pause() 570 Expect(err).ToNot(HaveOccurred()) 571 }) 572 573 It("does not fetch that job", func() { 574 jobs, err := jobFactory.JobsToSchedule() 575 Expect(err).ToNot(HaveOccurred()) 576 Expect(len(jobs)).To(Equal(0)) 577 }) 578 }) 579 580 Describe("scheduler jobs resources", func() { 581 Context("when the job needed to be schedule has no resources", func() { 582 BeforeEach(func() { 583 pipeline1, _, err := defaultTeam.SavePipeline("fake-pipeline", atc.Config{ 584 Jobs: atc.JobConfigs{ 585 {Name: "job-name"}, 586 }, 587 }, db.ConfigVersion(1), false) 588 Expect(err).ToNot(HaveOccurred()) 589 590 var found bool 591 job1, found, err = pipeline1.Job("job-name") 592 Expect(err).ToNot(HaveOccurred()) 593 Expect(found).To(BeTrue()) 594 595 err = job1.RequestSchedule() 596 Expect(err).ToNot(HaveOccurred()) 597 }) 598 599 It("fetches that job and no resources", func() { 600 jobs, err := jobFactory.JobsToSchedule() 601 Expect(err).ToNot(HaveOccurred()) 602 Expect(len(jobs)).To(Equal(1)) 603 Expect(jobs[0].Name()).To(Equal(job1.Name())) 604 Expect(jobs[0].Resources).To(BeNil()) 605 }) 606 }) 607 608 Context("when the job needed to be schedule uses resources", func() { 609 BeforeEach(func() { 610 pipeline1, _, err := defaultTeam.SavePipeline("fake-pipeline", atc.Config{ 611 Jobs: atc.JobConfigs{ 612 { 613 Name: "job-name", 614 PlanSequence: []atc.Step{ 615 { 616 Config: &atc.GetStep{ 617 Name: "some-resource", 618 }, 619 }, 620 }, 621 }, 622 }, 623 624 Resources: atc.ResourceConfigs{ 625 { 626 Name: "some-resource", 627 Type: "some-type", 628 Source: atc.Source{ 629 "some": "source", 630 }, 631 }, 632 { 633 Name: "unused-resource", 634 }, 635 }, 636 }, db.ConfigVersion(1), false) 637 Expect(err).ToNot(HaveOccurred()) 638 639 var found bool 640 job1, found, err = pipeline1.Job("job-name") 641 Expect(err).ToNot(HaveOccurred()) 642 Expect(found).To(BeTrue()) 643 644 err = job1.RequestSchedule() 645 Expect(err).ToNot(HaveOccurred()) 646 }) 647 648 It("fetches that job and the used resource", func() { 649 jobs, err := jobFactory.JobsToSchedule() 650 Expect(err).ToNot(HaveOccurred()) 651 Expect(len(jobs)).To(Equal(1)) 652 Expect(jobs[0].Name()).To(Equal(job1.Name())) 653 Expect(jobs[0].Resources).To(HaveLen(1)) 654 Expect(jobs[0].Resources).To(ConsistOf( 655 db.SchedulerResource{ 656 Name: "some-resource", 657 Type: "some-type", 658 Source: atc.Source{"some": "source"}, 659 }, 660 )) 661 }) 662 }) 663 664 Context("when multiple jobs needed to be schedule uses resources", func() { 665 BeforeEach(func() { 666 pipeline1, _, err := defaultTeam.SavePipeline("fake-pipeline", atc.Config{ 667 Jobs: atc.JobConfigs{ 668 { 669 Name: "job-1", 670 PlanSequence: []atc.Step{ 671 { 672 Config: &atc.GetStep{ 673 Name: "some-resource", 674 }, 675 }, 676 }, 677 }, 678 { 679 Name: "job-2", 680 PlanSequence: []atc.Step{ 681 { 682 Config: &atc.GetStep{ 683 Name: "some-resource", 684 }, 685 }, 686 { 687 Config: &atc.GetStep{ 688 Name: "other-resource", 689 }, 690 }, 691 }, 692 }, 693 }, 694 695 Resources: atc.ResourceConfigs{ 696 { 697 Name: "some-resource", 698 Type: "some-type", 699 }, 700 { 701 Name: "other-resource", 702 Type: "some-type", 703 }, 704 { 705 Name: "unused-resource", 706 Type: "some-type", 707 }, 708 }, 709 }, db.ConfigVersion(1), false) 710 Expect(err).ToNot(HaveOccurred()) 711 712 pipeline2, _, err := defaultTeam.SavePipeline("fake-pipeline-2", atc.Config{ 713 Jobs: atc.JobConfigs{ 714 { 715 Name: "job-3", 716 PlanSequence: []atc.Step{ 717 { 718 Config: &atc.GetStep{ 719 Name: "some-resource", 720 }, 721 }, 722 { 723 Config: &atc.GetStep{ 724 Name: "some-resource-2", 725 }, 726 }, 727 }, 728 }, 729 }, 730 731 Resources: atc.ResourceConfigs{ 732 { 733 Name: "some-resource", 734 Type: "other-type", 735 }, 736 { 737 Name: "some-resource-2", 738 Type: "other-type", 739 }, 740 }, 741 }, db.ConfigVersion(1), false) 742 Expect(err).ToNot(HaveOccurred()) 743 744 var found bool 745 job1, found, err = pipeline1.Job("job-1") 746 Expect(err).ToNot(HaveOccurred()) 747 Expect(found).To(BeTrue()) 748 749 job2, found, err = pipeline1.Job("job-2") 750 Expect(err).ToNot(HaveOccurred()) 751 Expect(found).To(BeTrue()) 752 753 job3, found, err = pipeline2.Job("job-3") 754 Expect(err).ToNot(HaveOccurred()) 755 Expect(found).To(BeTrue()) 756 757 err = job1.RequestSchedule() 758 Expect(err).ToNot(HaveOccurred()) 759 760 err = job2.RequestSchedule() 761 Expect(err).ToNot(HaveOccurred()) 762 763 err = job3.RequestSchedule() 764 Expect(err).ToNot(HaveOccurred()) 765 }) 766 767 It("fetches that job and the used resource", func() { 768 jobs, err := jobFactory.JobsToSchedule() 769 Expect(err).ToNot(HaveOccurred()) 770 771 jobResources := make(map[string]db.SchedulerResources) 772 for _, job := range jobs { 773 jobResources[job.Name()] = job.Resources 774 } 775 776 Expect(jobResources).To(MatchAllKeys(Keys{ 777 job1.Name(): ConsistOf( 778 db.SchedulerResource{ 779 Name: "some-resource", 780 Type: "some-type", 781 }, 782 ), 783 job2.Name(): ConsistOf( 784 db.SchedulerResource{ 785 Name: "some-resource", 786 Type: "some-type", 787 }, 788 db.SchedulerResource{ 789 Name: "other-resource", 790 Type: "some-type", 791 }), 792 job3.Name(): ConsistOf( 793 db.SchedulerResource{ 794 Name: "some-resource", 795 Type: "other-type", 796 }, 797 db.SchedulerResource{ 798 Name: "some-resource-2", 799 Type: "other-type", 800 }), 801 })) 802 }) 803 }) 804 805 Context("when the job needed to be schedule uses resources as puts", func() { 806 BeforeEach(func() { 807 pipeline1, _, err := defaultTeam.SavePipeline("fake-pipeline", atc.Config{ 808 Jobs: atc.JobConfigs{ 809 { 810 Name: "job-name", 811 PlanSequence: []atc.Step{ 812 { 813 Config: &atc.PutStep{ 814 Name: "some-resource", 815 }, 816 }, 817 }, 818 }, 819 }, 820 821 Resources: atc.ResourceConfigs{ 822 { 823 Name: "some-resource", 824 Type: "some-type", 825 Source: atc.Source{ 826 "some": "source", 827 }, 828 }, 829 { 830 Name: "unused-resource", 831 }, 832 }, 833 }, db.ConfigVersion(1), false) 834 Expect(err).ToNot(HaveOccurred()) 835 836 var found bool 837 job1, found, err = pipeline1.Job("job-name") 838 Expect(err).ToNot(HaveOccurred()) 839 Expect(found).To(BeTrue()) 840 841 err = job1.RequestSchedule() 842 Expect(err).ToNot(HaveOccurred()) 843 }) 844 845 It("fetches that job and the used resource", func() { 846 jobs, err := jobFactory.JobsToSchedule() 847 Expect(err).ToNot(HaveOccurred()) 848 Expect(len(jobs)).To(Equal(1)) 849 Expect(jobs[0].Name()).To(Equal(job1.Name())) 850 Expect(jobs[0].Resources).To(ConsistOf( 851 db.SchedulerResource{ 852 Name: "some-resource", 853 Type: "some-type", 854 Source: atc.Source{"some": "source"}, 855 }, 856 )) 857 }) 858 }) 859 860 Context("when the job needed to be schedule uses the resource as a put and a get", func() { 861 BeforeEach(func() { 862 pipeline1, _, err := defaultTeam.SavePipeline("fake-pipeline", atc.Config{ 863 Jobs: atc.JobConfigs{ 864 { 865 Name: "job-name", 866 PlanSequence: []atc.Step{ 867 { 868 Config: &atc.GetStep{ 869 Name: "some-resource", 870 }, 871 }, 872 { 873 Config: &atc.PutStep{ 874 Name: "some-resource", 875 }, 876 }, 877 }, 878 }, 879 }, 880 881 Resources: atc.ResourceConfigs{ 882 { 883 Name: "some-resource", 884 Type: "some-type", 885 Source: atc.Source{ 886 "some": "source", 887 }, 888 }, 889 { 890 Name: "unused-resource", 891 }, 892 }, 893 }, db.ConfigVersion(1), false) 894 Expect(err).ToNot(HaveOccurred()) 895 896 var found bool 897 job1, found, err = pipeline1.Job("job-name") 898 Expect(err).ToNot(HaveOccurred()) 899 Expect(found).To(BeTrue()) 900 901 err = job1.RequestSchedule() 902 Expect(err).ToNot(HaveOccurred()) 903 }) 904 905 It("fetches that job and the used resource", func() { 906 jobs, err := jobFactory.JobsToSchedule() 907 Expect(err).ToNot(HaveOccurred()) 908 Expect(len(jobs)).To(Equal(1)) 909 Expect(jobs[0].Name()).To(Equal(job1.Name())) 910 Expect(jobs[0].Resources).To(ConsistOf( 911 db.SchedulerResource{ 912 Name: "some-resource", 913 Type: "some-type", 914 Source: atc.Source{"some": "source"}, 915 }, 916 )) 917 }) 918 }) 919 }) 920 921 Describe("schedule jobs resource types", func() { 922 Context("when the pipeline for the job needed to be scheduled uses custom resource types", func() { 923 BeforeEach(func() { 924 pipeline1, _, err := defaultTeam.SavePipeline("fake-pipeline", atc.Config{ 925 Jobs: atc.JobConfigs{ 926 {Name: "job-name"}, 927 }, 928 ResourceTypes: atc.ResourceTypes{ 929 { 930 Name: "some-type", 931 Type: "other-type", 932 }, 933 }, 934 }, db.ConfigVersion(1), false) 935 Expect(err).ToNot(HaveOccurred()) 936 937 var found bool 938 job1, found, err = pipeline1.Job("job-name") 939 Expect(err).ToNot(HaveOccurred()) 940 Expect(found).To(BeTrue()) 941 942 err = job1.RequestSchedule() 943 Expect(err).ToNot(HaveOccurred()) 944 }) 945 946 It("fetches that job and resource type", func() { 947 jobs, err := jobFactory.JobsToSchedule() 948 Expect(err).ToNot(HaveOccurred()) 949 Expect(len(jobs)).To(Equal(1)) 950 Expect(jobs[0].Name()).To(Equal(job1.Name())) 951 Expect(jobs[0].ResourceTypes).To(ConsistOf( 952 atc.VersionedResourceType{ 953 ResourceType: atc.ResourceType{ 954 Name: "some-type", 955 Type: "other-type", 956 }, 957 }, 958 )) 959 }) 960 }) 961 962 Context("when multiple job from different pipelines uses custom resource types", func() { 963 BeforeEach(func() { 964 pipeline1, _, err := defaultTeam.SavePipeline("fake-pipeline", atc.Config{ 965 Jobs: atc.JobConfigs{ 966 {Name: "job-1"}, 967 {Name: "job-2"}, 968 }, 969 ResourceTypes: atc.ResourceTypes{ 970 { 971 Name: "some-type", 972 Type: "other-type", 973 }, 974 }, 975 }, db.ConfigVersion(1), false) 976 Expect(err).ToNot(HaveOccurred()) 977 978 pipeline2, _, err := defaultTeam.SavePipeline("fake-pipeline-2", atc.Config{ 979 Jobs: atc.JobConfigs{ 980 {Name: "job-3"}, 981 }, 982 ResourceTypes: atc.ResourceTypes{ 983 { 984 Name: "some-type-1", 985 Type: "other-type-1", 986 }, 987 { 988 Name: "some-type-2", 989 Type: "other-type-2", 990 }, 991 }, 992 }, db.ConfigVersion(1), false) 993 Expect(err).ToNot(HaveOccurred()) 994 995 var found bool 996 job1, found, err = pipeline1.Job("job-1") 997 Expect(err).ToNot(HaveOccurred()) 998 Expect(found).To(BeTrue()) 999 1000 err = job1.RequestSchedule() 1001 Expect(err).ToNot(HaveOccurred()) 1002 1003 job2, found, err = pipeline1.Job("job-2") 1004 Expect(err).ToNot(HaveOccurred()) 1005 Expect(found).To(BeTrue()) 1006 1007 err = job2.RequestSchedule() 1008 Expect(err).ToNot(HaveOccurred()) 1009 1010 job3, found, err = pipeline2.Job("job-3") 1011 Expect(err).ToNot(HaveOccurred()) 1012 Expect(found).To(BeTrue()) 1013 1014 err = job3.RequestSchedule() 1015 Expect(err).ToNot(HaveOccurred()) 1016 }) 1017 1018 It("fetches all jobs and resource types", func() { 1019 jobs, err := jobFactory.JobsToSchedule() 1020 Expect(err).ToNot(HaveOccurred()) 1021 1022 jobResourceTypes := make(map[string]atc.VersionedResourceTypes) 1023 for _, job := range jobs { 1024 jobResourceTypes[job.Name()] = job.ResourceTypes 1025 } 1026 1027 Expect(jobResourceTypes).To(MatchAllKeys(Keys{ 1028 job1.Name(): ConsistOf( 1029 atc.VersionedResourceType{ 1030 ResourceType: atc.ResourceType{ 1031 Name: "some-type", 1032 Type: "other-type", 1033 }, 1034 }, 1035 ), 1036 job2.Name(): ConsistOf( 1037 atc.VersionedResourceType{ 1038 ResourceType: atc.ResourceType{ 1039 Name: "some-type", 1040 Type: "other-type", 1041 }, 1042 }, 1043 ), 1044 job3.Name(): ConsistOf( 1045 atc.VersionedResourceType{ 1046 ResourceType: atc.ResourceType{ 1047 Name: "some-type-1", 1048 Type: "other-type-1", 1049 }, 1050 }, 1051 atc.VersionedResourceType{ 1052 ResourceType: atc.ResourceType{ 1053 Name: "some-type-2", 1054 Type: "other-type-2", 1055 }, 1056 }, 1057 ), 1058 })) 1059 }) 1060 }) 1061 }) 1062 }) 1063}) 1064 1065var _ = Context("SchedulerResource", func() { 1066 var resource db.SchedulerResource 1067 1068 BeforeEach(func() { 1069 resource = db.SchedulerResource{ 1070 Name: "some-name", 1071 Type: "some-type", 1072 Source: atc.Source{ 1073 "some-key": "some-value", 1074 }, 1075 } 1076 }) 1077 1078 Context("ApplySourceDefaults", func() { 1079 var resourceTypes atc.VersionedResourceTypes 1080 1081 BeforeEach(func() { 1082 resourceTypes = atc.VersionedResourceTypes{ 1083 { 1084 ResourceType: atc.ResourceType{ 1085 Name: "some-type", 1086 Defaults: atc.Source{"default-key": "default-value"}, 1087 }, 1088 }, 1089 } 1090 }) 1091 1092 JustBeforeEach(func() { 1093 resource.ApplySourceDefaults(resourceTypes) 1094 }) 1095 1096 It("should apply defaults", func() { 1097 Expect(resource).To(Equal(db.SchedulerResource{ 1098 Name: "some-name", 1099 Type: "some-type", 1100 Source: atc.Source{ 1101 "some-key": "some-value", 1102 "default-key": "default-value", 1103 }, 1104 })) 1105 }) 1106 1107 Context("when the parent resource is not found", func() { 1108 BeforeEach(func() { 1109 resourceTypes = atc.VersionedResourceTypes{} 1110 atc.LoadBaseResourceTypeDefaults(map[string]atc.Source{ 1111 "some-type": {"default-key": "default-value"}, 1112 }) 1113 }) 1114 1115 AfterEach(func() { 1116 atc.LoadBaseResourceTypeDefaults(map[string]atc.Source{}) 1117 }) 1118 1119 It("should apply defaults using the base resource type", func() { 1120 Expect(resource).To(Equal(db.SchedulerResource{ 1121 Name: "some-name", 1122 Type: "some-type", 1123 Source: atc.Source{ 1124 "some-key": "some-value", 1125 "default-key": "default-value", 1126 }, 1127 })) 1128 }) 1129 }) 1130 }) 1131}) 1132