github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/db/build_factory_test.go (about) 1 package db_test 2 3 import ( 4 "time" 5 6 "github.com/pf-qiu/concourse/v6/atc" 7 "github.com/pf-qiu/concourse/v6/atc/db" 8 . "github.com/onsi/ginkgo" 9 . "github.com/onsi/ginkgo/extensions/table" 10 . "github.com/onsi/gomega" 11 "github.com/onsi/gomega/types" 12 ) 13 14 var _ = Describe("BuildFactory", func() { 15 var team db.Team 16 17 BeforeEach(func() { 18 var err error 19 team, err = teamFactory.CreateTeam(atc.Team{Name: "some-team"}) 20 Expect(err).ToNot(HaveOccurred()) 21 }) 22 23 Describe("Build", func() { 24 var ( 25 foundBuild db.Build 26 createdBuild db.Build 27 found bool 28 ) 29 30 BeforeEach(func() { 31 var err error 32 createdBuild, err = team.CreateOneOffBuild() 33 Expect(err).ToNot(HaveOccurred()) 34 35 foundBuild, found, err = buildFactory.Build(createdBuild.ID()) 36 Expect(err).ToNot(HaveOccurred()) 37 }) 38 39 It("returns the correct build", func() { 40 Expect(found).To(BeTrue()) 41 Expect(foundBuild).To(Equal(createdBuild)) 42 }) 43 }) 44 45 Describe("MarkNonInterceptibleBuilds", func() { 46 Context("one-off builds", func() { 47 DescribeTable("completed and within grace period", 48 func(status db.BuildStatus, matcher types.GomegaMatcher) { 49 b, err := defaultTeam.CreateOneOffBuild() 50 Expect(err).NotTo(HaveOccurred()) 51 52 var i bool 53 err = b.Finish(status) 54 Expect(err).NotTo(HaveOccurred()) 55 56 err = buildFactory.MarkNonInterceptibleBuilds() 57 Expect(err).NotTo(HaveOccurred()) 58 59 i, err = b.Interceptible() 60 Expect(err).NotTo(HaveOccurred()) 61 Expect(i).To(matcher) 62 }, 63 Entry("succeeded is interceptible", db.BuildStatusSucceeded, BeTrue()), 64 Entry("aborted is interceptible", db.BuildStatusAborted, BeTrue()), 65 Entry("errored is interceptible", db.BuildStatusErrored, BeTrue()), 66 Entry("failed is interceptible", db.BuildStatusFailed, BeTrue()), 67 ) 68 DescribeTable("completed and past the grace period", 69 func(status db.BuildStatus, matcher types.GomegaMatcher) { 70 //set grace period to 0 for this test 71 buildFactory = db.NewBuildFactory(dbConn, lockFactory, 0, 0) 72 b, err := defaultTeam.CreateOneOffBuild() 73 Expect(err).NotTo(HaveOccurred()) 74 75 var i bool 76 err = b.Finish(status) 77 Expect(err).NotTo(HaveOccurred()) 78 79 err = buildFactory.MarkNonInterceptibleBuilds() 80 Expect(err).NotTo(HaveOccurred()) 81 82 i, err = b.Interceptible() 83 Expect(err).NotTo(HaveOccurred()) 84 Expect(i).To(matcher) 85 }, 86 Entry("succeeded is non-interceptible", db.BuildStatusSucceeded, BeFalse()), 87 Entry("aborted is non-interceptible", db.BuildStatusAborted, BeFalse()), 88 Entry("errored is non-interceptible", db.BuildStatusErrored, BeFalse()), 89 Entry("failed is non-interceptible", db.BuildStatusFailed, BeFalse()), 90 ) 91 92 It("non-completed is interceptible", func() { 93 b, err := defaultTeam.CreateOneOffBuild() 94 Expect(err).NotTo(HaveOccurred()) 95 96 var i bool 97 err = buildFactory.MarkNonInterceptibleBuilds() 98 Expect(err).NotTo(HaveOccurred()) 99 i, err = b.Interceptible() 100 Expect(err).NotTo(HaveOccurred()) 101 Expect(i).To(BeTrue()) 102 }) 103 }) 104 105 Context("pipeline builds", func() { 106 107 It("[#139963615] marks builds that aren't the latest as non-interceptible, ", func() { 108 build1, err := defaultJob.CreateBuild() 109 Expect(err).NotTo(HaveOccurred()) 110 111 build2, err := defaultJob.CreateBuild() 112 Expect(err).NotTo(HaveOccurred()) 113 114 err = build1.Finish(db.BuildStatusErrored) 115 Expect(err).NotTo(HaveOccurred()) 116 err = build2.Finish(db.BuildStatusErrored) 117 Expect(err).NotTo(HaveOccurred()) 118 119 p, _, err := defaultTeam.SavePipeline(atc.PipelineRef{Name: "other-pipeline"}, atc.Config{ 120 Jobs: atc.JobConfigs{ 121 { 122 Name: "some-other-job", 123 }, 124 }, 125 }, db.ConfigVersion(0), false) 126 Expect(err).NotTo(HaveOccurred()) 127 128 j, found, err := p.Job("some-other-job") 129 Expect(err).NotTo(HaveOccurred()) 130 Expect(found).To(BeTrue()) 131 132 pb1, err := j.CreateBuild() 133 Expect(err).NotTo(HaveOccurred()) 134 135 pb2, err := j.CreateBuild() 136 Expect(err).NotTo(HaveOccurred()) 137 138 err = pb1.Finish(db.BuildStatusErrored) 139 Expect(err).NotTo(HaveOccurred()) 140 err = pb2.Finish(db.BuildStatusErrored) 141 Expect(err).NotTo(HaveOccurred()) 142 143 err = buildFactory.MarkNonInterceptibleBuilds() 144 Expect(err).NotTo(HaveOccurred()) 145 146 var i bool 147 i, err = build1.Interceptible() 148 Expect(err).NotTo(HaveOccurred()) 149 Expect(i).To(BeFalse()) 150 151 i, err = build2.Interceptible() 152 Expect(err).NotTo(HaveOccurred()) 153 Expect(i).To(BeTrue()) 154 155 i, err = pb1.Interceptible() 156 Expect(err).NotTo(HaveOccurred()) 157 Expect(i).To(BeFalse()) 158 159 i, err = pb2.Interceptible() 160 Expect(err).NotTo(HaveOccurred()) 161 Expect(i).To(BeTrue()) 162 163 }) 164 165 DescribeTable("completed builds", 166 func(status db.BuildStatus, matcher types.GomegaMatcher) { 167 b, err := defaultJob.CreateBuild() 168 Expect(err).NotTo(HaveOccurred()) 169 170 var i bool 171 172 err = b.Finish(status) 173 Expect(err).NotTo(HaveOccurred()) 174 175 err = buildFactory.MarkNonInterceptibleBuilds() 176 Expect(err).NotTo(HaveOccurred()) 177 i, err = b.Interceptible() 178 Expect(err).NotTo(HaveOccurred()) 179 Expect(i).To(matcher) 180 }, 181 Entry("succeeded is non-interceptible", db.BuildStatusSucceeded, BeFalse()), 182 Entry("aborted is interceptible", db.BuildStatusAborted, BeTrue()), 183 Entry("errored is interceptible", db.BuildStatusErrored, BeTrue()), 184 Entry("failed is interceptible", db.BuildStatusFailed, BeTrue()), 185 ) 186 187 It("does not mark non-completed builds", func() { 188 b, err := defaultJob.CreateBuild() 189 Expect(err).NotTo(HaveOccurred()) 190 191 var i bool 192 i, err = b.Interceptible() 193 Expect(err).NotTo(HaveOccurred()) 194 Expect(i).To(BeTrue()) 195 196 err = buildFactory.MarkNonInterceptibleBuilds() 197 Expect(err).NotTo(HaveOccurred()) 198 i, err = b.Interceptible() 199 Expect(err).NotTo(HaveOccurred()) 200 Expect(i).To(BeTrue()) 201 202 _, err = b.Start(atc.Plan{}) 203 Expect(err).NotTo(HaveOccurred()) 204 205 err = buildFactory.MarkNonInterceptibleBuilds() 206 Expect(err).NotTo(HaveOccurred()) 207 i, err = b.Interceptible() 208 Expect(err).NotTo(HaveOccurred()) 209 Expect(i).To(BeTrue()) 210 }) 211 }) 212 Context("GC failed builds", func() { 213 It("marks failed builds non-interceptible after failed-grace-period", func() { 214 buildFactory = db.NewBuildFactory(dbConn, lockFactory, 0, 2*time.Second) // 1 second could create a flaky test 215 build, err := defaultJob.CreateBuild() 216 Expect(err).NotTo(HaveOccurred()) 217 218 err = build.Finish(db.BuildStatusFailed) 219 Expect(err).NotTo(HaveOccurred()) 220 221 err = buildFactory.MarkNonInterceptibleBuilds() 222 Expect(err).NotTo(HaveOccurred()) 223 224 var i bool 225 i, err = build.Interceptible() 226 Expect(err).NotTo(HaveOccurred()) 227 Expect(i).To(BeTrue()) 228 229 time.Sleep(3 * time.Second) // Wait is too long, only second granularity, better method? 230 231 err = buildFactory.MarkNonInterceptibleBuilds() 232 Expect(err).NotTo(HaveOccurred()) 233 234 i, err = build.Interceptible() 235 Expect(err).NotTo(HaveOccurred()) 236 Expect(i).To(BeFalse()) 237 }) 238 }) 239 }) 240 241 Describe("VisibleBuilds", func() { 242 var err error 243 var build1 db.Build 244 var build2 db.Build 245 var build3 db.Build 246 var build4 db.Build 247 var build5 db.Build 248 249 BeforeEach(func() { 250 build1, err = team.CreateOneOffBuild() 251 Expect(err).NotTo(HaveOccurred()) 252 253 config := atc.Config{Jobs: atc.JobConfigs{{Name: "some-job"}}} 254 privatePipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "private-pipeline"}, config, db.ConfigVersion(1), false) 255 Expect(err).NotTo(HaveOccurred()) 256 257 privateJob, found, err := privatePipeline.Job("some-job") 258 Expect(err).NotTo(HaveOccurred()) 259 Expect(found).To(BeTrue()) 260 261 build2, err = privateJob.CreateBuild() 262 Expect(err).NotTo(HaveOccurred()) 263 264 publicPipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "public-pipeline"}, config, db.ConfigVersion(1), false) 265 Expect(err).NotTo(HaveOccurred()) 266 err = publicPipeline.Expose() 267 Expect(err).NotTo(HaveOccurred()) 268 269 publicJob, found, err := publicPipeline.Job("some-job") 270 Expect(err).NotTo(HaveOccurred()) 271 Expect(found).To(BeTrue()) 272 273 build3, err = publicJob.CreateBuild() 274 Expect(err).NotTo(HaveOccurred()) 275 276 otherTeam, err := teamFactory.CreateTeam(atc.Team{Name: "some-other-team"}) 277 Expect(err).NotTo(HaveOccurred()) 278 279 build4, err = otherTeam.CreateOneOffBuild() 280 Expect(err).NotTo(HaveOccurred()) 281 282 build5, err = privateJob.RerunBuild(build2) 283 Expect(err).NotTo(HaveOccurred()) 284 }) 285 286 It("returns visible builds for the given teams", func() { 287 builds, _, err := buildFactory.VisibleBuilds([]string{"some-team"}, db.Page{Limit: 10}) 288 Expect(err).NotTo(HaveOccurred()) 289 290 Expect(builds).To(HaveLen(4)) 291 292 buildIDs := []int{} 293 for _, build := range builds { 294 buildIDs = append(buildIDs, build.ID()) 295 } 296 Expect(buildIDs).To(Equal([]int{build3.ID(), build5.ID(), build2.ID(), build1.ID()})) 297 Expect(builds).NotTo(ContainElement(build4)) 298 }) 299 }) 300 301 Describe("AllBuilds", func() { 302 var err error 303 var build1 db.Build 304 var build2 db.Build 305 var build3 db.Build 306 var build4 db.Build 307 308 BeforeEach(func() { 309 build1, err = team.CreateOneOffBuild() 310 Expect(err).NotTo(HaveOccurred()) 311 312 config := atc.Config{Jobs: atc.JobConfigs{{Name: "some-job"}}} 313 privatePipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "private-pipeline"}, config, db.ConfigVersion(1), false) 314 Expect(err).NotTo(HaveOccurred()) 315 316 privateJob, found, err := privatePipeline.Job("some-job") 317 Expect(err).NotTo(HaveOccurred()) 318 Expect(found).To(BeTrue()) 319 320 build2, err = privateJob.CreateBuild() 321 Expect(err).NotTo(HaveOccurred()) 322 323 publicPipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "public-pipeline"}, config, db.ConfigVersion(1), false) 324 Expect(err).NotTo(HaveOccurred()) 325 err = publicPipeline.Expose() 326 Expect(err).NotTo(HaveOccurred()) 327 328 publicJob, found, err := publicPipeline.Job("some-job") 329 Expect(err).NotTo(HaveOccurred()) 330 Expect(found).To(BeTrue()) 331 332 build3, err = publicJob.CreateBuild() 333 Expect(err).NotTo(HaveOccurred()) 334 335 otherTeam, err := teamFactory.CreateTeam(atc.Team{Name: "some-other-team"}) 336 Expect(err).NotTo(HaveOccurred()) 337 338 build4, err = otherTeam.CreateOneOffBuild() 339 Expect(err).NotTo(HaveOccurred()) 340 }) 341 342 It("returns all builds from all teams private and public pipelines", func() { 343 builds, _, err := buildFactory.AllBuilds(db.Page{Limit: 10}) 344 Expect(err).NotTo(HaveOccurred()) 345 346 Expect(builds).To(HaveLen(4)) 347 Expect(builds).To(ConsistOf(build1, build2, build3, build4)) 348 }) 349 }) 350 351 Describe("PublicBuilds", func() { 352 var publicBuild db.Build 353 354 BeforeEach(func() { 355 _, err := team.CreateOneOffBuild() 356 Expect(err).NotTo(HaveOccurred()) 357 358 config := atc.Config{Jobs: atc.JobConfigs{{Name: "some-job"}}} 359 privatePipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "private-pipeline"}, config, db.ConfigVersion(1), false) 360 Expect(err).NotTo(HaveOccurred()) 361 362 privateJob, found, err := privatePipeline.Job("some-job") 363 Expect(err).NotTo(HaveOccurred()) 364 Expect(found).To(BeTrue()) 365 366 _, err = privateJob.CreateBuild() 367 Expect(err).NotTo(HaveOccurred()) 368 369 publicPipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "public-pipeline"}, config, db.ConfigVersion(1), false) 370 Expect(err).NotTo(HaveOccurred()) 371 err = publicPipeline.Expose() 372 Expect(err).NotTo(HaveOccurred()) 373 374 publicJob, found, err := publicPipeline.Job("some-job") 375 Expect(err).NotTo(HaveOccurred()) 376 Expect(found).To(BeTrue()) 377 378 publicBuild, err = publicJob.CreateBuild() 379 Expect(err).NotTo(HaveOccurred()) 380 }) 381 382 It("returns public builds", func() { 383 builds, _, err := buildFactory.PublicBuilds(db.Page{Limit: 10}) 384 Expect(err).NotTo(HaveOccurred()) 385 386 Expect(builds).To(HaveLen(1)) 387 Expect(builds).To(ConsistOf(publicBuild)) 388 }) 389 }) 390 391 Describe("GetDrainableBuilds", func() { 392 var build2DB, build3DB, build4DB db.Build 393 394 BeforeEach(func() { 395 pipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "other-pipeline"}, atc.Config{ 396 Jobs: atc.JobConfigs{ 397 { 398 Name: "some-job", 399 }, 400 }, 401 }, db.ConfigVersion(0), false) 402 Expect(err).NotTo(HaveOccurred()) 403 404 job, found, err := pipeline.Job("some-job") 405 Expect(err).NotTo(HaveOccurred()) 406 Expect(found).To(BeTrue()) 407 408 _, err = team.CreateOneOffBuild() 409 Expect(err).NotTo(HaveOccurred()) 410 411 build2DB, err = team.CreateOneOffBuild() 412 Expect(err).NotTo(HaveOccurred()) 413 414 build3DB, err = job.CreateBuild() 415 Expect(err).NotTo(HaveOccurred()) 416 417 build4DB, err = job.CreateBuild() 418 Expect(err).NotTo(HaveOccurred()) 419 420 started, err := build2DB.Start(atc.Plan{}) 421 Expect(err).NotTo(HaveOccurred()) 422 Expect(started).To(BeTrue()) 423 424 err = build3DB.Finish("succeeded") 425 Expect(err).NotTo(HaveOccurred()) 426 427 err = build3DB.SetDrained(true) 428 Expect(err).NotTo(HaveOccurred()) 429 430 err = build4DB.Finish("failed") 431 Expect(err).NotTo(HaveOccurred()) 432 }) 433 434 It("returns all builds that have been completed and not drained", func() { 435 builds, err := buildFactory.GetDrainableBuilds() 436 Expect(err).NotTo(HaveOccurred()) 437 438 _, err = build4DB.Reload() 439 Expect(err).NotTo(HaveOccurred()) 440 441 Expect(builds).To(ConsistOf(build4DB)) 442 }) 443 }) 444 445 Describe("GetAllStartedBuilds", func() { 446 var build1DB db.Build 447 var build2DB db.Build 448 449 BeforeEach(func() { 450 pipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "other-pipeline"}, atc.Config{ 451 Jobs: atc.JobConfigs{ 452 { 453 Name: "some-job", 454 }, 455 }, 456 }, db.ConfigVersion(0), false) 457 Expect(err).NotTo(HaveOccurred()) 458 459 job, found, err := pipeline.Job("some-job") 460 Expect(err).NotTo(HaveOccurred()) 461 Expect(found).To(BeTrue()) 462 463 build1DB, err = team.CreateOneOffBuild() 464 Expect(err).NotTo(HaveOccurred()) 465 466 build2DB, err = job.CreateBuild() 467 Expect(err).NotTo(HaveOccurred()) 468 469 _, err = team.CreateOneOffBuild() 470 Expect(err).NotTo(HaveOccurred()) 471 472 started, err := build1DB.Start(atc.Plan{}) 473 Expect(err).NotTo(HaveOccurred()) 474 Expect(started).To(BeTrue()) 475 476 started, err = build2DB.Start(atc.Plan{}) 477 Expect(err).NotTo(HaveOccurred()) 478 Expect(started).To(BeTrue()) 479 }) 480 481 It("returns all builds that have been started, regardless of pipeline", func() { 482 builds, err := buildFactory.GetAllStartedBuilds() 483 Expect(err).NotTo(HaveOccurred()) 484 485 _, err = build1DB.Reload() 486 Expect(err).NotTo(HaveOccurred()) 487 _, err = build2DB.Reload() 488 Expect(err).NotTo(HaveOccurred()) 489 490 Expect(builds).To(ConsistOf(build1DB, build2DB)) 491 }) 492 }) 493 494 Describe("AllBuilds by date", func() { 495 var build1DB db.Build 496 var build2DB db.Build 497 498 BeforeEach(func() { 499 pipeline, _, err := team.SavePipeline(atc.PipelineRef{Name: "other-pipeline"}, atc.Config{ 500 Jobs: atc.JobConfigs{ 501 { 502 Name: "some-job", 503 }, 504 }, 505 }, db.ConfigVersion(0), false) 506 Expect(err).NotTo(HaveOccurred()) 507 508 job, found, err := pipeline.Job("some-job") 509 Expect(err).NotTo(HaveOccurred()) 510 Expect(found).To(BeTrue()) 511 512 build1DB, err = team.CreateOneOffBuild() 513 Expect(err).NotTo(HaveOccurred()) 514 515 build2DB, err = job.CreateBuild() 516 Expect(err).NotTo(HaveOccurred()) 517 518 _, err = team.CreateOneOffBuild() 519 Expect(err).NotTo(HaveOccurred()) 520 521 started, err := build1DB.Start(atc.Plan{}) 522 Expect(err).NotTo(HaveOccurred()) 523 Expect(started).To(BeTrue()) 524 525 started, err = build2DB.Start(atc.Plan{}) 526 Expect(err).NotTo(HaveOccurred()) 527 Expect(started).To(BeTrue()) 528 }) 529 530 It("returns builds started in the given timespan", func() { 531 page := db.Page{ 532 Limit: 10, 533 From: db.NewIntPtr(int(time.Now().Unix() - 10000)), 534 To: db.NewIntPtr(int(time.Now().Unix() + 10)), 535 UseDate: true, 536 } 537 builds, _, err := buildFactory.AllBuilds(page) 538 Expect(err).NotTo(HaveOccurred()) 539 Expect(len(builds)).To(Equal(2)) 540 }) 541 542 Describe("with a future date as Page.From", func() { 543 It("should return nothing", func() { 544 page := db.Page{ 545 Limit: 10, 546 From: db.NewIntPtr(int(time.Now().Unix() + 10)), 547 UseDate: true, 548 } 549 builds, _, err := buildFactory.AllBuilds(page) 550 Expect(err).NotTo(HaveOccurred()) 551 Expect(len(builds)).To(Equal(0)) 552 }) 553 }) 554 555 Describe("with a very old date as Page.To", func() { 556 It("should return nothing", func() { 557 page := db.Page{ 558 Limit: 10, 559 To: db.NewIntPtr(int(time.Now().Unix() - 10000)), 560 UseDate: true, 561 } 562 builds, _, err := buildFactory.AllBuilds(page) 563 Expect(err).NotTo(HaveOccurred()) 564 Expect(len(builds)).To(Equal(0)) 565 }) 566 }) 567 }) 568 })