// Release releases the created container for either SuccessfulStepTTL or // FailedStepTTL. func (step *PutStep) Release() { if step.resource == nil { return } if step.succeeded { step.resource.Release(worker.FinalTTL(SuccessfulStepTTL)) } else { step.resource.Release(worker.FinalTTL(FailedStepTTL)) } }
// Release releases the created container for either the configured // containerSuccessTTL or containerFailureTTL. func (step *TaskStep) Release() { if step.container == nil { return } if step.exitStatus == 0 { step.container.Release(worker.FinalTTL(step.containerSuccessTTL)) } else { step.container.Release(worker.FinalTTL(step.containerFailureTTL)) } }
// Release releases the created container for either SuccessfulStepTTL or // FailedStepTTL. func (step *TaskStep) Release() { if step.container == nil { return } if step.exitStatus == 0 { step.container.Release(worker.FinalTTL(SuccessfulStepTTL)) } else { step.container.Release(worker.FinalTTL(FailedStepTTL)) } }
// Release releases the created container for either the configured // containerSuccessTTL or containerFailureTTL. func (step *PutStep) Release() { if step.resource == nil { return } if step.succeeded { step.resource.Release(worker.FinalTTL(step.containerSuccessTTL)) } else { step.resource.Release(worker.FinalTTL(step.containerFailureTTL)) } }
func selectLowestAlphabeticalVolume(logger lager.Logger, volumes []worker.Volume) worker.Volume { var lowestVolume worker.Volume for _, v := range volumes { if lowestVolume == nil { lowestVolume = v } else if v.Handle() < lowestVolume.Handle() { lowestVolume = v } } for _, v := range volumes { if v != lowestVolume { v.Release(worker.FinalTTL(reapExtraVolumeTTL)) } } return lowestVolume }
}) It("calls the Initializing method on the delegate", func() { Expect(<-callCountDuringInit).To(Equal(1)) }) }) Describe("releasing", func() { It("releases the resource with a ttl of 5 minutes", func() { <-process.Wait() Expect(fakeResource.ReleaseCallCount()).To(BeZero()) step.Release() Expect(fakeResource.ReleaseCallCount()).To(Equal(1)) Expect(fakeResource.ReleaseArgsForCall(0)).To(Equal(worker.FinalTTL(5 * time.Minute))) }) }) Describe("signalling", func() { var receivedSignals <-chan os.Signal BeforeEach(func() { sigs := make(chan os.Signal) receivedSignals = sigs fakeVersionedSource.RunStub = func(signals <-chan os.Signal, ready chan<- struct{}) error { close(ready) sigs <- <-signals return nil }
bVolume = new(bfakes.FakeVolume) bVolume.HandleReturns("b") }) Context("with a, b order", func() { BeforeEach(func() { fakeBaggageclaimClient.ListVolumesReturns([]baggageclaim.Volume{aVolume, bVolume}, nil) }) It("selects the volume based on the lowest alphabetical name", func() { Expect(foundVolume).To(Equal(aVolume)) Expect(found).To(BeTrue()) Expect(aVolume.SetTTLCallCount()).To(Equal(0)) Expect(bVolume.ReleaseCallCount()).To(Equal(1)) Expect(bVolume.ReleaseArgsForCall(0)).To(Equal(worker.FinalTTL(time.Minute))) }) }) Context("with b, a order", func() { BeforeEach(func() { fakeBaggageclaimClient.ListVolumesReturns([]baggageclaim.Volume{bVolume, aVolume}, nil) }) It("selects the volume based on the lowest alphabetical name", func() { Expect(foundVolume).To(Equal(aVolume)) Expect(found).To(BeTrue()) Expect(aVolume.SetTTLCallCount()).To(Equal(0)) Expect(bVolume.ReleaseCallCount()).To(Equal(1)) Expect(bVolume.ReleaseArgsForCall(0)).To(Equal(worker.FinalTTL(time.Minute)))
Expect(fakePipelineDB.GetJobFinishedAndNextBuildArgsForCall(0)).To(Equal("my-precious-job")) Expect(fakeBaggageCollectorDB.GetImageVolumeIdentifiersByBuildIDCallCount()).To(Equal(1)) Expect(fakeBaggageCollectorDB.GetImageVolumeIdentifiersByBuildIDArgsForCall(0)).To(Equal(2)) Expect(fakeBaggageCollectorDB.GetVolumesCallCount()).To(Equal(1)) Expect(fakeWorkerClient.GetWorkerCallCount()).To(Equal(3)) Expect(workerA.VolumeManagerCallCount()).To(Equal(0)) Expect(workerB.VolumeManagerCallCount()).To(Equal(1)) Expect(workerC.VolumeManagerCallCount()).To(Equal(1)) var handle string Expect(workerBBaggageClaimClient.LookupVolumeCallCount()).To(Equal(1)) _, handle = workerBBaggageClaimClient.LookupVolumeArgsForCall(0) Expect(handle).To(Equal("docker-volume-handle")) Expect(dockerVolume.ReleaseCallCount()).To(Equal(1)) Expect(dockerVolume.ReleaseArgsForCall(0)).To(Equal(worker.FinalTTL(expectedLatestVersionTTL))) Expect(workerCBaggageClaimClient.LookupVolumeCallCount()).To(Equal(1)) _, handle = workerCBaggageClaimClient.LookupVolumeArgsForCall(0) Expect(handle).To(Equal("crossed-wires-volume-handle")) Expect(crossedWiresVolume.ReleaseCallCount()).To(Equal(1)) Expect(crossedWiresVolume.ReleaseArgsForCall(0)).To(Equal(worker.FinalTTL(expectedOldVersionTTL))) Expect(fakeBaggageCollectorDB.SetVolumeTTLCallCount()).To(Equal(2)) type setVolumeTTLArgs struct { Handle string TTL time.Duration } expectedSetVolumeTTLArgs := []setVolumeTTLArgs{
It("sets the ttl of each volume used in a one-off build to at least 24 hours", func() { err := baggageCollector.Collect() Expect(err).NotTo(HaveOccurred()) Expect(fakeBaggageCollectorDB.GetAllPipelinesCallCount()).To(Equal(1)) Expect(fakePipelineDBFactory.BuildCallCount()).To(Equal(1)) Expect(fakePipelineDBFactory.BuildArgsForCall(0)).To(Equal(savedPipeline)) Expect(fakePipelineDB.GetJobFinishedAndNextBuildCallCount()).To(Equal(1)) Expect(fakePipelineDB.GetJobFinishedAndNextBuildArgsForCall(0)).To(Equal("my-precious-job")) Expect(fakeBaggageCollectorDB.GetImageVolumeIdentifiersByBuildIDCallCount()).To(Equal(1)) Expect(fakeBaggageCollectorDB.GetImageVolumeIdentifiersByBuildIDArgsForCall(0)).To(Equal(2)) Expect(fakeBaggageCollectorDB.GetVolumesForOneOffBuildImageResourcesCallCount()).To(Equal(1)) Expect(fakeBaggageCollectorDB.GetVolumesCallCount()).To(Equal(1)) Expect(fakeWorkerClient.GetWorkerCallCount()).To(Equal(2)) Expect(worker1.VolumeManagerCallCount()).To(Equal(0)) Expect(worker2.VolumeManagerCallCount()).To(Equal(1)) Expect(baggageClaimClient2.LookupVolumeCallCount()).To(Equal(1)) _, handle := baggageClaimClient2.LookupVolumeArgsForCall(0) Expect(handle).To(Equal("volume2")) Expect(volume2.ReleaseCallCount()).To(Equal(1)) Expect(volume2.ReleaseArgsForCall(0)).To(Equal(worker.FinalTTL(expectedLatestVersionTTL))) Expect(fakeBaggageCollectorDB.SetVolumeTTLCallCount()).To(Equal(1)) handle, ttl := fakeBaggageCollectorDB.SetVolumeTTLArgsForCall(0) Expect(handle).To(Equal("volume2")) Expect(ttl).To(Equal(expectedLatestVersionTTL)) }) })
import ( "time" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" . "github.com/concourse/atc/resource" "github.com/concourse/atc/worker" bfakes "github.com/concourse/baggageclaim/fakes" ) var _ = Describe("Resource", func() { Describe("Release", func() { It("releases the container", func() { resource.Release(worker.FinalTTL(time.Hour)) Expect(fakeContainer.ReleaseCallCount()).To(Equal(1)) Expect(fakeContainer.ReleaseArgsForCall(0)).To(Equal(worker.FinalTTL(time.Hour))) }) }) Describe("CacheVolume", func() { Context("when the container has a volume mount for /tmp/build/get", func() { var vol1 *bfakes.FakeVolume var vol2 *bfakes.FakeVolume BeforeEach(func() { vol1 = new(bfakes.FakeVolume) vol2 = new(bfakes.FakeVolume) fakeContainer.VolumeMountsReturns([]worker.VolumeMount{
Expect(actualTTL).To(Equal(expectedTTL2)) Eventually(fakeDB.SetVolumeTTLCallCount).Should(Equal(2)) actualHandle, actualTTL = fakeDB.SetVolumeTTLArgsForCall(1) Expect(actualHandle).To(Equal(vol.Handle())) Expect(actualTTL).To(Equal(expectedTTL2)) By("being resiliant to db errors") fakeDB.GetVolumeTTLReturns(0, errors.New("disaster")) fakeClock.Increment(30 * time.Second) Eventually(fakeVolume.SetTTLCallCount).Should(Equal(3)) actualTTL = fakeVolume.SetTTLArgsForCall(2) Expect(actualTTL).To(Equal(expectedTTL2)) By("releasing the volume with a final ttl") vol.Release(worker.FinalTTL(2 * time.Second)) Eventually(fakeVolume.SetTTLCallCount).Should(Equal(4)) actualTTL = fakeVolume.SetTTLArgsForCall(3) Expect(actualTTL).To(Equal(2 * time.Second)) Eventually(fakeDB.SetVolumeTTLCallCount).Should(Equal(4)) actualHandle, actualTTL = fakeDB.SetVolumeTTLArgsForCall(3) Expect(actualHandle).To(Equal(vol.Handle())) Expect(actualTTL).To(Equal(2 * time.Second)) }) It("is resiliant to errors while heartbeating", func() { By("using the baggage claim volumes ttl if the initial db lookup fails") fakeVolume.ExpirationReturns(expectedTTL, time.Now(), nil) fakeDB.GetVolumeTTLReturns(0, errors.New("disaster")) _, err := volumeFactory.Build(logger, fakeVolume)
func (bc *baggageCollector) expireVolumes(latestVersions hashedVersionSet) error { volumesToExpire, err := bc.getSortedVolumes() seenVolumeIdentifierAndWorkerNameCombos := volumeIdentifierAndWorkerNameSet{} if err != nil { bc.logger.Error("could-not-get-volume-data", err) return err } for _, volumeToExpire := range volumesToExpire { version, _ := json.Marshal(volumeToExpire.ResourceVersion) hashKey := string(version) + volumeToExpire.ResourceHash var ttlForVol time.Duration volumeIdentifierAndWorkerNameCombo := hashKey + volumeToExpire.WorkerName if contains(seenVolumeIdentifierAndWorkerNameCombos, volumeIdentifierAndWorkerNameCombo) { ttlForVol = bc.oldResourceGracePeriod } else { seenVolumeIdentifierAndWorkerNameCombos[volumeIdentifierAndWorkerNameCombo] = true ttlForVol = getWithDefault(latestVersions, hashKey, bc.oldResourceGracePeriod) } volumeWorker, err := bc.workerClient.GetWorker(volumeToExpire.WorkerName) if err != nil { bc.logger.Info("could-not-locate-worker", lager.Data{ "error": err.Error(), "worker-id": volumeToExpire.WorkerName, }) bc.db.ReapVolume(volumeToExpire.Handle) continue } if volumeToExpire.TTL == ttlForVol { continue } baggageClaimClient, found := volumeWorker.VolumeManager() if !found { bc.logger.Info("no-volume-manager-on-worker", lager.Data{ "worker-id": volumeToExpire.WorkerName, }) bc.db.ReapVolume(volumeToExpire.Handle) continue } volume, found, err := baggageClaimClient.LookupVolume(bc.logger, volumeToExpire.Handle) if !found || err != nil { var e string if err != nil { e = err.Error() } bc.logger.Info("could-not-locate-volume", lager.Data{ "error": e, "worker-id": volumeToExpire.WorkerName, "handle": volumeToExpire.Handle, }) continue } volume.Release(worker.FinalTTL(ttlForVol)) err = bc.db.SetVolumeTTL(volumeToExpire.Handle, ttlForVol) if err != nil { bc.logger.Error("failed-to-update-ttl-in-db", err) } } return nil }
err = baggageCollector.Collect() Expect(err).NotTo(HaveOccurred()) Expect(fakeBaggageClaimClient.LookupVolumeCallCount()).To(Equal(len(example.expectedTTLs))) var actualHandles []string for i := 0; i < fakeBaggageClaimClient.LookupVolumeCallCount(); i++ { _, actualHandle := fakeBaggageClaimClient.LookupVolumeArgsForCall(i) actualHandles = append(actualHandles, actualHandle) } var expectedHandles []string for handle, expectedTTL := range example.expectedTTLs { Expect(fakeVolumes[handle].ReleaseCallCount()).To(Equal(1)) actualTTL := fakeVolumes[handle].ReleaseArgsForCall(0) Expect(actualTTL).To(Equal(worker.FinalTTL(expectedTTL))) expectedHandles = append(expectedHandles, handle) } Expect(actualHandles).To(ConsistOf(expectedHandles)) Expect(fakeBaggageCollectorDB.SetVolumeTTLCallCount()).To(Equal(len(example.expectedTTLs))) actualHandles = nil for i := 0; i < fakeBaggageCollectorDB.SetVolumeTTLCallCount(); i++ { actualHandle, actualTTL := fakeBaggageCollectorDB.SetVolumeTTLArgsForCall(i) actualHandles = append(actualHandles, actualHandle) Expect(actualTTL).To(Equal(example.expectedTTLs[actualHandle])) } Expect(actualHandles).To(ConsistOf(expectedHandles))
func (bc *baggageCollector) expireVolumes(latestVersions hashedVersionSet) error { volumesToExpire, err := bc.getSortedVolumes() seenResourceCacheIdentifierAndWorkerNameCombos := resourceCacheIdentifierAndWorkerNameSet{} if err != nil { bc.logger.Error("could-not-get-volume-data", err) return err } for _, volumeToExpire := range volumesToExpire { hashKey, isResourceCache := resourceCacheHashKey(volumeToExpire) if !isResourceCache { continue } var ttlForVol time.Duration resourceCacheIdentifierAndWorkerNameCombo := hashKey + volumeToExpire.WorkerName if contains(seenResourceCacheIdentifierAndWorkerNameCombos, resourceCacheIdentifierAndWorkerNameCombo) { ttlForVol = bc.oldResourceGracePeriod } else { seenResourceCacheIdentifierAndWorkerNameCombos[resourceCacheIdentifierAndWorkerNameCombo] = true ttlForVol = getWithDefault(latestVersions, hashKey, bc.oldResourceGracePeriod) } volumeWorker, err := bc.workerClient.GetWorker(volumeToExpire.WorkerName) if err != nil { bc.logger.Info("could-not-locate-worker", lager.Data{ "error": err.Error(), "worker-id": volumeToExpire.WorkerName, }) bc.db.ReapVolume(volumeToExpire.Handle) continue } if volumeToExpire.TTL == ttlForVol { continue } vLogger := bc.logger.Session("volume", lager.Data{ "worker-name": volumeToExpire.WorkerName, "handle": volumeToExpire.Handle, }) volume, found, err := volumeWorker.LookupVolume(bc.logger, volumeToExpire.Handle) if err != nil { vLogger.Error("failed-to-lookup-volume", err) continue } if !found { vLogger.Info("volume-not-found") bc.db.ReapVolume(volumeToExpire.Handle) continue } vLogger.Debug("releasing", lager.Data{ "ttl": ttlForVol, }) volume.Release(worker.FinalTTL(ttlForVol)) } return nil }