diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index e0b61a5f..1d8134a2 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -373,6 +373,7 @@ func (is *ImageStore) PutImageManifest(repo string, reference string, mediaType for _, l := range m.Layers { digest := l.Digest blobPath := is.BlobPath(repo, digest) + is.log.Info().Str("blobPath", blobPath).Str("reference", reference).Msg("manifest layers") if _, err := os.Stat(blobPath); err != nil { is.log.Error().Err(err).Str("blobPath", blobPath).Msg("unable to find blob") @@ -434,8 +435,17 @@ func (is *ImageStore) PutImageManifest(repo string, reference string, mediaType break } - // manifest contents have changed for the same tag + // manifest contents have changed for the same tag, + // so update index.json descriptor + is.log.Info(). + Int64("old size", desc.Size). + Int64("new size", int64(len(body))). + Str("old digest", desc.Digest.String()). + Str("new digest", mDigest.String()). + Msg("updating existing tag with new manifest contents") + desc = m + desc.Size = int64(len(body)) desc.Digest = mDigest index.Manifests = append(index.Manifests[:i], index.Manifests[i+1:]...) diff --git a/pkg/storage/storage_test.go b/pkg/storage/storage_test.go index 07f2a80e..2d52631f 100644 --- a/pkg/storage/storage_test.go +++ b/pkg/storage/storage_test.go @@ -257,6 +257,89 @@ func TestAPIs(t *testing.T) { So(err, ShouldNotBeNil) }) + Convey("Modify manifest in-place", func() { + // original blob + v, err := il.NewBlobUpload("replace") + So(err, ShouldBeNil) + So(v, ShouldNotBeEmpty) + + content := []byte("test-data-replace-1") + buf := bytes.NewBuffer(content) + l := buf.Len() + d := godigest.FromBytes(content) + b, err := il.PutBlobChunkStreamed("replace", v, buf) + So(err, ShouldBeNil) + So(b, ShouldEqual, l) + blobDigest1 := strings.Split(d.String(), ":")[1] + So(blobDigest1, ShouldNotBeEmpty) + + err = il.FinishBlobUpload("replace", v, buf, d.String()) + So(err, ShouldBeNil) + So(b, ShouldEqual, l) + + m := ispec.Manifest{} + m.SchemaVersion = 2 + m = ispec.Manifest{ + Config: ispec.Descriptor{ + Digest: d, + Size: int64(l), + }, + Layers: []ispec.Descriptor{ + { + MediaType: "application/vnd.oci.image.layer.v1.tar", + Digest: d, + Size: int64(l), + }, + }, + } + m.SchemaVersion = 2 + mb, _ := json.Marshal(m) + d = godigest.FromBytes(mb) + _, err = il.PutImageManifest("replace", "1.0", ispec.MediaTypeImageManifest, mb) + So(err, ShouldBeNil) + + _, _, _, err = il.GetImageManifest("replace", d.String()) + So(err, ShouldBeNil) + + // new blob to replace + v, err = il.NewBlobUpload("replace") + So(err, ShouldBeNil) + So(v, ShouldNotBeEmpty) + + content = []byte("test-data-replace-2") + buf = bytes.NewBuffer(content) + l = buf.Len() + d = godigest.FromBytes(content) + b, err = il.PutBlobChunkStreamed("replace", v, buf) + So(err, ShouldBeNil) + So(b, ShouldEqual, l) + blobDigest2 := strings.Split(d.String(), ":")[1] + So(blobDigest2, ShouldNotBeEmpty) + + err = il.FinishBlobUpload("replace", v, buf, d.String()) + So(err, ShouldBeNil) + So(b, ShouldEqual, l) + + m = ispec.Manifest{ + Config: ispec.Descriptor{ + Digest: d, + Size: int64(l), + }, + Layers: []ispec.Descriptor{ + { + MediaType: "application/vnd.oci.image.layer.v1.tar", + Digest: d, + Size: int64(l), + }, + }, + } + m.SchemaVersion = 2 + mb, _ = json.Marshal(m) + _ = godigest.FromBytes(mb) + _, err = il.PutImageManifest("replace", "1.0", ispec.MediaTypeImageManifest, mb) + So(err, ShouldBeNil) + }) + Convey("Dedupe", func() { blobDigest1 := "" blobDigest2 := ""