From f3aa8554050b01809ec26f4f430984038a9e5eb2 Mon Sep 17 00:00:00 2001 From: Josh Dolitsky <393494+jdolitsky@users.noreply.github.com> Date: Thu, 6 Jul 2023 12:31:40 -0500 Subject: [PATCH] fix: missing Oci-Subject header pushing index with subject (#1589) * fix: missing Oci-Subject header pushing index with subject Signed-off-by: Josh Dolitsky * fix(s3): Add a test to cover handling pushing indexes with a subject Signed-off-by: Andrei Aaron --------- Signed-off-by: Josh Dolitsky Signed-off-by: Andrei Aaron Co-authored-by: Andrei Aaron --- pkg/storage/local/local.go | 13 ++++ pkg/storage/s3/s3.go | 13 ++++ pkg/storage/s3/s3_test.go | 128 +++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+) diff --git a/pkg/storage/local/local.go b/pkg/storage/local/local.go index d4188ae2..e3d019c3 100644 --- a/pkg/storage/local/local.go +++ b/pkg/storage/local/local.go @@ -507,6 +507,19 @@ func (is *ImageStoreLocal) PutImageManifest(repo, reference, mediaType string, / } artifactType = zcommon.GetManifestArtifactType(manifest) + } else if mediaType == ispec.MediaTypeImageIndex { + var index ispec.Index + + err := json.Unmarshal(body, &index) + if err != nil { + return "", "", err + } + + if index.Subject != nil { + subjectDigest = index.Subject.Digest + } + + artifactType = zcommon.GetIndexArtifactType(index) } updateIndex, oldDgst, err := common.CheckIfIndexNeedsUpdate(&index, &desc, is.log) diff --git a/pkg/storage/s3/s3.go b/pkg/storage/s3/s3.go index 04a60252..961d9fca 100644 --- a/pkg/storage/s3/s3.go +++ b/pkg/storage/s3/s3.go @@ -418,6 +418,19 @@ func (is *ObjectStorage) PutImageManifest(repo, reference, mediaType string, //n } artifactType = zcommon.GetManifestArtifactType(manifest) + } else if mediaType == ispec.MediaTypeImageIndex { + var index ispec.Index + + err := json.Unmarshal(body, &index) + if err != nil { + return "", "", err + } + + if index.Subject != nil { + subjectDigest = index.Subject.Digest + } + + artifactType = zcommon.GetIndexArtifactType(index) } updateIndex, oldDgst, err := common.CheckIfIndexNeedsUpdate(&index, &desc, is.log) diff --git a/pkg/storage/s3/s3_test.go b/pkg/storage/s3/s3_test.go index 5cfa877f..e805470a 100644 --- a/pkg/storage/s3/s3_test.go +++ b/pkg/storage/s3/s3_test.go @@ -3394,6 +3394,134 @@ func TestS3ManifestImageIndex(t *testing.T) { }) }) }) + + Convey("Test image index as artifact with subject against s3 image store", t, func() { + uuid, err := guuid.NewV4() + if err != nil { + panic(err) + } + + testDir := path.Join("/oci-repo-test", uuid.String()) + + storeDriver, imgStore, _ := createObjectsStore(testDir, t.TempDir(), true) + defer cleanupStorage(storeDriver, testDir) + + // create and upload a blob/layer + // create and upload 2 configs + // create and upload 2 manifests + // index creation/testing is handled in the other conveys + + // layer blob + content := []byte("this is a blob1") + buf := bytes.NewBuffer(content) + buflen := buf.Len() + bdigest := godigest.FromBytes(content) + bsize := len(content) + So(bdigest, ShouldNotBeNil) + + _, clen, err := imgStore.FullBlobUpload("index", buf, bdigest) + So(err, ShouldBeNil) + So(clen, ShouldEqual, buflen) + + // first config + cblob, cdigest := test.GetRandomImageConfig() + buf = bytes.NewBuffer(cblob) + buflen = buf.Len() + + _, clen, err = imgStore.FullBlobUpload("index", buf, cdigest) + So(err, ShouldBeNil) + So(clen, ShouldEqual, buflen) + + // first manifest + manifest := ispec.Manifest{ + Config: ispec.Descriptor{ + MediaType: ispec.MediaTypeImageConfig, + Digest: cdigest, + Size: int64(len(cblob)), + }, + Layers: []ispec.Descriptor{ + { + MediaType: ispec.MediaTypeImageLayer, + Digest: bdigest, + Size: int64(bsize), + }, + }, + } + manifest.SchemaVersion = 2 + content, err = json.Marshal(manifest) + So(err, ShouldBeNil) + m1digest := godigest.FromBytes(content) + So(m1digest, ShouldNotBeNil) + m1size := len(content) + + _, _, err = imgStore.PutImageManifest("index", "test:1.0", ispec.MediaTypeImageManifest, content) + So(err, ShouldBeNil) + + // second config + cblob, cdigest = test.GetRandomImageConfig() + buf = bytes.NewBuffer(cblob) + buflen = buf.Len() + + _, clen, err = imgStore.FullBlobUpload("index", buf, cdigest) + So(err, ShouldBeNil) + So(clen, ShouldEqual, buflen) + + // second manifest + manifest = ispec.Manifest{ + Config: ispec.Descriptor{ + MediaType: ispec.MediaTypeImageConfig, + Digest: cdigest, + Size: int64(len(cblob)), + }, + Layers: []ispec.Descriptor{ + { + MediaType: ispec.MediaTypeImageLayer, + Digest: bdigest, + Size: int64(bsize), + }, + }, + } + manifest.SchemaVersion = 2 + content, err = json.Marshal(manifest) + So(err, ShouldBeNil) + m2digest := godigest.FromBytes(content) + So(m2digest, ShouldNotBeNil) + m2size := len(content) + _, _, err = imgStore.PutImageManifest("index", m2digest.String(), ispec.MediaTypeImageManifest, content) + So(err, ShouldBeNil) + + Convey("Put image index with valid subject", func() { + // create an image index containing the 2nd manifest, having the 1st manifest as subject + + var index ispec.Index + index.SchemaVersion = 2 + index.Manifests = []ispec.Descriptor{ + { + MediaType: ispec.MediaTypeImageManifest, + Digest: m2digest, + Size: int64(m2size), + }, + } + index.Subject = &ispec.Descriptor{ + MediaType: ispec.MediaTypeImageManifest, + Digest: m1digest, + Size: int64(m1size), + } + + content, err := json.Marshal(index) + So(err, ShouldBeNil) + idigest := godigest.FromBytes(content) + So(idigest, ShouldNotBeNil) + + digest1, digest2, err := imgStore.PutImageManifest("index", "test:index1", ispec.MediaTypeImageIndex, content) + So(err, ShouldBeNil) + So(digest1.String(), ShouldEqual, idigest.String()) + So(digest2.String(), ShouldEqual, m1digest.String()) + + _, _, _, err = imgStore.GetImageManifest("index", "test:index1") + So(err, ShouldBeNil) + }) + }) } func TestS3DedupeErr(t *testing.T) {