0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2024-12-16 21:56:37 -05:00
zot/pkg/meta/parse_test.go
Ramkumar Chinchani cb2af94b0b
feat: add support for docker images (#2714)
* feat: add support for docker images

Issue #724

A new config section under "HTTP" called "Compat" is added which
currently takes a list of possible compatible legacy media-types.

https://github.com/opencontainers/image-spec/blob/main/media-types.md#compatibility-matrix

Only "docker2s2" (Docker Manifest V2 Schema V2) is currently supported.

Garbage collection also needs to be made aware of non-OCI compatible
layer types.
feat: add cve support for non-OCI compatible layer types

Signed-off-by: Ramkumar Chinchani <rchincha@cisco.com>

* 

Signed-off-by: Ramkumar Chinchani <rchincha@cisco.com>

* test: add more docker compat tests

Signed-off-by: Ramkumar Chinchani <rchincha@cisco.com>

* feat: add additional validation checks for non-OCI images

Signed-off-by: Ramkumar Chinchani <rchincha@cisco.com>

* ci: make "full" images docker-compatible

Signed-off-by: Ramkumar Chinchani <rchincha@cisco.com>

---------

Signed-off-by: Ramkumar Chinchani <rchincha@cisco.com>
2024-10-31 09:44:04 +02:00

702 lines
22 KiB
Go

package meta_test
import (
"context"
"encoding/json"
"fmt"
"io"
"os"
"path"
"path/filepath"
"testing"
"time"
godigest "github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1"
. "github.com/smartystreets/goconvey/convey"
zcommon "zotregistry.dev/zot/pkg/common"
"zotregistry.dev/zot/pkg/extensions/monitoring"
"zotregistry.dev/zot/pkg/log"
"zotregistry.dev/zot/pkg/meta"
"zotregistry.dev/zot/pkg/meta/boltdb"
"zotregistry.dev/zot/pkg/meta/dynamodb"
mTypes "zotregistry.dev/zot/pkg/meta/types"
"zotregistry.dev/zot/pkg/storage"
"zotregistry.dev/zot/pkg/storage/local"
storageTypes "zotregistry.dev/zot/pkg/storage/types"
tcommon "zotregistry.dev/zot/pkg/test/common"
. "zotregistry.dev/zot/pkg/test/image-utils"
"zotregistry.dev/zot/pkg/test/mocks"
ociutils "zotregistry.dev/zot/pkg/test/oci-utils"
"zotregistry.dev/zot/pkg/test/signature"
tskip "zotregistry.dev/zot/pkg/test/skip"
)
const repo = "repo"
func TestParseStorageErrors(t *testing.T) {
ctx := context.Background()
Convey("ParseStorage", t, func() {
imageStore := mocks.MockedImageStore{
GetIndexContentFn: func(repo string) ([]byte, error) {
return nil, ErrTestError
},
GetRepositoriesFn: func() ([]string, error) {
return []string{"repo1", "repo2"}, nil
},
}
storeController := storage.StoreController{DefaultStore: imageStore}
metaDB := mocks.MetaDBMock{}
// sync repo fail
err := meta.ParseStorage(metaDB, storeController, log.NewLogger("debug", ""))
So(err, ShouldBeNil)
Convey("getAllRepos errors", func() {
imageStore1 := mocks.MockedImageStore{
GetRepositoriesFn: func() ([]string, error) {
return []string{"repo1", "repo2"}, nil
},
}
imageStore2 := mocks.MockedImageStore{
GetRepositoriesFn: func() ([]string, error) {
return nil, ErrTestError
},
}
storeController := storage.StoreController{
DefaultStore: imageStore1,
SubStore: map[string]storageTypes.ImageStore{
"a": imageStore2,
},
}
err := meta.ParseStorage(metaDB, storeController, log.NewLogger("debug", ""))
So(err, ShouldNotBeNil)
})
Convey("metaDB.GetAllRepoNames errors", func() {
metaDB.GetAllRepoNamesFn = func() ([]string, error) { return nil, ErrTestError }
err := meta.ParseStorage(metaDB, storeController, log.NewLogger("debug", ""))
So(err, ShouldNotBeNil)
})
Convey("metaDB.DeleteRepoMeta errors", func() {
imageStore1 := mocks.MockedImageStore{
GetRepositoriesFn: func() ([]string, error) { return []string{"repo1", "repo2"}, nil },
}
storeController := storage.StoreController{DefaultStore: imageStore1}
metaDB.GetAllRepoNamesFn = func() ([]string, error) { return []string{"deleted"}, nil }
metaDB.DeleteRepoMetaFn = func(repo string) error { return ErrTestError }
err := meta.ParseStorage(metaDB, storeController, log.NewLogger("debug", ""))
So(err, ShouldNotBeNil)
})
Convey("StatIndex errors", func() {
imageStore1 := mocks.MockedImageStore{
GetRepositoriesFn: func() ([]string, error) { return []string{"repo1", "repo2"}, nil },
}
imageStore1.StatIndexFn = func(repo string) (bool, int64, time.Time, error) {
return false, 0, time.Time{}, ErrTestError
}
storeController := storage.StoreController{DefaultStore: imageStore1}
err := meta.ParseStorage(metaDB, storeController, log.NewLogger("debug", ""))
So(err, ShouldBeNil)
})
})
Convey("Parse Repo", t, func() {
imageStore := mocks.MockedImageStore{}
storeController := storage.StoreController{DefaultStore: &imageStore}
metaDB := mocks.MetaDBMock{}
log := log.NewLogger("debug", "")
Convey("imageStore.GetIndexContent errors", func() {
imageStore.GetIndexContentFn = func(repo string) ([]byte, error) {
return nil, ErrTestError
}
err := meta.ParseRepo("repo", metaDB, storeController, log)
So(err, ShouldNotBeNil)
})
Convey("json.Unmarshal errors", func() {
imageStore.GetIndexContentFn = func(repo string) ([]byte, error) {
return []byte("Invalid JSON"), nil
}
err := meta.ParseRepo("repo", metaDB, storeController, log)
So(err, ShouldNotBeNil)
})
Convey("resetRepoReferences errors", func() {
imageStore.GetIndexContentFn = func(repo string) ([]byte, error) {
return []byte("{}"), nil
}
metaDB.ResetRepoReferencesFn = func(repo string) error { return ErrTestError }
err := meta.ParseRepo("repo", metaDB, storeController, log)
So(err, ShouldNotBeNil)
})
Convey("zcommon.IsReferrersTag", func() {
imageStore.GetIndexContentFn = func(repo string) ([]byte, error) {
return getIndexBlob(ispec.Index{
Manifests: []ispec.Descriptor{
{
MediaType: ispec.MediaTypeImageManifest,
Digest: godigest.FromString("digest"),
Annotations: map[string]string{
ispec.AnnotationRefName: "sha256-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
},
},
},
}), nil
}
err := meta.ParseRepo("repo", metaDB, storeController, log)
So(err, ShouldBeNil)
})
Convey("imageStore.GetImageManifest errors", func() {
imageStore.GetIndexContentFn = func(repo string) ([]byte, error) {
return getIndexBlob(ispec.Index{
Manifests: []ispec.Descriptor{
{
MediaType: ispec.MediaTypeImageManifest,
Digest: godigest.FromString("digest"),
Annotations: map[string]string{
ispec.AnnotationRefName: "tag",
},
},
},
}), nil
}
imageStore.GetImageManifestFn = func(repo, reference string) ([]byte, godigest.Digest, string, error) {
return nil, "", "", ErrTestError
}
err := meta.ParseRepo("repo", metaDB, storeController, log)
So(err, ShouldNotBeNil)
})
Convey("manifestMetaIsPresent true", func() {
indexContent := ispec.Index{
Manifests: []ispec.Descriptor{
{
Digest: godigest.FromString("manifest1"),
MediaType: ispec.MediaTypeImageManifest,
Annotations: map[string]string{
ispec.AnnotationRefName: "tag1",
},
},
},
}
indexBlob, err := json.Marshal(indexContent)
So(err, ShouldBeNil)
imageStore.GetIndexContentFn = func(repo string) ([]byte, error) {
return indexBlob, nil
}
Convey("metaDB.SetRepoReference", func() {
metaDB.SetRepoReferenceFn = func(ctx context.Context, repo, reference string, imageMeta mTypes.ImageMeta) error {
return ErrTestError
}
err = meta.ParseRepo("repo", metaDB, storeController, log)
So(err, ShouldNotBeNil)
})
})
})
image := CreateRandomImage()
Convey("SetImageMetaFromInput errors", t, func() {
mockImageStore := mocks.MockedImageStore{}
mockedMetaDB := mocks.MetaDBMock{}
log := log.NewLogger("debug", "")
Convey("Image Manifest errors", func() {
Convey("Get Config blob error", func() {
mockImageStore.GetBlobContentFn = func(repo string, digest godigest.Digest) ([]byte, error) {
return []byte{}, ErrTestError
}
err := meta.SetImageMetaFromInput(ctx, "repo", "tag", ispec.MediaTypeImageManifest, image.Digest(),
image.ManifestDescriptor.Data, mockImageStore, mockedMetaDB, log)
So(err, ShouldNotBeNil)
})
Convey("Unmarshal config blob error", func() {
mockImageStore.GetBlobContentFn = func(repo string, digest godigest.Digest) ([]byte, error) {
return []byte("bad-blob"), nil
}
err := meta.SetImageMetaFromInput(ctx, "repo", "tag", ispec.MediaTypeImageManifest, image.Digest(),
image.ManifestDescriptor.Data, mockImageStore, mockedMetaDB, log)
So(err, ShouldNotBeNil)
})
Convey("Is Signature", func() {
image := CreateDefaultImage()
mediaType := ispec.MediaTypeImageManifest
// it has more than 1 layer
badNotationSignature := CreateImageWith().RandomLayers(2, 10).EmptyConfig().Subject(image.DescriptorRef()).
ArtifactType(zcommon.ArtifactTypeNotation).Build()
goodNotationSignature := CreateMockNotationSignature(image.DescriptorRef())
Convey("GetSignatureLayersInfo errors", func() {
err := meta.SetImageMetaFromInput(ctx, "repo", "tag", mediaType, badNotationSignature.Digest(),
badNotationSignature.ManifestDescriptor.Data, mockImageStore, mockedMetaDB, log)
So(err, ShouldNotBeNil)
})
Convey("UpdateSignaturesValidity errors", func() {
mockedMetaDB.UpdateSignaturesValidityFn = func(ctx context.Context, repo string,
manifestDigest godigest.Digest,
) error {
return ErrTestError
}
err := meta.SetImageMetaFromInput(ctx, "repo", "tag", mediaType, goodNotationSignature.Digest(),
goodNotationSignature.ManifestDescriptor.Data, mockImageStore, mockedMetaDB, log)
So(err, ShouldNotBeNil)
})
})
})
Convey("Image Index errors", func() {
Convey("Unmarshal error", func() {
err := meta.SetImageMetaFromInput(ctx, "repo", "tag", ispec.MediaTypeImageIndex, "",
[]byte("bad-json"), mockImageStore, mockedMetaDB, log)
So(err, ShouldNotBeNil)
})
})
})
}
func getIndexBlob(index ispec.Index) []byte {
index.MediaType = ispec.MediaTypeImageIndex
blob, err := json.Marshal(index)
if err != nil {
panic("image index should always be marshable")
}
return blob
}
func TestParseStorageWithBoltDB(t *testing.T) {
Convey("Boltdb", t, func() {
rootDir := t.TempDir()
log := log.NewLogger("debug", "/dev/null")
boltDB, err := boltdb.GetBoltDriver(boltdb.DBParameters{
RootDir: rootDir,
})
So(err, ShouldBeNil)
metaDB, err := boltdb.New(boltDB, log)
So(err, ShouldBeNil)
RunParseStorageTests(rootDir, metaDB, log)
})
}
func TestParseStorageDynamoWrapper(t *testing.T) {
tskip.SkipDynamo(t)
Convey("Dynamodb", t, func() {
rootDir := t.TempDir()
log := log.NewLogger("debug", "/dev/null")
params := dynamodb.DBDriverParameters{
Endpoint: os.Getenv("DYNAMODBMOCK_ENDPOINT"),
Region: "us-east-2",
RepoMetaTablename: "RepoMetadataTable",
RepoBlobsInfoTablename: "RepoBlobsInfoTablename",
ImageMetaTablename: "ImageMetaTablename",
UserDataTablename: "UserDataTable",
APIKeyTablename: "ApiKeyTable",
VersionTablename: "Version",
}
dynamoClient, err := dynamodb.GetDynamoClient(params)
So(err, ShouldBeNil)
dynamoWrapper, err := dynamodb.New(dynamoClient, params, log)
So(err, ShouldBeNil)
err = dynamoWrapper.ResetTable(dynamoWrapper.RepoMetaTablename)
So(err, ShouldBeNil)
err = dynamoWrapper.ResetTable(dynamoWrapper.RepoBlobsTablename)
So(err, ShouldBeNil)
err = dynamoWrapper.ResetTable(dynamoWrapper.ImageMetaTablename)
So(err, ShouldBeNil)
RunParseStorageTests(rootDir, dynamoWrapper, log)
})
}
func RunParseStorageTests(rootDir string, metaDB mTypes.MetaDB, log log.Logger) {
ctx := context.Background()
Convey("Test with simple case", func() {
imageStore := local.NewImageStore(rootDir, false, false,
log, monitoring.NewMetricsServer(false, log), nil, nil, nil)
storeController := storage.StoreController{DefaultStore: imageStore}
manifests := []ispec.Manifest{}
for i := 0; i < 3; i++ {
image := CreateRandomImage() //nolint:staticcheck
manifests = append(manifests, image.Manifest)
err := WriteImageToFileSystem(
image, repo, fmt.Sprintf("tag%d", i), storeController)
So(err, ShouldBeNil)
}
// add fake signature for tag1
signatureTag, err := signature.GetCosignSignatureTagForManifest(manifests[1])
So(err, ShouldBeNil)
manifestBlob, err := json.Marshal(manifests[1])
So(err, ShouldBeNil)
signedManifestDigest := godigest.FromBytes(manifestBlob)
image := CreateRandomImage()
err = WriteImageToFileSystem(image, repo, signatureTag, storeController)
So(err, ShouldBeNil)
// remove tag2 from index.json
indexPath := path.Join(rootDir, repo, "index.json")
indexFile, err := os.Open(indexPath)
So(err, ShouldBeNil)
buf, err := io.ReadAll(indexFile)
So(err, ShouldBeNil)
var index ispec.Index
if err = json.Unmarshal(buf, &index); err == nil {
for _, manifest := range index.Manifests {
if val, ok := manifest.Annotations[ispec.AnnotationRefName]; ok && val == "tag2" {
delete(manifest.Annotations, ispec.AnnotationRefName)
break
}
}
}
buf, err = json.Marshal(index)
So(err, ShouldBeNil)
err = os.WriteFile(indexPath, buf, 0o600)
So(err, ShouldBeNil)
err = meta.ParseStorage(metaDB, storeController, log) //nolint: contextcheck
So(err, ShouldBeNil)
repos, err := metaDB.GetMultipleRepoMeta(ctx,
func(repoMeta mTypes.RepoMeta) bool { return true })
So(err, ShouldBeNil)
So(len(repos), ShouldEqual, 1)
So(len(repos[0].Tags), ShouldEqual, 2)
for tag, descriptor := range repos[0].Tags {
imageManifestData, err := metaDB.GetFullImageMeta(ctx, repo, tag)
So(err, ShouldBeNil)
if descriptor.Digest == signedManifestDigest.String() {
So(imageManifestData.Signatures, ShouldNotBeEmpty)
}
}
})
Convey("Accept orphan signatures", func() {
imageStore := local.NewImageStore(rootDir, false, false,
log, monitoring.NewMetricsServer(false, log), nil, nil, nil)
storeController := storage.StoreController{DefaultStore: imageStore}
// add an image
image := CreateRandomImage()
err := WriteImageToFileSystem(image, repo, "tag1", storeController)
So(err, ShouldBeNil)
// add mock cosign signature without pushing the signed image
image = CreateRandomImage()
So(err, ShouldBeNil)
signatureTag, err := signature.GetCosignSignatureTagForManifest(image.Manifest)
So(err, ShouldBeNil)
missingImageDigest := image.ManifestDescriptor.Digest
// get the body of the signature
signature := CreateRandomImage()
err = WriteImageToFileSystem(signature, repo, signatureTag, storeController)
So(err, ShouldBeNil)
err = meta.ParseStorage(metaDB, storeController, log) //nolint: contextcheck
So(err, ShouldBeNil)
repos, err := metaDB.GetMultipleRepoMeta(ctx,
func(repoMeta mTypes.RepoMeta) bool { return true })
So(err, ShouldBeNil)
for _, desc := range repos[0].Tags {
So(desc.Digest, ShouldNotResemble, missingImageDigest.String())
}
So(len(repos), ShouldEqual, 1)
So(repos[0].Tags, ShouldContainKey, "tag1")
So(repos[0].Tags, ShouldNotContainKey, signatureTag)
So(repos[0].Signatures, ShouldContainKey, missingImageDigest.String())
})
Convey("Check statistics after load", func() {
imageStore := local.NewImageStore(rootDir, false, false,
log, monitoring.NewMetricsServer(false, log), nil, nil, nil)
storeController := storage.StoreController{DefaultStore: imageStore}
// add an image
image := CreateRandomImage() //nolint:staticcheck
err := WriteImageToFileSystem(image, repo, "tag", storeController)
So(err, ShouldBeNil)
err = metaDB.SetRepoReference(ctx, repo, "tag", image.AsImageMeta())
So(err, ShouldBeNil)
err = metaDB.IncrementRepoStars(repo)
So(err, ShouldBeNil)
err = metaDB.UpdateStatsOnDownload(repo, "tag")
So(err, ShouldBeNil)
err = metaDB.UpdateStatsOnDownload(repo, "tag")
So(err, ShouldBeNil)
err = metaDB.UpdateStatsOnDownload(repo, "tag")
So(err, ShouldBeNil)
repoMeta, err := metaDB.GetRepoMeta(ctx, repo)
So(err, ShouldBeNil)
So(repoMeta.Statistics[image.DigestStr()].DownloadCount, ShouldEqual, 3)
So(repoMeta.StarCount, ShouldEqual, 1)
So(time.Now(), ShouldHappenAfter, repoMeta.Statistics[image.DigestStr()].LastPullTimestamp)
err = meta.ParseStorage(metaDB, storeController, log) //nolint: contextcheck
So(err, ShouldBeNil)
repoMeta, err = metaDB.GetRepoMeta(ctx, repo)
So(err, ShouldBeNil)
So(repoMeta.Statistics[image.DigestStr()].DownloadCount, ShouldEqual, 3)
So(repoMeta.StarCount, ShouldEqual, 1)
})
// make sure pushTimestamp is always populated to not interfere with retention logic
Convey("Always update pushTimestamp if its value is 0(time.Time{})", func() {
imageStore := local.NewImageStore(rootDir, false, false,
log, monitoring.NewMetricsServer(false, log), nil, nil, nil)
storeController := storage.StoreController{DefaultStore: imageStore}
// add an image
image := CreateRandomImage() //nolint:staticcheck
err := WriteImageToFileSystem(image, repo, "tag", storeController)
So(err, ShouldBeNil)
err = metaDB.SetRepoReference(ctx, repo, "tag", image.AsImageMeta())
So(err, ShouldBeNil)
err = metaDB.UpdateStatsOnDownload(repo, "tag")
So(err, ShouldBeNil)
repoMeta, err := metaDB.GetRepoMeta(ctx, repo)
So(err, ShouldBeNil)
So(repoMeta.Statistics[image.DigestStr()].DownloadCount, ShouldEqual, 1)
So(time.Now(), ShouldHappenAfter, repoMeta.Statistics[image.DigestStr()].LastPullTimestamp)
So(time.Now(), ShouldHappenAfter, repoMeta.Statistics[image.DigestStr()].PushTimestamp)
// update statistics (simulate that a metaDB has statistics, but pushTimestamp is 0)
stats := repoMeta.Statistics[image.DigestStr()]
oldPushTimestamp := stats.PushTimestamp
stats.PushTimestamp = time.Time{}
repoMeta.Statistics[image.DigestStr()] = stats
err = metaDB.SetRepoMeta(repo, repoMeta)
So(err, ShouldBeNil)
// metaDB should detect that pushTimestamp is 0 and update it.
err = meta.ParseStorage(metaDB, storeController, log) //nolint: contextcheck
So(err, ShouldBeNil)
repoMeta, err = metaDB.GetRepoMeta(ctx, repo)
So(err, ShouldBeNil)
So(repoMeta.Statistics[image.DigestStr()].DownloadCount, ShouldEqual, 1)
So(repoMeta.DownloadCount, ShouldEqual, 1)
So(repoMeta.Statistics[image.DigestStr()].PushTimestamp, ShouldHappenAfter, oldPushTimestamp)
})
Convey("Parse 2 times and check correct update of the metaDB for modified and deleted repos", func() {
storeController := ociutils.GetDefaultStoreController(rootDir, log)
notModifiedRepo := "not-modified-repo"
modifiedAddImageRepo := "modified-add-image-repo"
modifiedRemoveImageRepo := "modified-remove-image-repo"
deletedRepo := "deleted-repo"
addedRepo := "added-repo"
tag := "tag"
tag2 := "tag2"
newTag := "newTag"
image := CreateRandomImage()
err := WriteImageToFileSystem(image, notModifiedRepo, tag, storeController)
So(err, ShouldBeNil)
err = WriteImageToFileSystem(image, modifiedAddImageRepo, tag, storeController)
So(err, ShouldBeNil)
err = WriteImageToFileSystem(image, modifiedRemoveImageRepo, tag, storeController)
So(err, ShouldBeNil)
err = WriteImageToFileSystem(image, modifiedRemoveImageRepo, tag2, storeController)
So(err, ShouldBeNil)
err = WriteImageToFileSystem(image, deletedRepo, tag, storeController)
So(err, ShouldBeNil)
err = meta.ParseStorage(metaDB, storeController, log) //nolint: contextcheck
So(err, ShouldBeNil)
repoMetaList, err := metaDB.SearchRepos(ctx, "")
So(err, ShouldBeNil)
So(len(repoMetaList), ShouldEqual, 4)
repoNames := tcommon.AccumulateField(repoMetaList, func(rm mTypes.RepoMeta) string { return rm.Name })
So(repoNames, ShouldContain, notModifiedRepo)
So(repoNames, ShouldContain, modifiedAddImageRepo)
So(repoNames, ShouldContain, modifiedRemoveImageRepo)
So(repoNames, ShouldContain, deletedRepo)
time.Sleep(time.Second)
// Update the storage
err = WriteImageToFileSystem(image, modifiedAddImageRepo, newTag, storeController)
So(err, ShouldBeNil)
err = storeController.GetDefaultImageStore().DeleteImageManifest(modifiedRemoveImageRepo, tag2, false)
So(err, ShouldBeNil)
err = os.RemoveAll(filepath.Join(rootDir, deletedRepo))
So(err, ShouldBeNil)
err = WriteImageToFileSystem(image, addedRepo, tag, storeController)
So(err, ShouldBeNil)
// Parse again
err = meta.ParseStorage(metaDB, storeController, log) //nolint: contextcheck
So(err, ShouldBeNil)
repoMetaList, err = metaDB.SearchRepos(ctx, "")
So(err, ShouldBeNil)
So(len(repoMetaList), ShouldEqual, 4)
repoNames = tcommon.AccumulateField(repoMetaList, func(rm mTypes.RepoMeta) string { return rm.Name })
So(repoNames, ShouldContain, notModifiedRepo)
So(repoNames, ShouldContain, modifiedAddImageRepo)
So(repoNames, ShouldContain, modifiedRemoveImageRepo)
So(repoNames, ShouldNotContain, deletedRepo)
So(repoNames, ShouldContain, addedRepo)
repoMeta, err := metaDB.GetRepoMeta(ctx, modifiedAddImageRepo)
So(err, ShouldBeNil)
So(repoMeta.Tags, ShouldContainKey, tag)
So(repoMeta.Tags, ShouldContainKey, newTag)
repoMeta, err = metaDB.GetRepoMeta(ctx, modifiedRemoveImageRepo)
So(err, ShouldBeNil)
So(repoMeta.Tags, ShouldContainKey, tag)
So(repoMeta.Tags, ShouldNotContainKey, tag2)
})
}
func TestGetSignatureLayersInfo(t *testing.T) {
Convey("wrong signature type", t, func() {
layers, err := meta.GetSignatureLayersInfo("repo", "tag", "123", "wrong signature type", []byte{},
nil, log.NewLogger("debug", ""))
So(err, ShouldBeNil)
So(layers, ShouldBeEmpty)
})
Convey("notation index", t, func() {
notationIndex := ispec.Index{
MediaType: ispec.MediaTypeImageIndex,
}
notationIndexBlob, err := json.Marshal(notationIndex)
So(err, ShouldBeNil)
layers, err := meta.GetSignatureLayersInfo("repo", "tag", "123", zcommon.NotationSignature, notationIndexBlob,
nil, log.NewLogger("debug", ""))
So(err, ShouldBeNil)
So(layers, ShouldBeEmpty)
})
Convey("GetBlobContent errors", t, func() {
mockImageStore := mocks.MockedImageStore{}
mockImageStore.GetBlobContentFn = func(repo string, digest godigest.Digest) ([]byte, error) {
return nil, ErrTestError
}
image := CreateRandomImage()
layers, err := meta.GetSignatureLayersInfo("repo", "tag", "123", zcommon.CosignSignature,
image.ManifestDescriptor.Data, mockImageStore, log.NewLogger("debug", ""))
So(err, ShouldNotBeNil)
So(layers, ShouldBeEmpty)
})
Convey("notation len(manifestContent.Layers) != 1", t, func() {
mockImageStore := mocks.MockedImageStore{}
image := CreateImageWith().RandomLayers(3, 10).RandomConfig().Build()
layers, err := meta.GetSignatureLayersInfo("repo", "tag", "123", zcommon.NotationSignature,
image.ManifestDescriptor.Data, mockImageStore, log.NewLogger("debug", ""))
So(err, ShouldNotBeNil)
So(layers, ShouldBeEmpty)
})
Convey("notation GetBlobContent errors", t, func() {
mockImageStore := mocks.MockedImageStore{}
mockImageStore.GetBlobContentFn = func(repo string, digest godigest.Digest) ([]byte, error) {
return nil, ErrTestError
}
image := CreateImageWith().RandomLayers(1, 10).RandomConfig().Build()
layers, err := meta.GetSignatureLayersInfo("repo", "tag", "123", zcommon.NotationSignature,
image.ManifestDescriptor.Data, mockImageStore, log.NewLogger("debug", ""))
So(err, ShouldNotBeNil)
So(layers, ShouldBeEmpty)
})
Convey("error while unmarshaling manifest content", t, func() {
_, err := meta.GetSignatureLayersInfo("repo", "tag", "123", zcommon.CosignSignature, []byte("bad manifest"),
nil, log.NewLogger("debug", ""))
So(err, ShouldNotBeNil)
_, err = meta.GetSignatureLayersInfo("repo", "tag", "123", zcommon.NotationSignature, []byte("bad manifest"),
nil, log.NewLogger("debug", ""))
So(err, ShouldNotBeNil)
})
}