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

     1  package worker_test
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  
     7  	"code.cloudfoundry.org/garden"
     8  	"code.cloudfoundry.org/garden/gardenfakes"
     9  	"code.cloudfoundry.org/lager/lagertest"
    10  	"github.com/pf-qiu/concourse/v6/atc"
    11  	"github.com/pf-qiu/concourse/v6/atc/db"
    12  	"github.com/pf-qiu/concourse/v6/atc/db/dbfakes"
    13  	"github.com/pf-qiu/concourse/v6/atc/resource"
    14  	"github.com/pf-qiu/concourse/v6/atc/resource/resourcefakes"
    15  	"github.com/pf-qiu/concourse/v6/atc/runtime"
    16  	"github.com/pf-qiu/concourse/v6/atc/worker"
    17  	"github.com/pf-qiu/concourse/v6/atc/worker/workerfakes"
    18  
    19  	. "github.com/onsi/ginkgo"
    20  	. "github.com/onsi/gomega"
    21  )
    22  
    23  var _ = Describe("FetchSource", func() {
    24  	var (
    25  		fetchSourceFactory worker.FetchSourceFactory
    26  		fetchSource        worker.FetchSource
    27  
    28  		fakeContainer            *workerfakes.FakeContainer
    29  		fakeVolume               *workerfakes.FakeVolume
    30  		fakeWorker               *workerfakes.FakeWorker
    31  		fakeResourceCacheFactory *dbfakes.FakeResourceCacheFactory
    32  		fakeUsedResourceCache    *dbfakes.FakeUsedResourceCache
    33  		fakeResource             *resourcefakes.FakeResource
    34  		metadata                 db.ContainerMetadata
    35  		owner                    db.ContainerOwner
    36  
    37  		ctx    context.Context
    38  		cancel func()
    39  	)
    40  
    41  	BeforeEach(func() {
    42  		logger := lagertest.NewTestLogger("test")
    43  		fakeContainer = new(workerfakes.FakeContainer)
    44  
    45  		ctx, cancel = context.WithCancel(context.Background())
    46  
    47  		fakeContainer.PropertyReturns("", errors.New("nope"))
    48  		inProcess := new(gardenfakes.FakeProcess)
    49  		inProcess.IDReturns("process-id")
    50  		inProcess.WaitStub = func() (int, error) {
    51  			return 0, nil
    52  		}
    53  
    54  		fakeContainer.AttachReturns(nil, errors.New("process not found"))
    55  
    56  		fakeContainer.RunStub = func(ctx context.Context, spec garden.ProcessSpec, io garden.ProcessIO) (garden.Process, error) {
    57  			_, err := io.Stdout.Write([]byte("{}"))
    58  			Expect(err).NotTo(HaveOccurred())
    59  
    60  			return inProcess, nil
    61  		}
    62  
    63  		fakeVolume = new(workerfakes.FakeVolume)
    64  		fakeVolume.HandleReturns("some-handle")
    65  		fakeContainer.VolumeMountsReturns([]worker.VolumeMount{
    66  			{
    67  				Volume:    fakeVolume,
    68  				MountPath: resource.ResourcesDir("get"),
    69  			},
    70  		})
    71  
    72  		fakeWorker = new(workerfakes.FakeWorker)
    73  		fakeWorker.FindOrCreateContainerReturns(fakeContainer, nil)
    74  
    75  		fakeResourceCacheFactory = new(dbfakes.FakeResourceCacheFactory)
    76  		fakeUsedResourceCache = new(dbfakes.FakeUsedResourceCache)
    77  		fakeUsedResourceCache.IDReturns(42)
    78  		fakeResourceCacheFactory.FindOrCreateResourceCacheReturns(fakeUsedResourceCache, nil)
    79  
    80  		owner = db.NewBuildStepContainerOwner(43, atc.PlanID("some-plan-id"), 42)
    81  		metadata = db.ContainerMetadata{Type: db.ContainerTypeGet}
    82  
    83  		fakeResource = new(resourcefakes.FakeResource)
    84  		fakeResourceCacheFactory = new(dbfakes.FakeResourceCacheFactory)
    85  		fakeResourceCacheFactory.UpdateResourceCacheMetadataReturns(nil)
    86  		fakeResourceCacheFactory.ResourceCacheMetadataReturns([]db.ResourceConfigMetadataField{
    87  			{Name: "some", Value: "metadata"},
    88  		}, nil)
    89  
    90  		getProcessSpec := runtime.ProcessSpec{
    91  			Path: "/opt/resource/in",
    92  			Args: []string{resource.ResourcesDir("get")},
    93  		}
    94  
    95  		fetchSourceFactory = worker.NewFetchSourceFactory(fakeResourceCacheFactory)
    96  		fetchSource = fetchSourceFactory.NewFetchSource(
    97  			logger,
    98  			fakeWorker,
    99  			owner,
   100  			fakeUsedResourceCache,
   101  			fakeResource,
   102  			worker.ContainerSpec{
   103  				TeamID: 42,
   104  				ImageSpec: worker.ImageSpec{
   105  					ResourceType: "fake-resource-type",
   106  				},
   107  				Outputs: map[string]string{
   108  					"resource": resource.ResourcesDir("get"),
   109  				},
   110  			},
   111  			getProcessSpec,
   112  			metadata,
   113  		)
   114  	})
   115  
   116  	AfterEach(func() {
   117  		cancel()
   118  	})
   119  
   120  	Describe("Find", func() {
   121  		var expectedGetResult worker.GetResult
   122  
   123  		Context("when there is volume", func() {
   124  			BeforeEach(func() {
   125  				fakeWorker.FindVolumeForResourceCacheReturns(fakeVolume, true, nil)
   126  
   127  				expectedMetadata := []atc.MetadataField{
   128  					{Name: "some", Value: "metadata"},
   129  				}
   130  				expectedGetResult = worker.GetResult{
   131  					ExitStatus:    0,
   132  					VersionResult: runtime.VersionResult{Metadata: expectedMetadata},
   133  					GetArtifact:   runtime.GetArtifact{VolumeHandle: fakeVolume.Handle()},
   134  				}
   135  			})
   136  
   137  			It("finds the resource cache volume and returns the correct result", func() {
   138  				getResult, volume, found, err := fetchSource.Find()
   139  				Expect(err).NotTo(HaveOccurred())
   140  				Expect(found).To(BeTrue())
   141  				Expect(volume).To(Equal(fakeVolume))
   142  				Expect(getResult).To(Equal(expectedGetResult))
   143  			})
   144  		})
   145  
   146  		Context("when there is no volume", func() {
   147  			BeforeEach(func() {
   148  				fakeWorker.FindVolumeForResourceCacheReturns(nil, false, nil)
   149  				expectedGetResult = worker.GetResult{}
   150  			})
   151  
   152  			It("does not find volume", func() {
   153  				getResult, volume, found, err := fetchSource.Find()
   154  				Expect(err).NotTo(HaveOccurred())
   155  				Expect(found).To(BeFalse())
   156  				Expect(volume).To(BeNil())
   157  				Expect(getResult).To(Equal(expectedGetResult))
   158  			})
   159  		})
   160  	})
   161  
   162  	Describe("Create", func() {
   163  		var (
   164  			err               error
   165  			getResult         worker.GetResult
   166  			expectedGetResult worker.GetResult
   167  			volume            worker.Volume
   168  		)
   169  
   170  		JustBeforeEach(func() {
   171  			getResult, volume, err = fetchSource.Create(ctx)
   172  		})
   173  
   174  		Context("when there is initialized volume", func() {
   175  			BeforeEach(func() {
   176  				fakeWorker.FindVolumeForResourceCacheReturns(fakeVolume, true, nil)
   177  
   178  				expectedMetadata := []atc.MetadataField{
   179  					{Name: "some", Value: "metadata"},
   180  				}
   181  				expectedGetResult = worker.GetResult{
   182  					ExitStatus:    0,
   183  					VersionResult: runtime.VersionResult{Metadata: expectedMetadata},
   184  					GetArtifact:   runtime.GetArtifact{VolumeHandle: fakeVolume.Handle()},
   185  				}
   186  			})
   187  
   188  			It("does not fetch resource", func() {
   189  				Expect(err).NotTo(HaveOccurred())
   190  				Expect(fakeWorker.FindOrCreateContainerCallCount()).To(Equal(0))
   191  				Expect(fakeResource.GetCallCount()).To(Equal(0))
   192  			})
   193  
   194  			It("finds initialized volume and returns a successful GetResult", func() {
   195  				Expect(err).NotTo(HaveOccurred())
   196  				Expect(getResult).To(Equal(expectedGetResult))
   197  				Expect(volume).ToNot(BeNil())
   198  			})
   199  		})
   200  
   201  		Context("when there is no initialized volume", func() {
   202  			var atcMetadata []atc.MetadataField
   203  			BeforeEach(func() {
   204  				atcMetadata = []atc.MetadataField{{Name: "foo", Value: "bar"}}
   205  				fakeWorker.FindVolumeForResourceCacheReturns(nil, false, nil)
   206  				fakeResource.GetReturns(runtime.VersionResult{Metadata: atcMetadata}, nil)
   207  			})
   208  
   209  			It("creates container with volume and worker", func() {
   210  				Expect(err).NotTo(HaveOccurred())
   211  
   212  				Expect(fakeWorker.FindOrCreateContainerCallCount()).To(Equal(1))
   213  				_, logger, owner, actualMetadata, containerSpec := fakeWorker.FindOrCreateContainerArgsForCall(0)
   214  				Expect(owner).To(Equal(db.NewBuildStepContainerOwner(43, atc.PlanID("some-plan-id"), 42)))
   215  				Expect(actualMetadata).To(Equal(metadata))
   216  				Expect(containerSpec).To(Equal(
   217  					worker.ContainerSpec{
   218  						TeamID: 42,
   219  						ImageSpec: worker.ImageSpec{
   220  							ResourceType: "fake-resource-type",
   221  						},
   222  						BindMounts: []worker.BindMountSource{&worker.CertsVolumeMount{Logger: logger}},
   223  						Outputs: map[string]string{
   224  							"resource": resource.ResourcesDir("get"),
   225  						},
   226  					}))
   227  			})
   228  
   229  			It("executes the get script", func() {
   230  				Expect(err).NotTo(HaveOccurred())
   231  				Expect(fakeResource.GetCallCount()).To(Equal(1))
   232  			})
   233  
   234  			It("initializes cache", func() {
   235  				Expect(err).NotTo(HaveOccurred())
   236  				Expect(fakeVolume.InitializeResourceCacheCallCount()).To(Equal(1))
   237  				rc := fakeVolume.InitializeResourceCacheArgsForCall(0)
   238  				Expect(rc).To(Equal(fakeUsedResourceCache))
   239  			})
   240  
   241  			It("updates resource cache metadata", func() {
   242  				Expect(fakeResourceCacheFactory.UpdateResourceCacheMetadataCallCount()).To(Equal(1))
   243  				passedResourceCache, versionResultMetadata := fakeResourceCacheFactory.UpdateResourceCacheMetadataArgsForCall(0)
   244  				Expect(passedResourceCache).To(Equal(fakeUsedResourceCache))
   245  				Expect(versionResultMetadata).To(Equal(atcMetadata))
   246  			})
   247  
   248  			Context("when getting resource fails with other error", func() {
   249  				var disaster error
   250  
   251  				BeforeEach(func() {
   252  					disaster = errors.New("failed")
   253  					fakeResource.GetReturns(runtime.VersionResult{}, disaster)
   254  				})
   255  
   256  				It("returns the error", func() {
   257  					Expect(err).To(HaveOccurred())
   258  					Expect(err).To(Equal(disaster))
   259  				})
   260  			})
   261  
   262  			It("returns a successful GetResult and volume with fetched bits", func() {
   263  				Expect(getResult.ExitStatus).To(BeZero())
   264  				Expect(getResult.GetArtifact.VolumeHandle).To(Equal(fakeVolume.Handle()))
   265  				Expect(volume).ToNot(BeNil())
   266  			})
   267  		})
   268  	})
   269  })