github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/db/pipeline_test.go (about) 1 package db_test 2 3 import ( 4 "fmt" 5 "strconv" 6 "time" 7 8 "code.cloudfoundry.org/clock" 9 "github.com/pf-qiu/concourse/v6/atc/creds" 10 "github.com/pf-qiu/concourse/v6/atc/creds/credsfakes" 11 "github.com/pf-qiu/concourse/v6/atc/db/dbtest" 12 "github.com/pf-qiu/concourse/v6/vars" 13 14 "github.com/pf-qiu/concourse/v6/atc" 15 "github.com/pf-qiu/concourse/v6/atc/db" 16 "github.com/pf-qiu/concourse/v6/atc/event" 17 18 // load dummy credential manager 19 _ "github.com/pf-qiu/concourse/v6/atc/creds/dummy" 20 21 . "github.com/onsi/ginkgo" 22 . "github.com/onsi/gomega" 23 ) 24 25 var _ = Describe("Pipeline", func() { 26 var ( 27 pipeline db.Pipeline 28 team db.Team 29 pipelineConfig atc.Config 30 ) 31 32 BeforeEach(func() { 33 var err error 34 team, err = teamFactory.CreateTeam(atc.Team{Name: "some-team"}) 35 Expect(err).ToNot(HaveOccurred()) 36 37 pipelineConfig = atc.Config{ 38 Groups: atc.GroupConfigs{ 39 { 40 Name: "some-group", 41 Jobs: []string{"job-1", "job-2"}, 42 Resources: []string{"some-resource", "some-other-resource"}, 43 }, 44 }, 45 VarSources: atc.VarSourceConfigs{ 46 { 47 Name: "some-var-source", 48 Type: "dummy", 49 Config: map[string]interface{}{ 50 "vars": map[string]interface{}{"pk": "pv"}, 51 }, 52 }, 53 }, 54 Display: &atc.DisplayConfig{ 55 BackgroundImage: "background.jpg", 56 }, 57 Jobs: atc.JobConfigs{ 58 { 59 Name: "job-name", 60 61 Public: true, 62 63 Serial: true, 64 65 SerialGroups: []string{"serial-group"}, 66 67 PlanSequence: []atc.Step{ 68 { 69 Config: &atc.PutStep{ 70 Name: "some-resource", 71 Params: atc.Params{ 72 "some-param": "some-value", 73 }, 74 }, 75 }, 76 { 77 Config: &atc.GetStep{ 78 Name: "some-input", 79 Resource: "some-resource", 80 Params: atc.Params{ 81 "some-param": "some-value", 82 }, 83 Passed: []string{"job-1", "job-2"}, 84 Trigger: true, 85 }, 86 }, 87 { 88 Config: &atc.TaskStep{ 89 Name: "some-task", 90 Privileged: true, 91 ConfigPath: "some/config/path.yml", 92 Config: &atc.TaskConfig{ 93 RootfsURI: "some-image", 94 }, 95 }, 96 }, 97 { 98 Config: &atc.SetPipelineStep{ 99 Name: "some-pipeline", 100 File: "some-file", 101 VarFiles: []string{"var-file1", "var-file2"}, 102 Vars: map[string]interface{}{ 103 "k1": "v1", 104 "k2": "v2", 105 }, 106 }, 107 }, 108 }, 109 }, 110 { 111 Name: "some-other-job", 112 Serial: true, 113 }, 114 { 115 Name: "a-job", 116 }, 117 { 118 Name: "shared-job", 119 }, 120 { 121 Name: "random-job", 122 }, 123 { 124 Name: "job-1", 125 }, 126 { 127 Name: "job-2", 128 }, 129 { 130 Name: "other-serial-group-job", 131 SerialGroups: []string{"serial-group", "really-different-group"}, 132 }, 133 { 134 Name: "different-serial-group-job", 135 SerialGroups: []string{"different-serial-group"}, 136 }, 137 }, 138 Resources: atc.ResourceConfigs{ 139 { 140 Name: "some-other-resource", 141 Type: "some-type", 142 Source: atc.Source{"some": "other-source"}, 143 }, 144 { 145 Name: "some-resource", 146 Type: "some-type", 147 Source: atc.Source{"some": "source"}, 148 }, 149 }, 150 ResourceTypes: atc.ResourceTypes{ 151 { 152 Name: "some-other-resource-type", 153 Type: "base-type", 154 Source: atc.Source{"some": "other-type-soure"}, 155 }, 156 { 157 Name: "some-resource-type", 158 Type: "base-type", 159 Source: atc.Source{"some": "type-soure"}, 160 }, 161 }, 162 } 163 var created bool 164 pipeline, created, err = team.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, pipelineConfig, db.ConfigVersion(0), false) 165 Expect(err).ToNot(HaveOccurred()) 166 Expect(created).To(BeTrue()) 167 168 _, found, err := pipeline.Job("job-name") 169 Expect(err).ToNot(HaveOccurred()) 170 Expect(found).To(BeTrue()) 171 172 setupTx, err := dbConn.Begin() 173 Expect(err).ToNot(HaveOccurred()) 174 175 brt := db.BaseResourceType{ 176 Name: "some-type", 177 } 178 179 _, err = brt.FindOrCreate(setupTx, false) 180 Expect(err).NotTo(HaveOccurred()) 181 Expect(setupTx.Commit()).To(Succeed()) 182 }) 183 184 Describe("CheckPaused", func() { 185 var paused bool 186 JustBeforeEach(func() { 187 var err error 188 paused, err = pipeline.CheckPaused() 189 Expect(err).ToNot(HaveOccurred()) 190 }) 191 192 Context("when the pipeline is unpaused", func() { 193 BeforeEach(func() { 194 Expect(pipeline.Unpause()).To(Succeed()) 195 }) 196 197 It("returns the pipeline is paused", func() { 198 Expect(paused).To(BeFalse()) 199 }) 200 }) 201 202 Context("when the pipeline is paused", func() { 203 BeforeEach(func() { 204 Expect(pipeline.Pause()).To(Succeed()) 205 }) 206 207 It("returns the pipeline is paused", func() { 208 Expect(paused).To(BeTrue()) 209 }) 210 }) 211 }) 212 213 Describe("Pause", func() { 214 JustBeforeEach(func() { 215 Expect(pipeline.Pause()).To(Succeed()) 216 217 found, err := pipeline.Reload() 218 Expect(err).ToNot(HaveOccurred()) 219 Expect(found).To(BeTrue()) 220 }) 221 222 Context("when the pipeline is unpaused", func() { 223 BeforeEach(func() { 224 Expect(pipeline.Unpause()).To(Succeed()) 225 }) 226 227 It("pauses the pipeline", func() { 228 Expect(pipeline.Paused()).To(BeTrue()) 229 }) 230 }) 231 }) 232 233 Describe("Archive", func() { 234 var initialLastUpdated time.Time 235 236 BeforeEach(func() { 237 initialLastUpdated = pipeline.LastUpdated() 238 }) 239 240 JustBeforeEach(func() { 241 pipeline.Archive() 242 pipeline.Reload() 243 }) 244 245 It("archives the pipeline", func() { 246 Expect(pipeline.Archived()).To(BeTrue(), "pipeline was not archived") 247 }) 248 249 It("updates last updated", func() { 250 lastUpdated := pipeline.LastUpdated() 251 252 Expect(lastUpdated).To(BeTemporally(">", initialLastUpdated)) 253 }) 254 255 It("resets the pipeline version to zero", func() { 256 version := pipeline.ConfigVersion() 257 258 Expect(version).To(Equal(db.ConfigVersion(0))) 259 }) 260 261 It("removes the config of each job", func() { 262 jobs, err := pipeline.Jobs() 263 Expect(err).ToNot(HaveOccurred()) 264 265 jobConfigs, err := jobs.Configs() 266 emptyJobConfigs := make(atc.JobConfigs, len(pipelineConfig.Jobs)) 267 Expect(jobConfigs).To(Equal(emptyJobConfigs)) 268 }) 269 270 It("removes the config of each resource", func() { 271 resources, err := pipeline.Resources() 272 Expect(err).ToNot(HaveOccurred()) 273 274 resourceConfigs := resources.Configs() 275 276 emptyResourceConfigs := make(atc.ResourceConfigs, len(pipelineConfig.Resources)) 277 Expect(resourceConfigs).To(Equal(emptyResourceConfigs)) 278 }) 279 280 It("removes the config of each resource_type", func() { 281 resourceTypes, err := pipeline.ResourceTypes() 282 Expect(err).ToNot(HaveOccurred()) 283 284 resourceTypeConfigs := resourceTypes.Configs() 285 286 emptyResourceTypeConfigs := atc.ResourceTypes{ 287 {Name: "some-other-resource-type", Type: "base-type"}, 288 {Name: "some-resource-type", Type: "base-type"}, 289 } 290 Expect(resourceTypeConfigs).To(Equal(emptyResourceTypeConfigs)) 291 }) 292 }) 293 294 Describe("Unpause", func() { 295 JustBeforeEach(func() { 296 Expect(pipeline.Unpause()).To(Succeed()) 297 298 found, err := pipeline.Reload() 299 Expect(err).ToNot(HaveOccurred()) 300 Expect(found).To(BeTrue()) 301 }) 302 303 Context("when the pipeline is paused", func() { 304 BeforeEach(func() { 305 Expect(pipeline.Pause()).To(Succeed()) 306 }) 307 308 It("unpauses the pipeline", func() { 309 Expect(pipeline.Paused()).To(BeFalse()) 310 }) 311 }) 312 313 Context("when requesting schedule for unpausing pipeline", func() { 314 var found bool 315 var err error 316 var job1, job2, job3, job4, job5, job6, job7, job8, job9 db.Job 317 var initialRequestedTime1, initialRequestedTime2, initialRequestedTime3, initialRequestedTime4, initialRequestedTime5, initialRequestedTime6, initialRequestedTime7, initialRequestedTime8, initialRequestedTime9 time.Time 318 319 BeforeEach(func() { 320 job1, found, err = pipeline.Job("job-name") 321 Expect(err).ToNot(HaveOccurred()) 322 Expect(found).To(BeTrue()) 323 initialRequestedTime1 = job1.ScheduleRequestedTime() 324 325 job2, found, err = pipeline.Job("some-other-job") 326 Expect(err).ToNot(HaveOccurred()) 327 Expect(found).To(BeTrue()) 328 initialRequestedTime2 = job2.ScheduleRequestedTime() 329 330 job3, found, err = pipeline.Job("a-job") 331 Expect(err).ToNot(HaveOccurred()) 332 Expect(found).To(BeTrue()) 333 initialRequestedTime3 = job3.ScheduleRequestedTime() 334 335 job4, found, err = pipeline.Job("shared-job") 336 Expect(err).ToNot(HaveOccurred()) 337 Expect(found).To(BeTrue()) 338 initialRequestedTime4 = job4.ScheduleRequestedTime() 339 340 job5, found, err = pipeline.Job("random-job") 341 Expect(err).ToNot(HaveOccurred()) 342 Expect(found).To(BeTrue()) 343 initialRequestedTime5 = job5.ScheduleRequestedTime() 344 345 job6, found, err = pipeline.Job("job-1") 346 Expect(err).ToNot(HaveOccurred()) 347 Expect(found).To(BeTrue()) 348 initialRequestedTime6 = job6.ScheduleRequestedTime() 349 350 job7, found, err = pipeline.Job("job-2") 351 Expect(err).ToNot(HaveOccurred()) 352 Expect(found).To(BeTrue()) 353 initialRequestedTime7 = job7.ScheduleRequestedTime() 354 355 job8, found, err = pipeline.Job("other-serial-group-job") 356 Expect(err).ToNot(HaveOccurred()) 357 Expect(found).To(BeTrue()) 358 initialRequestedTime8 = job8.ScheduleRequestedTime() 359 360 job9, found, err = pipeline.Job("different-serial-group-job") 361 Expect(err).ToNot(HaveOccurred()) 362 Expect(found).To(BeTrue()) 363 initialRequestedTime9 = job9.ScheduleRequestedTime() 364 }) 365 366 It("requests schedule on all the jobs in the pipeline", func() { 367 found, err = job1.Reload() 368 Expect(err).ToNot(HaveOccurred()) 369 Expect(found).To(BeTrue()) 370 371 found, err = job2.Reload() 372 Expect(err).ToNot(HaveOccurred()) 373 Expect(found).To(BeTrue()) 374 375 found, err = job3.Reload() 376 Expect(err).ToNot(HaveOccurred()) 377 Expect(found).To(BeTrue()) 378 379 found, err = job4.Reload() 380 Expect(err).ToNot(HaveOccurred()) 381 Expect(found).To(BeTrue()) 382 383 found, err = job5.Reload() 384 Expect(err).ToNot(HaveOccurred()) 385 Expect(found).To(BeTrue()) 386 387 found, err = job6.Reload() 388 Expect(err).ToNot(HaveOccurred()) 389 Expect(found).To(BeTrue()) 390 391 found, err = job7.Reload() 392 Expect(err).ToNot(HaveOccurred()) 393 Expect(found).To(BeTrue()) 394 395 found, err = job8.Reload() 396 Expect(err).ToNot(HaveOccurred()) 397 Expect(found).To(BeTrue()) 398 399 found, err = job9.Reload() 400 Expect(err).ToNot(HaveOccurred()) 401 Expect(found).To(BeTrue()) 402 403 Expect(job1.ScheduleRequestedTime()).Should(BeTemporally(">", initialRequestedTime1)) 404 Expect(job2.ScheduleRequestedTime()).Should(BeTemporally(">", initialRequestedTime2)) 405 Expect(job3.ScheduleRequestedTime()).Should(BeTemporally(">", initialRequestedTime3)) 406 Expect(job4.ScheduleRequestedTime()).Should(BeTemporally(">", initialRequestedTime4)) 407 Expect(job5.ScheduleRequestedTime()).Should(BeTemporally(">", initialRequestedTime5)) 408 Expect(job6.ScheduleRequestedTime()).Should(BeTemporally(">", initialRequestedTime6)) 409 Expect(job7.ScheduleRequestedTime()).Should(BeTemporally(">", initialRequestedTime7)) 410 Expect(job8.ScheduleRequestedTime()).Should(BeTemporally(">", initialRequestedTime8)) 411 Expect(job9.ScheduleRequestedTime()).Should(BeTemporally(">", initialRequestedTime9)) 412 }) 413 }) 414 }) 415 416 Describe("Rename", func() { 417 JustBeforeEach(func() { 418 Expect(pipeline.Rename("oopsies")).To(Succeed()) 419 }) 420 421 It("renames the pipeline", func() { 422 pipeline, found, err := team.Pipeline(atc.PipelineRef{Name: "oopsies"}) 423 Expect(pipeline.Name()).To(Equal("oopsies")) 424 Expect(found).To(BeTrue()) 425 Expect(err).ToNot(HaveOccurred()) 426 }) 427 }) 428 429 Describe("Resource Config Versions", func() { 430 resourceName := "some-resource" 431 otherResourceName := "some-other-resource" 432 reallyOtherResourceName := "some-really-other-resource" 433 434 var ( 435 scenarioPipeline1 *dbtest.Scenario 436 scenarioPipeline2 *dbtest.Scenario 437 438 resource db.Resource 439 otherResource db.Resource 440 reallyOtherResource db.Resource 441 otherPipelineResource db.Resource 442 ) 443 444 BeforeEach(func() { 445 pipelineConfig := atc.Config{ 446 Groups: atc.GroupConfigs{ 447 { 448 Name: "some-group", 449 Jobs: []string{"job-1", "job-2"}, 450 Resources: []string{"some-resource", "some-other-resource"}, 451 }, 452 }, 453 454 Resources: atc.ResourceConfigs{ 455 { 456 Name: "some-resource", 457 Type: "some-type", 458 Source: atc.Source{ 459 "source-config": "some-value", 460 }, 461 }, 462 { 463 Name: "some-other-resource", 464 Type: "some-type", 465 Source: atc.Source{ 466 "source-config": "some-other-value", 467 }, 468 }, 469 { 470 Name: "some-really-other-resource", 471 Type: "some-type", 472 Source: atc.Source{ 473 "source-config": "some-really-other-value", 474 }, 475 }, 476 }, 477 478 ResourceTypes: atc.ResourceTypes{ 479 { 480 Name: "some-resource-type", 481 Type: "some-type", 482 Source: atc.Source{ 483 "source-config": "some-value", 484 }, 485 }, 486 }, 487 488 Jobs: atc.JobConfigs{ 489 { 490 Name: "some-job", 491 492 Public: true, 493 494 Serial: true, 495 496 SerialGroups: []string{"serial-group"}, 497 498 PlanSequence: []atc.Step{ 499 { 500 Config: &atc.PutStep{ 501 Name: "some-resource", 502 Params: atc.Params{ 503 "some-param": "some-value", 504 }, 505 }, 506 }, 507 { 508 Config: &atc.GetStep{ 509 Name: "some-input", 510 Resource: "some-resource", 511 Params: atc.Params{ 512 "some-param": "some-value", 513 }, 514 Passed: []string{"job-1", "job-2"}, 515 Trigger: true, 516 }, 517 }, 518 { 519 Config: &atc.TaskStep{ 520 Name: "some-task", 521 Privileged: true, 522 ConfigPath: "some/config/path.yml", 523 Config: &atc.TaskConfig{ 524 RootfsURI: "some-image", 525 }, 526 }, 527 }, 528 }, 529 }, 530 { 531 Name: "some-other-job", 532 Serial: true, 533 }, 534 { 535 Name: "a-job", 536 }, 537 { 538 Name: "shared-job", 539 }, 540 { 541 Name: "random-job", 542 }, 543 { 544 Name: "other-serial-group-job", 545 SerialGroups: []string{"serial-group", "really-different-group"}, 546 }, 547 { 548 Name: "different-serial-group-job", 549 SerialGroups: []string{"different-serial-group"}, 550 }, 551 { 552 Name: "job-1", 553 }, 554 { 555 Name: "job-2", 556 }, 557 }, 558 } 559 560 scenarioPipeline1 = dbtest.Setup( 561 builder.WithPipeline(pipelineConfig), 562 builder.WithResourceVersions("some-resource"), 563 builder.WithResourceVersions("some-really-other-resource"), 564 ) 565 566 otherPipelineConfig := atc.Config{ 567 Groups: atc.GroupConfigs{ 568 { 569 Name: "some-group", 570 Jobs: []string{"job-1", "job-2"}, 571 Resources: []string{"some-resource", "some-other-resource"}, 572 }, 573 }, 574 575 Resources: atc.ResourceConfigs{ 576 { 577 Name: "some-resource", 578 Type: "some-type", 579 Source: atc.Source{ 580 "other-source-config": "some-value", 581 }, 582 }, 583 { 584 Name: "some-other-resource", 585 Type: "some-type", 586 Source: atc.Source{ 587 "other-source-config": "some-other-value", 588 }, 589 }, 590 }, 591 592 Jobs: atc.JobConfigs{ 593 { 594 Name: "some-job", 595 }, 596 { 597 Name: "some-other-job", 598 }, 599 { 600 Name: "a-job", 601 }, 602 { 603 Name: "shared-job", 604 }, 605 { 606 Name: "other-serial-group-job", 607 }, 608 }, 609 } 610 611 scenarioPipeline2 = dbtest.Setup( 612 builder.WithPipeline(otherPipelineConfig), 613 builder.WithResourceVersions("some-other-resource"), 614 ) 615 616 resource = scenarioPipeline1.Resource(resourceName) 617 otherResource = scenarioPipeline1.Resource(otherResourceName) 618 reallyOtherResource = scenarioPipeline1.Resource(reallyOtherResourceName) 619 otherPipelineResource = scenarioPipeline2.Resource(otherResourceName) 620 }) 621 622 It("returns correct resource", func() { 623 Expect(resource.Name()).To(Equal("some-resource")) 624 Expect(resource.PipelineName()).To(Equal("some-pipeline")) 625 Expect(resource.Type()).To(Equal("some-type")) 626 Expect(resource.Source()).To(Equal(atc.Source{"source-config": "some-value"})) 627 }) 628 629 Context("DebugLoadVersionsDB", func() { 630 It("it can load all information about the current state of the db", func() { 631 versions, err := scenarioPipeline1.Pipeline.LoadDebugVersionsDB() 632 Expect(err).ToNot(HaveOccurred()) 633 Expect(versions.ResourceVersions).To(BeEmpty()) 634 Expect(versions.BuildOutputs).To(BeEmpty()) 635 Expect(versions.Resources).To(ConsistOf([]atc.DebugResource{ 636 { 637 ID: resource.ID(), 638 Name: resource.Name(), 639 ScopeID: intptr(resource.ResourceConfigScopeID()), 640 }, 641 { 642 ID: otherResource.ID(), 643 Name: otherResource.Name(), 644 ScopeID: nil, 645 }, 646 { 647 ID: reallyOtherResource.ID(), 648 Name: reallyOtherResource.Name(), 649 ScopeID: intptr(reallyOtherResource.ResourceConfigScopeID()), 650 }, 651 })) 652 653 jobs := []atc.DebugJob{ 654 {Name: "some-job", ID: scenarioPipeline1.Job("some-job").ID()}, 655 {Name: "some-other-job", ID: scenarioPipeline1.Job("some-other-job").ID()}, 656 {Name: "a-job", ID: scenarioPipeline1.Job("a-job").ID()}, 657 {Name: "shared-job", ID: scenarioPipeline1.Job("shared-job").ID()}, 658 {Name: "random-job", ID: scenarioPipeline1.Job("random-job").ID()}, 659 {Name: "other-serial-group-job", ID: scenarioPipeline1.Job("other-serial-group-job").ID()}, 660 {Name: "different-serial-group-job", ID: scenarioPipeline1.Job("different-serial-group-job").ID()}, 661 {Name: "job-1", ID: scenarioPipeline1.Job("job-1").ID()}, 662 {Name: "job-2", ID: scenarioPipeline1.Job("job-2").ID()}, 663 } 664 665 Expect(versions.Jobs).To(ConsistOf(jobs)) 666 667 By("initially having no versions") 668 resourceVersions, _, _, err := resource.Versions(db.Page{Limit: 10}, nil) 669 Expect(err).ToNot(HaveOccurred()) 670 Expect(resourceVersions).To(HaveLen(0)) 671 672 By("including saved versioned resources of the current pipeline") 673 scenarioPipeline1.Run(builder.WithResourceVersions(resourceName, atc.Version{"version": "1"})) 674 675 savedVR1, found, err := resource.FindVersion(atc.Version{"version": "1"}) 676 Expect(err).ToNot(HaveOccurred()) 677 Expect(found).To(BeTrue()) 678 679 scenarioPipeline1.Run(builder.WithResourceVersions(resourceName, atc.Version{"version": "2"})) 680 681 savedVR2, found, err := resource.FindVersion(atc.Version{"version": "2"}) 682 Expect(err).ToNot(HaveOccurred()) 683 Expect(found).To(BeTrue()) 684 685 versions, err = scenarioPipeline1.Pipeline.LoadDebugVersionsDB() 686 Expect(err).ToNot(HaveOccurred()) 687 Expect(versions.ResourceVersions).To(ConsistOf([]atc.DebugResourceVersion{ 688 {VersionID: savedVR1.ID(), ResourceID: resource.ID(), ScopeID: resource.ResourceConfigScopeID(), CheckOrder: savedVR1.CheckOrder()}, 689 {VersionID: savedVR2.ID(), ResourceID: resource.ID(), ScopeID: resource.ResourceConfigScopeID(), CheckOrder: savedVR2.CheckOrder()}, 690 })) 691 692 Expect(versions.BuildOutputs).To(BeEmpty()) 693 Expect(versions.Resources).To(ConsistOf([]atc.DebugResource{ 694 { 695 ID: resource.ID(), 696 Name: resource.Name(), 697 ScopeID: intptr(resource.ResourceConfigScopeID()), 698 }, 699 { 700 ID: otherResource.ID(), 701 Name: otherResource.Name(), 702 ScopeID: nil, 703 }, 704 { 705 ID: reallyOtherResource.ID(), 706 Name: reallyOtherResource.Name(), 707 ScopeID: intptr(reallyOtherResource.ResourceConfigScopeID()), 708 }, 709 })) 710 Expect(versions.Jobs).To(ConsistOf(jobs)) 711 712 By("not including saved versioned resources of other pipelines") 713 scenarioPipeline2.Run(builder.WithResourceVersions(otherResourceName, atc.Version{"version": "1"})) 714 715 _, found, err = otherPipelineResource.FindVersion(atc.Version{"version": "1"}) 716 Expect(err).ToNot(HaveOccurred()) 717 Expect(found).To(BeTrue()) 718 719 versions, err = scenarioPipeline1.Pipeline.LoadDebugVersionsDB() 720 Expect(err).ToNot(HaveOccurred()) 721 Expect(versions.ResourceVersions).To(ConsistOf([]atc.DebugResourceVersion{ 722 { 723 VersionID: savedVR1.ID(), 724 ResourceID: resource.ID(), 725 ScopeID: resource.ResourceConfigScopeID(), 726 CheckOrder: savedVR1.CheckOrder(), 727 }, 728 { 729 VersionID: savedVR2.ID(), 730 ResourceID: resource.ID(), 731 ScopeID: resource.ResourceConfigScopeID(), 732 CheckOrder: savedVR2.CheckOrder(), 733 }, 734 })) 735 736 Expect(versions.BuildOutputs).To(BeEmpty()) 737 Expect(versions.Resources).To(ConsistOf([]atc.DebugResource{ 738 { 739 ID: resource.ID(), 740 Name: resource.Name(), 741 ScopeID: intptr(resource.ResourceConfigScopeID()), 742 }, 743 { 744 ID: otherResource.ID(), 745 Name: otherResource.Name(), 746 ScopeID: nil, 747 }, 748 { 749 ID: reallyOtherResource.ID(), 750 Name: reallyOtherResource.Name(), 751 ScopeID: intptr(reallyOtherResource.ResourceConfigScopeID()), 752 }, 753 })) 754 Expect(versions.Jobs).To(ConsistOf(jobs)) 755 756 By("including outputs of successful builds") 757 build1DB, err := scenarioPipeline1.Job("a-job").CreateBuild() 758 Expect(err).ToNot(HaveOccurred()) 759 760 err = build1DB.SaveOutput("some-type", atc.Source{"source-config": "some-value"}, atc.VersionedResourceTypes{}, atc.Version{"version": "1"}, nil, "some-output-name", "some-resource") 761 Expect(err).ToNot(HaveOccurred()) 762 763 err = build1DB.Finish(db.BuildStatusSucceeded) 764 Expect(err).ToNot(HaveOccurred()) 765 766 versions, err = scenarioPipeline1.Pipeline.LoadDebugVersionsDB() 767 Expect(err).ToNot(HaveOccurred()) 768 Expect(versions.ResourceVersions).To(ConsistOf([]atc.DebugResourceVersion{ 769 {VersionID: savedVR1.ID(), ResourceID: resource.ID(), ScopeID: resource.ResourceConfigScopeID(), CheckOrder: savedVR1.CheckOrder()}, 770 {VersionID: savedVR2.ID(), ResourceID: resource.ID(), ScopeID: resource.ResourceConfigScopeID(), CheckOrder: savedVR2.CheckOrder()}, 771 })) 772 773 explicitOutput := atc.DebugBuildOutput{ 774 DebugResourceVersion: atc.DebugResourceVersion{ 775 VersionID: savedVR1.ID(), 776 ResourceID: resource.ID(), 777 ScopeID: resource.ResourceConfigScopeID(), 778 CheckOrder: savedVR1.CheckOrder(), 779 }, 780 JobID: scenarioPipeline1.Job("a-job").ID(), 781 BuildID: build1DB.ID(), 782 } 783 784 Expect(versions.BuildOutputs).To(ConsistOf([]atc.DebugBuildOutput{ 785 explicitOutput, 786 })) 787 788 Expect(versions.Resources).To(ConsistOf([]atc.DebugResource{ 789 { 790 ID: resource.ID(), 791 Name: resource.Name(), 792 ScopeID: intptr(resource.ResourceConfigScopeID()), 793 }, 794 { 795 ID: otherResource.ID(), 796 Name: otherResource.Name(), 797 ScopeID: nil, 798 }, 799 { 800 ID: reallyOtherResource.ID(), 801 Name: reallyOtherResource.Name(), 802 ScopeID: intptr(reallyOtherResource.ResourceConfigScopeID()), 803 }, 804 })) 805 Expect(versions.Jobs).To(ConsistOf(jobs)) 806 807 By("not including outputs of failed builds") 808 build2DB, err := scenarioPipeline1.Job("a-job").CreateBuild() 809 Expect(err).ToNot(HaveOccurred()) 810 811 err = build2DB.SaveOutput("some-type", atc.Source{"source-config": "some-value"}, atc.VersionedResourceTypes{}, atc.Version{"version": "1"}, nil, "some-output-name", "some-resource") 812 Expect(err).ToNot(HaveOccurred()) 813 814 err = build2DB.Finish(db.BuildStatusFailed) 815 Expect(err).ToNot(HaveOccurred()) 816 817 versions, err = scenarioPipeline1.Pipeline.LoadDebugVersionsDB() 818 Expect(err).ToNot(HaveOccurred()) 819 Expect(versions.ResourceVersions).To(ConsistOf([]atc.DebugResourceVersion{ 820 {VersionID: savedVR1.ID(), ResourceID: resource.ID(), ScopeID: resource.ResourceConfigScopeID(), CheckOrder: savedVR1.CheckOrder()}, 821 {VersionID: savedVR2.ID(), ResourceID: resource.ID(), ScopeID: resource.ResourceConfigScopeID(), CheckOrder: savedVR2.CheckOrder()}, 822 })) 823 824 Expect(versions.BuildOutputs).To(ConsistOf([]atc.DebugBuildOutput{ 825 { 826 DebugResourceVersion: atc.DebugResourceVersion{ 827 VersionID: savedVR1.ID(), 828 ResourceID: resource.ID(), 829 ScopeID: resource.ResourceConfigScopeID(), 830 CheckOrder: savedVR1.CheckOrder(), 831 }, 832 JobID: scenarioPipeline1.Job("a-job").ID(), 833 BuildID: build1DB.ID(), 834 }, 835 })) 836 837 Expect(versions.Resources).To(ConsistOf([]atc.DebugResource{ 838 { 839 ID: resource.ID(), 840 Name: resource.Name(), 841 ScopeID: intptr(resource.ResourceConfigScopeID()), 842 }, 843 { 844 ID: otherResource.ID(), 845 Name: otherResource.Name(), 846 ScopeID: nil, 847 }, 848 { 849 ID: reallyOtherResource.ID(), 850 Name: reallyOtherResource.Name(), 851 ScopeID: intptr(reallyOtherResource.ResourceConfigScopeID()), 852 }, 853 })) 854 Expect(versions.Jobs).To(ConsistOf(jobs)) 855 856 By("not including outputs of builds in other pipelines") 857 otherPipelineBuild, err := scenarioPipeline1.Job("a-job").CreateBuild() 858 Expect(err).ToNot(HaveOccurred()) 859 860 err = otherPipelineBuild.SaveOutput("some-type", atc.Source{"other-source-config": "some-other-value"}, atc.VersionedResourceTypes{}, atc.Version{"version": "1"}, nil, "some-output-name", "some-other-resource") 861 Expect(err).ToNot(HaveOccurred()) 862 863 // After SaveOutput to other resource, we need to reload it because its resourceConfigScopeID 864 // is supposed to be updated. 865 otherResource = scenarioPipeline1.Resource(otherResourceName) 866 Expect(otherResource).ToNot(BeNil()) 867 868 savedVR3, found, err := otherResource.FindVersion(atc.Version{"version": "1"}) 869 Expect(err).ToNot(HaveOccurred()) 870 Expect(found).To(BeTrue()) 871 872 err = otherPipelineBuild.Finish(db.BuildStatusSucceeded) 873 Expect(err).ToNot(HaveOccurred()) 874 875 versions, err = scenarioPipeline1.Pipeline.LoadDebugVersionsDB() 876 Expect(err).ToNot(HaveOccurred()) 877 Expect(versions.ResourceVersions).To(ConsistOf([]atc.DebugResourceVersion{ 878 {VersionID: savedVR1.ID(), ResourceID: resource.ID(), ScopeID: resource.ResourceConfigScopeID(), CheckOrder: savedVR1.CheckOrder()}, 879 {VersionID: savedVR2.ID(), ResourceID: resource.ID(), ScopeID: resource.ResourceConfigScopeID(), CheckOrder: savedVR2.CheckOrder()}, 880 {VersionID: savedVR3.ID(), ResourceID: otherResource.ID(), ScopeID: otherResource.ResourceConfigScopeID(), CheckOrder: savedVR3.CheckOrder()}, 881 })) 882 883 Expect(versions.BuildOutputs).To(ConsistOf([]atc.DebugBuildOutput{ 884 { 885 DebugResourceVersion: atc.DebugResourceVersion{ 886 VersionID: savedVR3.ID(), 887 ResourceID: otherResource.ID(), 888 ScopeID: otherResource.ResourceConfigScopeID(), 889 CheckOrder: savedVR3.CheckOrder(), 890 }, 891 JobID: scenarioPipeline1.Job("a-job").ID(), 892 BuildID: otherPipelineBuild.ID(), 893 }, 894 { 895 DebugResourceVersion: atc.DebugResourceVersion{ 896 VersionID: savedVR1.ID(), 897 ResourceID: resource.ID(), 898 ScopeID: resource.ResourceConfigScopeID(), 899 CheckOrder: savedVR1.CheckOrder(), 900 }, 901 JobID: scenarioPipeline1.Job("a-job").ID(), 902 BuildID: build1DB.ID(), 903 }, 904 })) 905 906 Expect(versions.Resources).To(ConsistOf([]atc.DebugResource{ 907 { 908 ID: resource.ID(), 909 Name: resource.Name(), 910 ScopeID: intptr(resource.ResourceConfigScopeID()), 911 }, 912 { 913 ID: otherResource.ID(), 914 Name: otherResource.Name(), 915 ScopeID: intptr(otherResource.ResourceConfigScopeID()), 916 }, 917 { 918 ID: reallyOtherResource.ID(), 919 Name: reallyOtherResource.Name(), 920 ScopeID: intptr(reallyOtherResource.ResourceConfigScopeID()), 921 }, 922 })) 923 Expect(versions.Jobs).To(ConsistOf(jobs)) 924 925 err = scenarioPipeline1.Job("a-job").SaveNextInputMapping(db.InputMapping{ 926 "some-input-name": db.InputResult{ 927 Input: &db.AlgorithmInput{ 928 AlgorithmVersion: db.AlgorithmVersion{ 929 Version: db.ResourceVersion(convertToMD5(atc.Version{"version": "1"})), 930 ResourceID: resource.ID(), 931 }, 932 FirstOccurrence: true, 933 }, 934 PassedBuildIDs: []int{}, 935 }}, true) 936 Expect(err).ToNot(HaveOccurred()) 937 938 build1DB, err = scenarioPipeline1.Job("a-job").CreateBuild() 939 Expect(err).ToNot(HaveOccurred()) 940 941 _, found, err = build1DB.AdoptInputsAndPipes() 942 Expect(err).ToNot(HaveOccurred()) 943 Expect(found).To(BeTrue()) 944 945 err = build1DB.Finish(db.BuildStatusSucceeded) 946 Expect(err).ToNot(HaveOccurred()) 947 948 versions, err = scenarioPipeline1.Pipeline.LoadDebugVersionsDB() 949 Expect(err).ToNot(HaveOccurred()) 950 951 Expect(versions.BuildInputs).To(ConsistOf([]atc.DebugBuildInput{ 952 { 953 DebugResourceVersion: atc.DebugResourceVersion{ 954 VersionID: savedVR1.ID(), 955 ResourceID: resource.ID(), 956 ScopeID: resource.ResourceConfigScopeID(), 957 CheckOrder: savedVR1.CheckOrder(), 958 }, 959 JobID: scenarioPipeline1.Job("a-job").ID(), 960 BuildID: build1DB.ID(), 961 InputName: "some-input-name", 962 }, 963 })) 964 965 By("including implicit outputs of successful builds") 966 implicitOutput := atc.DebugBuildOutput{ 967 DebugResourceVersion: atc.DebugResourceVersion{ 968 VersionID: savedVR1.ID(), 969 ResourceID: resource.ID(), 970 ScopeID: resource.ResourceConfigScopeID(), 971 CheckOrder: savedVR1.CheckOrder(), 972 }, 973 JobID: scenarioPipeline1.Job("a-job").ID(), 974 BuildID: build1DB.ID(), 975 } 976 977 By("including put-only resource's outputs of successful builds") 978 otherExplicitOutput := atc.DebugBuildOutput{ 979 DebugResourceVersion: atc.DebugResourceVersion{ 980 VersionID: savedVR3.ID(), 981 ResourceID: otherResource.ID(), 982 ScopeID: otherResource.ResourceConfigScopeID(), 983 CheckOrder: savedVR3.CheckOrder(), 984 }, 985 JobID: scenarioPipeline1.Job("a-job").ID(), 986 BuildID: otherPipelineBuild.ID(), 987 } 988 989 Expect(versions.BuildOutputs).To(ConsistOf([]atc.DebugBuildOutput{ 990 otherExplicitOutput, 991 explicitOutput, 992 implicitOutput, 993 })) 994 995 By("including build rerun mappings for builds") 996 build2DB, err = scenarioPipeline1.Job("a-job").RerunBuild(build1DB) 997 Expect(err).ToNot(HaveOccurred()) 998 999 versions, err = scenarioPipeline1.Pipeline.LoadDebugVersionsDB() 1000 Expect(err).ToNot(HaveOccurred()) 1001 1002 Expect(versions.BuildReruns).To(ConsistOf([]atc.DebugBuildRerun{ 1003 { 1004 JobID: build1DB.JobID(), 1005 BuildID: build2DB.ID(), 1006 RerunOf: build1DB.ID(), 1007 }, 1008 })) 1009 }) 1010 }) 1011 1012 It("can load up the latest versioned resource, enabled or not", func() { 1013 By("initially having no versions") 1014 resourceVersions, _, found, err := resource.Versions(db.Page{Limit: 10}, nil) 1015 Expect(err).ToNot(HaveOccurred()) 1016 Expect(resourceVersions).To(HaveLen(0)) 1017 1018 By("including saved versioned resources of the current pipeline") 1019 scenarioPipeline1.Run(builder.WithResourceVersions(resourceName, atc.Version{"version": "1"})) 1020 1021 savedVR1, found, err := resource.FindVersion(atc.Version{"version": "1"}) 1022 Expect(err).ToNot(HaveOccurred()) 1023 Expect(found).To(BeTrue()) 1024 1025 scenarioPipeline1.Run(builder.WithResourceVersions(resourceName, atc.Version{"version": "2"})) 1026 1027 savedVR2, found, err := resource.FindVersion(atc.Version{"version": "2"}) 1028 Expect(err).ToNot(HaveOccurred()) 1029 Expect(found).To(BeTrue()) 1030 1031 Expect(savedVR1.Version()).To(Equal(db.Version{"version": "1"})) 1032 Expect(savedVR2.Version()).To(Equal(db.Version{"version": "2"})) 1033 1034 By("not including saved versioned resources of other pipelines") 1035 scenarioPipeline2.Run(builder.WithResourceVersions(otherResourceName, atc.Version{"version": "3"}, atc.Version{"version": "4"}, atc.Version{"version": "5"})) 1036 1037 _, found, err = scenarioPipeline2.Resource(otherResourceName).FindVersion(atc.Version{"version": "3"}) 1038 Expect(err).ToNot(HaveOccurred()) 1039 Expect(found).To(BeTrue()) 1040 1041 _, found, err = scenarioPipeline2.Resource(otherResourceName).FindVersion(atc.Version{"version": "1"}) 1042 Expect(err).ToNot(HaveOccurred()) 1043 Expect(found).To(BeFalse()) 1044 1045 By("including disabled versions") 1046 err = resource.DisableVersion(savedVR2.ID()) 1047 Expect(err).ToNot(HaveOccurred()) 1048 1049 latestVR, found, err := resource.FindVersion(atc.Version{"version": "2"}) 1050 Expect(err).ToNot(HaveOccurred()) 1051 Expect(found).To(BeTrue()) 1052 1053 Expect(latestVR.Version()).To(Equal(db.Version{"version": "2"})) 1054 }) 1055 1056 It("initially has no pending build for a job", func() { 1057 pendingBuilds, err := scenarioPipeline1.Job("some-job").GetPendingBuilds() 1058 Expect(err).ToNot(HaveOccurred()) 1059 Expect(pendingBuilds).To(HaveLen(0)) 1060 }) 1061 }) 1062 1063 Describe("Destroy", func() { 1064 var scenario *dbtest.Scenario 1065 1066 It("removes the pipeline and all of its data", func() { 1067 By("populating resources table") 1068 scenario = dbtest.Setup( 1069 builder.WithPipeline(atc.Config{ 1070 Resources: atc.ResourceConfigs{ 1071 { 1072 Name: "some-resource", 1073 Type: "some-type", 1074 Source: atc.Source{"some": "source"}, 1075 }, 1076 }, 1077 Jobs: atc.JobConfigs{ 1078 { 1079 Name: "some-job", 1080 PlanSequence: []atc.Step{ 1081 { 1082 Config: &atc.GetStep{ 1083 Name: "some-input", 1084 Resource: "some-resource", 1085 }, 1086 }, 1087 }, 1088 }, 1089 }, 1090 }), 1091 builder.WithResourceVersions("some-resource", atc.Version{"key": "value"}), 1092 ) 1093 1094 By("populating builds") 1095 build, err := scenario.Job("some-job").CreateBuild() 1096 Expect(err).ToNot(HaveOccurred()) 1097 1098 By("populating build inputs") 1099 err = scenario.Job("some-job").SaveNextInputMapping(db.InputMapping{ 1100 "build-input": db.InputResult{ 1101 Input: &db.AlgorithmInput{ 1102 AlgorithmVersion: db.AlgorithmVersion{ 1103 Version: db.ResourceVersion(convertToMD5(atc.Version{"key": "value"})), 1104 ResourceID: scenario.Resource("some-resource").ID(), 1105 }, 1106 FirstOccurrence: true, 1107 }, 1108 PassedBuildIDs: []int{}, 1109 }}, true) 1110 Expect(err).ToNot(HaveOccurred()) 1111 1112 _, found, err := build.AdoptInputsAndPipes() 1113 Expect(err).ToNot(HaveOccurred()) 1114 Expect(found).To(BeTrue()) 1115 1116 By("populating build outputs") 1117 err = build.SaveOutput("some-type", atc.Source{"some": "source"}, atc.VersionedResourceTypes{}, atc.Version{"key": "value"}, nil, "some-output-name", "some-resource") 1118 Expect(err).ToNot(HaveOccurred()) 1119 1120 By("populating build events") 1121 err = build.SaveEvent(event.StartTask{}) 1122 Expect(err).ToNot(HaveOccurred()) 1123 1124 err = scenario.Pipeline.Destroy() 1125 Expect(err).ToNot(HaveOccurred()) 1126 1127 found, err = scenario.Pipeline.Reload() 1128 Expect(err).ToNot(HaveOccurred()) 1129 Expect(found).To(BeFalse()) 1130 1131 found, err = build.Reload() 1132 Expect(err).ToNot(HaveOccurred()) 1133 Expect(found).To(BeFalse()) 1134 1135 _, found, err = scenario.Team.Pipeline(atc.PipelineRef{Name: pipeline.Name()}) 1136 Expect(err).ToNot(HaveOccurred()) 1137 Expect(found).To(BeFalse()) 1138 }) 1139 1140 It("marks the pipeline ID in the deleted_pipelines table", func() { 1141 destroy(pipeline) 1142 1143 var exists bool 1144 err := dbConn.QueryRow(fmt.Sprintf("SELECT EXISTS (SELECT 1 FROM deleted_pipelines WHERE id = %d)", pipeline.ID())).Scan(&exists) 1145 Expect(err).ToNot(HaveOccurred()) 1146 Expect(exists).To(BeTrue(), "did not mark the pipeline id in deleted_pipelines") 1147 }) 1148 }) 1149 1150 Describe("Dashboard", func() { 1151 It("returns a Dashboard object with a DashboardJob corresponding to each configured job", func() { 1152 job, found, err := pipeline.Job("job-name") 1153 Expect(err).ToNot(HaveOccurred()) 1154 Expect(found).To(BeTrue()) 1155 1156 err = job.UpdateFirstLoggedBuildID(57) 1157 Expect(err).ToNot(HaveOccurred()) 1158 1159 otherJob, found, err := pipeline.Job("some-other-job") 1160 Expect(err).ToNot(HaveOccurred()) 1161 Expect(found).To(BeTrue()) 1162 1163 aJob, found, err := pipeline.Job("a-job") 1164 Expect(err).ToNot(HaveOccurred()) 1165 Expect(found).To(BeTrue()) 1166 1167 sharedJob, found, err := pipeline.Job("shared-job") 1168 Expect(err).ToNot(HaveOccurred()) 1169 Expect(found).To(BeTrue()) 1170 1171 randomJob, found, err := pipeline.Job("random-job") 1172 Expect(err).ToNot(HaveOccurred()) 1173 Expect(found).To(BeTrue()) 1174 1175 job1, found, err := pipeline.Job("job-1") 1176 Expect(err).ToNot(HaveOccurred()) 1177 Expect(found).To(BeTrue()) 1178 1179 job2, found, err := pipeline.Job("job-2") 1180 Expect(err).ToNot(HaveOccurred()) 1181 Expect(found).To(BeTrue()) 1182 1183 otherSerialGroupJob, found, err := pipeline.Job("other-serial-group-job") 1184 Expect(err).ToNot(HaveOccurred()) 1185 Expect(found).To(BeTrue()) 1186 1187 differentSerialGroupJob, found, err := pipeline.Job("different-serial-group-job") 1188 Expect(err).ToNot(HaveOccurred()) 1189 Expect(found).To(BeTrue()) 1190 1191 By("returning jobs with no builds") 1192 actualDashboard, err := pipeline.Dashboard() 1193 Expect(err).ToNot(HaveOccurred()) 1194 1195 Expect(actualDashboard[0].Name).To(Equal(job.Name())) 1196 Expect(actualDashboard[1].Name).To(Equal(otherJob.Name())) 1197 Expect(actualDashboard[2].Name).To(Equal(aJob.Name())) 1198 Expect(actualDashboard[3].Name).To(Equal(sharedJob.Name())) 1199 Expect(actualDashboard[4].Name).To(Equal(randomJob.Name())) 1200 Expect(actualDashboard[5].Name).To(Equal(job1.Name())) 1201 Expect(actualDashboard[6].Name).To(Equal(job2.Name())) 1202 Expect(actualDashboard[7].Name).To(Equal(otherSerialGroupJob.Name())) 1203 Expect(actualDashboard[8].Name).To(Equal(differentSerialGroupJob.Name())) 1204 1205 By("returning a job's most recent pending build if there are no running builds") 1206 job, found, err = pipeline.Job("job-name") 1207 Expect(err).ToNot(HaveOccurred()) 1208 Expect(found).To(BeTrue()) 1209 1210 firstJobBuild, err := job.CreateBuild() 1211 Expect(err).ToNot(HaveOccurred()) 1212 1213 actualDashboard, err = pipeline.Dashboard() 1214 Expect(err).ToNot(HaveOccurred()) 1215 1216 Expect(actualDashboard[0].Name).To(Equal(job.Name())) 1217 Expect(actualDashboard[0].NextBuild.ID).To(Equal(firstJobBuild.ID())) 1218 1219 By("returning a job's most recent started build") 1220 found, err = firstJobBuild.Start(atc.Plan{ID: "some-id"}) 1221 Expect(err).ToNot(HaveOccurred()) 1222 Expect(found).To(BeTrue()) 1223 1224 found, err = firstJobBuild.Reload() 1225 Expect(err).ToNot(HaveOccurred()) 1226 Expect(found).To(BeTrue()) 1227 1228 actualDashboard, err = pipeline.Dashboard() 1229 Expect(err).ToNot(HaveOccurred()) 1230 1231 Expect(actualDashboard[0].Name).To(Equal(job.Name())) 1232 Expect(actualDashboard[0].NextBuild.ID).To(Equal(firstJobBuild.ID())) 1233 Expect(actualDashboard[0].NextBuild.Status).To(Equal(atc.StatusStarted)) 1234 1235 By("returning a job's most recent started build even if there is a newer pending build") 1236 job, found, err = pipeline.Job("job-name") 1237 Expect(err).ToNot(HaveOccurred()) 1238 Expect(found).To(BeTrue()) 1239 1240 secondJobBuild, err := job.CreateBuild() 1241 Expect(err).ToNot(HaveOccurred()) 1242 1243 actualDashboard, err = pipeline.Dashboard() 1244 Expect(err).ToNot(HaveOccurred()) 1245 1246 Expect(actualDashboard[0].Name).To(Equal(job.Name())) 1247 Expect(actualDashboard[0].NextBuild.ID).To(Equal(firstJobBuild.ID())) 1248 1249 By("returning a job's most recent finished build") 1250 err = firstJobBuild.Finish(db.BuildStatusSucceeded) 1251 Expect(err).ToNot(HaveOccurred()) 1252 1253 err = secondJobBuild.Finish(db.BuildStatusSucceeded) 1254 Expect(err).ToNot(HaveOccurred()) 1255 1256 found, err = secondJobBuild.Reload() 1257 Expect(err).ToNot(HaveOccurred()) 1258 Expect(found).To(BeTrue()) 1259 1260 actualDashboard, err = pipeline.Dashboard() 1261 Expect(err).ToNot(HaveOccurred()) 1262 1263 Expect(actualDashboard[0].Name).To(Equal(job.Name())) 1264 Expect(actualDashboard[0].NextBuild).To(BeNil()) 1265 Expect(actualDashboard[0].FinishedBuild.ID).To(Equal(secondJobBuild.ID())) 1266 1267 By("returning the job inputs and outputs") 1268 Expect(actualDashboard[0].Outputs).To(ConsistOf(atc.JobOutputSummary{ 1269 Name: "some-resource", 1270 Resource: "some-resource", 1271 })) 1272 Expect(actualDashboard[0].Inputs).To(ConsistOf(atc.JobInputSummary{ 1273 Name: "some-input", 1274 Resource: "some-resource", 1275 Passed: []string{"job-1", "job-2"}, 1276 Trigger: true, 1277 })) 1278 }) 1279 }) 1280 1281 Describe("DeleteBuildEventsByBuildIDs", func() { 1282 It("deletes all build logs corresponding to the given build ids", func() { 1283 build1DB, err := team.CreateOneOffBuild() 1284 Expect(err).ToNot(HaveOccurred()) 1285 1286 err = build1DB.SaveEvent(event.Log{ 1287 Payload: "log 1", 1288 }) 1289 Expect(err).ToNot(HaveOccurred()) 1290 1291 build2DB, err := team.CreateOneOffBuild() 1292 Expect(err).ToNot(HaveOccurred()) 1293 1294 err = build2DB.SaveEvent(event.Log{ 1295 Payload: "log 2", 1296 }) 1297 Expect(err).ToNot(HaveOccurred()) 1298 1299 build3DB, err := team.CreateOneOffBuild() 1300 Expect(err).ToNot(HaveOccurred()) 1301 1302 err = build3DB.Finish(db.BuildStatusSucceeded) 1303 Expect(err).ToNot(HaveOccurred()) 1304 1305 err = build1DB.Finish(db.BuildStatusSucceeded) 1306 Expect(err).ToNot(HaveOccurred()) 1307 1308 err = build2DB.Finish(db.BuildStatusSucceeded) 1309 Expect(err).ToNot(HaveOccurred()) 1310 1311 build4DB, err := team.CreateOneOffBuild() 1312 Expect(err).ToNot(HaveOccurred()) 1313 1314 By("doing nothing if the list is empty") 1315 err = pipeline.DeleteBuildEventsByBuildIDs([]int{}) 1316 Expect(err).ToNot(HaveOccurred()) 1317 1318 By("not returning an error") 1319 err = pipeline.DeleteBuildEventsByBuildIDs([]int{build3DB.ID(), build4DB.ID(), build1DB.ID()}) 1320 Expect(err).ToNot(HaveOccurred()) 1321 1322 err = build4DB.Finish(db.BuildStatusSucceeded) 1323 Expect(err).ToNot(HaveOccurred()) 1324 1325 By("deleting events for build 1") 1326 events1, err := build1DB.Events(0) 1327 Expect(err).ToNot(HaveOccurred()) 1328 defer db.Close(events1) 1329 1330 _, err = events1.Next() 1331 Expect(err).To(Equal(db.ErrEndOfBuildEventStream)) 1332 1333 By("preserving events for build 2") 1334 events2, err := build2DB.Events(0) 1335 Expect(err).ToNot(HaveOccurred()) 1336 defer db.Close(events2) 1337 1338 build2Event1, err := events2.Next() 1339 Expect(err).ToNot(HaveOccurred()) 1340 Expect(build2Event1).To(Equal(envelope(event.Log{ 1341 Payload: "log 2", 1342 }))) 1343 1344 _, err = events2.Next() // finish event 1345 Expect(err).ToNot(HaveOccurred()) 1346 1347 _, err = events2.Next() 1348 Expect(err).To(Equal(db.ErrEndOfBuildEventStream)) 1349 1350 By("deleting events for build 3") 1351 events3, err := build3DB.Events(0) 1352 Expect(err).ToNot(HaveOccurred()) 1353 defer db.Close(events3) 1354 1355 _, err = events3.Next() 1356 Expect(err).To(Equal(db.ErrEndOfBuildEventStream)) 1357 1358 By("being unflapped by build 4, which had no events at the time") 1359 events4, err := build4DB.Events(0) 1360 Expect(err).ToNot(HaveOccurred()) 1361 defer db.Close(events4) 1362 1363 _, err = events4.Next() // finish event 1364 Expect(err).ToNot(HaveOccurred()) 1365 1366 _, err = events4.Next() 1367 Expect(err).To(Equal(db.ErrEndOfBuildEventStream)) 1368 1369 By("updating ReapTime for the affected builds") 1370 found, err := build1DB.Reload() 1371 Expect(err).ToNot(HaveOccurred()) 1372 Expect(found).To(BeTrue()) 1373 1374 Expect(build1DB.ReapTime()).To(BeTemporally(">", build1DB.EndTime())) 1375 1376 found, err = build2DB.Reload() 1377 Expect(err).ToNot(HaveOccurred()) 1378 Expect(found).To(BeTrue()) 1379 1380 Expect(build2DB.ReapTime()).To(BeZero()) 1381 1382 found, err = build3DB.Reload() 1383 Expect(err).ToNot(HaveOccurred()) 1384 Expect(found).To(BeTrue()) 1385 1386 Expect(build3DB.ReapTime()).To(Equal(build1DB.ReapTime())) 1387 1388 found, err = build4DB.Reload() 1389 Expect(err).ToNot(HaveOccurred()) 1390 Expect(found).To(BeTrue()) 1391 1392 // Not required behavior, just a sanity check for what I think will happen 1393 Expect(build4DB.ReapTime()).To(Equal(build1DB.ReapTime())) 1394 }) 1395 }) 1396 1397 Describe("Jobs", func() { 1398 var jobs []db.Job 1399 1400 BeforeEach(func() { 1401 var err error 1402 jobs, err = pipeline.Jobs() 1403 Expect(err).ToNot(HaveOccurred()) 1404 }) 1405 1406 It("returns all the jobs", func() { 1407 Expect(jobs[0].Name()).To(Equal("job-name")) 1408 Expect(jobs[1].Name()).To(Equal("some-other-job")) 1409 Expect(jobs[2].Name()).To(Equal("a-job")) 1410 Expect(jobs[3].Name()).To(Equal("shared-job")) 1411 Expect(jobs[4].Name()).To(Equal("random-job")) 1412 Expect(jobs[5].Name()).To(Equal("job-1")) 1413 Expect(jobs[6].Name()).To(Equal("job-2")) 1414 Expect(jobs[7].Name()).To(Equal("other-serial-group-job")) 1415 Expect(jobs[8].Name()).To(Equal("different-serial-group-job")) 1416 }) 1417 }) 1418 1419 Describe("GetBuildsWithVersionAsInput", func() { 1420 var ( 1421 resourceConfigVersion int 1422 expectedBuilds []int 1423 dbSecondBuild db.Build 1424 scenario *dbtest.Scenario 1425 ) 1426 1427 BeforeEach(func() { 1428 scenario = dbtest.Setup( 1429 builder.WithPipeline(atc.Config{ 1430 Jobs: atc.JobConfigs{ 1431 { 1432 Name: "job-name", 1433 PlanSequence: []atc.Step{ 1434 { 1435 Config: &atc.GetStep{ 1436 Name: "some-input", 1437 Resource: "some-resource", 1438 }, 1439 }, 1440 }, 1441 }, 1442 { 1443 Name: "some-other-job", 1444 Serial: true, 1445 }, 1446 }, 1447 Resources: atc.ResourceConfigs{ 1448 { 1449 Name: "some-resource", 1450 Type: "some-type", 1451 Source: atc.Source{"some": "source"}, 1452 }, 1453 }, 1454 }), 1455 builder.WithResourceVersions("some-resource", atc.Version{"version": "v1"}), 1456 ) 1457 1458 build, err := scenario.Job("job-name").CreateBuild() 1459 Expect(err).ToNot(HaveOccurred()) 1460 expectedBuilds = append(expectedBuilds, build.ID()) 1461 1462 secondBuild, err := scenario.Job("job-name").CreateBuild() 1463 Expect(err).ToNot(HaveOccurred()) 1464 expectedBuilds = append(expectedBuilds, secondBuild.ID()) 1465 1466 _, err = scenario.Job("some-other-job").CreateBuild() 1467 Expect(err).ToNot(HaveOccurred()) 1468 1469 dbBuild, found, err := buildFactory.Build(build.ID()) 1470 Expect(err).ToNot(HaveOccurred()) 1471 Expect(found).To(BeTrue()) 1472 1473 err = scenario.Job("job-name").SaveNextInputMapping(db.InputMapping{ 1474 "some-input": db.InputResult{ 1475 Input: &db.AlgorithmInput{ 1476 AlgorithmVersion: db.AlgorithmVersion{ 1477 Version: db.ResourceVersion(convertToMD5(atc.Version{"version": "v1"})), 1478 ResourceID: scenario.Resource("some-resource").ID(), 1479 }, 1480 FirstOccurrence: true, 1481 }, 1482 PassedBuildIDs: []int{}, 1483 }}, true) 1484 Expect(err).ToNot(HaveOccurred()) 1485 1486 _, found, err = dbBuild.AdoptInputsAndPipes() 1487 Expect(err).ToNot(HaveOccurred()) 1488 Expect(found).To(BeTrue()) 1489 1490 dbSecondBuild, found, err = buildFactory.Build(secondBuild.ID()) 1491 Expect(err).ToNot(HaveOccurred()) 1492 Expect(found).To(BeTrue()) 1493 1494 scenario.Run(builder.WithResourceVersions( 1495 "some-resource", 1496 atc.Version{"version": "v2"}, 1497 atc.Version{"version": "v3"}, 1498 atc.Version{"version": "v4"}, 1499 )) 1500 1501 err = scenario.Job("job-name").SaveNextInputMapping(db.InputMapping{ 1502 "some-input": db.InputResult{ 1503 Input: &db.AlgorithmInput{ 1504 AlgorithmVersion: db.AlgorithmVersion{ 1505 Version: db.ResourceVersion(convertToMD5(atc.Version{"version": "v1"})), 1506 ResourceID: scenario.Resource("some-resource").ID(), 1507 }, 1508 FirstOccurrence: true, 1509 }, 1510 PassedBuildIDs: []int{}, 1511 }, 1512 "some-other-input": db.InputResult{ 1513 Input: &db.AlgorithmInput{ 1514 AlgorithmVersion: db.AlgorithmVersion{ 1515 Version: db.ResourceVersion(convertToMD5(atc.Version{"version": "v3"})), 1516 ResourceID: scenario.Resource("some-resource").ID(), 1517 }, 1518 FirstOccurrence: true, 1519 }, 1520 PassedBuildIDs: []int{}, 1521 }, 1522 }, true) 1523 Expect(err).ToNot(HaveOccurred()) 1524 1525 _, found, err = dbSecondBuild.AdoptInputsAndPipes() 1526 Expect(err).ToNot(HaveOccurred()) 1527 Expect(found).To(BeTrue()) 1528 1529 rcv1 := scenario.ResourceVersion("some-resource", atc.Version{"version": "v1"}) 1530 1531 resourceConfigVersion = rcv1.ID() 1532 }) 1533 1534 It("returns the two builds for which the provided version id was an input", func() { 1535 builds, err := pipeline.GetBuildsWithVersionAsInput(scenario.Resource("some-resource").ID(), resourceConfigVersion) 1536 Expect(err).ToNot(HaveOccurred()) 1537 Expect(builds).To(HaveLen(len(expectedBuilds))) 1538 1539 buildIDs := []int{} 1540 for _, b := range builds { 1541 buildIDs = append(buildIDs, b.ID()) 1542 } 1543 1544 Expect(buildIDs).To(ConsistOf(expectedBuilds)) 1545 }) 1546 1547 It("returns the one build that uses the version as an input", func() { 1548 rcv3 := scenario.ResourceVersion("some-resource", atc.Version{"version": "v3"}) 1549 1550 builds, err := pipeline.GetBuildsWithVersionAsInput(scenario.Resource("some-resource").ID(), rcv3.ID()) 1551 Expect(err).ToNot(HaveOccurred()) 1552 Expect(builds).To(HaveLen(1)) 1553 Expect(builds[0].ID()).To(Equal(dbSecondBuild.ID())) 1554 }) 1555 1556 It("returns an empty slice of builds when the provided version id exists but is not used", func() { 1557 rcv4 := scenario.ResourceVersion("some-resource", atc.Version{"version": "v4"}) 1558 1559 builds, err := pipeline.GetBuildsWithVersionAsInput(scenario.Resource("some-resource").ID(), rcv4.ID()) 1560 Expect(err).ToNot(HaveOccurred()) 1561 Expect(builds).To(Equal([]db.Build{})) 1562 }) 1563 1564 It("returns an empty slice of builds when the provided version id doesn't exist", func() { 1565 builds, err := pipeline.GetBuildsWithVersionAsInput(scenario.Resource("some-resource").ID(), resourceConfigVersion+100) 1566 Expect(err).ToNot(HaveOccurred()) 1567 Expect(builds).To(Equal([]db.Build{})) 1568 }) 1569 1570 It("returns an empty slice of builds when the provided resource id doesn't exist", func() { 1571 builds, err := pipeline.GetBuildsWithVersionAsInput(10293912, resourceConfigVersion) 1572 Expect(err).ToNot(HaveOccurred()) 1573 Expect(builds).To(Equal([]db.Build{})) 1574 }) 1575 }) 1576 1577 Describe("GetBuildsWithVersionAsOutput", func() { 1578 var ( 1579 resourceConfigVersion int 1580 expectedBuilds []db.Build 1581 secondBuild db.Build 1582 scenario *dbtest.Scenario 1583 ) 1584 1585 BeforeEach(func() { 1586 scenario = dbtest.Setup( 1587 builder.WithPipeline(atc.Config{ 1588 Jobs: atc.JobConfigs{ 1589 { 1590 Name: "job-name", 1591 PlanSequence: []atc.Step{ 1592 { 1593 Config: &atc.GetStep{ 1594 Name: "some-input", 1595 Resource: "some-resource", 1596 }, 1597 }, 1598 }, 1599 }, 1600 { 1601 Name: "some-other-job", 1602 Serial: true, 1603 }, 1604 }, 1605 Resources: atc.ResourceConfigs{ 1606 { 1607 Name: "some-resource", 1608 Type: "some-type", 1609 Source: atc.Source{"some": "source"}, 1610 }, 1611 }, 1612 }), 1613 builder.WithResourceVersions("some-resource", atc.Version{"version": "v3"}, atc.Version{"version": "v4"}), 1614 ) 1615 1616 build, err := scenario.Job("job-name").CreateBuild() 1617 Expect(err).ToNot(HaveOccurred()) 1618 expectedBuilds = append(expectedBuilds, build) 1619 1620 secondBuild, err = scenario.Job("job-name").CreateBuild() 1621 Expect(err).ToNot(HaveOccurred()) 1622 expectedBuilds = append(expectedBuilds, secondBuild) 1623 1624 _, err = scenario.Job("some-other-job").CreateBuild() 1625 Expect(err).ToNot(HaveOccurred()) 1626 1627 dbBuild, found, err := buildFactory.Build(build.ID()) 1628 Expect(err).ToNot(HaveOccurred()) 1629 Expect(found).To(BeTrue()) 1630 1631 err = dbBuild.SaveOutput("some-type", atc.Source{"some": "source"}, atc.VersionedResourceTypes{}, atc.Version{"version": "v1"}, []db.ResourceConfigMetadataField{ 1632 { 1633 Name: "some", 1634 Value: "value", 1635 }, 1636 }, "some-output-name", "some-resource") 1637 Expect(err).ToNot(HaveOccurred()) 1638 1639 dbSecondBuild, found, err := buildFactory.Build(secondBuild.ID()) 1640 Expect(err).ToNot(HaveOccurred()) 1641 Expect(found).To(BeTrue()) 1642 1643 err = dbSecondBuild.SaveOutput("some-type", atc.Source{"some": "source"}, atc.VersionedResourceTypes{}, atc.Version{"version": "v1"}, []db.ResourceConfigMetadataField{ 1644 { 1645 Name: "some", 1646 Value: "value", 1647 }, 1648 }, "some-output-name", "some-resource") 1649 Expect(err).ToNot(HaveOccurred()) 1650 1651 err = dbSecondBuild.SaveOutput("some-type", atc.Source{"some": "source"}, atc.VersionedResourceTypes{}, atc.Version{"version": "v3"}, nil, "some-output-name", "some-resource") 1652 Expect(err).ToNot(HaveOccurred()) 1653 1654 rcv1 := scenario.ResourceVersion("some-resource", atc.Version{"version": "v1"}) 1655 1656 resourceConfigVersion = rcv1.ID() 1657 }) 1658 1659 It("returns the two builds for which the provided version id was an output", func() { 1660 builds, err := pipeline.GetBuildsWithVersionAsOutput(scenario.Resource("some-resource").ID(), resourceConfigVersion) 1661 Expect(err).ToNot(HaveOccurred()) 1662 Expect(builds).To(ConsistOf(expectedBuilds)) 1663 }) 1664 1665 It("returns the one build that uses the version as an input", func() { 1666 rcv3 := scenario.ResourceVersion("some-resource", atc.Version{"version": "v3"}) 1667 1668 builds, err := pipeline.GetBuildsWithVersionAsOutput(scenario.Resource("some-resource").ID(), rcv3.ID()) 1669 Expect(err).ToNot(HaveOccurred()) 1670 Expect(builds).To(HaveLen(1)) 1671 Expect(builds[0].ID()).To(Equal(secondBuild.ID())) 1672 }) 1673 1674 It("returns an empty slice of builds when the provided version id exists but is not used", func() { 1675 rcv4 := scenario.ResourceVersion("some-resource", atc.Version{"version": "v4"}) 1676 1677 builds, err := pipeline.GetBuildsWithVersionAsOutput(scenario.Resource("some-resource").ID(), rcv4.ID()) 1678 Expect(err).ToNot(HaveOccurred()) 1679 Expect(builds).To(Equal([]db.Build{})) 1680 }) 1681 1682 It("returns an empty slice of builds when the provided resource id doesn't exist", func() { 1683 builds, err := pipeline.GetBuildsWithVersionAsOutput(10293912, resourceConfigVersion) 1684 Expect(err).ToNot(HaveOccurred()) 1685 Expect(builds).To(Equal([]db.Build{})) 1686 }) 1687 1688 It("returns an empty slice of builds when the provided version id doesn't exist", func() { 1689 builds, err := pipeline.GetBuildsWithVersionAsOutput(scenario.Resource("some-resource").ID(), resourceConfigVersion+100) 1690 Expect(err).ToNot(HaveOccurred()) 1691 Expect(builds).To(Equal([]db.Build{})) 1692 }) 1693 }) 1694 1695 Describe("Builds", func() { 1696 var expectedBuilds []db.Build 1697 1698 BeforeEach(func() { 1699 _, err := team.CreateOneOffBuild() 1700 Expect(err).NotTo(HaveOccurred()) 1701 1702 job, found, err := pipeline.Job("job-name") 1703 Expect(err).ToNot(HaveOccurred()) 1704 Expect(found).To(BeTrue()) 1705 1706 build, err := job.CreateBuild() 1707 Expect(err).ToNot(HaveOccurred()) 1708 expectedBuilds = append(expectedBuilds, build) 1709 1710 secondBuild, err := job.CreateBuild() 1711 Expect(err).ToNot(HaveOccurred()) 1712 expectedBuilds = append(expectedBuilds, secondBuild) 1713 1714 someOtherJob, found, err := pipeline.Job("some-other-job") 1715 Expect(err).ToNot(HaveOccurred()) 1716 Expect(found).To(BeTrue()) 1717 1718 thirdBuild, err := someOtherJob.CreateBuild() 1719 Expect(err).ToNot(HaveOccurred()) 1720 expectedBuilds = append(expectedBuilds, thirdBuild) 1721 }) 1722 1723 It("returns builds for the current pipeline", func() { 1724 builds, _, err := pipeline.Builds(db.Page{Limit: 10}) 1725 Expect(err).NotTo(HaveOccurred()) 1726 Expect(builds).To(ConsistOf(expectedBuilds)) 1727 }) 1728 }) 1729 1730 Describe("CreateStartedBuild", func() { 1731 var ( 1732 plan atc.Plan 1733 startedBuild db.Build 1734 err error 1735 ) 1736 1737 BeforeEach(func() { 1738 plan = atc.Plan{ 1739 ID: atc.PlanID("56"), 1740 Get: &atc.GetPlan{ 1741 Type: "some-type", 1742 Name: "some-name", 1743 Resource: "some-resource", 1744 Source: atc.Source{"some": "source"}, 1745 Params: atc.Params{"some": "params"}, 1746 Version: &atc.Version{"some": "version"}, 1747 Tags: atc.Tags{"some-tags"}, 1748 VersionedResourceTypes: atc.VersionedResourceTypes{ 1749 { 1750 ResourceType: atc.ResourceType{ 1751 Name: "some-name", 1752 Source: atc.Source{"some": "source"}, 1753 Type: "some-type", 1754 Privileged: true, 1755 Tags: atc.Tags{"some-tags"}, 1756 }, 1757 Version: atc.Version{"some-resource-type": "version"}, 1758 }, 1759 }, 1760 }, 1761 } 1762 1763 startedBuild, err = pipeline.CreateStartedBuild(plan) 1764 Expect(err).ToNot(HaveOccurred()) 1765 }) 1766 1767 It("can create started builds with plans", func() { 1768 Expect(startedBuild.ID()).ToNot(BeZero()) 1769 Expect(startedBuild.JobName()).To(BeZero()) 1770 Expect(startedBuild.PipelineName()).To(Equal("fake-pipeline")) 1771 Expect(startedBuild.Name()).To(Equal(strconv.Itoa(startedBuild.ID()))) 1772 Expect(startedBuild.TeamName()).To(Equal(team.Name())) 1773 Expect(startedBuild.Status()).To(Equal(db.BuildStatusStarted)) 1774 }) 1775 1776 It("saves the public plan", func() { 1777 found, err := startedBuild.Reload() 1778 Expect(err).NotTo(HaveOccurred()) 1779 Expect(found).To(BeTrue()) 1780 Expect(startedBuild.PublicPlan()).To(Equal(plan.Public())) 1781 }) 1782 1783 It("creates Start event", func() { 1784 found, err := startedBuild.Reload() 1785 Expect(err).NotTo(HaveOccurred()) 1786 Expect(found).To(BeTrue()) 1787 1788 events, err := startedBuild.Events(0) 1789 Expect(err).NotTo(HaveOccurred()) 1790 1791 defer db.Close(events) 1792 1793 Expect(events.Next()).To(Equal(envelope(event.Status{ 1794 Status: atc.StatusStarted, 1795 Time: startedBuild.StartTime().Unix(), 1796 }))) 1797 }) 1798 }) 1799 1800 Describe("Resources", func() { 1801 var resourceTypes db.ResourceTypes 1802 var scenario *dbtest.Scenario 1803 1804 BeforeEach(func() { 1805 scenario = dbtest.Setup( 1806 builder.WithPipeline(atc.Config{ 1807 ResourceTypes: atc.ResourceTypes{ 1808 { 1809 Name: "some-other-resource-type", 1810 Type: "global-base-type", 1811 Source: atc.Source{"some": "other-type-soure"}, 1812 }, 1813 { 1814 Name: "some-resource-type", 1815 Type: "global-base-type", 1816 Source: atc.Source{"some": "type-soure"}, 1817 }, 1818 }, 1819 }), 1820 builder.WithResourceTypeVersions("some-resource-type", 1821 atc.Version{"version": "1"}, 1822 atc.Version{"version": "2"}, 1823 ), 1824 builder.WithResourceTypeVersions("some-other-resource-type", 1825 atc.Version{"version": "3"}, 1826 ), 1827 builder.WithResourceTypeVersions("some-other-resource-type", 1828 atc.Version{"version": "3"}, 1829 atc.Version{"version": "5"}, 1830 ), 1831 ) 1832 }) 1833 1834 JustBeforeEach(func() { 1835 var err error 1836 resourceTypes, err = scenario.Pipeline.ResourceTypes() 1837 Expect(err).ToNot(HaveOccurred()) 1838 }) 1839 1840 It("returns the version", func() { 1841 resourceTypeVersions := []atc.Version{resourceTypes[0].Version()} 1842 resourceTypeVersions = append(resourceTypeVersions, resourceTypes[1].Version()) 1843 Expect(resourceTypeVersions).To(ConsistOf(atc.Version{"version": "2"}, atc.Version{"version": "5"})) 1844 }) 1845 }) 1846 1847 Describe("ResourceVersion", func() { 1848 var ( 1849 rv atc.ResourceVersion 1850 resourceConfigVersion db.ResourceConfigVersion 1851 scenario *dbtest.Scenario 1852 ) 1853 1854 BeforeEach(func() { 1855 scenario = dbtest.Setup( 1856 builder.WithPipeline(atc.Config{ 1857 Resources: atc.ResourceConfigs{ 1858 { 1859 Name: "some-resource", 1860 Type: "some-type", 1861 Source: atc.Source{"some": "source"}, 1862 }, 1863 }, 1864 }), 1865 builder.WithResourceVersions("some-resource", 1866 atc.Version{"version": "1"}, 1867 ), 1868 ) 1869 1870 resourceConfigVersion = scenario.ResourceVersion("some-resource", atc.Version{"version": "1"}) 1871 }) 1872 1873 JustBeforeEach(func() { 1874 var found bool 1875 var err error 1876 1877 rv, found, err = pipeline.ResourceVersion(resourceConfigVersion.ID()) 1878 Expect(err).ToNot(HaveOccurred()) 1879 Expect(found).To(BeTrue()) 1880 }) 1881 1882 Context("when a resource is enabled", func() { 1883 It("should return the version with enabled set to true", func() { 1884 Expect(rv).To(Equal(atc.ResourceVersion{ 1885 Version: atc.Version{"version": "1"}, 1886 ID: resourceConfigVersion.ID(), 1887 Enabled: true, 1888 })) 1889 }) 1890 }) 1891 1892 Context("when a resource is not enabled", func() { 1893 BeforeEach(func() { 1894 err := scenario.Resource("some-resource").DisableVersion(resourceConfigVersion.ID()) 1895 Expect(err).ToNot(HaveOccurred()) 1896 }) 1897 1898 It("should return the version with enabled set to false", func() { 1899 Expect(rv).To(Equal(atc.ResourceVersion{ 1900 Version: atc.Version{"version": "1"}, 1901 ID: resourceConfigVersion.ID(), 1902 Enabled: false, 1903 })) 1904 }) 1905 }) 1906 }) 1907 1908 Describe("BuildsWithTime", func() { 1909 var ( 1910 pipeline db.Pipeline 1911 builds = make([]db.Build, 4) 1912 job db.Job 1913 ) 1914 1915 BeforeEach(func() { 1916 var ( 1917 err error 1918 found bool 1919 ) 1920 1921 config := atc.Config{ 1922 Jobs: atc.JobConfigs{ 1923 { 1924 Name: "some-job", 1925 }, 1926 { 1927 Name: "some-other-job", 1928 }, 1929 }, 1930 } 1931 pipeline, _, err = team.SavePipeline(atc.PipelineRef{Name: "some-pipeline"}, config, db.ConfigVersion(1), false) 1932 Expect(err).ToNot(HaveOccurred()) 1933 1934 job, found, err = pipeline.Job("some-job") 1935 Expect(err).ToNot(HaveOccurred()) 1936 Expect(found).To(BeTrue()) 1937 1938 for i := range builds { 1939 builds[i], err = job.CreateBuild() 1940 Expect(err).ToNot(HaveOccurred()) 1941 1942 buildStart := time.Date(2020, 11, i+1, 0, 0, 0, 0, time.UTC) 1943 _, err = dbConn.Exec("UPDATE builds SET start_time = to_timestamp($1) WHERE id = $2", buildStart.Unix(), builds[i].ID()) 1944 Expect(err).NotTo(HaveOccurred()) 1945 1946 builds[i], found, err = job.Build(builds[i].Name()) 1947 Expect(err).ToNot(HaveOccurred()) 1948 Expect(found).To(BeTrue()) 1949 } 1950 1951 otherPipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "another-pipeline"}, config, db.ConfigVersion(1), false) 1952 Expect(err).ToNot(HaveOccurred()) 1953 1954 otherJob, found, err := otherPipeline.Job("some-job") 1955 Expect(err).ToNot(HaveOccurred()) 1956 Expect(found).To(BeTrue()) 1957 1958 _, err = otherJob.CreateBuild() 1959 }) 1960 1961 Context("when not providing boundaries", func() { 1962 Context("without a limit specified", func() { 1963 It("returns no builds", func() { 1964 returnedBuilds, _, err := pipeline.BuildsWithTime(db.Page{}) 1965 Expect(err).NotTo(HaveOccurred()) 1966 1967 Expect(returnedBuilds).To(BeEmpty()) 1968 }) 1969 }) 1970 1971 Context("with a limit specified", func() { 1972 It("returns a subset of the builds", func() { 1973 returnedBuilds, _, err := pipeline.BuildsWithTime(db.Page{ 1974 Limit: 2, 1975 }) 1976 Expect(err).NotTo(HaveOccurred()) 1977 Expect(returnedBuilds).To(ConsistOf(builds[3], builds[2])) 1978 }) 1979 }) 1980 }) 1981 1982 Context("when providing boundaries", func() { 1983 1984 Context("only to", func() { 1985 It("returns only those before and including to", func() { 1986 returnedBuilds, _, err := pipeline.BuildsWithTime(db.Page{ 1987 To: db.NewIntPtr(int(builds[2].StartTime().Unix())), 1988 Limit: 50, 1989 }) 1990 1991 Expect(err).NotTo(HaveOccurred()) 1992 Expect(returnedBuilds).To(ConsistOf(builds[0], builds[1], builds[2])) 1993 }) 1994 }) 1995 1996 Context("only from", func() { 1997 It("returns only those after from", func() { 1998 returnedBuilds, _, err := pipeline.BuildsWithTime(db.Page{ 1999 From: db.NewIntPtr(int(builds[1].StartTime().Unix())), 2000 Limit: 50, 2001 }) 2002 2003 Expect(err).NotTo(HaveOccurred()) 2004 Expect(returnedBuilds).To(ConsistOf(builds[1], builds[2], builds[3])) 2005 }) 2006 }) 2007 2008 Context("from and to", func() { 2009 It("returns only elements in the range", func() { 2010 returnedBuilds, _, err := pipeline.BuildsWithTime(db.Page{ 2011 From: db.NewIntPtr(int(builds[1].StartTime().Unix())), 2012 To: db.NewIntPtr(int(builds[2].StartTime().Unix())), 2013 Limit: 50, 2014 }) 2015 Expect(err).NotTo(HaveOccurred()) 2016 Expect(returnedBuilds).To(ConsistOf(builds[1], builds[2])) 2017 }) 2018 }) 2019 }) 2020 }) 2021 2022 Describe("Variables", func() { 2023 var ( 2024 fakeGlobalSecrets *credsfakes.FakeSecrets 2025 pool creds.VarSourcePool 2026 2027 pvars vars.Variables 2028 err error 2029 ) 2030 2031 BeforeEach(func() { 2032 credentialManagement := creds.CredentialManagementConfig{ 2033 RetryConfig: creds.SecretRetryConfig{ 2034 Attempts: 5, 2035 Interval: time.Second, 2036 }, 2037 CacheConfig: creds.SecretCacheConfig{ 2038 Enabled: true, 2039 Duration: time.Minute, 2040 DurationNotFound: time.Minute, 2041 PurgeInterval: time.Minute * 10, 2042 }, 2043 } 2044 pool = creds.NewVarSourcePool(logger, credentialManagement, 1*time.Minute, 1*time.Second, clock.NewClock()) 2045 }) 2046 2047 AfterEach(func() { 2048 pool.Close() 2049 }) 2050 2051 JustBeforeEach(func() { 2052 fakeGlobalSecrets = new(credsfakes.FakeSecrets) 2053 fakeGlobalSecrets.GetStub = func(key string) (interface{}, *time.Time, bool, error) { 2054 if key == "gk" { 2055 return "gv", nil, true, nil 2056 } 2057 return nil, nil, false, nil 2058 } 2059 2060 pvars, err = pipeline.Variables(logger, fakeGlobalSecrets, pool) 2061 Expect(err).NotTo(HaveOccurred()) 2062 }) 2063 2064 It("should get var from pipeline var source", func() { 2065 v, found, err := pvars.Get(vars.Reference{Source: "some-var-source", Path: "pk"}) 2066 Expect(err).NotTo(HaveOccurred()) 2067 Expect(found).To(BeTrue()) 2068 Expect(v.(string)).To(Equal("pv")) 2069 }) 2070 2071 It("should not get pipeline var 'pk' without specifying var_source name", func() { 2072 _, found, err := pvars.Get(vars.Reference{Path: "pk"}) 2073 Expect(err).NotTo(HaveOccurred()) 2074 Expect(found).To(BeFalse()) 2075 }) 2076 2077 It("should not get from global secrets if found in the pipeline var source", func() { 2078 pvars.Get(vars.Reference{Source: "some-var-source", Path: "pk"}) 2079 Expect(fakeGlobalSecrets.GetCallCount()).To(Equal(0)) 2080 }) 2081 2082 It("should get var from global var source", func() { 2083 v, found, err := pvars.Get(vars.Reference{Path: "gk"}) 2084 Expect(err).NotTo(HaveOccurred()) 2085 Expect(found).To(BeTrue()) 2086 Expect(v.(string)).To(Equal("gv")) 2087 }) 2088 2089 It("should not get var 'foo'", func() { 2090 _, found, err := pvars.Get(vars.Reference{Path: "foo"}) 2091 Expect(err).NotTo(HaveOccurred()) 2092 Expect(found).To(BeFalse()) 2093 }) 2094 2095 Context("with the second var_source", func() { 2096 BeforeEach(func() { 2097 pipelineConfig.VarSources = append(pipelineConfig.VarSources, atc.VarSourceConfig{ 2098 Name: "second-var-source", 2099 Type: "dummy", 2100 Config: map[string]interface{}{ 2101 "vars": map[string]interface{}{"pk": "((some-var-source:pk))"}, 2102 }, 2103 }) 2104 2105 var created bool 2106 pipeline, created, err = team.SavePipeline(atc.PipelineRef{Name: "fake-pipeline"}, pipelineConfig, pipeline.ConfigVersion(), false) 2107 Expect(err).ToNot(HaveOccurred()) 2108 Expect(created).To(BeFalse()) 2109 }) 2110 2111 // The second var source is configured with vars that needs to be interpolated 2112 // from "some-var-source". 2113 It("should get pipeline var 'pk' from the second var_source", func() { 2114 v, found, err := pvars.Get(vars.Reference{Source: "second-var-source", Path: "pk"}) 2115 Expect(err).NotTo(HaveOccurred()) 2116 Expect(found).To(BeTrue()) 2117 Expect(v.(string)).To(Equal("pv")) 2118 }) 2119 }) 2120 }) 2121 2122 Describe("SetParentIDs", func() { 2123 It("sets the parent_job_id and parent_build_id fields", func() { 2124 jobID := 123 2125 buildID := 456 2126 Expect(pipeline.SetParentIDs(jobID, buildID)).To(Succeed()) 2127 2128 found, err := pipeline.Reload() 2129 Expect(err).ToNot(HaveOccurred()) 2130 Expect(found).To(BeTrue()) 2131 Expect(pipeline.ParentJobID()).To(Equal(jobID)) 2132 Expect(pipeline.ParentBuildID()).To(Equal(buildID)) 2133 }) 2134 2135 It("returns an error if job or build ID are less than or equal to zero", func() { 2136 err := pipeline.SetParentIDs(0, 0) 2137 Expect(err).To(MatchError("job and build id cannot be negative or zero-value")) 2138 err = pipeline.SetParentIDs(-1, -6) 2139 Expect(err).To(MatchError("job and build id cannot be negative or zero-value")) 2140 }) 2141 2142 Context("pipeline was saved by a newer build", func() { 2143 It("returns ErrSetByNewerBuild", func() { 2144 By("setting the build ID to a high number") 2145 pipeline.SetParentIDs(1, 60) 2146 2147 By("trying to set the build ID to a lower number") 2148 err := pipeline.SetParentIDs(1, 2) 2149 Expect(err).To(MatchError(db.ErrSetByNewerBuild)) 2150 }) 2151 }) 2152 2153 Context("pipeline was previously saved by team.SavePipeline", func() { 2154 It("successfully updates the parent build and job IDs", func() { 2155 By("using the defaultPipeline saved by defaultTeam at the suite level") 2156 Expect(defaultPipeline.ParentJobID()).To(Equal(0), "should be zero if sql value is null") 2157 Expect(defaultPipeline.ParentBuildID()).To(Equal(0), "should be zero if sql value is null") 2158 2159 err := defaultPipeline.SetParentIDs(1, 6) 2160 Expect(err).ToNot(HaveOccurred()) 2161 defaultPipeline.Reload() 2162 Expect(defaultPipeline.ParentJobID()).To(Equal(1), "should be zero if sql value is null") 2163 Expect(defaultPipeline.ParentBuildID()).To(Equal(6), "should be zero if sql value is null") 2164 }) 2165 }) 2166 }) 2167 2168 Context("Config", func() { 2169 It("should return config correctly", func() { 2170 Expect(pipeline.Config()).To(Equal(pipelineConfig)) 2171 }) 2172 }) 2173 }) 2174 2175 func intptr(i int) *int { 2176 return &i 2177 }