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  }