github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/worker/volume_client_test.go (about)

     1  package worker_test
     2  
     3  import (
     4  	"errors"
     5  	"time"
     6  
     7  	"code.cloudfoundry.org/clock/fakeclock"
     8  	"code.cloudfoundry.org/lager"
     9  	"code.cloudfoundry.org/lager/lagertest"
    10  	"github.com/concourse/baggageclaim"
    11  	"github.com/concourse/baggageclaim/baggageclaimfakes"
    12  	"github.com/pf-qiu/concourse/v6/atc/db"
    13  	"github.com/pf-qiu/concourse/v6/atc/db/dbfakes"
    14  	"github.com/pf-qiu/concourse/v6/atc/db/lock"
    15  	"github.com/pf-qiu/concourse/v6/atc/db/lock/lockfakes"
    16  	"github.com/pf-qiu/concourse/v6/atc/worker"
    17  	"github.com/pf-qiu/concourse/v6/atc/worker/workerfakes"
    18  	. "github.com/onsi/ginkgo"
    19  	. "github.com/onsi/gomega"
    20  )
    21  
    22  var _ = Describe("VolumeClient", func() {
    23  	var (
    24  		fakeLock   *lockfakes.FakeLock
    25  		testLogger *lagertest.TestLogger
    26  
    27  		fakeBaggageclaimClient            *baggageclaimfakes.FakeClient
    28  		fakeLockFactory                   *lockfakes.FakeLockFactory
    29  		fakeDBVolumeRepository            *dbfakes.FakeVolumeRepository
    30  		fakeWorkerBaseResourceTypeFactory *dbfakes.FakeWorkerBaseResourceTypeFactory
    31  		fakeWorkerTaskCacheFactory        *dbfakes.FakeWorkerTaskCacheFactory
    32  		fakeTaskCacheFactory              *dbfakes.FakeTaskCacheFactory
    33  		fakeClock                         *fakeclock.FakeClock
    34  		dbWorker                          *dbfakes.FakeWorker
    35  
    36  		volumeClient worker.VolumeClient
    37  	)
    38  
    39  	BeforeEach(func() {
    40  		fakeBaggageclaimClient = new(baggageclaimfakes.FakeClient)
    41  		fakeLockFactory = new(lockfakes.FakeLockFactory)
    42  		fakeClock = fakeclock.NewFakeClock(time.Unix(123, 456))
    43  		dbWorker = new(dbfakes.FakeWorker)
    44  		dbWorker.NameReturns("some-worker")
    45  
    46  		testLogger = lagertest.NewTestLogger("test")
    47  
    48  		fakeDBVolumeRepository = new(dbfakes.FakeVolumeRepository)
    49  		fakeWorkerBaseResourceTypeFactory = new(dbfakes.FakeWorkerBaseResourceTypeFactory)
    50  		fakeTaskCacheFactory = new(dbfakes.FakeTaskCacheFactory)
    51  		fakeWorkerTaskCacheFactory = new(dbfakes.FakeWorkerTaskCacheFactory)
    52  		fakeLock = new(lockfakes.FakeLock)
    53  
    54  		volumeClient = worker.NewVolumeClient(
    55  			fakeBaggageclaimClient,
    56  			dbWorker,
    57  			fakeClock,
    58  
    59  			fakeLockFactory,
    60  			fakeDBVolumeRepository,
    61  			fakeWorkerBaseResourceTypeFactory,
    62  			fakeTaskCacheFactory,
    63  			fakeWorkerTaskCacheFactory,
    64  		)
    65  	})
    66  
    67  	Describe("FindOrCreateVolumeForContainer", func() {
    68  		var fakeBaggageclaimVolume *baggageclaimfakes.FakeVolume
    69  		var foundOrCreatedVolume worker.Volume
    70  		var foundOrCreatedErr error
    71  		var container db.CreatingContainer
    72  		var fakeCreatingVolume *dbfakes.FakeCreatingVolume
    73  		var volumeStrategy baggageclaim.Strategy
    74  
    75  		BeforeEach(func() {
    76  			fakeBaggageclaimVolume = new(baggageclaimfakes.FakeVolume)
    77  			fakeCreatingVolume = new(dbfakes.FakeCreatingVolume)
    78  			fakeBaggageclaimClient.CreateVolumeReturns(fakeBaggageclaimVolume, nil)
    79  			fakeDBVolumeRepository.CreateContainerVolumeReturns(fakeCreatingVolume, nil)
    80  
    81  			volumeStrategy = baggageclaim.ImportStrategy{
    82  				Path: "/some/path",
    83  			}
    84  		})
    85  
    86  		JustBeforeEach(func() {
    87  			container = new(dbfakes.FakeCreatingContainer)
    88  			foundOrCreatedVolume, foundOrCreatedErr = volumeClient.FindOrCreateVolumeForContainer(
    89  				testLogger,
    90  				worker.VolumeSpec{
    91  					Strategy: volumeStrategy,
    92  				},
    93  				container,
    94  				42,
    95  				"some-mount-path",
    96  			)
    97  		})
    98  
    99  		Context("when volume exists in creating state", func() {
   100  			BeforeEach(func() {
   101  				fakeDBVolumeRepository.FindContainerVolumeReturns(fakeCreatingVolume, nil, nil)
   102  			})
   103  
   104  			Context("when acquiring volume creating lock fails", func() {
   105  				var disaster = errors.New("disaster")
   106  
   107  				BeforeEach(func() {
   108  					fakeLockFactory.AcquireReturns(nil, false, disaster)
   109  				})
   110  
   111  				It("returns error", func() {
   112  					Expect(fakeLockFactory.AcquireCallCount()).To(Equal(1))
   113  					Expect(foundOrCreatedErr).To(Equal(disaster))
   114  				})
   115  			})
   116  
   117  			Context("when it could not acquire creating lock", func() {
   118  				BeforeEach(func() {
   119  					callCount := 0
   120  					fakeLockFactory.AcquireStub = func(logger lager.Logger, lockID lock.LockID) (lock.Lock, bool, error) {
   121  						callCount++
   122  						go fakeClock.WaitForWatcherAndIncrement(time.Second)
   123  
   124  						if callCount < 3 {
   125  							return nil, false, nil
   126  						}
   127  
   128  						return fakeLock, true, nil
   129  					}
   130  				})
   131  
   132  				It("retries to find volume again", func() {
   133  					Expect(fakeLockFactory.AcquireCallCount()).To(Equal(3))
   134  					Expect(fakeDBVolumeRepository.FindContainerVolumeCallCount()).To(Equal(3))
   135  				})
   136  			})
   137  
   138  			Context("when it acquires the lock", func() {
   139  				BeforeEach(func() {
   140  					fakeLockFactory.AcquireReturns(fakeLock, true, nil)
   141  				})
   142  
   143  				Context("when checking for the volume in baggageclaim", func() {
   144  					BeforeEach(func() {
   145  						fakeBaggageclaimClient.LookupVolumeStub = func(lager.Logger, string) (baggageclaim.Volume, bool, error) {
   146  							Expect(fakeLockFactory.AcquireCallCount()).To(Equal(1))
   147  							return nil, false, nil
   148  						}
   149  					})
   150  
   151  					It("does so with the lock held", func() {
   152  						Expect(fakeBaggageclaimClient.LookupVolumeCallCount()).To(Equal(1))
   153  					})
   154  				})
   155  
   156  				Context("when volume exists in baggageclaim", func() {
   157  					BeforeEach(func() {
   158  						fakeBaggageclaimClient.LookupVolumeReturns(fakeBaggageclaimVolume, true, nil)
   159  					})
   160  
   161  					It("returns the volume", func() {
   162  						Expect(foundOrCreatedErr).NotTo(HaveOccurred())
   163  						Expect(foundOrCreatedVolume).NotTo(BeNil())
   164  					})
   165  				})
   166  
   167  				Context("when volume does not exist in baggageclaim", func() {
   168  					BeforeEach(func() {
   169  						fakeBaggageclaimClient.LookupVolumeReturns(nil, false, nil)
   170  					})
   171  
   172  					It("creates volume in baggageclaim", func() {
   173  						Expect(foundOrCreatedErr).NotTo(HaveOccurred())
   174  						Expect(foundOrCreatedVolume).NotTo(BeNil())
   175  						Expect(fakeBaggageclaimClient.CreateVolumeCallCount()).To(Equal(1))
   176  					})
   177  
   178  					Context("when creating the volume in baggageclaim fails", func() {
   179  						BeforeEach(func() {
   180  							fakeBaggageclaimClient.CreateVolumeReturns(nil, errors.New("failed to create volume, oh no"))
   181  						})
   182  
   183  						It("marks the creating volume as failed", func() {
   184  							Expect(fakeCreatingVolume.FailedCallCount()).To(Equal(1))
   185  						})
   186  					})
   187  				})
   188  
   189  				It("releases the lock", func() {
   190  					Expect(fakeLock.ReleaseCallCount()).To(Equal(1))
   191  				})
   192  			})
   193  		})
   194  
   195  		Context("when volume exists in created state", func() {
   196  			BeforeEach(func() {
   197  				fakeCreatedVolume := new(dbfakes.FakeCreatedVolume)
   198  				fakeCreatedVolume.HandleReturns("fake-handle")
   199  				fakeCreatedVolume.WorkerNameReturns("fake-worker")
   200  				fakeDBVolumeRepository.FindContainerVolumeReturns(nil, fakeCreatedVolume, nil)
   201  			})
   202  
   203  			Context("when volume exists in baggageclaim", func() {
   204  				BeforeEach(func() {
   205  					fakeBaggageclaimClient.LookupVolumeReturns(fakeBaggageclaimVolume, true, nil)
   206  				})
   207  
   208  				It("returns the volume", func() {
   209  					Expect(foundOrCreatedErr).NotTo(HaveOccurred())
   210  					Expect(foundOrCreatedVolume).NotTo(BeNil())
   211  				})
   212  			})
   213  
   214  			Context("when volume does not exist in baggageclaim", func() {
   215  				BeforeEach(func() {
   216  					fakeBaggageclaimClient.LookupVolumeReturns(nil, false, nil)
   217  				})
   218  
   219  				It("returns an error", func() {
   220  					Expect(foundOrCreatedErr).To(HaveOccurred())
   221  					Expect(foundOrCreatedErr.Error()).To(ContainSubstring("volume 'fake-handle' disappeared from worker 'fake-worker'"))
   222  				})
   223  			})
   224  		})
   225  
   226  		Context("when volume does not exist in db", func() {
   227  			var fakeCreatedVolume *dbfakes.FakeCreatedVolume
   228  
   229  			BeforeEach(func() {
   230  				fakeDBVolumeRepository.FindContainerVolumeReturns(nil, nil, nil)
   231  				fakeLockFactory.AcquireReturns(fakeLock, true, nil)
   232  				fakeDBVolumeRepository.CreateContainerVolumeReturns(fakeCreatingVolume, nil)
   233  				fakeCreatedVolume = new(dbfakes.FakeCreatedVolume)
   234  				fakeCreatingVolume.CreatedReturns(fakeCreatedVolume, nil)
   235  			})
   236  
   237  			It("acquires the lock", func() {
   238  				Expect(fakeLockFactory.AcquireCallCount()).To(Equal(1))
   239  			})
   240  
   241  			It("creates volume in creating state", func() {
   242  				Expect(fakeDBVolumeRepository.CreateContainerVolumeCallCount()).To(Equal(1))
   243  				actualTeamID, actualWorkerName, actualContainer, actualMountPath := fakeDBVolumeRepository.CreateContainerVolumeArgsForCall(0)
   244  				Expect(actualTeamID).To(Equal(42))
   245  				Expect(actualWorkerName).To(Equal(dbWorker.Name()))
   246  				Expect(actualContainer).To(Equal(container))
   247  				Expect(actualMountPath).To(Equal("some-mount-path"))
   248  			})
   249  
   250  			It("creates volume in baggageclaim", func() {
   251  				Expect(foundOrCreatedErr).NotTo(HaveOccurred())
   252  				Expect(foundOrCreatedVolume).To(Equal(worker.NewVolume(fakeBaggageclaimVolume, fakeCreatedVolume, volumeClient)))
   253  				Expect(fakeBaggageclaimClient.CreateVolumeCallCount()).To(Equal(1))
   254  			})
   255  
   256  			Context("when creating the volume in baggageclaim fails", func() {
   257  				BeforeEach(func() {
   258  					fakeBaggageclaimClient.CreateVolumeReturns(nil, errors.New("failed to create volume, oh no"))
   259  				})
   260  
   261  				It("marks the creating volume for removal", func() {
   262  					Expect(fakeCreatingVolume.FailedCallCount()).To(Equal(1))
   263  				})
   264  			})
   265  		})
   266  	})
   267  
   268  	Describe("FindOrCreateCOWVolumeForContainer", func() {
   269  		var fakeBaggageclaimVolume *baggageclaimfakes.FakeVolume
   270  		var foundOrCreatedVolume worker.Volume
   271  		var foundOrCreatedErr error
   272  		var container db.CreatingContainer
   273  		var fakeCreatingVolume *dbfakes.FakeCreatingVolume
   274  		var fakeCreatedVolume *dbfakes.FakeCreatedVolume
   275  		var volumeStrategy baggageclaim.Strategy
   276  		var parentVolume *workerfakes.FakeVolume
   277  		var fakeParentBCVolume *baggageclaimfakes.FakeVolume
   278  
   279  		BeforeEach(func() {
   280  			parentVolume = new(workerfakes.FakeVolume)
   281  			parentVolume.HandleReturns("fake-parent-handle")
   282  
   283  			fakeParentBCVolume = new(baggageclaimfakes.FakeVolume)
   284  
   285  			volumeStrategy = baggageclaim.COWStrategy{
   286  				Parent: fakeParentBCVolume,
   287  			}
   288  
   289  			fakeCreatingVolume = new(dbfakes.FakeCreatingVolume)
   290  			parentVolume.CreateChildForContainerReturns(fakeCreatingVolume, nil)
   291  
   292  			fakeBaggageclaimVolume = new(baggageclaimfakes.FakeVolume)
   293  			fakeBaggageclaimClient.CreateVolumeReturns(fakeBaggageclaimVolume, nil)
   294  
   295  			fakeCreatedVolume = new(dbfakes.FakeCreatedVolume)
   296  			fakeCreatingVolume.CreatedReturns(fakeCreatedVolume, nil)
   297  		})
   298  
   299  		JustBeforeEach(func() {
   300  			container = new(dbfakes.FakeCreatingContainer)
   301  			foundOrCreatedVolume, foundOrCreatedErr = volumeClient.FindOrCreateCOWVolumeForContainer(
   302  				testLogger,
   303  				worker.VolumeSpec{
   304  					Strategy: volumeStrategy,
   305  				},
   306  				container,
   307  				parentVolume,
   308  				42,
   309  				"some-mount-path",
   310  			)
   311  		})
   312  
   313  		Context("when volume exists in creating state", func() {
   314  			BeforeEach(func() {
   315  				fakeDBVolumeRepository.FindContainerVolumeReturns(fakeCreatingVolume, nil, nil)
   316  			})
   317  
   318  			Context("when acquiring volume creating lock fails", func() {
   319  				var disaster = errors.New("disaster")
   320  
   321  				BeforeEach(func() {
   322  					fakeLockFactory.AcquireReturns(nil, false, disaster)
   323  				})
   324  
   325  				It("returns error", func() {
   326  					Expect(fakeLockFactory.AcquireCallCount()).To(Equal(1))
   327  					Expect(foundOrCreatedErr).To(Equal(disaster))
   328  				})
   329  			})
   330  
   331  			Context("when it could not acquire creating lock", func() {
   332  				BeforeEach(func() {
   333  					callCount := 0
   334  					fakeLockFactory.AcquireStub = func(logger lager.Logger, lockID lock.LockID) (lock.Lock, bool, error) {
   335  						callCount++
   336  						go fakeClock.WaitForWatcherAndIncrement(time.Second)
   337  
   338  						if callCount < 3 {
   339  							return nil, false, nil
   340  						}
   341  
   342  						return fakeLock, true, nil
   343  					}
   344  				})
   345  
   346  				It("retries to find volume again", func() {
   347  					Expect(fakeLockFactory.AcquireCallCount()).To(Equal(3))
   348  					Expect(fakeDBVolumeRepository.FindContainerVolumeCallCount()).To(Equal(3))
   349  				})
   350  			})
   351  
   352  			Context("when it acquires the lock", func() {
   353  				BeforeEach(func() {
   354  					fakeLockFactory.AcquireReturns(fakeLock, true, nil)
   355  				})
   356  
   357  				Context("when volume exists in baggageclaim", func() {
   358  					BeforeEach(func() {
   359  						fakeBaggageclaimClient.LookupVolumeReturns(fakeBaggageclaimVolume, true, nil)
   360  					})
   361  
   362  					It("returns the volume", func() {
   363  						Expect(foundOrCreatedErr).NotTo(HaveOccurred())
   364  						Expect(foundOrCreatedVolume).NotTo(BeNil())
   365  					})
   366  				})
   367  
   368  				Context("when volume does not exist in baggageclaim", func() {
   369  					BeforeEach(func() {
   370  						fakeBaggageclaimClient.LookupVolumeReturns(nil, false, nil)
   371  					})
   372  
   373  					It("creates volume in baggageclaim", func() {
   374  						Expect(foundOrCreatedErr).NotTo(HaveOccurred())
   375  						Expect(foundOrCreatedVolume).NotTo(BeNil())
   376  						Expect(fakeBaggageclaimClient.CreateVolumeCallCount()).To(Equal(1))
   377  					})
   378  				})
   379  
   380  				It("releases the lock", func() {
   381  					Expect(fakeLock.ReleaseCallCount()).To(Equal(1))
   382  				})
   383  			})
   384  		})
   385  
   386  		Context("when volume exists in created state", func() {
   387  			BeforeEach(func() {
   388  				fakeCreatedVolume := new(dbfakes.FakeCreatedVolume)
   389  				fakeCreatedVolume.HandleReturns("fake-handle")
   390  				fakeCreatedVolume.WorkerNameReturns("fake-worker")
   391  				fakeDBVolumeRepository.FindContainerVolumeReturns(nil, fakeCreatedVolume, nil)
   392  			})
   393  
   394  			Context("when volume exists in baggageclaim", func() {
   395  				BeforeEach(func() {
   396  					fakeBaggageclaimClient.LookupVolumeReturns(fakeBaggageclaimVolume, true, nil)
   397  				})
   398  
   399  				It("returns the volume", func() {
   400  					Expect(foundOrCreatedErr).NotTo(HaveOccurred())
   401  					Expect(foundOrCreatedVolume).NotTo(BeNil())
   402  				})
   403  			})
   404  
   405  			Context("when volume does not exist in baggageclaim", func() {
   406  				BeforeEach(func() {
   407  					fakeBaggageclaimClient.LookupVolumeReturns(nil, false, nil)
   408  				})
   409  
   410  				It("returns an error", func() {
   411  					Expect(foundOrCreatedErr).To(HaveOccurred())
   412  					Expect(foundOrCreatedErr.Error()).To(ContainSubstring("volume 'fake-handle' disappeared from worker 'fake-worker'"))
   413  				})
   414  			})
   415  		})
   416  
   417  		Context("when volume does not exist in db", func() {
   418  			BeforeEach(func() {
   419  				fakeDBVolumeRepository.FindContainerVolumeReturns(nil, nil, nil)
   420  				fakeLockFactory.AcquireReturns(fakeLock, true, nil)
   421  			})
   422  
   423  			It("acquires the lock", func() {
   424  				Expect(fakeLockFactory.AcquireCallCount()).To(Equal(1))
   425  			})
   426  
   427  			It("creates volume in creating state with parent volume", func() {
   428  				Expect(parentVolume.CreateChildForContainerCallCount()).To(Equal(1))
   429  				actualContainer, actualMountPath := parentVolume.CreateChildForContainerArgsForCall(0)
   430  				Expect(actualContainer).To(Equal(container))
   431  				Expect(actualMountPath).To(Equal("some-mount-path"))
   432  			})
   433  
   434  			It("creates volume in baggageclaim", func() {
   435  				Expect(foundOrCreatedErr).NotTo(HaveOccurred())
   436  				Expect(foundOrCreatedVolume).To(Equal(worker.NewVolume(fakeBaggageclaimVolume, fakeCreatedVolume, volumeClient)))
   437  				Expect(fakeBaggageclaimClient.CreateVolumeCallCount()).To(Equal(1))
   438  			})
   439  		})
   440  	})
   441  
   442  	Describe("FindOrCreateVolumeForResourceCerts", func() {
   443  		var (
   444  			fakeBaggageclaimVolume *baggageclaimfakes.FakeVolume
   445  			fakeCreatingVolume     *dbfakes.FakeCreatingVolume
   446  			fakeCreatedVolume      *dbfakes.FakeCreatedVolume
   447  			volume                 worker.Volume
   448  			found                  bool
   449  			err                    error
   450  		)
   451  
   452  		BeforeEach(func() {
   453  			fakeBaggageclaimVolume = new(baggageclaimfakes.FakeVolume)
   454  			fakeBaggageclaimVolume.HandleReturns("fake-handle")
   455  
   456  			fakeCreatedVolume = new(dbfakes.FakeCreatedVolume)
   457  			fakeCreatedVolume.HandleReturns("fake-handle")
   458  
   459  			fakeCreatingVolume = new(dbfakes.FakeCreatingVolume)
   460  			fakeCreatingVolume.HandleReturns("fake-handle")
   461  			fakeCreatingVolume.CreatedReturns(fakeCreatedVolume, nil)
   462  
   463  			fakeLockFactory.AcquireReturns(fakeLock, true, nil)
   464  
   465  			certPath := "/some/path/to/a/directory/of/certs"
   466  			dbWorker.ResourceCertsReturns(&db.UsedWorkerResourceCerts{ID: 123}, true, nil)
   467  			dbWorker.CertsPathReturns(&certPath)
   468  
   469  			fakeBaggageclaimClient.LookupVolumeReturns(fakeBaggageclaimVolume, true, nil)
   470  		})
   471  
   472  		JustBeforeEach(func() {
   473  			volume, found, err = volumeClient.FindOrCreateVolumeForResourceCerts(testLogger)
   474  		})
   475  
   476  		Context("when the worker resource certs entry does not exist", func() {
   477  			BeforeEach(func() {
   478  				dbWorker.ResourceCertsReturns(nil, false, nil)
   479  			})
   480  
   481  			It("doesn't find a volume", func() {
   482  				Expect(found).To(BeFalse())
   483  			})
   484  		})
   485  
   486  		Context("when a created volume exists in the database", func() {
   487  			BeforeEach(func() {
   488  				fakeCreatedVolume.HandleReturns("created-handle")
   489  				fakeDBVolumeRepository.FindResourceCertsVolumeReturns(nil, fakeCreatedVolume, nil)
   490  			})
   491  
   492  			It("looks up the volume in baggageclaim", func() {
   493  				Expect(fakeBaggageclaimClient.LookupVolumeCallCount()).To(Equal(1))
   494  				_, handle := fakeBaggageclaimClient.LookupVolumeArgsForCall(0)
   495  				Expect(handle).To(Equal("created-handle"))
   496  			})
   497  
   498  			It("finds a volume", func() {
   499  				Expect(found).To(BeTrue())
   500  				Expect(volume).ToNot(BeNil())
   501  			})
   502  		})
   503  
   504  		Context("when a creating volume exists in the database", func() {
   505  			BeforeEach(func() {
   506  				fakeCreatingVolume.HandleReturns("creating-handle")
   507  				fakeDBVolumeRepository.FindResourceCertsVolumeReturns(fakeCreatingVolume, nil, nil)
   508  			})
   509  
   510  			It("looks up the volume in baggageclaim", func() {
   511  				Expect(fakeBaggageclaimClient.LookupVolumeCallCount()).To(Equal(1))
   512  				_, handle := fakeBaggageclaimClient.LookupVolumeArgsForCall(0)
   513  				Expect(handle).To(Equal("creating-handle"))
   514  			})
   515  
   516  			It("marks the volume as created in the db", func() {
   517  				Expect(fakeCreatingVolume.CreatedCallCount()).To(Equal(1))
   518  			})
   519  		})
   520  
   521  		Context("when the volume doesn't exist on the worker", func() {
   522  			BeforeEach(func() {
   523  				fakeBaggageclaimClient.LookupVolumeReturns(nil, false, nil)
   524  				fakeBaggageclaimClient.CreateVolumeReturns(fakeBaggageclaimVolume, nil)
   525  				fakeDBVolumeRepository.CreateResourceCertsVolumeReturns(fakeCreatingVolume, nil)
   526  			})
   527  
   528  			Context("when the resource certs volume doesn't exist in the db", func() {
   529  				BeforeEach(func() {
   530  					fakeDBVolumeRepository.FindResourceCertsVolumeReturns(nil, nil, nil)
   531  				})
   532  
   533  				It("creates the resource certs volume in the db", func() {
   534  					Expect(err).NotTo(HaveOccurred())
   535  					Expect(fakeDBVolumeRepository.CreateResourceCertsVolumeCallCount()).To(Equal(1))
   536  				})
   537  
   538  				It("creates the volume in baggageclaim", func() {
   539  					Expect(fakeBaggageclaimClient.CreateVolumeCallCount()).To(Equal(1))
   540  				})
   541  			})
   542  
   543  			Context("when a creating volume exists in the database", func() {
   544  				BeforeEach(func() {
   545  					fakeCreatingVolume.HandleReturns("creating-handle")
   546  					fakeDBVolumeRepository.FindResourceCertsVolumeReturns(fakeCreatingVolume, nil, nil)
   547  				})
   548  
   549  				It("looks up the volume in baggageclaim", func() {
   550  					Expect(fakeBaggageclaimClient.LookupVolumeCallCount()).To(Equal(1))
   551  					_, handle := fakeBaggageclaimClient.LookupVolumeArgsForCall(0)
   552  					Expect(handle).To(Equal("creating-handle"))
   553  				})
   554  
   555  				It("marks the volume as created in the db", func() {
   556  					Expect(fakeCreatingVolume.CreatedCallCount()).To(Equal(1))
   557  				})
   558  			})
   559  
   560  			It("marks the volume as created in the db", func() {
   561  				Expect(fakeCreatingVolume.CreatedCallCount()).To(Equal(1))
   562  			})
   563  
   564  			It("creates the volume in baggageclaim", func() {
   565  				Expect(fakeBaggageclaimClient.CreateVolumeCallCount()).To(Equal(1))
   566  			})
   567  		})
   568  	})
   569  
   570  	Describe("FindVolumeForTaskCache", func() {
   571  		Context("when worker task cache does not exist", func() {
   572  			BeforeEach(func() {
   573  				// fakeWorkerTaskCacheFactory.FindReturns(nil, false, nil)
   574  				fakeTaskCacheFactory.FindReturns(nil, false, nil)
   575  			})
   576  
   577  			It("returns false", func() {
   578  				_, found, err := volumeClient.FindVolumeForTaskCache(testLogger, 123, 456, "some-step", "some-cache-path")
   579  				Expect(err).NotTo(HaveOccurred())
   580  				Expect(found).To(BeFalse())
   581  			})
   582  		})
   583  
   584  		Context("when worker task cache exists", func() {
   585  			var taskCache *db.UsedWorkerTaskCache
   586  			BeforeEach(func() {
   587  				taskCache = &db.UsedWorkerTaskCache{
   588  					ID: 123,
   589  				}
   590  
   591  				fakeWorkerTaskCacheFactory.FindReturns(taskCache, true, nil)
   592  			})
   593  
   594  			Context("when task cache volume does not exist in db", func() {
   595  				BeforeEach(func() {
   596  					fakeDBVolumeRepository.FindTaskCacheVolumeReturns(nil, false, nil)
   597  				})
   598  
   599  				It("returns false", func() {
   600  					_, found, err := volumeClient.FindVolumeForTaskCache(testLogger, 123, 456, "some-step", "some-cache-path")
   601  					Expect(err).NotTo(HaveOccurred())
   602  					Expect(found).To(BeFalse())
   603  				})
   604  			})
   605  
   606  			Context("when task cache volume exists in db", func() {
   607  				var dbVolume db.CreatedVolume
   608  
   609  				BeforeEach(func() {
   610  					dbVolume = new(dbfakes.FakeCreatedVolume)
   611  					fakeDBVolumeRepository.FindTaskCacheVolumeReturns(dbVolume, true, nil)
   612  				})
   613  
   614  				Context("when task cache volume does not exist in baggageclaim", func() {
   615  					BeforeEach(func() {
   616  						fakeBaggageclaimClient.LookupVolumeReturns(nil, false, nil)
   617  					})
   618  
   619  					It("returns false", func() {
   620  						_, found, err := volumeClient.FindVolumeForTaskCache(testLogger, 123, 456, "some-step", "some-cache-path")
   621  						Expect(err).NotTo(HaveOccurred())
   622  						Expect(found).To(BeFalse())
   623  					})
   624  				})
   625  
   626  				Context("when task cache volume exists in baggageclaim", func() {
   627  					var bcVolume *baggageclaimfakes.FakeVolume
   628  
   629  					BeforeEach(func() {
   630  						bcVolume = new(baggageclaimfakes.FakeVolume)
   631  						fakeBaggageclaimClient.LookupVolumeReturns(bcVolume, true, nil)
   632  						fakeTaskCacheFactory.FindReturns(nil, true, nil)
   633  					})
   634  
   635  					It("returns volume", func() {
   636  						volume, found, err := volumeClient.FindVolumeForTaskCache(testLogger, 123, 456, "some-step", "some-cache-path")
   637  						Expect(err).NotTo(HaveOccurred())
   638  						Expect(found).To(BeTrue())
   639  
   640  						Expect(volume).To(Equal(worker.NewVolume(bcVolume, dbVolume, volumeClient)))
   641  					})
   642  				})
   643  			})
   644  		})
   645  	})
   646  
   647  	Describe("CreateVolume", func() {
   648  		var err error
   649  		var workerVolume worker.Volume
   650  
   651  		BeforeEach(func() {
   652  			fakeLockFactory.AcquireReturns(nil, false, errors.New("nope"))
   653  		})
   654  
   655  		JustBeforeEach(func() {
   656  			workerVolume, err = volumeClient.CreateVolume(testLogger, worker.VolumeSpec{}, 42, "some-mount", db.VolumeTypeArtifact)
   657  		})
   658  
   659  		Context("when trying to create a new volume", func() {
   660  
   661  			Context("when creating the volume in the db fails", func() {
   662  				BeforeEach(func() {
   663  					fakeDBVolumeRepository.CreateVolumeReturns(nil, errors.New("nope"))
   664  				})
   665  
   666  				It("errors", func() {
   667  					Expect(err).To(HaveOccurred())
   668  				})
   669  			})
   670  
   671  			Context("when creating the volume in the db succeeds", func() {
   672  				var fakeCreatingVolume *dbfakes.FakeCreatingVolume
   673  
   674  				BeforeEach(func() {
   675  					fakeCreatingVolume = new(dbfakes.FakeCreatingVolume)
   676  
   677  					fakeDBVolumeRepository.CreateVolumeReturns(fakeCreatingVolume, nil)
   678  				})
   679  
   680  				Context("when it fails to acquire a lock", func() {
   681  					BeforeEach(func() {
   682  						fakeLockFactory.AcquireReturns(nil, false, errors.New("nope"))
   683  					})
   684  
   685  					It("errors", func() {
   686  						Expect(err).To(HaveOccurred())
   687  					})
   688  				})
   689  
   690  				Context("when it acquires the lock", func() {
   691  					BeforeEach(func() {
   692  						fakeLockFactory.AcquireReturns(fakeLock, true, nil)
   693  					})
   694  
   695  					It("creates volume in baggageclaim", func() {
   696  						Expect(fakeBaggageclaimClient.CreateVolumeCallCount()).To(Equal(1))
   697  					})
   698  
   699  					Context("when creating the volume in baggage claim fails", func() {
   700  						BeforeEach(func() {
   701  							fakeBaggageclaimClient.CreateVolumeReturns(nil, errors.New("nope"))
   702  						})
   703  
   704  						It("errors", func() {
   705  							Expect(err).To(HaveOccurred())
   706  						})
   707  					})
   708  
   709  					Context("when creating the volume in baggage claim succeeds", func() {
   710  						var fakeBGVolume *baggageclaimfakes.FakeVolume
   711  
   712  						BeforeEach(func() {
   713  							fakeBGVolume = new(baggageclaimfakes.FakeVolume)
   714  							fakeBaggageclaimClient.CreateVolumeReturns(fakeBGVolume, nil)
   715  						})
   716  
   717  						It("transitions the volume to created in the db", func() {
   718  							Expect(fakeCreatingVolume.CreatedCallCount()).To(Equal(1))
   719  						})
   720  
   721  						Context("when transitioning the build fails", func() {
   722  							BeforeEach(func() {
   723  								fakeCreatingVolume.CreatedReturns(nil, errors.New("nope"))
   724  							})
   725  
   726  							It("errors", func() {
   727  								Expect(err).To(HaveOccurred())
   728  							})
   729  						})
   730  
   731  						Context("when transitioning the build succeeds", func() {
   732  							var fakeCreatedVolume *dbfakes.FakeCreatedVolume
   733  
   734  							BeforeEach(func() {
   735  								fakeCreatedVolume = new(dbfakes.FakeCreatedVolume)
   736  								fakeCreatingVolume.CreatedReturns(fakeCreatedVolume, nil)
   737  							})
   738  
   739  							It("returns a new volume with the bg volume and created volume", func() {
   740  								Expect(err).NotTo(HaveOccurred())
   741  								Expect(workerVolume).To(Equal(worker.NewVolume(fakeBGVolume, fakeCreatedVolume, volumeClient)))
   742  							})
   743  						})
   744  					})
   745  				})
   746  			})
   747  		})
   748  	})
   749  
   750  	Describe("LookupVolume", func() {
   751  		var handle string
   752  
   753  		var found bool
   754  		var lookupErr error
   755  
   756  		BeforeEach(func() {
   757  			handle = "some-handle"
   758  
   759  			fakeCreatedVolume := new(dbfakes.FakeCreatedVolume)
   760  			fakeDBVolumeRepository.FindCreatedVolumeReturns(fakeCreatedVolume, true, nil)
   761  		})
   762  
   763  		JustBeforeEach(func() {
   764  			_, found, lookupErr = worker.NewVolumeClient(
   765  				fakeBaggageclaimClient,
   766  				dbWorker,
   767  				fakeClock,
   768  
   769  				fakeLockFactory,
   770  				fakeDBVolumeRepository,
   771  				fakeWorkerBaseResourceTypeFactory,
   772  				fakeTaskCacheFactory,
   773  				fakeWorkerTaskCacheFactory,
   774  			).LookupVolume(testLogger, handle)
   775  		})
   776  
   777  		Context("when the volume can be found on baggageclaim", func() {
   778  			var fakeBaggageclaimVolume *baggageclaimfakes.FakeVolume
   779  
   780  			BeforeEach(func() {
   781  				fakeBaggageclaimVolume = new(baggageclaimfakes.FakeVolume)
   782  				fakeBaggageclaimVolume.HandleReturns(handle)
   783  				fakeBaggageclaimClient.LookupVolumeReturns(fakeBaggageclaimVolume, true, nil)
   784  			})
   785  
   786  			It("succeeds", func() {
   787  				Expect(lookupErr).ToNot(HaveOccurred())
   788  			})
   789  
   790  			It("looks up the volume via BaggageClaim", func() {
   791  				Expect(fakeBaggageclaimClient.LookupVolumeCallCount()).To(Equal(1))
   792  
   793  				_, lookedUpHandle := fakeBaggageclaimClient.LookupVolumeArgsForCall(0)
   794  				Expect(lookedUpHandle).To(Equal(handle))
   795  			})
   796  		})
   797  
   798  		Context("when the volume cannot be found on baggageclaim", func() {
   799  			BeforeEach(func() {
   800  				fakeBaggageclaimClient.LookupVolumeReturns(nil, false, nil)
   801  			})
   802  
   803  			It("succeeds", func() {
   804  				Expect(lookupErr).ToNot(HaveOccurred())
   805  			})
   806  
   807  			It("returns false", func() {
   808  				Expect(found).To(BeFalse())
   809  			})
   810  		})
   811  
   812  		Context("when the volume cannot be found in database", func() {
   813  			BeforeEach(func() {
   814  				fakeDBVolumeRepository.FindCreatedVolumeReturns(nil, false, nil)
   815  			})
   816  
   817  			It("succeeds", func() {
   818  				Expect(lookupErr).ToNot(HaveOccurred())
   819  			})
   820  
   821  			It("returns false", func() {
   822  				Expect(found).To(BeFalse())
   823  			})
   824  		})
   825  
   826  		Context("when looking up the volume fails", func() {
   827  			disaster := errors.New("nope")
   828  
   829  			BeforeEach(func() {
   830  				fakeBaggageclaimClient.LookupVolumeReturns(nil, false, disaster)
   831  			})
   832  
   833  			It("returns the error", func() {
   834  				Expect(lookupErr).To(Equal(disaster))
   835  			})
   836  		})
   837  	})
   838  })