zotregistry.io/zot@v1.4.4-0.20231124084042-02a8ed785457/pkg/extensions/sync/sync_internal_test.go (about) 1 //go:build sync 2 // +build sync 3 4 package sync 5 6 import ( 7 "bytes" 8 "context" 9 "encoding/json" 10 "fmt" 11 "os" 12 "path" 13 "testing" 14 15 dockerManifest "github.com/containers/image/v5/manifest" 16 "github.com/containers/image/v5/oci/layout" 17 "github.com/containers/image/v5/types" 18 godigest "github.com/opencontainers/go-digest" 19 ispec "github.com/opencontainers/image-spec/specs-go/v1" 20 "github.com/rs/zerolog" 21 . "github.com/smartystreets/goconvey/convey" 22 23 zerr "zotregistry.io/zot/errors" 24 "zotregistry.io/zot/pkg/extensions/config" 25 syncconf "zotregistry.io/zot/pkg/extensions/config/sync" 26 "zotregistry.io/zot/pkg/extensions/lint" 27 "zotregistry.io/zot/pkg/extensions/monitoring" 28 client "zotregistry.io/zot/pkg/extensions/sync/httpclient" 29 "zotregistry.io/zot/pkg/log" 30 mTypes "zotregistry.io/zot/pkg/meta/types" 31 "zotregistry.io/zot/pkg/storage" 32 "zotregistry.io/zot/pkg/storage/cache" 33 storageConstants "zotregistry.io/zot/pkg/storage/constants" 34 "zotregistry.io/zot/pkg/storage/local" 35 . "zotregistry.io/zot/pkg/test/image-utils" 36 "zotregistry.io/zot/pkg/test/inject" 37 "zotregistry.io/zot/pkg/test/mocks" 38 ociutils "zotregistry.io/zot/pkg/test/oci-utils" 39 ) 40 41 const ( 42 testImage = "zot-test" 43 testImageTag = "0.0.1" 44 45 host = "127.0.0.1:45117" 46 ) 47 48 var ErrTestError = fmt.Errorf("testError") 49 50 func TestInjectSyncUtils(t *testing.T) { 51 Convey("Inject errors in utils functions", t, func() { 52 repositoryReference := fmt.Sprintf("%s/%s", host, testImage) 53 ref, err := parseRepositoryReference(repositoryReference) 54 So(err, ShouldBeNil) 55 So(ref.Name(), ShouldEqual, repositoryReference) 56 57 injected := inject.InjectFailure(0) 58 if injected { 59 _, err = getRepoTags(context.Background(), &types.SystemContext{}, host, testImage) 60 So(err, ShouldNotBeNil) 61 } 62 63 injected = inject.InjectFailure(0) 64 _, err = getPolicyContext(log.NewLogger("debug", "")) 65 if injected { 66 So(err, ShouldNotBeNil) 67 } else { 68 So(err, ShouldBeNil) 69 } 70 71 log := log.Logger{Logger: zerolog.New(os.Stdout)} 72 metrics := monitoring.NewMetricsServer(false, log) 73 imageStore := local.NewImageStore(t.TempDir(), false, false, log, metrics, nil, nil) 74 injected = inject.InjectFailure(0) 75 76 ols := NewOciLayoutStorage(storage.StoreController{DefaultStore: imageStore}) 77 _, err = ols.GetImageReference(testImage, testImageTag) 78 if injected { 79 So(err, ShouldNotBeNil) 80 } else { 81 So(err, ShouldBeNil) 82 } 83 }) 84 } 85 86 func TestSyncInternal(t *testing.T) { 87 Convey("Verify parseRepositoryReference func", t, func() { 88 repositoryReference := fmt.Sprintf("%s/%s", host, testImage) 89 ref, err := parseRepositoryReference(repositoryReference) 90 So(err, ShouldBeNil) 91 So(ref.Name(), ShouldEqual, repositoryReference) 92 93 repositoryReference = fmt.Sprintf("%s/%s:tagged", host, testImage) 94 _, err = parseRepositoryReference(repositoryReference) 95 So(err, ShouldEqual, zerr.ErrInvalidRepositoryName) 96 97 repositoryReference = fmt.Sprintf("http://%s/%s", host, testImage) 98 _, err = parseRepositoryReference(repositoryReference) 99 So(err, ShouldNotBeNil) 100 101 repositoryReference = fmt.Sprintf("docker://%s/%s", host, testImage) 102 _, err = parseRepositoryReference(repositoryReference) 103 So(err, ShouldNotBeNil) 104 105 _, err = getFileCredentials("/path/to/inexistent/file") 106 So(err, ShouldNotBeNil) 107 108 tempFile, err := os.CreateTemp("", "sync-credentials-") 109 if err != nil { 110 panic(err) 111 } 112 113 content := []byte(`{`) 114 if err := os.WriteFile(tempFile.Name(), content, 0o600); err != nil { 115 panic(err) 116 } 117 118 _, err = getFileCredentials(tempFile.Name()) 119 So(err, ShouldNotBeNil) 120 121 srcCtx := &types.SystemContext{} 122 _, err = getRepoTags(context.Background(), srcCtx, host, testImage) 123 So(err, ShouldNotBeNil) 124 125 _, err = getRepoTags(context.Background(), srcCtx, host, testImage) 126 So(err, ShouldNotBeNil) 127 128 _, err = getFileCredentials("/invalid/path/to/file") 129 So(err, ShouldNotBeNil) 130 131 ok := isSupportedMediaType("unknown") 132 So(ok, ShouldBeFalse) 133 }) 134 } 135 136 func TestRemoteRegistry(t *testing.T) { 137 Convey("test remote registry", t, func() { 138 logger := log.NewLogger("debug", "") 139 cfg := client.Config{ 140 URL: "url", 141 TLSVerify: false, 142 } 143 144 client, err := client.New(cfg, logger) 145 So(err, ShouldBeNil) 146 147 remote := NewRemoteRegistry(client, logger) 148 imageRef, err := layout.NewReference("dir", "image") 149 So(err, ShouldBeNil) 150 _, _, _, err = remote.GetManifestContent(imageRef) 151 So(err, ShouldNotBeNil) 152 153 tags, err := remote.GetRepoTags("repo") 154 So(tags, ShouldBeEmpty) 155 So(err, ShouldNotBeNil) 156 }) 157 } 158 159 func TestService(t *testing.T) { 160 Convey("trigger fetch tags error", t, func() { 161 conf := syncconf.RegistryConfig{ 162 URLs: []string{"http://localhost"}, 163 } 164 165 service, err := New(conf, "", storage.StoreController{}, mocks.MetaDBMock{}, log.Logger{}) 166 So(err, ShouldBeNil) 167 168 err = service.SyncRepo(context.Background(), "repo") 169 So(err, ShouldNotBeNil) 170 }) 171 } 172 173 func TestLocalRegistry(t *testing.T) { 174 Convey("make StoreController", t, func() { 175 dir := t.TempDir() 176 177 log := log.NewLogger("debug", "") 178 metrics := monitoring.NewMetricsServer(false, log) 179 cacheDriver, _ := storage.Create("boltdb", cache.BoltDBDriverParameters{ 180 RootDir: dir, 181 Name: "cache", 182 UseRelPaths: true, 183 }, log) 184 185 syncImgStore := local.NewImageStore(dir, true, true, log, metrics, nil, cacheDriver) 186 repoName := "repo" 187 188 registry := NewLocalRegistry(storage.StoreController{DefaultStore: syncImgStore}, nil, log) 189 imageReference, err := registry.GetImageReference(repoName, "1.0") 190 So(err, ShouldBeNil) 191 So(imageReference, ShouldNotBeNil) 192 193 imgStore := getImageStoreFromImageReference(imageReference, repoName, "1.0") 194 195 // create a blob/layer 196 upload, err := imgStore.NewBlobUpload(repoName) 197 So(err, ShouldBeNil) 198 So(upload, ShouldNotBeEmpty) 199 200 content := []byte("this is a blob1") 201 buf := bytes.NewBuffer(content) 202 buflen := buf.Len() 203 digest := godigest.FromBytes(content) 204 So(digest, ShouldNotBeNil) 205 blob, err := imgStore.PutBlobChunkStreamed(repoName, upload, buf) 206 So(err, ShouldBeNil) 207 So(blob, ShouldEqual, buflen) 208 bdgst1 := digest 209 bsize1 := len(content) 210 211 err = imgStore.FinishBlobUpload(repoName, upload, buf, digest) 212 So(err, ShouldBeNil) 213 So(blob, ShouldEqual, buflen) 214 215 // push index image 216 var index ispec.Index 217 index.SchemaVersion = 2 218 index.MediaType = ispec.MediaTypeImageIndex 219 220 for i := 0; i < 4; i++ { 221 // upload image config blob 222 upload, err := imgStore.NewBlobUpload(repoName) 223 So(err, ShouldBeNil) 224 So(upload, ShouldNotBeEmpty) 225 226 cblob, cdigest := GetRandomImageConfig() 227 buf := bytes.NewBuffer(cblob) 228 buflen := buf.Len() 229 blob, err := imgStore.PutBlobChunkStreamed(repoName, upload, buf) 230 So(err, ShouldBeNil) 231 So(blob, ShouldEqual, buflen) 232 233 err = imgStore.FinishBlobUpload(repoName, upload, buf, cdigest) 234 So(err, ShouldBeNil) 235 So(blob, ShouldEqual, buflen) 236 237 // create a manifest 238 manifest := ispec.Manifest{ 239 Config: ispec.Descriptor{ 240 MediaType: ispec.MediaTypeImageConfig, 241 Digest: cdigest, 242 Size: int64(len(cblob)), 243 }, 244 Layers: []ispec.Descriptor{ 245 { 246 MediaType: ispec.MediaTypeImageLayer, 247 Digest: bdgst1, 248 Size: int64(bsize1), 249 }, 250 }, 251 } 252 manifest.SchemaVersion = 2 253 content, err = json.Marshal(manifest) 254 So(err, ShouldBeNil) 255 digest = godigest.FromBytes(content) 256 So(digest, ShouldNotBeNil) 257 _, _, err = imgStore.PutImageManifest(repoName, digest.String(), ispec.MediaTypeImageManifest, content) 258 So(err, ShouldBeNil) 259 260 index.Manifests = append(index.Manifests, ispec.Descriptor{ 261 Digest: digest, 262 MediaType: ispec.MediaTypeImageManifest, 263 Size: int64(len(content)), 264 }) 265 } 266 267 // upload index image 268 indexContent, err := json.Marshal(index) 269 So(err, ShouldBeNil) 270 indexDigest := godigest.FromBytes(indexContent) 271 So(indexDigest, ShouldNotBeNil) 272 273 _, _, err = imgStore.PutImageManifest(repoName, "1.0", ispec.MediaTypeImageIndex, indexContent) 274 So(err, ShouldBeNil) 275 276 Convey("sync index image", func() { 277 ok, err := registry.CanSkipImage(repoName, "1.0", indexDigest) 278 So(ok, ShouldBeFalse) 279 So(err, ShouldBeNil) 280 281 err = registry.CommitImage(imageReference, repoName, "1.0") 282 So(err, ShouldBeNil) 283 }) 284 285 Convey("trigger GetImageManifest error in CommitImage()", func() { 286 err = os.Chmod(imgStore.BlobPath(repoName, indexDigest), 0o000) 287 So(err, ShouldBeNil) 288 289 err = registry.CommitImage(imageReference, repoName, "1.0") 290 So(err, ShouldNotBeNil) 291 }) 292 293 Convey("trigger linter error in CommitImage()", func() { 294 defaultVal := true 295 linter := lint.NewLinter(&config.LintConfig{ 296 BaseConfig: config.BaseConfig{ 297 Enable: &defaultVal, 298 }, 299 MandatoryAnnotations: []string{"annot1"}, 300 }, log) 301 302 syncImgStore := local.NewImageStore(dir, true, true, log, metrics, linter, cacheDriver) 303 repoName := "repo" 304 305 registry := NewLocalRegistry(storage.StoreController{DefaultStore: syncImgStore}, nil, log) 306 307 err = registry.CommitImage(imageReference, repoName, "1.0") 308 So(err, ShouldBeNil) 309 }) 310 311 Convey("trigger GetBlobContent on manifest error in CommitImage()", func() { 312 err = os.Chmod(imgStore.BlobPath(repoName, digest), 0o000) 313 So(err, ShouldBeNil) 314 315 err = registry.CommitImage(imageReference, repoName, "1.0") 316 So(err, ShouldNotBeNil) 317 }) 318 319 Convey("trigger copyBlob() error in CommitImage()", func() { 320 err = os.Chmod(imgStore.BlobPath(repoName, bdgst1), 0o000) 321 So(err, ShouldBeNil) 322 323 err = registry.CommitImage(imageReference, repoName, "1.0") 324 So(err, ShouldNotBeNil) 325 }) 326 327 Convey("trigger PutImageManifest error on index manifest in CommitImage()", func() { 328 err = os.MkdirAll(syncImgStore.BlobPath(repoName, indexDigest), storageConstants.DefaultDirPerms) 329 So(err, ShouldBeNil) 330 331 err = os.Chmod(syncImgStore.BlobPath(repoName, indexDigest), 0o000) 332 So(err, ShouldBeNil) 333 334 err = registry.CommitImage(imageReference, repoName, "1.0") 335 So(err, ShouldNotBeNil) 336 }) 337 338 Convey("trigger metaDB error on index manifest in CommitImage()", func() { 339 registry := NewLocalRegistry(storage.StoreController{DefaultStore: syncImgStore}, mocks.MetaDBMock{ 340 SetRepoReferenceFn: func(ctx context.Context, repo string, reference string, imageMeta mTypes.ImageMeta) error { 341 if reference == "1.0" { 342 return zerr.ErrRepoMetaNotFound 343 } 344 345 return nil 346 }, 347 }, log) 348 349 err = registry.CommitImage(imageReference, repoName, "1.0") 350 So(err, ShouldNotBeNil) 351 }) 352 353 Convey("trigger metaDB error on image manifest in CommitImage()", func() { 354 registry := NewLocalRegistry(storage.StoreController{DefaultStore: syncImgStore}, mocks.MetaDBMock{ 355 SetRepoReferenceFn: func(ctx context.Context, repo, reference string, imageMeta mTypes.ImageMeta) error { 356 return zerr.ErrRepoMetaNotFound 357 }, 358 }, log) 359 360 err = registry.CommitImage(imageReference, repoName, "1.0") 361 So(err, ShouldNotBeNil) 362 }) 363 364 Convey("push image", func() { 365 imageReference, err := registry.GetImageReference(repoName, "2.0") 366 So(err, ShouldBeNil) 367 So(imageReference, ShouldNotBeNil) 368 369 imgStore := getImageStoreFromImageReference(imageReference, repoName, "2.0") 370 371 // upload image 372 373 // create a blob/layer 374 upload, err := imgStore.NewBlobUpload(repoName) 375 So(err, ShouldBeNil) 376 So(upload, ShouldNotBeEmpty) 377 378 content := []byte("this is a blob1") 379 buf := bytes.NewBuffer(content) 380 buflen := buf.Len() 381 digest := godigest.FromBytes(content) 382 So(digest, ShouldNotBeNil) 383 blob, err := imgStore.PutBlobChunkStreamed(repoName, upload, buf) 384 So(err, ShouldBeNil) 385 So(blob, ShouldEqual, buflen) 386 bdgst1 := digest 387 bsize1 := len(content) 388 389 err = imgStore.FinishBlobUpload(repoName, upload, buf, digest) 390 So(err, ShouldBeNil) 391 So(blob, ShouldEqual, buflen) 392 393 // upload image config blob 394 upload, err = imgStore.NewBlobUpload(repoName) 395 So(err, ShouldBeNil) 396 So(upload, ShouldNotBeEmpty) 397 398 cblob, cdigest := GetRandomImageConfig() 399 buf = bytes.NewBuffer(cblob) 400 buflen = buf.Len() 401 blob, err = imgStore.PutBlobChunkStreamed(repoName, upload, buf) 402 So(err, ShouldBeNil) 403 So(blob, ShouldEqual, buflen) 404 405 err = imgStore.FinishBlobUpload(repoName, upload, buf, cdigest) 406 So(err, ShouldBeNil) 407 So(blob, ShouldEqual, buflen) 408 409 // create a manifest 410 manifest := ispec.Manifest{ 411 Config: ispec.Descriptor{ 412 MediaType: ispec.MediaTypeImageConfig, 413 Digest: cdigest, 414 Size: int64(len(cblob)), 415 }, 416 Layers: []ispec.Descriptor{ 417 { 418 MediaType: ispec.MediaTypeImageLayer, 419 Digest: bdgst1, 420 Size: int64(bsize1), 421 }, 422 }, 423 } 424 manifest.SchemaVersion = 2 425 content, err = json.Marshal(manifest) 426 So(err, ShouldBeNil) 427 digest = godigest.FromBytes(content) 428 So(digest, ShouldNotBeNil) 429 430 _, _, err = imgStore.PutImageManifest(repoName, "2.0", ispec.MediaTypeImageManifest, content) 431 So(err, ShouldBeNil) 432 433 Convey("sync image", func() { 434 ok, err := registry.CanSkipImage(repoName, "2.0", digest) 435 So(ok, ShouldBeFalse) 436 So(err, ShouldBeNil) 437 438 err = registry.CommitImage(imageReference, repoName, "2.0") 439 So(err, ShouldBeNil) 440 }) 441 }) 442 }) 443 } 444 445 func TestConvertDockerToOCI(t *testing.T) { 446 Convey("test converting docker to oci functions", t, func() { 447 dir := t.TempDir() 448 449 srcStorageCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", "")) 450 451 err := WriteImageToFileSystem(CreateDefaultImage(), "zot-test", "0.0.1", srcStorageCtlr) 452 So(err, ShouldBeNil) 453 454 imageRef, err := layout.NewReference(path.Join(dir, "zot-test"), "0.0.1") 455 So(err, ShouldBeNil) 456 457 imageSource, err := imageRef.NewImageSource(context.Background(), &types.SystemContext{}) 458 So(err, ShouldBeNil) 459 460 defer imageSource.Close() 461 462 Convey("trigger Unmarshal manifest error", func() { 463 _, err = convertDockerManifestToOCI(imageSource, []byte{}) 464 So(err, ShouldNotBeNil) 465 }) 466 467 Convey("trigger getImageConfigContent() error", func() { 468 manifestBuf, _, err := imageSource.GetManifest(context.Background(), nil) 469 So(err, ShouldBeNil) 470 471 var manifest ispec.Manifest 472 473 err = json.Unmarshal(manifestBuf, &manifest) 474 So(err, ShouldBeNil) 475 476 err = os.Chmod(path.Join(dir, "zot-test", "blobs/sha256", manifest.Config.Digest.Encoded()), 0o000) 477 So(err, ShouldBeNil) 478 479 _, err = convertDockerManifestToOCI(imageSource, manifestBuf) 480 So(err, ShouldNotBeNil) 481 }) 482 483 Convey("trigger Unmarshal config error", func() { 484 manifestBuf, _, err := imageSource.GetManifest(context.Background(), nil) 485 So(err, ShouldBeNil) 486 487 var manifest ispec.Manifest 488 489 err = json.Unmarshal(manifestBuf, &manifest) 490 So(err, ShouldBeNil) 491 492 err = os.WriteFile(path.Join(dir, "zot-test", "blobs/sha256", manifest.Config.Digest.Encoded()), 493 []byte{}, storageConstants.DefaultFilePerms) 494 So(err, ShouldBeNil) 495 496 _, err = convertDockerManifestToOCI(imageSource, manifestBuf) 497 So(err, ShouldNotBeNil) 498 }) 499 500 Convey("trigger convertDockerLayersToOCI error", func() { 501 manifestBuf, _, err := imageSource.GetManifest(context.Background(), nil) 502 So(err, ShouldBeNil) 503 504 var manifest ispec.Manifest 505 506 err = json.Unmarshal(manifestBuf, &manifest) 507 So(err, ShouldBeNil) 508 509 manifestDigest := godigest.FromBytes(manifestBuf) 510 511 manifest.Layers[0].MediaType = "unknown" 512 513 newManifest, err := json.Marshal(manifest) 514 So(err, ShouldBeNil) 515 516 err = os.WriteFile(path.Join(dir, "zot-test", "blobs/sha256", manifestDigest.Encoded()), 517 newManifest, storageConstants.DefaultFilePerms) 518 So(err, ShouldBeNil) 519 520 _, err = convertDockerManifestToOCI(imageSource, manifestBuf) 521 So(err, ShouldNotBeNil) 522 }) 523 524 Convey("trigger convertDockerIndexToOCI error", func() { 525 manifestBuf, _, err := imageSource.GetManifest(context.Background(), nil) 526 So(err, ShouldBeNil) 527 528 _, err = convertDockerIndexToOCI(imageSource, manifestBuf) 529 So(err, ShouldNotBeNil) 530 531 // make zot-test image an index image 532 533 var manifest ispec.Manifest 534 535 err = json.Unmarshal(manifestBuf, &manifest) 536 So(err, ShouldBeNil) 537 538 dockerNewManifest := ispec.Manifest{ 539 MediaType: dockerManifest.DockerV2Schema2MediaType, 540 Config: manifest.Config, 541 Layers: manifest.Layers, 542 } 543 544 dockerNewManifestBuf, err := json.Marshal(dockerNewManifest) 545 So(err, ShouldBeNil) 546 547 dockerManifestDigest := godigest.FromBytes(manifestBuf) 548 549 err = os.WriteFile(path.Join(dir, "zot-test", "blobs/sha256", dockerManifestDigest.Encoded()), 550 dockerNewManifestBuf, storageConstants.DefaultFilePerms) 551 So(err, ShouldBeNil) 552 553 var index ispec.Index 554 555 index.Manifests = append(index.Manifests, ispec.Descriptor{ 556 Digest: dockerManifestDigest, 557 Size: int64(len(dockerNewManifestBuf)), 558 MediaType: dockerManifest.DockerV2Schema2MediaType, 559 }) 560 561 index.MediaType = dockerManifest.DockerV2ListMediaType 562 563 dockerIndexBuf, err := json.Marshal(index) 564 So(err, ShouldBeNil) 565 566 dockerIndexDigest := godigest.FromBytes(dockerIndexBuf) 567 568 err = os.WriteFile(path.Join(dir, "zot-test", "blobs/sha256", dockerIndexDigest.Encoded()), 569 dockerIndexBuf, storageConstants.DefaultFilePerms) 570 So(err, ShouldBeNil) 571 572 // write index.json 573 574 var indexJSON ispec.Index 575 576 indexJSONBuf, err := os.ReadFile(path.Join(dir, "zot-test", "index.json")) 577 So(err, ShouldBeNil) 578 579 err = json.Unmarshal(indexJSONBuf, &indexJSON) 580 So(err, ShouldBeNil) 581 582 indexJSON.Manifests = append(indexJSON.Manifests, ispec.Descriptor{ 583 Digest: dockerIndexDigest, 584 Size: int64(len(dockerIndexBuf)), 585 MediaType: ispec.MediaTypeImageIndex, 586 Annotations: map[string]string{ 587 ispec.AnnotationRefName: "0.0.2", 588 }, 589 }) 590 591 indexJSONBuf, err = json.Marshal(indexJSON) 592 So(err, ShouldBeNil) 593 594 err = os.WriteFile(path.Join(dir, "zot-test", "index.json"), indexJSONBuf, storageConstants.DefaultFilePerms) 595 So(err, ShouldBeNil) 596 597 imageRef, err := layout.NewReference(path.Join(dir, "zot-test"), "0.0.2") 598 So(err, ShouldBeNil) 599 600 imageSource, err := imageRef.NewImageSource(context.Background(), &types.SystemContext{}) 601 So(err, ShouldBeNil) 602 603 _, err = convertDockerIndexToOCI(imageSource, dockerIndexBuf) 604 So(err, ShouldNotBeNil) 605 606 err = os.Chmod(path.Join(dir, "zot-test", "blobs/sha256", dockerManifestDigest.Encoded()), 0o000) 607 So(err, ShouldBeNil) 608 609 _, err = convertDockerIndexToOCI(imageSource, dockerIndexBuf) 610 So(err, ShouldNotBeNil) 611 }) 612 }) 613 } 614 615 func TestConvertDockerLayersToOCI(t *testing.T) { 616 Convey("test converting docker to oci functions", t, func() { 617 dockerLayers := []ispec.Descriptor{ 618 { 619 MediaType: dockerManifest.DockerV2Schema2ForeignLayerMediaType, 620 }, 621 { 622 MediaType: dockerManifest.DockerV2Schema2ForeignLayerMediaTypeGzip, 623 }, 624 { 625 MediaType: dockerManifest.DockerV2SchemaLayerMediaTypeUncompressed, 626 }, 627 { 628 MediaType: dockerManifest.DockerV2Schema2LayerMediaType, 629 }, 630 } 631 632 err := convertDockerLayersToOCI(dockerLayers) 633 So(err, ShouldBeNil) 634 635 So(dockerLayers[0].MediaType, ShouldEqual, ispec.MediaTypeImageLayerNonDistributable) //nolint: staticcheck 636 So(dockerLayers[1].MediaType, ShouldEqual, ispec.MediaTypeImageLayerNonDistributableGzip) //nolint: staticcheck 637 So(dockerLayers[2].MediaType, ShouldEqual, ispec.MediaTypeImageLayer) 638 So(dockerLayers[3].MediaType, ShouldEqual, ispec.MediaTypeImageLayerGzip) 639 }) 640 }