From da34812db6890f80c7fac6f6021e27452fa1162a Mon Sep 17 00:00:00 2001 From: Derek McGowan Date: Wed, 9 Aug 2017 22:35:49 -0700 Subject: [PATCH] Update differ to support compressed archives Differ is updated to set a label for the uncompressed hash of compressed content. This allows compressed blobs to be used and looked up for their uncompressed hashes. Uses commit options to set labels. Updates rootfs default to create compressed archives. Signed-off-by: Derek McGowan --- differ/differ.go | 48 +++++++++++++++++++++++++++++++----------------- rootfs/diff.go | 2 +- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/differ/differ.go b/differ/differ.go index 9cd525399..ad603a366 100644 --- a/differ/differ.go +++ b/differ/differ.go @@ -102,7 +102,17 @@ func (s *BaseDiff) Apply(ctx context.Context, desc ocispec.Descriptor, mounts [] } func (s *BaseDiff) DiffMounts(ctx context.Context, lower, upper []mount.Mount, media, ref string) (ocispec.Descriptor, error) { - + var isCompressed bool + switch media { + case ocispec.MediaTypeImageLayer: + case ocispec.MediaTypeImageLayerGzip: + isCompressed = true + case "": + media = ocispec.MediaTypeImageLayerGzip + isCompressed = true + default: + return emptyDesc, errors.Errorf("unsupported diff media type: %v", media) + } aDir, err := ioutil.TempDir("", "left-") if err != nil { return emptyDesc, errors.Wrap(err, "failed to create temporary directory") @@ -130,25 +140,29 @@ func (s *BaseDiff) DiffMounts(ctx context.Context, lower, upper []mount.Mount, m return emptyDesc, errors.Wrap(err, "failed to open writer") } - // TODO: Validate media type - - // TODO: Support compressed media types (link compressed to uncompressed) - //dgstr := digest.SHA256.Digester() - //wc := &writeCounter{} - //compressed, err := compression.CompressStream(cw, compression.Gzip) - //if err != nil { - // return nil, errors.Wrap(err, "failed to get compressed stream") - //} - //err = archive.WriteDiff(ctx, io.MultiWriter(compressed, dgstr.Hash(), wc), lowerDir, upperDir) - //compressed.Close() - - err = archive.WriteDiff(ctx, cw, aDir, bDir) - if err != nil { - return emptyDesc, errors.Wrap(err, "failed to write diff") + var opts []content.Opt + if isCompressed { + dgstr := digest.SHA256.Digester() + compressed, err := compression.CompressStream(cw, compression.Gzip) + if err != nil { + return emptyDesc, errors.Wrap(err, "failed to get compressed stream") + } + err = archive.WriteDiff(ctx, io.MultiWriter(compressed, dgstr.Hash()), aDir, bDir) + compressed.Close() + if err != nil { + return emptyDesc, errors.Wrap(err, "failed to write compressed diff") + } + opts = append(opts, content.WithLabels(map[string]string{ + "containerd.io/uncompressed": dgstr.Digest().String(), + })) + } else { + if err = archive.WriteDiff(ctx, cw, aDir, bDir); err != nil { + return emptyDesc, errors.Wrap(err, "failed to write diff") + } } dgst := cw.Digest() - if err := cw.Commit(0, dgst); err != nil { + if err := cw.Commit(0, dgst, opts...); err != nil { return emptyDesc, errors.Wrap(err, "failed to commit") } diff --git a/rootfs/diff.go b/rootfs/diff.go index c83ab4f1f..1a16fb9d9 100644 --- a/rootfs/diff.go +++ b/rootfs/diff.go @@ -49,5 +49,5 @@ func Diff(ctx context.Context, snapshotID, contentRef string, sn snapshot.Snapsh defer sn.Remove(ctx, lowerKey) } - return md.DiffMounts(ctx, lower, upper, ocispec.MediaTypeImageLayer, contentRef) + return md.DiffMounts(ctx, lower, upper, ocispec.MediaTypeImageLayerGzip, contentRef) }