github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/db/volume_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/pf-qiu/concourse/v6/atc/db/dbtest"
     9  	. "github.com/onsi/ginkgo"
    10  	. "github.com/onsi/gomega"
    11  )
    12  
    13  var _ = Describe("Volume", func() {
    14  	var defaultCreatingContainer db.CreatingContainer
    15  	var defaultCreatedContainer db.CreatedContainer
    16  
    17  	BeforeEach(func() {
    18  		expiries := db.ContainerOwnerExpiries{
    19  			Min: 5 * time.Minute,
    20  			Max: 1 * time.Hour,
    21  		}
    22  
    23  		resourceConfig, err := resourceConfigFactory.FindOrCreateResourceConfig("some-base-resource-type", atc.Source{}, atc.VersionedResourceTypes{})
    24  		Expect(err).ToNot(HaveOccurred())
    25  
    26  		defaultCreatingContainer, err = defaultWorker.CreateContainer(
    27  			db.NewResourceConfigCheckSessionContainerOwner(
    28  				resourceConfig.ID(),
    29  				resourceConfig.OriginBaseResourceType().ID,
    30  				expiries,
    31  			),
    32  			db.ContainerMetadata{Type: "check"},
    33  		)
    34  		Expect(err).ToNot(HaveOccurred())
    35  
    36  		defaultCreatedContainer, err = defaultCreatingContainer.Created()
    37  		Expect(err).ToNot(HaveOccurred())
    38  	})
    39  
    40  	Describe("creatingVolume.Failed", func() {
    41  		var (
    42  			creatingVolume db.CreatingVolume
    43  			failedVolume   db.FailedVolume
    44  			failErr        error
    45  		)
    46  
    47  		BeforeEach(func() {
    48  			var err error
    49  			creatingVolume, err = volumeRepository.CreateContainerVolume(defaultTeam.ID(), defaultWorker.Name(), defaultCreatingContainer, "/path/to/volume")
    50  			Expect(err).ToNot(HaveOccurred())
    51  		})
    52  
    53  		JustBeforeEach(func() {
    54  			failedVolume, failErr = creatingVolume.Failed()
    55  		})
    56  
    57  		Describe("the database query fails", func() {
    58  			Context("when the volume is not in creating or failed state", func() {
    59  				BeforeEach(func() {
    60  					_, err := creatingVolume.Created()
    61  					Expect(err).ToNot(HaveOccurred())
    62  				})
    63  
    64  				It("returns the correct error", func() {
    65  					Expect(failErr).To(HaveOccurred())
    66  					Expect(failErr).To(Equal(db.ErrVolumeMarkStateFailed{db.VolumeStateFailed}))
    67  				})
    68  			})
    69  
    70  			Context("there is no such id in the table", func() {
    71  				BeforeEach(func() {
    72  					createdVol, err := creatingVolume.Created()
    73  					Expect(err).ToNot(HaveOccurred())
    74  
    75  					destroyingVol, err := createdVol.Destroying()
    76  					Expect(err).ToNot(HaveOccurred())
    77  
    78  					deleted, err := destroyingVol.Destroy()
    79  					Expect(err).ToNot(HaveOccurred())
    80  					Expect(deleted).To(BeTrue())
    81  				})
    82  
    83  				It("returns the correct error", func() {
    84  					Expect(failErr).To(HaveOccurred())
    85  					Expect(failErr).To(Equal(db.ErrVolumeMarkStateFailed{db.VolumeStateFailed}))
    86  				})
    87  			})
    88  		})
    89  
    90  		Describe("the database query succeeds", func() {
    91  			Context("when the volume is already in the failed state", func() {
    92  				BeforeEach(func() {
    93  					_, err := creatingVolume.Failed()
    94  					Expect(err).ToNot(HaveOccurred())
    95  				})
    96  
    97  				It("returns the failed volume", func() {
    98  					Expect(failedVolume).ToNot(BeNil())
    99  				})
   100  
   101  				It("does not fail to transition", func() {
   102  					Expect(failErr).ToNot(HaveOccurred())
   103  				})
   104  			})
   105  		})
   106  	})
   107  
   108  	Describe("creatingVolume.Created", func() {
   109  		var (
   110  			creatingVolume db.CreatingVolume
   111  			createdVolume  db.CreatedVolume
   112  			createErr      error
   113  		)
   114  
   115  		BeforeEach(func() {
   116  			var err error
   117  			creatingVolume, err = volumeRepository.CreateContainerVolume(defaultTeam.ID(), defaultWorker.Name(), defaultCreatingContainer, "/path/to/volume")
   118  			Expect(err).ToNot(HaveOccurred())
   119  		})
   120  
   121  		JustBeforeEach(func() {
   122  			createdVolume, createErr = creatingVolume.Created()
   123  		})
   124  
   125  		Describe("the database query fails", func() {
   126  			Context("when the volume is not in creating or created state", func() {
   127  				BeforeEach(func() {
   128  					createdVolume, err := creatingVolume.Created()
   129  					Expect(err).ToNot(HaveOccurred())
   130  					_, err = createdVolume.Destroying()
   131  					Expect(err).ToNot(HaveOccurred())
   132  				})
   133  
   134  				It("returns the correct error", func() {
   135  					Expect(createErr).To(HaveOccurred())
   136  					Expect(createErr).To(Equal(db.ErrVolumeMarkCreatedFailed{Handle: creatingVolume.Handle()}))
   137  				})
   138  			})
   139  
   140  			Context("there is no such id in the table", func() {
   141  				BeforeEach(func() {
   142  					vc, err := creatingVolume.Created()
   143  					Expect(err).ToNot(HaveOccurred())
   144  
   145  					vd, err := vc.Destroying()
   146  					Expect(err).ToNot(HaveOccurred())
   147  
   148  					deleted, err := vd.Destroy()
   149  					Expect(err).ToNot(HaveOccurred())
   150  					Expect(deleted).To(BeTrue())
   151  				})
   152  
   153  				It("returns the correct error", func() {
   154  					Expect(createErr).To(HaveOccurred())
   155  					Expect(createErr).To(Equal(db.ErrVolumeMarkCreatedFailed{Handle: creatingVolume.Handle()}))
   156  				})
   157  			})
   158  		})
   159  
   160  		Describe("the database query succeeds", func() {
   161  			It("updates the record to be `created`", func() {
   162  				foundVolumes, err := volumeRepository.FindVolumesForContainer(defaultCreatedContainer)
   163  				Expect(err).ToNot(HaveOccurred())
   164  				Expect(foundVolumes).To(ContainElement(WithTransform(db.CreatedVolume.Path, Equal("/path/to/volume"))))
   165  			})
   166  
   167  			It("returns a createdVolume and no error", func() {
   168  				Expect(createdVolume).ToNot(BeNil())
   169  				Expect(createErr).ToNot(HaveOccurred())
   170  			})
   171  
   172  			Context("when volume is already in provided state", func() {
   173  				BeforeEach(func() {
   174  					_, err := creatingVolume.Created()
   175  					Expect(err).ToNot(HaveOccurred())
   176  				})
   177  
   178  				It("returns a createdVolume and no error", func() {
   179  					Expect(createdVolume).ToNot(BeNil())
   180  					Expect(createErr).ToNot(HaveOccurred())
   181  				})
   182  			})
   183  		})
   184  	})
   185  
   186  	Describe("createdVolume.InitializeResourceCache", func() {
   187  		var createdVolume db.CreatedVolume
   188  		var resourceCache db.UsedResourceCache
   189  		var build db.Build
   190  
   191  		BeforeEach(func() {
   192  			var err error
   193  			build, err = defaultTeam.CreateOneOffBuild()
   194  			Expect(err).ToNot(HaveOccurred())
   195  
   196  			resourceCache, err = resourceCacheFactory.FindOrCreateResourceCache(
   197  				db.ForBuild(build.ID()),
   198  				"some-type",
   199  				atc.Version{"some": "version"},
   200  				atc.Source{
   201  					"some": "source",
   202  				},
   203  				atc.Params{"some": "params"},
   204  				atc.VersionedResourceTypes{
   205  					atc.VersionedResourceType{
   206  						ResourceType: atc.ResourceType{
   207  							Name: "some-type",
   208  							Type: "some-base-resource-type",
   209  							Source: atc.Source{
   210  								"some-type": "source",
   211  							},
   212  						},
   213  						Version: atc.Version{"some-type": "version"},
   214  					},
   215  				},
   216  			)
   217  			Expect(err).ToNot(HaveOccurred())
   218  
   219  			creatingContainer, err := defaultWorker.CreateContainer(db.NewBuildStepContainerOwner(build.ID(), "some-plan", defaultTeam.ID()), db.ContainerMetadata{
   220  				Type:     "get",
   221  				StepName: "some-resource",
   222  			})
   223  			Expect(err).ToNot(HaveOccurred())
   224  
   225  			resourceCacheVolume, err := volumeRepository.CreateContainerVolume(defaultTeam.ID(), defaultWorker.Name(), creatingContainer, "some-path")
   226  			Expect(err).ToNot(HaveOccurred())
   227  
   228  			createdVolume, err = resourceCacheVolume.Created()
   229  			Expect(err).ToNot(HaveOccurred())
   230  
   231  			err = createdVolume.InitializeResourceCache(resourceCache)
   232  			Expect(err).ToNot(HaveOccurred())
   233  		})
   234  
   235  		It("associates the volume to the resource cache", func() {
   236  			foundVolume, found, err := volumeRepository.FindResourceCacheVolume(defaultWorker.Name(), resourceCache)
   237  			Expect(err).ToNot(HaveOccurred())
   238  			Expect(foundVolume.Handle()).To(Equal(createdVolume.Handle()))
   239  			Expect(found).To(BeTrue())
   240  		})
   241  
   242  		Context("when there's already an initialized resource cache on the same worker", func() {
   243  			It("leaves the volume owned by the the container", func() {
   244  				creatingContainer, err := defaultWorker.CreateContainer(db.NewBuildStepContainerOwner(build.ID(), "some-plan", defaultTeam.ID()), db.ContainerMetadata{
   245  					Type:     "get",
   246  					StepName: "some-resource",
   247  				})
   248  				Expect(err).ToNot(HaveOccurred())
   249  
   250  				resourceCacheVolume, err := volumeRepository.CreateContainerVolume(defaultTeam.ID(), defaultWorker.Name(), creatingContainer, "some-path")
   251  				Expect(err).ToNot(HaveOccurred())
   252  
   253  				createdVolume, err = resourceCacheVolume.Created()
   254  				Expect(err).ToNot(HaveOccurred())
   255  
   256  				err = createdVolume.InitializeResourceCache(resourceCache)
   257  				Expect(err).ToNot(HaveOccurred())
   258  
   259  				Expect(createdVolume.Type()).To(Equal(db.VolumeTypeContainer))
   260  			})
   261  		})
   262  	})
   263  
   264  	Describe("createdVolume.InitializeArtifact", func() {
   265  		var (
   266  			workerArtifact db.WorkerArtifact
   267  			creatingVolume db.CreatingVolume
   268  			createdVolume  db.CreatedVolume
   269  			err            error
   270  		)
   271  
   272  		BeforeEach(func() {
   273  			creatingVolume, err = volumeRepository.CreateVolume(defaultTeam.ID(), defaultWorker.Name(), db.VolumeTypeArtifact)
   274  			Expect(err).ToNot(HaveOccurred())
   275  
   276  			createdVolume, err = creatingVolume.Created()
   277  			Expect(err).ToNot(HaveOccurred())
   278  		})
   279  
   280  		JustBeforeEach(func() {
   281  			workerArtifact, err = createdVolume.InitializeArtifact("some-name", 0)
   282  			Expect(err).ToNot(HaveOccurred())
   283  		})
   284  
   285  		It("initializes the worker artifact", func() {
   286  			Expect(workerArtifact.ID()).To(Equal(1))
   287  			Expect(workerArtifact.Name()).To(Equal("some-name"))
   288  			Expect(workerArtifact.BuildID()).To(Equal(0))
   289  			Expect(workerArtifact.CreatedAt()).ToNot(BeNil())
   290  		})
   291  
   292  		It("associates worker artifact with the volume", func() {
   293  			created, found, err := volumeRepository.FindCreatedVolume(createdVolume.Handle())
   294  			Expect(err).ToNot(HaveOccurred())
   295  			Expect(found).To(BeTrue())
   296  			Expect(created.WorkerArtifactID()).To(Equal(workerArtifact.ID()))
   297  		})
   298  	})
   299  
   300  	Describe("createdVolume.InitializeTaskCache", func() {
   301  		Context("when there is a volume that belongs to worker task cache", func() {
   302  			var (
   303  				existingTaskCacheVolume db.CreatedVolume
   304  				volume                  db.CreatedVolume
   305  			)
   306  
   307  			BeforeEach(func() {
   308  				build, err := defaultTeam.CreateOneOffBuild()
   309  				Expect(err).ToNot(HaveOccurred())
   310  
   311  				creatingContainer, err := defaultWorker.CreateContainer(db.NewBuildStepContainerOwner(build.ID(), "some-plan", defaultTeam.ID()), db.ContainerMetadata{})
   312  				Expect(err).ToNot(HaveOccurred())
   313  
   314  				v, err := volumeRepository.CreateContainerVolume(defaultTeam.ID(), defaultWorker.Name(), creatingContainer, "some-path")
   315  				Expect(err).ToNot(HaveOccurred())
   316  
   317  				existingTaskCacheVolume, err = v.Created()
   318  				Expect(err).ToNot(HaveOccurred())
   319  
   320  				err = existingTaskCacheVolume.InitializeTaskCache(defaultJob.ID(), "some-step", "some-cache-path")
   321  				Expect(err).ToNot(HaveOccurred())
   322  
   323  				v, err = volumeRepository.CreateContainerVolume(defaultTeam.ID(), defaultWorker.Name(), creatingContainer, "some-other-path")
   324  				Expect(err).ToNot(HaveOccurred())
   325  
   326  				volume, err = v.Created()
   327  				Expect(err).ToNot(HaveOccurred())
   328  			})
   329  
   330  			It("sets current volume as worker task cache volume", func() {
   331  				taskCache, err := taskCacheFactory.FindOrCreate(defaultJob.ID(), "some-step", "some-cache-path")
   332  				Expect(err).ToNot(HaveOccurred())
   333  
   334  				createdVolume, found, err := volumeRepository.FindTaskCacheVolume(defaultTeam.ID(), defaultWorker.Name(), taskCache)
   335  				Expect(err).ToNot(HaveOccurred())
   336  				Expect(found).To(BeTrue())
   337  				Expect(createdVolume).ToNot(BeNil())
   338  				Expect(createdVolume.Handle()).To(Equal(existingTaskCacheVolume.Handle()))
   339  
   340  				err = volume.InitializeTaskCache(defaultJob.ID(), "some-step", "some-cache-path")
   341  				Expect(err).ToNot(HaveOccurred())
   342  
   343  				createdVolume, found, err = volumeRepository.FindTaskCacheVolume(defaultTeam.ID(), defaultWorker.Name(), taskCache)
   344  				Expect(err).ToNot(HaveOccurred())
   345  				Expect(createdVolume).ToNot(BeNil())
   346  				Expect(createdVolume.Handle()).To(Equal(volume.Handle()))
   347  
   348  				Expect(existingTaskCacheVolume.Handle()).ToNot(Equal(volume.Handle()))
   349  			})
   350  		})
   351  	})
   352  
   353  	Describe("Container volumes", func() {
   354  		It("returns volume type, container handle, mount path", func() {
   355  			creatingVolume, err := volumeRepository.CreateContainerVolume(defaultTeam.ID(), defaultWorker.Name(), defaultCreatingContainer, "/path/to/volume")
   356  			Expect(err).ToNot(HaveOccurred())
   357  			createdVolume, err := creatingVolume.Created()
   358  			Expect(err).ToNot(HaveOccurred())
   359  
   360  			Expect(createdVolume.Type()).To(Equal(db.VolumeType(db.VolumeTypeContainer)))
   361  			Expect(createdVolume.ContainerHandle()).To(Equal(defaultCreatingContainer.Handle()))
   362  			Expect(createdVolume.Path()).To(Equal("/path/to/volume"))
   363  
   364  			_, createdVolume, err = volumeRepository.FindContainerVolume(defaultTeam.ID(), defaultWorker.Name(), defaultCreatingContainer, "/path/to/volume")
   365  			Expect(err).ToNot(HaveOccurred())
   366  			Expect(createdVolume.Type()).To(Equal(db.VolumeType(db.VolumeTypeContainer)))
   367  			Expect(createdVolume.ContainerHandle()).To(Equal(defaultCreatingContainer.Handle()))
   368  			Expect(createdVolume.Path()).To(Equal("/path/to/volume"))
   369  		})
   370  	})
   371  
   372  	Describe("Volumes created from a parent", func() {
   373  		It("returns parent handle", func() {
   374  			creatingParentVolume, err := volumeRepository.CreateContainerVolume(defaultTeam.ID(), defaultWorker.Name(), defaultCreatingContainer, "/path/to/volume")
   375  			Expect(err).ToNot(HaveOccurred())
   376  			createdParentVolume, err := creatingParentVolume.Created()
   377  			Expect(err).ToNot(HaveOccurred())
   378  
   379  			childCreatingVolume, err := createdParentVolume.CreateChildForContainer(defaultCreatingContainer, "/path/to/child/volume")
   380  			Expect(err).ToNot(HaveOccurred())
   381  			childVolume, err := childCreatingVolume.Created()
   382  			Expect(err).ToNot(HaveOccurred())
   383  
   384  			Expect(childVolume.Type()).To(Equal(db.VolumeType(db.VolumeTypeContainer)))
   385  			Expect(childVolume.ContainerHandle()).To(Equal(defaultCreatingContainer.Handle()))
   386  			Expect(childVolume.Path()).To(Equal("/path/to/child/volume"))
   387  			Expect(childVolume.ParentHandle()).To(Equal(createdParentVolume.Handle()))
   388  
   389  			_, childVolume, err = volumeRepository.FindContainerVolume(defaultTeam.ID(), defaultWorker.Name(), defaultCreatingContainer, "/path/to/child/volume")
   390  			Expect(err).ToNot(HaveOccurred())
   391  			Expect(childVolume.Type()).To(Equal(db.VolumeType(db.VolumeTypeContainer)))
   392  			Expect(childVolume.ContainerHandle()).To(Equal(defaultCreatingContainer.Handle()))
   393  			Expect(childVolume.Path()).To(Equal("/path/to/child/volume"))
   394  			Expect(childVolume.ParentHandle()).To(Equal(createdParentVolume.Handle()))
   395  		})
   396  
   397  		It("prevents the parent from being destroyed", func() {
   398  			creatingParentVolume, err := volumeRepository.CreateContainerVolume(defaultTeam.ID(), defaultWorker.Name(), defaultCreatingContainer, "/path/to/volume")
   399  			Expect(err).ToNot(HaveOccurred())
   400  			createdParentVolume, err := creatingParentVolume.Created()
   401  			Expect(err).ToNot(HaveOccurred())
   402  
   403  			childCreatingVolume, err := createdParentVolume.CreateChildForContainer(defaultCreatingContainer, "/path/to/child/volume")
   404  			Expect(err).ToNot(HaveOccurred())
   405  			_, err = childCreatingVolume.Created()
   406  			Expect(err).ToNot(HaveOccurred())
   407  
   408  			_, err = createdParentVolume.Destroying()
   409  			Expect(err).To(Equal(db.ErrVolumeCannotBeDestroyedWithChildrenPresent))
   410  		})
   411  	})
   412  
   413  	Describe("Resource cache volumes", func() {
   414  		It("returns volume type, resource type, resource version", func() {
   415  			scenario := dbtest.Setup(
   416  				builder.WithPipeline(atc.Config{
   417  					ResourceTypes: atc.ResourceTypes{
   418  						{
   419  							Name: "some-type",
   420  							Type: "some-base-resource-type",
   421  							Source: atc.Source{
   422  								"some-type": "source",
   423  							},
   424  						},
   425  					},
   426  				}),
   427  				builder.WithResourceTypeVersions(
   428  					"some-type",
   429  					atc.Version{"some": "version"},
   430  					atc.Version{"some-custom-type": "version"},
   431  				),
   432  			)
   433  
   434  			build, err := scenario.Team.CreateOneOffBuild()
   435  			Expect(err).ToNot(HaveOccurred())
   436  
   437  			resourceCache, err := resourceCacheFactory.FindOrCreateResourceCache(
   438  				db.ForBuild(build.ID()),
   439  				"some-type",
   440  				atc.Version{"some": "version"},
   441  				atc.Source{"some": "source"},
   442  				atc.Params{"some": "params"},
   443  				atc.VersionedResourceTypes{
   444  					{
   445  						ResourceType: atc.ResourceType{
   446  							Name:   "some-type",
   447  							Type:   "some-base-resource-type",
   448  							Source: atc.Source{"some-type": "((source-param))"},
   449  						},
   450  						Version: atc.Version{"some-custom-type": "version"},
   451  					},
   452  				},
   453  			)
   454  			Expect(err).ToNot(HaveOccurred())
   455  
   456  			creatingContainer, err := defaultWorker.CreateContainer(db.NewBuildStepContainerOwner(build.ID(), "some-plan", defaultTeam.ID()), db.ContainerMetadata{
   457  				Type:     "get",
   458  				StepName: "some-resource",
   459  			})
   460  			Expect(err).ToNot(HaveOccurred())
   461  
   462  			creatingVolume, err := volumeRepository.CreateContainerVolume(defaultTeam.ID(), defaultWorker.Name(), creatingContainer, "some-path")
   463  			Expect(err).ToNot(HaveOccurred())
   464  
   465  			createdVolume, err := creatingVolume.Created()
   466  			Expect(err).ToNot(HaveOccurred())
   467  
   468  			Expect(createdVolume.Type()).To(Equal(db.VolumeType(db.VolumeTypeContainer)))
   469  
   470  			err = createdVolume.InitializeResourceCache(resourceCache)
   471  			Expect(err).ToNot(HaveOccurred())
   472  
   473  			Expect(createdVolume.Type()).To(Equal(db.VolumeType(db.VolumeTypeResource)))
   474  
   475  			volumeResourceType, err := createdVolume.ResourceType()
   476  			Expect(err).ToNot(HaveOccurred())
   477  			Expect(volumeResourceType.ResourceType.WorkerBaseResourceType.Name).To(Equal("some-base-resource-type"))
   478  			Expect(volumeResourceType.ResourceType.WorkerBaseResourceType.Version).To(Equal("some-brt-version"))
   479  			Expect(volumeResourceType.ResourceType.Version).To(Equal(atc.Version{"some-custom-type": "version"}))
   480  			Expect(volumeResourceType.Version).To(Equal(atc.Version{"some": "version"}))
   481  
   482  			createdVolume, found, err := volumeRepository.FindResourceCacheVolume(defaultWorker.Name(), resourceCache)
   483  			Expect(err).ToNot(HaveOccurred())
   484  			Expect(found).To(BeTrue())
   485  			Expect(createdVolume.Type()).To(Equal(db.VolumeType(db.VolumeTypeResource)))
   486  			volumeResourceType, err = createdVolume.ResourceType()
   487  			Expect(err).ToNot(HaveOccurred())
   488  			Expect(volumeResourceType.ResourceType.WorkerBaseResourceType.Name).To(Equal("some-base-resource-type"))
   489  			Expect(volumeResourceType.ResourceType.WorkerBaseResourceType.Version).To(Equal("some-brt-version"))
   490  			Expect(volumeResourceType.ResourceType.Version).To(Equal(atc.Version{"some-custom-type": "version"}))
   491  			Expect(volumeResourceType.Version).To(Equal(atc.Version{"some": "version"}))
   492  		})
   493  	})
   494  
   495  	Describe("Resource type volumes", func() {
   496  		It("returns volume type, base resource type name, base resource type version", func() {
   497  			usedWorkerBaseResourceType, found, err := workerBaseResourceTypeFactory.Find("some-base-resource-type", defaultWorker)
   498  			Expect(err).ToNot(HaveOccurred())
   499  			Expect(found).To(BeTrue())
   500  			creatingVolume, err := volumeRepository.CreateBaseResourceTypeVolume(usedWorkerBaseResourceType)
   501  			Expect(err).ToNot(HaveOccurred())
   502  			createdVolume, err := creatingVolume.Created()
   503  			Expect(err).ToNot(HaveOccurred())
   504  
   505  			Expect(createdVolume.Type()).To(Equal(db.VolumeType(db.VolumeTypeResourceType)))
   506  			volumeBaseResourceType, err := createdVolume.BaseResourceType()
   507  			Expect(err).ToNot(HaveOccurred())
   508  			Expect(volumeBaseResourceType.Name).To(Equal("some-base-resource-type"))
   509  			Expect(volumeBaseResourceType.Version).To(Equal("some-brt-version"))
   510  
   511  			_, createdVolume, err = volumeRepository.FindBaseResourceTypeVolume(usedWorkerBaseResourceType)
   512  			Expect(err).ToNot(HaveOccurred())
   513  			Expect(createdVolume.Type()).To(Equal(db.VolumeType(db.VolumeTypeResourceType)))
   514  			volumeBaseResourceType, err = createdVolume.BaseResourceType()
   515  			Expect(err).ToNot(HaveOccurred())
   516  			Expect(volumeBaseResourceType.Name).To(Equal("some-base-resource-type"))
   517  			Expect(volumeBaseResourceType.Version).To(Equal("some-brt-version"))
   518  		})
   519  	})
   520  
   521  	Describe("Task cache volumes", func() {
   522  		It("returns volume type and task identifier", func() {
   523  			taskCache, err := taskCacheFactory.FindOrCreate(defaultJob.ID(), "some-task", "some-path")
   524  			Expect(err).ToNot(HaveOccurred())
   525  
   526  			uwtc, err := workerTaskCacheFactory.FindOrCreate(db.WorkerTaskCache{
   527  				WorkerName: defaultWorker.Name(),
   528  				TaskCache:  taskCache,
   529  			})
   530  			Expect(err).ToNot(HaveOccurred())
   531  
   532  			creatingVolume, err := volumeRepository.CreateTaskCacheVolume(defaultTeam.ID(), uwtc)
   533  			Expect(err).ToNot(HaveOccurred())
   534  
   535  			createdVolume, err := creatingVolume.Created()
   536  			Expect(err).ToNot(HaveOccurred())
   537  
   538  			Expect(createdVolume.Type()).To(Equal(db.VolumeTypeTaskCache))
   539  
   540  			pipelineID, pipelineRef, jobName, stepName, err := createdVolume.TaskIdentifier()
   541  			Expect(err).ToNot(HaveOccurred())
   542  
   543  			Expect(pipelineID).To(Equal(defaultPipeline.ID()))
   544  			Expect(pipelineRef).To(Equal(defaultPipelineRef))
   545  			Expect(jobName).To(Equal(defaultJob.Name()))
   546  			Expect(stepName).To(Equal("some-task"))
   547  		})
   548  	})
   549  
   550  	Describe("createdVolume.CreateChildForContainer", func() {
   551  		var parentVolume db.CreatedVolume
   552  		var creatingContainer db.CreatingContainer
   553  
   554  		BeforeEach(func() {
   555  			build, err := defaultTeam.CreateOneOffBuild()
   556  			Expect(err).ToNot(HaveOccurred())
   557  
   558  			creatingContainer, err = defaultWorker.CreateContainer(db.NewBuildStepContainerOwner(build.ID(), "some-plan", defaultTeam.ID()), db.ContainerMetadata{
   559  				Type:     "task",
   560  				StepName: "some-task",
   561  			})
   562  			Expect(err).ToNot(HaveOccurred())
   563  
   564  			usedResourceCache, err := resourceCacheFactory.FindOrCreateResourceCache(
   565  				db.ForBuild(build.ID()),
   566  				"some-type",
   567  				atc.Version{"some": "version"},
   568  				atc.Source{"some": "source"},
   569  				atc.Params{"some": "params"},
   570  				atc.VersionedResourceTypes{
   571  					{
   572  						ResourceType: atc.ResourceType{
   573  							Name:   "some-type",
   574  							Type:   "some-base-resource-type",
   575  							Source: atc.Source{"some-type": "source"},
   576  						},
   577  						Version: atc.Version{"some-custom-type": "version"},
   578  					},
   579  				},
   580  			)
   581  			Expect(err).ToNot(HaveOccurred())
   582  
   583  			creatingContainer, err := defaultWorker.CreateContainer(db.NewBuildStepContainerOwner(build.ID(), "some-plan", defaultTeam.ID()), db.ContainerMetadata{
   584  				Type:     "get",
   585  				StepName: "some-resource",
   586  			})
   587  			Expect(err).ToNot(HaveOccurred())
   588  
   589  			creatingParentVolume, err := volumeRepository.CreateContainerVolume(defaultTeam.ID(), defaultWorker.Name(), creatingContainer, "some-path")
   590  			Expect(err).ToNot(HaveOccurred())
   591  
   592  			parentVolume, err = creatingParentVolume.Created()
   593  			Expect(err).ToNot(HaveOccurred())
   594  
   595  			err = parentVolume.InitializeResourceCache(usedResourceCache)
   596  			Expect(err).ToNot(HaveOccurred())
   597  		})
   598  
   599  		It("creates volume for parent volume", func() {
   600  			creatingChildVolume, err := parentVolume.CreateChildForContainer(creatingContainer, "some-path-3")
   601  			Expect(err).ToNot(HaveOccurred())
   602  
   603  			_, err = parentVolume.Destroying()
   604  			Expect(err).To(HaveOccurred())
   605  
   606  			createdChildVolume, err := creatingChildVolume.Created()
   607  			Expect(err).ToNot(HaveOccurred())
   608  
   609  			destroyingChildVolume, err := createdChildVolume.Destroying()
   610  			Expect(err).ToNot(HaveOccurred())
   611  			destroyed, err := destroyingChildVolume.Destroy()
   612  			Expect(err).ToNot(HaveOccurred())
   613  			Expect(destroyed).To(Equal(true))
   614  
   615  			destroyingParentVolume, err := parentVolume.Destroying()
   616  			Expect(err).ToNot(HaveOccurred())
   617  			destroyed, err = destroyingParentVolume.Destroy()
   618  			Expect(err).ToNot(HaveOccurred())
   619  			Expect(destroyed).To(Equal(true))
   620  		})
   621  	})
   622  
   623  	Context("when worker is no longer in database", func() {
   624  		BeforeEach(func() {
   625  			var err error
   626  			_, err = volumeRepository.CreateContainerVolume(defaultTeam.ID(), defaultWorker.Name(), defaultCreatingContainer, "/path/to/volume")
   627  			Expect(err).ToNot(HaveOccurred())
   628  		})
   629  
   630  		It("the container goes away from the db", func() {
   631  			err := defaultWorker.Delete()
   632  			Expect(err).ToNot(HaveOccurred())
   633  
   634  			creatingVolume, createdVolume, err := volumeRepository.FindContainerVolume(defaultTeam.ID(), defaultWorker.Name(), defaultCreatingContainer, "/path/to/volume")
   635  			Expect(err).ToNot(HaveOccurred())
   636  			Expect(creatingVolume).To(BeNil())
   637  			Expect(createdVolume).To(BeNil())
   638  		})
   639  	})
   640  })