github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/db/worker_factory_test.go (about) 1 package db_test 2 3 import ( 4 "time" 5 6 sq "github.com/Masterminds/squirrel" 7 "github.com/pf-qiu/concourse/v6/atc" 8 "github.com/pf-qiu/concourse/v6/atc/db" 9 "github.com/pf-qiu/concourse/v6/atc/db/dbfakes" 10 "github.com/pf-qiu/concourse/v6/atc/db/dbtest" 11 12 . "github.com/onsi/ginkgo" 13 . "github.com/onsi/gomega" 14 ) 15 16 var _ = Describe("WorkerFactory", func() { 17 var ( 18 atcWorker atc.Worker 19 worker db.Worker 20 ) 21 22 BeforeEach(func() { 23 atcWorker = atc.Worker{ 24 GardenAddr: "some-garden-addr", 25 BaggageclaimURL: "some-bc-url", 26 HTTPProxyURL: "some-http-proxy-url", 27 HTTPSProxyURL: "some-https-proxy-url", 28 NoProxy: "some-no-proxy", 29 Ephemeral: true, 30 ActiveContainers: 140, 31 ActiveVolumes: 550, 32 ResourceTypes: []atc.WorkerResourceType{ 33 { 34 Type: "some-resource-type", 35 Image: "some-image", 36 Version: "some-version", 37 Privileged: true, 38 }, 39 { 40 Type: "other-resource-type", 41 Image: "other-image", 42 Version: "other-version", 43 Privileged: false, 44 }, 45 }, 46 Platform: "some-platform", 47 Tags: atc.Tags{"some", "tags"}, 48 Name: "some-name", 49 StartTime: 1565367209, 50 } 51 }) 52 53 Describe("SaveWorker", func() { 54 resourceTypeIDs := func(workerName string) map[string]int { 55 ids := map[string]int{} 56 rows, err := psql.Select("w.id", "b.name"). 57 From("worker_base_resource_types w"). 58 Join("base_resource_types AS b ON w.base_resource_type_id = b.id"). 59 Where(sq.Eq{"w.worker_name": workerName}). 60 RunWith(dbConn). 61 Query() 62 Expect(err).NotTo(HaveOccurred()) 63 for rows.Next() { 64 var id int 65 var name string 66 err = rows.Scan(&id, &name) 67 Expect(err).NotTo(HaveOccurred()) 68 ids[name] = id 69 } 70 return ids 71 } 72 73 Context("when the worker already exists", func() { 74 BeforeEach(func() { 75 var err error 76 worker, err = workerFactory.SaveWorker(atcWorker, 5*time.Minute) 77 Expect(err).NotTo(HaveOccurred()) 78 }) 79 80 It("saves resource types", func() { 81 worker, found, err := workerFactory.GetWorker(atcWorker.Name) 82 Expect(found).To(BeTrue()) 83 Expect(err).NotTo(HaveOccurred()) 84 85 Expect(worker.ResourceTypes()).To(Equal(atcWorker.ResourceTypes)) 86 }) 87 88 It("removes old worker resource type", func() { 89 atcWorker.ResourceTypes = []atc.WorkerResourceType{ 90 { 91 Type: "other-resource-type", 92 Image: "other-image", 93 Version: "other-version", 94 Privileged: false, 95 }, 96 } 97 98 _, err := workerFactory.SaveWorker(atcWorker, 5*time.Minute) 99 Expect(err).NotTo(HaveOccurred()) 100 101 var count int 102 err = psql.Select("count(*)"). 103 From("worker_base_resource_types"). 104 Where(sq.Eq{"worker_name": "some-name"}). 105 RunWith(dbConn). 106 QueryRow().Scan(&count) 107 Expect(err).NotTo(HaveOccurred()) 108 Expect(count).To(Equal(1)) 109 }) 110 111 It("replaces outdated worker resource type image", func() { 112 beforeIDs := resourceTypeIDs("some-name") 113 Expect(len(beforeIDs)).To(Equal(2)) 114 115 atcWorker.ResourceTypes[0].Image = "some-wild-new-image" 116 117 _, err := workerFactory.SaveWorker(atcWorker, 5*time.Minute) 118 Expect(err).NotTo(HaveOccurred()) 119 120 afterIDs := resourceTypeIDs("some-name") 121 Expect(len(afterIDs)).To(Equal(2)) 122 123 Expect(afterIDs).ToNot(Equal(beforeIDs)) 124 125 Expect(beforeIDs["some-resource-type"]).ToNot(Equal(afterIDs["some-resource-type"])) 126 Expect(beforeIDs["other-resource-type"]).To(Equal(afterIDs["other-resource-type"])) 127 }) 128 129 It("replaces outdated worker resource type version", func() { 130 beforeIDs := resourceTypeIDs("some-name") 131 Expect(len(beforeIDs)).To(Equal(2)) 132 133 atcWorker.ResourceTypes[0].Version = "some-wild-new-version" 134 135 _, err := workerFactory.SaveWorker(atcWorker, 5*time.Minute) 136 Expect(err).NotTo(HaveOccurred()) 137 138 afterIDs := resourceTypeIDs("some-name") 139 Expect(len(afterIDs)).To(Equal(2)) 140 141 Expect(afterIDs).ToNot(Equal(beforeIDs)) 142 143 Expect(beforeIDs["some-resource-type"]).ToNot(Equal(afterIDs["some-resource-type"])) 144 Expect(beforeIDs["other-resource-type"]).To(Equal(afterIDs["other-resource-type"])) 145 }) 146 147 Context("when the worker is in stalled state", func() { 148 BeforeEach(func() { 149 _, err := workerFactory.SaveWorker(atcWorker, -5*time.Minute) 150 Expect(err).NotTo(HaveOccurred()) 151 152 _, err = workerLifecycle.StallUnresponsiveWorkers() 153 Expect(err).NotTo(HaveOccurred()) 154 }) 155 156 It("repopulates the garden address", func() { 157 savedWorker, err := workerFactory.SaveWorker(atcWorker, 5*time.Minute) 158 Expect(err).NotTo(HaveOccurred()) 159 Expect(savedWorker.Name()).To(Equal("some-name")) 160 Expect(*savedWorker.GardenAddr()).To(Equal("some-garden-addr")) 161 Expect(savedWorker.State()).To(Equal(db.WorkerStateRunning)) 162 }) 163 }) 164 165 Context("when the worker has a new version", func() { 166 BeforeEach(func() { 167 atcWorker.Version = "1.0.0" 168 }) 169 170 It("updates the version of the worker", func() { 171 savedWorker, err := workerFactory.SaveWorker(atcWorker, 5*time.Minute) 172 Expect(err).NotTo(HaveOccurred()) 173 Expect(worker.Version()).To(BeNil()) 174 Expect(*savedWorker.Version()).To(Equal("1.0.0")) 175 }) 176 }) 177 }) 178 179 Context("no worker with same name exists", func() { 180 BeforeEach(func() { 181 atcWorker.Version = "1.0.0" 182 }) 183 184 It("saves worker", func() { 185 savedWorker, err := workerFactory.SaveWorker(atcWorker, 5*time.Minute) 186 Expect(err).NotTo(HaveOccurred()) 187 Expect(savedWorker.Name()).To(Equal("some-name")) 188 Expect(*savedWorker.GardenAddr()).To(Equal("some-garden-addr")) 189 Expect(savedWorker.State()).To(Equal(db.WorkerStateRunning)) 190 Expect(*savedWorker.Version()).To(Equal("1.0.0")) 191 }) 192 193 It("saves worker resource types as base resource types", func() { 194 _, err := workerFactory.SaveWorker(atcWorker, 5*time.Minute) 195 Expect(err).NotTo(HaveOccurred()) 196 197 var count int 198 err = psql.Select("count(*)"). 199 From("worker_base_resource_types"). 200 Where(sq.Eq{"worker_name": "some-name"}). 201 RunWith(dbConn). 202 QueryRow().Scan(&count) 203 Expect(err).NotTo(HaveOccurred()) 204 Expect(count).To(Equal(2)) 205 }) 206 }) 207 }) 208 209 Describe("GetWorker", func() { 210 Context("when the worker is present", func() { 211 BeforeEach(func() { 212 _, err := workerFactory.SaveWorker(atcWorker, 5*time.Minute) 213 Expect(err).NotTo(HaveOccurred()) 214 }) 215 216 It("finds the worker", func() { 217 foundWorker, found, err := workerFactory.GetWorker("some-name") 218 Expect(err).NotTo(HaveOccurred()) 219 Expect(found).To(BeTrue()) 220 221 Expect(foundWorker.Name()).To(Equal("some-name")) 222 Expect(*foundWorker.GardenAddr()).To(Equal("some-garden-addr")) 223 Expect(foundWorker.State()).To(Equal(db.WorkerStateRunning)) 224 Expect(*foundWorker.BaggageclaimURL()).To(Equal("some-bc-url")) 225 Expect(foundWorker.HTTPProxyURL()).To(Equal("some-http-proxy-url")) 226 Expect(foundWorker.HTTPSProxyURL()).To(Equal("some-https-proxy-url")) 227 Expect(foundWorker.NoProxy()).To(Equal("some-no-proxy")) 228 Expect(foundWorker.Ephemeral()).To(Equal(true)) 229 Expect(foundWorker.ActiveContainers()).To(Equal(140)) 230 Expect(foundWorker.ActiveVolumes()).To(Equal(550)) 231 Expect(foundWorker.ResourceTypes()).To(Equal([]atc.WorkerResourceType{ 232 { 233 Type: "some-resource-type", 234 Image: "some-image", 235 Version: "some-version", 236 Privileged: true, 237 }, 238 { 239 Type: "other-resource-type", 240 Image: "other-image", 241 Version: "other-version", 242 }, 243 })) 244 Expect(foundWorker.Platform()).To(Equal("some-platform")) 245 Expect(foundWorker.Tags()).To(Equal([]string{"some", "tags"})) 246 Expect(foundWorker.StartTime().Unix()).To(Equal(int64(1565367209))) 247 Expect(foundWorker.State()).To(Equal(db.WorkerStateRunning)) 248 }) 249 250 Context("when worker is stalled", func() { 251 BeforeEach(func() { 252 _, err := workerFactory.SaveWorker(atcWorker, -1*time.Minute) 253 Expect(err).NotTo(HaveOccurred()) 254 stalled, err := workerLifecycle.StallUnresponsiveWorkers() 255 Expect(err).NotTo(HaveOccurred()) 256 Expect(stalled).To(ContainElement("some-name")) 257 }) 258 }) 259 }) 260 261 Context("when the worker is not present", func() { 262 It("returns false but no error", func() { 263 foundWorker, found, err := workerFactory.GetWorker("some-name") 264 Expect(err).NotTo(HaveOccurred()) 265 Expect(found).To(BeFalse()) 266 Expect(foundWorker).To(BeNil()) 267 }) 268 }) 269 }) 270 271 Describe("VisibleWorkers", func() { 272 BeforeEach(func() { 273 postgresRunner.Truncate() 274 }) 275 276 Context("when there are public and private workers on multiple teams", func() { 277 BeforeEach(func() { 278 team1, err := teamFactory.CreateTeam(atc.Team{Name: "some-team"}) 279 Expect(err).NotTo(HaveOccurred()) 280 team2, err := teamFactory.CreateTeam(atc.Team{Name: "some-other-team"}) 281 Expect(err).NotTo(HaveOccurred()) 282 team3, err := teamFactory.CreateTeam(atc.Team{Name: "not-this-team"}) 283 Expect(err).NotTo(HaveOccurred()) 284 285 _, err = workerFactory.SaveWorker(atcWorker, 0) 286 Expect(err).NotTo(HaveOccurred()) 287 288 atcWorker.Name = "some-new-worker" 289 atcWorker.GardenAddr = "some-other-garden-addr" 290 atcWorker.BaggageclaimURL = "some-other-bc-url" 291 _, err = team1.SaveWorker(atcWorker, 0) 292 Expect(err).NotTo(HaveOccurred()) 293 294 atcWorker.Name = "some-other-new-worker" 295 atcWorker.GardenAddr = "some-other-other-garden-addr" 296 atcWorker.BaggageclaimURL = "some-other-other-bc-url" 297 _, err = team2.SaveWorker(atcWorker, 0) 298 Expect(err).NotTo(HaveOccurred()) 299 300 atcWorker.Name = "not-this-worker" 301 atcWorker.GardenAddr = "not-this-garden-addr" 302 atcWorker.BaggageclaimURL = "not-this-bc-url" 303 _, err = team3.SaveWorker(atcWorker, 0) 304 Expect(err).NotTo(HaveOccurred()) 305 }) 306 307 It("finds visble workers for the given teams", func() { 308 workers, err := workerFactory.VisibleWorkers([]string{"some-team", "some-other-team"}) 309 Expect(err).NotTo(HaveOccurred()) 310 Expect(len(workers)).To(Equal(3)) 311 312 w1, found, err := workerFactory.GetWorker("some-name") 313 Expect(found).To(BeTrue()) 314 Expect(err).NotTo(HaveOccurred()) 315 316 w2, found, err := workerFactory.GetWorker("some-new-worker") 317 Expect(found).To(BeTrue()) 318 Expect(err).NotTo(HaveOccurred()) 319 320 w3, found, err := workerFactory.GetWorker("some-other-new-worker") 321 Expect(found).To(BeTrue()) 322 Expect(err).NotTo(HaveOccurred()) 323 324 w4, found, err := workerFactory.GetWorker("not-this-worker") 325 Expect(found).To(BeTrue()) 326 Expect(err).NotTo(HaveOccurred()) 327 328 Expect(workers).To(ConsistOf(w1, w2, w3)) 329 Expect(workers).NotTo(ContainElement(w4)) 330 }) 331 }) 332 333 Context("when there are no workers", func() { 334 It("returns an error", func() { 335 workers, err := workerFactory.VisibleWorkers([]string{"some-team"}) 336 Expect(err).NotTo(HaveOccurred()) 337 Expect(workers).To(BeEmpty()) 338 }) 339 }) 340 }) 341 342 Describe("Workers", func() { 343 BeforeEach(func() { 344 postgresRunner.Truncate() 345 }) 346 347 Context("when there are workers", func() { 348 BeforeEach(func() { 349 _, err := workerFactory.SaveWorker(atcWorker, 0) 350 Expect(err).NotTo(HaveOccurred()) 351 352 atcWorker.Name = "some-new-worker" 353 atcWorker.GardenAddr = "some-other-garden-addr" 354 atcWorker.BaggageclaimURL = "some-other-bc-url" 355 _, err = workerFactory.SaveWorker(atcWorker, 0) 356 Expect(err).NotTo(HaveOccurred()) 357 }) 358 359 It("finds them without error", func() { 360 workers, err := workerFactory.Workers() 361 Expect(err).NotTo(HaveOccurred()) 362 Expect(len(workers)).To(Equal(2)) 363 364 strptr := func(s string) *string { 365 return &s 366 } 367 368 Expect(workers).To(ConsistOf( 369 And( 370 WithTransform((db.Worker).Name, Equal("some-name")), 371 WithTransform((db.Worker).GardenAddr, Equal(strptr("some-garden-addr"))), 372 WithTransform((db.Worker).BaggageclaimURL, Equal(strptr("some-bc-url"))), 373 ), 374 And( 375 WithTransform((db.Worker).Name, Equal("some-new-worker")), 376 WithTransform((db.Worker).GardenAddr, Equal(strptr("some-other-garden-addr"))), 377 WithTransform((db.Worker).BaggageclaimURL, Equal(strptr("some-other-bc-url"))), 378 ), 379 )) 380 }) 381 }) 382 383 Context("when there are no workers", func() { 384 It("returns an error", func() { 385 workers, err := workerFactory.Workers() 386 Expect(err).NotTo(HaveOccurred()) 387 Expect(workers).To(BeEmpty()) 388 }) 389 }) 390 }) 391 392 Describe("HeartbeatWorker", func() { 393 var ( 394 ttl time.Duration 395 epsilon time.Duration 396 activeContainers int 397 activeVolumes int 398 ) 399 400 BeforeEach(func() { 401 ttl = 5 * time.Minute 402 epsilon = 30 * time.Second 403 activeContainers = 0 404 activeVolumes = 0 405 406 atcWorker.ActiveContainers = activeContainers 407 atcWorker.ActiveVolumes = activeVolumes 408 }) 409 410 Context("when the worker is present", func() { 411 JustBeforeEach(func() { 412 _, err := workerFactory.SaveWorker(atcWorker, 1*time.Second) 413 Expect(err).NotTo(HaveOccurred()) 414 }) 415 416 It("updates the expires field, and the number of active containers and volumes", func() { 417 atcWorker.ActiveContainers = 1 418 atcWorker.ActiveVolumes = 3 419 420 now := time.Now() 421 By("current time") 422 By(now.String()) 423 later := now.Add(ttl) 424 By("later time") 425 By(later.String()) 426 By("found worker expiry") 427 foundWorker, err := workerFactory.HeartbeatWorker(atcWorker, ttl) 428 Expect(err).NotTo(HaveOccurred()) 429 By(foundWorker.ExpiresAt().String()) 430 431 Expect(foundWorker.Name()).To(Equal(atcWorker.Name)) 432 Expect(foundWorker.ExpiresAt()).To(BeTemporally("~", later, epsilon)) 433 Expect(foundWorker.ActiveContainers()).To(And(Not(Equal(activeContainers)), Equal(1))) 434 Expect(foundWorker.ActiveVolumes()).To(And(Not(Equal(activeVolumes)), Equal(3))) 435 Expect(*foundWorker.GardenAddr()).To(Equal("some-garden-addr")) 436 Expect(*foundWorker.BaggageclaimURL()).To(Equal("some-bc-url")) 437 }) 438 439 Context("when the current state is landing", func() { 440 BeforeEach(func() { 441 atcWorker.State = string(db.WorkerStateLanding) 442 }) 443 444 It("keeps the state as landing", func() { 445 foundWorker, err := workerFactory.HeartbeatWorker(atcWorker, ttl) 446 Expect(err).NotTo(HaveOccurred()) 447 448 Expect(foundWorker.State()).To(Equal(db.WorkerStateLanding)) 449 }) 450 }) 451 452 Context("when the current state is retiring", func() { 453 BeforeEach(func() { 454 atcWorker.State = string(db.WorkerStateRetiring) 455 }) 456 457 It("keeps the state as retiring", func() { 458 foundWorker, err := workerFactory.HeartbeatWorker(atcWorker, ttl) 459 Expect(err).NotTo(HaveOccurred()) 460 461 Expect(foundWorker.State()).To(Equal(db.WorkerStateRetiring)) 462 }) 463 }) 464 465 Context("when the current state is running", func() { 466 BeforeEach(func() { 467 atcWorker.State = string(db.WorkerStateRunning) 468 }) 469 470 It("keeps the state as running", func() { 471 foundWorker, err := workerFactory.HeartbeatWorker(atcWorker, ttl) 472 Expect(err).NotTo(HaveOccurred()) 473 474 Expect(foundWorker.State()).To(Equal(db.WorkerStateRunning)) 475 }) 476 }) 477 478 Context("when the current state is stalled", func() { 479 var ( 480 unresponsiveWorker db.Worker 481 err error 482 ) 483 484 JustBeforeEach(func() { 485 unresponsiveWorker, err = workerFactory.SaveWorker(atcWorker, -5*time.Minute) 486 Expect(err).NotTo(HaveOccurred()) 487 488 _, err = workerLifecycle.StallUnresponsiveWorkers() 489 Expect(err).NotTo(HaveOccurred()) 490 }) 491 492 It("sets the state as running", func() { 493 stalledWorker, found, err := workerFactory.GetWorker(unresponsiveWorker.Name()) 494 Expect(err).NotTo(HaveOccurred()) 495 Expect(found).To(BeTrue()) 496 497 Expect(stalledWorker.State()).To(Equal(db.WorkerStateStalled)) 498 499 foundWorker, err := workerFactory.HeartbeatWorker(atcWorker, ttl) 500 Expect(err).NotTo(HaveOccurred()) 501 502 Expect(foundWorker.State()).To(Equal(db.WorkerStateRunning)) 503 }) 504 }) 505 }) 506 507 Context("when the worker is not present", func() { 508 It("returns an error", func() { 509 foundWorker, err := workerFactory.HeartbeatWorker(atcWorker, ttl) 510 Expect(err).To(HaveOccurred()) 511 Expect(err).To(Equal(db.ErrWorkerNotPresent)) 512 Expect(foundWorker).To(BeNil()) 513 }) 514 }) 515 }) 516 517 Describe("FindWorkerForContainerByOwner", func() { 518 var ( 519 containerMetadata db.ContainerMetadata 520 build db.Build 521 fakeOwner *dbfakes.FakeContainerOwner 522 otherFakeOwner *dbfakes.FakeContainerOwner 523 ) 524 525 BeforeEach(func() { 526 var err error 527 containerMetadata = db.ContainerMetadata{ 528 Type: "task", 529 StepName: "some-task", 530 } 531 build, err = defaultTeam.CreateOneOffBuild() 532 Expect(err).ToNot(HaveOccurred()) 533 534 fakeOwner = new(dbfakes.FakeContainerOwner) 535 fakeOwner.FindReturns(sq.Eq{ 536 "build_id": build.ID(), 537 "plan_id": "simple-plan", 538 "team_id": 1, 539 }, true, nil) 540 fakeOwner.CreateReturns(map[string]interface{}{ 541 "build_id": build.ID(), 542 "plan_id": "simple-plan", 543 "team_id": 1, 544 }, nil) 545 546 otherFakeOwner = new(dbfakes.FakeContainerOwner) 547 otherFakeOwner.FindReturns(sq.Eq{ 548 "build_id": build.ID(), 549 "plan_id": "simple-plan", 550 "team_id": 2, 551 }, true, nil) 552 otherFakeOwner.CreateReturns(map[string]interface{}{ 553 "build_id": build.ID(), 554 "plan_id": "simple-plan", 555 "team_id": 2, 556 }, nil) 557 }) 558 559 Context("when there are check containers", func() { 560 Context("when there are multiple of the same containers on the global, team and tagged worker", func() { 561 var ( 562 scenario *dbtest.Scenario 563 ) 564 565 BeforeEach(func() { 566 scenario = dbtest.Setup( 567 builder.WithPipeline(atc.Config{ 568 Resources: atc.ResourceConfigs{ 569 { 570 Name: "some-resource", 571 Type: "some-base-resource-type", 572 Source: atc.Source{ 573 "some": "source", 574 }, 575 }, 576 }, 577 }), 578 builder.WithWorker(atc.Worker{ 579 ResourceTypes: []atc.WorkerResourceType{defaultWorkerResourceType}, 580 GardenAddr: "some-tagged-garden-addr", 581 BaggageclaimURL: "some-tagged-bc-url", 582 Name: "some-tagged-name", 583 Tags: []string{"some-tag"}, 584 }), 585 builder.WithWorker(atc.Worker{ 586 ResourceTypes: []atc.WorkerResourceType{defaultWorkerResourceType}, 587 GardenAddr: "some-team-garden-addr", 588 BaggageclaimURL: "some-team-bc-url", 589 Name: "some-team-name", 590 Team: "default-team", 591 }), 592 builder.WithWorker(atc.Worker{ 593 ResourceTypes: []atc.WorkerResourceType{defaultWorkerResourceType}, 594 GardenAddr: "some-other-garden-addr", 595 BaggageclaimURL: "some-other-bc-url", 596 Name: "some-other-name", 597 }), 598 builder.WithResourceVersions( 599 "some-resource", 600 ), 601 builder.WithCheckContainer( 602 "some-resource", 603 "some-other-name", 604 ), 605 builder.WithCheckContainer( 606 "some-resource", 607 "some-tagged-name", 608 ), 609 builder.WithCheckContainer( 610 "some-resource", 611 "some-team-name", 612 ), 613 ) 614 }) 615 616 It("should find all the workers that have the same container", func() { 617 resource, found, err := scenario.Pipeline.Resource("some-resource") 618 Expect(err).ToNot(HaveOccurred()) 619 Expect(found).To(BeTrue(), "resource '%s' not found", "some-resource") 620 621 rc, found, err := resourceConfigFactory.FindResourceConfigByID(resource.ResourceConfigID()) 622 Expect(err).ToNot(HaveOccurred()) 623 Expect(found).To(BeTrue(), "resource config '%s' not found", rc.ID()) 624 625 owner := db.NewResourceConfigCheckSessionContainerOwner( 626 rc.ID(), 627 rc.OriginBaseResourceType().ID, 628 db.ContainerOwnerExpiries{ 629 Min: 5 * time.Minute, 630 Max: 5 * time.Minute, 631 }, 632 ) 633 634 workers, err := workerFactory.FindWorkersForContainerByOwner(owner) 635 Expect(err).ToNot(HaveOccurred()) 636 637 var workerNames []string 638 for _, w := range workers { 639 workerNames = append(workerNames, w.Name()) 640 } 641 642 Expect(workerNames).To(ConsistOf([]string{"some-other-name", "some-tagged-name", "some-team-name"})) 643 }) 644 }) 645 }) 646 647 Context("when there are build containers", func() { 648 Context("when there is a creating container", func() { 649 BeforeEach(func() { 650 _, err := defaultWorker.CreateContainer(fakeOwner, containerMetadata) 651 Expect(err).ToNot(HaveOccurred()) 652 }) 653 654 It("returns it", func() { 655 workers, err := workerFactory.FindWorkersForContainerByOwner(fakeOwner) 656 Expect(err).ToNot(HaveOccurred()) 657 Expect(workers).To(HaveLen(1)) 658 Expect(workers[0].Name()).To(Equal(defaultWorker.Name())) 659 }) 660 661 It("does not find container for another team", func() { 662 workers, err := workerFactory.FindWorkersForContainerByOwner(otherFakeOwner) 663 Expect(err).ToNot(HaveOccurred()) 664 Expect(workers).To(HaveLen(0)) 665 }) 666 }) 667 668 Context("when there is a created container", func() { 669 BeforeEach(func() { 670 creatingContainer, err := defaultWorker.CreateContainer(fakeOwner, containerMetadata) 671 Expect(err).ToNot(HaveOccurred()) 672 673 _, err = creatingContainer.Created() 674 Expect(err).ToNot(HaveOccurred()) 675 }) 676 677 It("returns it", func() { 678 workers, err := workerFactory.FindWorkersForContainerByOwner(fakeOwner) 679 Expect(err).ToNot(HaveOccurred()) 680 Expect(workers).To(HaveLen(1)) 681 Expect(workers[0].Name()).To(Equal(defaultWorker.Name())) 682 }) 683 684 It("does not find container for another team", func() { 685 workers, err := workerFactory.FindWorkersForContainerByOwner(otherFakeOwner) 686 Expect(err).ToNot(HaveOccurred()) 687 Expect(workers).To(HaveLen(0)) 688 }) 689 }) 690 691 Context("when there is no container", func() { 692 It("returns nil", func() { 693 bogusOwner := new(dbfakes.FakeContainerOwner) 694 bogusOwner.FindReturns(sq.Eq{ 695 "build_id": build.ID() + 1, 696 "plan_id": "how-could-this-happen-to-me", 697 "team_id": 1, 698 }, true, nil) 699 bogusOwner.CreateReturns(map[string]interface{}{ 700 "build_id": build.ID() + 1, 701 "plan_id": "how-could-this-happen-to-me", 702 "team_id": 1, 703 }, nil) 704 705 workers, err := workerFactory.FindWorkersForContainerByOwner(bogusOwner) 706 Expect(err).ToNot(HaveOccurred()) 707 Expect(workers).To(HaveLen(0)) 708 }) 709 }) 710 }) 711 }) 712 713 Describe("BuildContainersCountPerWorker", func() { 714 var ( 715 fakeOwner *dbfakes.FakeContainerOwner 716 otherFakeOwner *dbfakes.FakeContainerOwner 717 build db.Build 718 ) 719 720 BeforeEach(func() { 721 var err error 722 723 build, err = defaultTeam.CreateOneOffBuild() 724 Expect(err).ToNot(HaveOccurred()) 725 726 worker, err = workerFactory.SaveWorker(atcWorker, 5*time.Minute) 727 Expect(err).ToNot(HaveOccurred()) 728 729 fakeOwner = new(dbfakes.FakeContainerOwner) 730 fakeOwner.FindReturns(sq.Eq{ 731 "build_id": build.ID(), 732 "plan_id": "simple-plan", 733 "team_id": 1, 734 }, true, nil) 735 fakeOwner.CreateReturns(map[string]interface{}{ 736 "build_id": build.ID(), 737 "plan_id": "simple-plan", 738 "team_id": 1, 739 }, nil) 740 741 otherFakeOwner = new(dbfakes.FakeContainerOwner) 742 otherFakeOwner.FindReturns(sq.Eq{ 743 "build_id": nil, 744 "plan_id": "simple-plan", 745 "team_id": 1, 746 }, true, nil) 747 otherFakeOwner.CreateReturns(map[string]interface{}{ 748 "build_id": nil, 749 "plan_id": "simple-plan", 750 "team_id": 1, 751 }, nil) 752 753 creatingContainer, err := defaultWorker.CreateContainer(fakeOwner, db.ContainerMetadata{ 754 Type: "task", 755 StepName: "some-task", 756 }) 757 Expect(err).ToNot(HaveOccurred()) 758 759 _, err = creatingContainer.Created() 760 Expect(err).ToNot(HaveOccurred()) 761 762 _, err = defaultWorker.CreateContainer(otherFakeOwner, db.ContainerMetadata{ 763 Type: "check", 764 }) 765 Expect(err).ToNot(HaveOccurred()) 766 767 _, err = worker.CreateContainer(fakeOwner, db.ContainerMetadata{ 768 Type: "task", 769 StepName: "other-task", 770 }) 771 Expect(err).ToNot(HaveOccurred()) 772 773 _, err = worker.CreateContainer(otherFakeOwner, db.ContainerMetadata{ 774 Type: "check", 775 }) 776 Expect(err).ToNot(HaveOccurred()) 777 }) 778 779 It("returns a map of worker to number of active build containers", func() { 780 containersCountByWorker, err := workerFactory.BuildContainersCountPerWorker() 781 Expect(err).ToNot(HaveOccurred()) 782 783 Expect(containersCountByWorker).To(HaveLen(2)) 784 Expect(containersCountByWorker[defaultWorker.Name()]).To(Equal(1)) 785 Expect(containersCountByWorker[worker.Name()]).To(Equal(1)) 786 }) 787 }) 788 })