github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/worker/image/image_test.go (about) 1 package image_test 2 3 import ( 4 "context" 5 "errors" 6 "io/ioutil" 7 "strings" 8 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" 13 "github.com/pf-qiu/concourse/v6/atc/db/dbfakes" 14 "github.com/pf-qiu/concourse/v6/atc/worker" 15 "github.com/pf-qiu/concourse/v6/atc/worker/image" 16 "github.com/pf-qiu/concourse/v6/atc/worker/workerfakes" 17 . "github.com/onsi/ginkgo" 18 . "github.com/onsi/gomega" 19 ) 20 21 var _ = Describe("Image", func() { 22 var ( 23 imageFactory worker.ImageFactory 24 img worker.Image 25 ctx context.Context 26 logger *lagertest.TestLogger 27 fakeWorker *workerfakes.FakeWorker 28 fakeVolumeClient *workerfakes.FakeVolumeClient 29 fakeContainer *dbfakes.FakeCreatingContainer 30 ) 31 32 BeforeEach(func() { 33 logger = lagertest.NewTestLogger("image-tests") 34 fakeWorker = new(workerfakes.FakeWorker) 35 fakeWorker.TagsReturns(atc.Tags{"worker", "tags"}) 36 37 ctx = context.Background() 38 fakeVolumeClient = new(workerfakes.FakeVolumeClient) 39 fakeContainer = new(dbfakes.FakeCreatingContainer) 40 imageFactory = image.NewImageFactory() 41 }) 42 43 Describe("imageProvidedByPreviousStepOnSameWorker", func() { 44 var fakeArtifactVolume *workerfakes.FakeVolume 45 var cowStrategy baggageclaim.COWStrategy 46 47 BeforeEach(func() { 48 fakeArtifactVolume = new(workerfakes.FakeVolume) 49 cowStrategy = baggageclaim.COWStrategy{ 50 Parent: new(baggageclaimfakes.FakeVolume), 51 } 52 fakeArtifactVolume.COWStrategyReturns(cowStrategy) 53 54 fakeImageArtifactSource := new(workerfakes.FakeStreamableArtifactSource) 55 fakeImageArtifactSource.ExistsOnReturns(fakeArtifactVolume, true, nil) 56 metadataReader := ioutil.NopCloser(strings.NewReader( 57 `{"env": ["A=1", "B=2"], "user":"image-volume-user"}`, 58 )) 59 fakeImageArtifactSource.StreamFileReturns(metadataReader, nil) 60 61 fakeContainerRootfsVolume := new(workerfakes.FakeVolume) 62 fakeContainerRootfsVolume.PathReturns("some-path") 63 fakeVolumeClient.FindOrCreateCOWVolumeForContainerReturns(fakeContainerRootfsVolume, nil) 64 65 var err error 66 img, err = imageFactory.GetImage( 67 logger, 68 fakeWorker, 69 fakeVolumeClient, 70 worker.ImageSpec{ 71 ImageArtifactSource: fakeImageArtifactSource, 72 Privileged: true, 73 }, 74 42, 75 ) 76 Expect(err).NotTo(HaveOccurred()) 77 }) 78 79 It("finds or creates cow volume", func() { 80 _, err := img.FetchForContainer(ctx, logger, fakeContainer) 81 Expect(err).NotTo(HaveOccurred()) 82 Expect(fakeVolumeClient.FindOrCreateCOWVolumeForContainerCallCount()).To(Equal(1)) 83 _, volumeSpec, container, volume, teamID, path := fakeVolumeClient.FindOrCreateCOWVolumeForContainerArgsForCall(0) 84 Expect(volumeSpec).To(Equal(worker.VolumeSpec{ 85 Strategy: cowStrategy, 86 Privileged: true, 87 })) 88 Expect(container).To(Equal(fakeContainer)) 89 Expect(volume).To(Equal(fakeArtifactVolume)) 90 Expect(teamID).To(Equal(42)) 91 Expect(path).To(Equal("/")) 92 }) 93 94 It("returns fetched image", func() { 95 fetchedImage, err := img.FetchForContainer(ctx, logger, fakeContainer) 96 Expect(err).NotTo(HaveOccurred()) 97 98 Expect(fetchedImage).To(Equal(worker.FetchedImage{ 99 Metadata: worker.ImageMetadata{ 100 Env: []string{"A=1", "B=2"}, 101 User: "image-volume-user", 102 }, 103 URL: "raw://some-path/rootfs", 104 Privileged: true, 105 })) 106 }) 107 }) 108 109 Describe("imageProvidedByPreviousStepOnDifferentWorker", func() { 110 var ( 111 fakeArtifactVolume *workerfakes.FakeVolume 112 fakeImageArtifactSource *workerfakes.FakeStreamableArtifactSource 113 fakeContainerRootfsVolume *workerfakes.FakeVolume 114 ) 115 116 BeforeEach(func() { 117 fakeArtifactVolume = new(workerfakes.FakeVolume) 118 fakeImageArtifactSource = new(workerfakes.FakeStreamableArtifactSource) 119 fakeImageArtifactSource.ExistsOnReturns(fakeArtifactVolume, false, nil) 120 metadataReader := ioutil.NopCloser(strings.NewReader( 121 `{"env": ["A=1", "B=2"], "user":"image-volume-user"}`, 122 )) 123 fakeImageArtifactSource.StreamFileReturns(metadataReader, nil) 124 125 fakeContainerRootfsVolume = new(workerfakes.FakeVolume) 126 fakeContainerRootfsVolume.PathReturns("some-path") 127 fakeVolumeClient.FindOrCreateVolumeForContainerReturns(fakeContainerRootfsVolume, nil) 128 129 var err error 130 img, err = imageFactory.GetImage( 131 logger, 132 fakeWorker, 133 fakeVolumeClient, 134 worker.ImageSpec{ 135 ImageArtifactSource: fakeImageArtifactSource, 136 Privileged: true, 137 }, 138 42, 139 ) 140 Expect(err).NotTo(HaveOccurred()) 141 }) 142 143 It("finds or creates volume", func() { 144 _, err := img.FetchForContainer(ctx, logger, fakeContainer) 145 Expect(err).NotTo(HaveOccurred()) 146 Expect(fakeVolumeClient.FindOrCreateVolumeForContainerCallCount()).To(Equal(1)) 147 _, volumeSpec, container, teamID, path := fakeVolumeClient.FindOrCreateVolumeForContainerArgsForCall(0) 148 Expect(volumeSpec).To(Equal(worker.VolumeSpec{ 149 Strategy: baggageclaim.EmptyStrategy{}, 150 Privileged: true, 151 })) 152 Expect(container).To(Equal(fakeContainer)) 153 Expect(teamID).To(Equal(42)) 154 Expect(path).To(Equal("/")) 155 }) 156 157 Context("when VolumeClient fails to create a volume", func() { 158 BeforeEach(func() { 159 fakeVolumeClient.FindOrCreateVolumeForContainerReturns(nil, errors.New("some error")) 160 }) 161 162 It("returns an error", func() { 163 _, err := img.FetchForContainer(ctx, logger, fakeContainer) 164 Expect(err).To(HaveOccurred()) 165 Expect(fakeVolumeClient.FindOrCreateVolumeForContainerCallCount()).To(Equal(1)) 166 }) 167 }) 168 169 It("streams the volume from another worker", func() { 170 _, err := img.FetchForContainer(ctx, logger, fakeContainer) 171 Expect(err).NotTo(HaveOccurred()) 172 173 Expect(fakeImageArtifactSource.StreamToCallCount()).To(Equal(1)) 174 175 _, artifactDestination := fakeImageArtifactSource.StreamToArgsForCall(0) 176 artifactDestination.StreamIn(context.TODO(), "fake-path", baggageclaim.GzipEncoding, strings.NewReader("fake-tar-stream")) 177 Expect(fakeContainerRootfsVolume.StreamInCallCount()).To(Equal(1)) 178 }) 179 180 Context("when streamTo fails", func() { 181 BeforeEach(func() { 182 fakeImageArtifactSource.StreamFileReturns(nil, errors.New("some error")) 183 }) 184 185 It("returns an error", func() { 186 _, err := img.FetchForContainer(ctx, logger, fakeContainer) 187 Expect(err).To(HaveOccurred()) 188 Expect(fakeImageArtifactSource.StreamToCallCount()).To(Equal(1)) 189 }) 190 }) 191 192 It("returns fetched image", func() { 193 fetchedImage, err := img.FetchForContainer(ctx, logger, fakeContainer) 194 Expect(err).NotTo(HaveOccurred()) 195 196 Expect(fetchedImage).To(Equal(worker.FetchedImage{ 197 Metadata: worker.ImageMetadata{ 198 Env: []string{"A=1", "B=2"}, 199 User: "image-volume-user", 200 }, 201 URL: "raw://some-path/rootfs", 202 Privileged: true, 203 })) 204 }) 205 }) 206 207 Describe("imageFromBaseResourceType", func() { 208 var cowStrategy baggageclaim.COWStrategy 209 var workerResourceType atc.WorkerResourceType 210 var fakeContainerRootfsVolume *workerfakes.FakeVolume 211 var fakeImportVolume *workerfakes.FakeVolume 212 213 BeforeEach(func() { 214 fakeContainerRootfsVolume = new(workerfakes.FakeVolume) 215 fakeContainerRootfsVolume.PathReturns("some-path") 216 fakeVolumeClient.FindOrCreateCOWVolumeForContainerReturns(fakeContainerRootfsVolume, nil) 217 218 fakeImportVolume = new(workerfakes.FakeVolume) 219 cowStrategy = baggageclaim.COWStrategy{ 220 Parent: new(baggageclaimfakes.FakeVolume), 221 } 222 fakeImportVolume.COWStrategyReturns(cowStrategy) 223 fakeVolumeClient.FindOrCreateVolumeForBaseResourceTypeReturns(fakeImportVolume, nil) 224 225 workerResourceType = atc.WorkerResourceType{ 226 Type: "some-base-resource-type", 227 Image: "some-base-image-path", 228 Version: "some-base-version", 229 Privileged: false, 230 } 231 232 fakeWorker.ResourceTypesReturns([]atc.WorkerResourceType{workerResourceType}) 233 234 fakeWorker.NameReturns("some-worker-name") 235 236 var err error 237 img, err = imageFactory.GetImage( 238 logger, 239 fakeWorker, 240 fakeVolumeClient, 241 worker.ImageSpec{ 242 ResourceType: "some-base-resource-type", 243 }, 244 42, 245 ) 246 Expect(err).NotTo(HaveOccurred()) 247 }) 248 249 It("finds or creates unprivileged import volume", func() { 250 _, err := img.FetchForContainer(ctx, logger, fakeContainer) 251 Expect(err).NotTo(HaveOccurred()) 252 Expect(fakeVolumeClient.FindOrCreateVolumeForBaseResourceTypeCallCount()).To(Equal(1)) 253 _, volumeSpec, teamID, resourceTypeName := fakeVolumeClient.FindOrCreateVolumeForBaseResourceTypeArgsForCall(0) 254 Expect(volumeSpec).To(Equal(worker.VolumeSpec{ 255 Strategy: baggageclaim.ImportStrategy{ 256 Path: "some-base-image-path", 257 }, 258 Privileged: false, 259 })) 260 Expect(teamID).To(Equal(42)) 261 Expect(resourceTypeName).To(Equal("some-base-resource-type")) 262 }) 263 264 It("finds or creates unprivileged cow volume", func() { 265 _, err := img.FetchForContainer(ctx, logger, fakeContainer) 266 Expect(err).NotTo(HaveOccurred()) 267 Expect(fakeVolumeClient.FindOrCreateCOWVolumeForContainerCallCount()).To(Equal(1)) 268 _, volumeSpec, container, volume, teamID, path := fakeVolumeClient.FindOrCreateCOWVolumeForContainerArgsForCall(0) 269 Expect(volumeSpec).To(Equal(worker.VolumeSpec{ 270 Strategy: cowStrategy, 271 Privileged: false, 272 })) 273 Expect(teamID).To(Equal(42)) 274 Expect(container).To(Equal(fakeContainer)) 275 Expect(volume).To(Equal(fakeImportVolume)) 276 Expect(path).To(Equal("/")) 277 }) 278 279 It("returns fetched image", func() { 280 fetchedImage, err := img.FetchForContainer(ctx, logger, fakeContainer) 281 Expect(err).NotTo(HaveOccurred()) 282 283 Expect(fetchedImage).To(Equal(worker.FetchedImage{ 284 Metadata: worker.ImageMetadata{}, 285 URL: "raw://some-path", 286 Version: atc.Version{"some-base-resource-type": "some-base-version"}, 287 Privileged: false, 288 })) 289 }) 290 291 Context("when the worker base resource type is privileged", func() { 292 BeforeEach(func() { 293 workerResourceType.Privileged = true 294 fakeWorker.ResourceTypesReturns([]atc.WorkerResourceType{workerResourceType}) 295 }) 296 297 It("finds or creates privileged import volume", func() { 298 _, err := img.FetchForContainer(ctx, logger, fakeContainer) 299 Expect(err).NotTo(HaveOccurred()) 300 Expect(fakeVolumeClient.FindOrCreateVolumeForBaseResourceTypeCallCount()).To(Equal(1)) 301 _, volumeSpec, teamID, resourceTypeName := fakeVolumeClient.FindOrCreateVolumeForBaseResourceTypeArgsForCall(0) 302 Expect(volumeSpec).To(Equal(worker.VolumeSpec{ 303 Strategy: baggageclaim.ImportStrategy{ 304 Path: "some-base-image-path", 305 }, 306 Privileged: true, 307 })) 308 Expect(teamID).To(Equal(42)) 309 Expect(resourceTypeName).To(Equal("some-base-resource-type")) 310 }) 311 312 It("finds or creates privileged cow volume", func() { 313 _, err := img.FetchForContainer(ctx, logger, fakeContainer) 314 Expect(err).NotTo(HaveOccurred()) 315 Expect(fakeVolumeClient.FindOrCreateCOWVolumeForContainerCallCount()).To(Equal(1)) 316 _, volumeSpec, container, volume, teamID, path := fakeVolumeClient.FindOrCreateCOWVolumeForContainerArgsForCall(0) 317 Expect(volumeSpec).To(Equal(worker.VolumeSpec{ 318 Strategy: cowStrategy, 319 Privileged: true, 320 })) 321 Expect(teamID).To(Equal(42)) 322 Expect(container).To(Equal(fakeContainer)) 323 Expect(volume).To(Equal(fakeImportVolume)) 324 Expect(path).To(Equal("/")) 325 }) 326 327 It("returns privileged fetched image", func() { 328 fetchedImage, err := img.FetchForContainer(ctx, logger, fakeContainer) 329 Expect(err).NotTo(HaveOccurred()) 330 331 Expect(fetchedImage).To(Equal(worker.FetchedImage{ 332 Metadata: worker.ImageMetadata{}, 333 URL: "raw://some-path", 334 Version: atc.Version{"some-base-resource-type": "some-base-version"}, 335 Privileged: true, 336 })) 337 }) 338 }) 339 }) 340 341 Describe("imageFromRootfsURI", func() { 342 BeforeEach(func() { 343 var err error 344 img, err = imageFactory.GetImage( 345 logger, 346 fakeWorker, 347 fakeVolumeClient, 348 worker.ImageSpec{ 349 ImageURL: "some-image-url", 350 }, 351 42, 352 ) 353 Expect(err).NotTo(HaveOccurred()) 354 }) 355 356 It("returns the fetched image", func() { 357 fetchedImage, err := img.FetchForContainer(ctx, logger, fakeContainer) 358 Expect(err).NotTo(HaveOccurred()) 359 360 Expect(fetchedImage).To(Equal(worker.FetchedImage{ 361 URL: "some-image-url", 362 })) 363 }) 364 }) 365 })