From 66ecfa70ad0b2d14a95f7c484297ca65eeff8101 Mon Sep 17 00:00:00 2001 From: Lantao Liu Date: Fri, 1 Dec 2017 04:37:06 +0000 Subject: [PATCH] Add gc.root back in vendored containerd client. Signed-off-by: Lantao Liu --- .../containerd/containerd/client.go | 7 +++++- .../containerd/containerd/container_opts.go | 12 +++++++-- .../containerd/container_opts_unix.go | 15 +++++++---- .../github.com/containerd/containerd/image.go | 23 +++++++++++++++++ .../remotes/docker/schema1/converter.go | 13 ++++++++-- .../containerd/containerd/remotes/handlers.go | 15 ++++++----- .../github.com/containerd/containerd/task.go | 25 ++++++++++++++++++- 7 files changed, 93 insertions(+), 17 deletions(-) diff --git a/vendor/github.com/containerd/containerd/client.go b/vendor/github.com/containerd/containerd/client.go index 5c20335ea..5c3b430ad 100644 --- a/vendor/github.com/containerd/containerd/client.go +++ b/vendor/github.com/containerd/containerd/client.go @@ -238,7 +238,7 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image handler = images.Handlers(append(pullCtx.BaseHandlers, schema1Converter)...) } else { handler = images.Handlers(append(pullCtx.BaseHandlers, - remotes.FetchHandler(store, fetcher), + remotes.FetchHandler(store, fetcher, desc), images.ChildrenHandler(store, platforms.Default()))..., ) } @@ -275,6 +275,11 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image imgrec = created } + // Remove root tag from manifest now that image refers to it + if _, err := store.Update(ctx, content.Info{Digest: desc.Digest}, "labels.containerd.io/gc.root"); err != nil { + return nil, errors.Wrap(err, "failed to remove manifest root tag") + } + img := &image{ client: c, i: imgrec, diff --git a/vendor/github.com/containerd/containerd/container_opts.go b/vendor/github.com/containerd/containerd/container_opts.go index fb22a9096..8fa19dbfb 100644 --- a/vendor/github.com/containerd/containerd/container_opts.go +++ b/vendor/github.com/containerd/containerd/container_opts.go @@ -2,11 +2,13 @@ package containerd import ( "context" + "time" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/oci" "github.com/containerd/containerd/platforms" + "github.com/containerd/containerd/snapshots" "github.com/containerd/typeurl" "github.com/gogo/protobuf/types" "github.com/opencontainers/image-spec/identity" @@ -93,8 +95,11 @@ func WithNewSnapshot(id string, i Image) NewContainerOpts { return err } setSnapshotterIfEmpty(c) + labels := map[string]string{ + "containerd.io/gc.root": time.Now().String(), + } parent := identity.ChainID(diffIDs).String() - if _, err := client.SnapshotService(c.Snapshotter).Prepare(ctx, id, parent); err != nil { + if _, err := client.SnapshotService(c.Snapshotter).Prepare(ctx, id, parent, snapshots.WithLabels(labels)); err != nil { return err } c.SnapshotKey = id @@ -123,8 +128,11 @@ func WithNewSnapshotView(id string, i Image) NewContainerOpts { return err } setSnapshotterIfEmpty(c) + labels := map[string]string{ + "containerd.io/gc.root": time.Now().String(), + } parent := identity.ChainID(diffIDs).String() - if _, err := client.SnapshotService(c.Snapshotter).View(ctx, id, parent); err != nil { + if _, err := client.SnapshotService(c.Snapshotter).View(ctx, id, parent, snapshots.WithLabels(labels)); err != nil { return err } c.SnapshotKey = id diff --git a/vendor/github.com/containerd/containerd/container_opts_unix.go b/vendor/github.com/containerd/containerd/container_opts_unix.go index bb431e51f..dea3b8bf5 100644 --- a/vendor/github.com/containerd/containerd/container_opts_unix.go +++ b/vendor/github.com/containerd/containerd/container_opts_unix.go @@ -10,6 +10,7 @@ import ( "os" "path/filepath" "syscall" + "time" "github.com/containerd/containerd/api/types" "github.com/containerd/containerd/containers" @@ -18,6 +19,7 @@ import ( "github.com/containerd/containerd/images" "github.com/containerd/containerd/mount" "github.com/containerd/containerd/platforms" + "github.com/containerd/containerd/snapshots" "github.com/gogo/protobuf/proto" protobuf "github.com/gogo/protobuf/types" digest "github.com/opencontainers/go-digest" @@ -153,9 +155,12 @@ func withRemappedSnapshotBase(id string, i Image, uid, gid uint32, readonly bool snapshotter = client.SnapshotService(c.Snapshotter) parent = identity.ChainID(diffIDs).String() usernsID = fmt.Sprintf("%s-%d-%d", parent, uid, gid) + opt = snapshots.WithLabels(map[string]string{ + "containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339), + }) ) if _, err := snapshotter.Stat(ctx, usernsID); err == nil { - if _, err := snapshotter.Prepare(ctx, id, usernsID); err == nil { + if _, err := snapshotter.Prepare(ctx, id, usernsID, opt); err == nil { c.SnapshotKey = id c.Image = i.Name() return nil @@ -163,7 +168,7 @@ func withRemappedSnapshotBase(id string, i Image, uid, gid uint32, readonly bool return err } } - mounts, err := snapshotter.Prepare(ctx, usernsID+"-remap", parent) + mounts, err := snapshotter.Prepare(ctx, usernsID+"-remap", parent, opt) if err != nil { return err } @@ -171,13 +176,13 @@ func withRemappedSnapshotBase(id string, i Image, uid, gid uint32, readonly bool snapshotter.Remove(ctx, usernsID) return err } - if err := snapshotter.Commit(ctx, usernsID, usernsID+"-remap"); err != nil { + if err := snapshotter.Commit(ctx, usernsID, usernsID+"-remap", opt); err != nil { return err } if readonly { - _, err = snapshotter.View(ctx, id, usernsID) + _, err = snapshotter.View(ctx, id, usernsID, opt) } else { - _, err = snapshotter.Prepare(ctx, id, usernsID) + _, err = snapshotter.Prepare(ctx, id, usernsID, opt) } if err != nil { return err diff --git a/vendor/github.com/containerd/containerd/image.go b/vendor/github.com/containerd/containerd/image.go index 202fc42bd..d421406f1 100644 --- a/vendor/github.com/containerd/containerd/image.go +++ b/vendor/github.com/containerd/containerd/image.go @@ -3,6 +3,7 @@ package containerd import ( "context" "fmt" + "time" "github.com/containerd/containerd/content" "github.com/containerd/containerd/errdefs" @@ -109,14 +110,27 @@ func (i *image) Unpack(ctx context.Context, snapshotterName string) error { ) for _, layer := range layers { labels := map[string]string{ + "containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339), "containerd.io/uncompressed": layer.Diff.Digest.String(), } + lastUnpacked := unpacked unpacked, err = rootfs.ApplyLayer(ctx, layer, chain, sn, a, snapshots.WithLabels(labels)) if err != nil { return err } + if lastUnpacked { + info := snapshots.Info{ + Name: identity.ChainID(chain).String(), + } + + // Remove previously created gc.root label + if _, err := sn.Update(ctx, info, "labels.containerd.io/gc.root"); err != nil { + return err + } + } + chain = append(chain, layer.Diff.Digest) } @@ -137,6 +151,15 @@ func (i *image) Unpack(ctx context.Context, snapshotterName string) error { if _, err := cs.Update(ctx, cinfo, fmt.Sprintf("labels.containerd.io/gc.ref.snapshot.%s", snapshotterName)); err != nil { return err } + + sinfo := snapshots.Info{ + Name: rootfs, + } + + // Config now referenced snapshot, release root reference + if _, err := sn.Update(ctx, sinfo, "labels.containerd.io/gc.root"); err != nil { + return err + } } return nil diff --git a/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go b/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go index 6b74cd67e..02a42a028 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go +++ b/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go @@ -157,6 +157,7 @@ func (c *Converter) Convert(ctx context.Context) (ocispec.Descriptor, error) { } labels := map[string]string{} + labels["containerd.io/gc.root"] = time.Now().UTC().Format(time.RFC3339) labels["containerd.io/gc.ref.content.0"] = manifest.Config.Digest.String() for i, ch := range manifest.Layers { labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i+1)] = ch.Digest.String() @@ -172,6 +173,12 @@ func (c *Converter) Convert(ctx context.Context) (ocispec.Descriptor, error) { return ocispec.Descriptor{}, errors.Wrap(err, "failed to write config") } + for _, ch := range manifest.Layers { + if _, err := c.contentStore.Update(ctx, content.Info{Digest: ch.Digest}, "labels.containerd.io/gc.root"); err != nil { + return ocispec.Descriptor{}, errors.Wrap(err, "failed to remove blob root tag") + } + } + return desc, nil } @@ -280,8 +287,10 @@ tryit: eg.Go(func() error { defer pw.Close() - - return content.Copy(ctx, cw, io.TeeReader(rc, pw), size, desc.Digest) + opt := content.WithLabels(map[string]string{ + "containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339), + }) + return content.Copy(ctx, cw, io.TeeReader(rc, pw), size, desc.Digest, opt) }) if err := eg.Wait(); err != nil { diff --git a/vendor/github.com/containerd/containerd/remotes/handlers.go b/vendor/github.com/containerd/containerd/remotes/handlers.go index e583391d8..7b1dad99e 100644 --- a/vendor/github.com/containerd/containerd/remotes/handlers.go +++ b/vendor/github.com/containerd/containerd/remotes/handlers.go @@ -45,7 +45,7 @@ func MakeRefKey(ctx context.Context, desc ocispec.Descriptor) string { // FetchHandler returns a handler that will fetch all content into the ingester // discovered in a call to Dispatch. Use with ChildrenHandler to do a full // recursive fetch. -func FetchHandler(ingester content.Ingester, fetcher Fetcher) images.HandlerFunc { +func FetchHandler(ingester content.Ingester, fetcher Fetcher, root ocispec.Descriptor) images.HandlerFunc { return func(ctx context.Context, desc ocispec.Descriptor) (subdescs []ocispec.Descriptor, err error) { ctx = log.WithLogger(ctx, log.G(ctx).WithFields(logrus.Fields{ "digest": desc.Digest, @@ -57,13 +57,13 @@ func FetchHandler(ingester content.Ingester, fetcher Fetcher) images.HandlerFunc case images.MediaTypeDockerSchema1Manifest: return nil, fmt.Errorf("%v not supported", desc.MediaType) default: - err := fetch(ctx, ingester, fetcher, desc) + err := fetch(ctx, ingester, fetcher, desc, desc.Digest == root.Digest) return nil, err } } } -func fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc ocispec.Descriptor) error { +func fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc ocispec.Descriptor, root bool) error { log.G(ctx).Debug("fetch") var ( @@ -105,13 +105,13 @@ func fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc } defer rc.Close() - r, opts := commitOpts(desc, rc) + r, opts := commitOpts(desc, rc, root) return content.Copy(ctx, cw, r, desc.Size, desc.Digest, opts...) } // commitOpts gets the appropriate content options to alter // the content info on commit based on media type. -func commitOpts(desc ocispec.Descriptor, r io.Reader) (io.Reader, []content.Opt) { +func commitOpts(desc ocispec.Descriptor, r io.Reader, root bool) (io.Reader, []content.Opt) { var childrenF func(r io.Reader) ([]ocispec.Descriptor, error) switch desc.MediaType { @@ -163,10 +163,13 @@ func commitOpts(desc ocispec.Descriptor, r io.Reader) (io.Reader, []content.Opt) return errors.Wrap(err, "unable to get commit labels") } - if len(children) > 0 { + if len(children) > 0 || root { if info.Labels == nil { info.Labels = map[string]string{} } + if root { + info.Labels["containerd.io/gc.root"] = time.Now().UTC().Format(time.RFC3339) + } for i, ch := range children { info.Labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i)] = ch.Digest.String() } diff --git a/vendor/github.com/containerd/containerd/task.go b/vendor/github.com/containerd/containerd/task.go index 8d256834f..e0528ba96 100644 --- a/vendor/github.com/containerd/containerd/task.go +++ b/vendor/github.com/containerd/containerd/task.go @@ -18,6 +18,7 @@ import ( "github.com/containerd/containerd/diff" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/images" + "github.com/containerd/containerd/log" "github.com/containerd/containerd/mount" "github.com/containerd/containerd/plugin" "github.com/containerd/containerd/rootfs" @@ -25,6 +26,7 @@ import ( google_protobuf "github.com/gogo/protobuf/types" digest "github.com/opencontainers/go-digest" "github.com/opencontainers/image-spec/specs-go/v1" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" ) @@ -401,6 +403,15 @@ func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Imag index := v1.Index{ Annotations: make(map[string]string), } + // make sure we clear the gc root labels reguardless of success + var clearRoots []ocispec.Descriptor + defer func() { + for _, r := range append(index.Manifests, clearRoots...) { + if err := clearRootGCLabel(ctx, t.client, r); err != nil { + log.G(ctx).WithError(err).WithField("dgst", r.Digest).Warnf("failed to remove root marker") + } + } + }() if err := t.checkpointTask(ctx, &index, request); err != nil { return nil, err } @@ -419,6 +430,7 @@ func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Imag if err != nil { return nil, err } + clearRoots = append(clearRoots, desc) im := images.Image{ Name: i.Name, Target: desc, @@ -534,6 +546,9 @@ func (t *task) checkpointTask(ctx context.Context, index *v1.Index, request *tas func (t *task) checkpointRWSnapshot(ctx context.Context, index *v1.Index, snapshotterName string, id string) error { opts := []diff.Opt{ diff.WithReference(fmt.Sprintf("checkpoint-rw-%s", id)), + diff.WithLabels(map[string]string{ + "containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339), + }), } rw, err := rootfs.Diff(ctx, id, t.client.SnapshotService(snapshotterName), t.client.DiffService(), opts...) if err != nil { @@ -560,7 +575,9 @@ func (t *task) checkpointImage(ctx context.Context, index *v1.Index, image strin } func (t *task) writeIndex(ctx context.Context, index *v1.Index) (d v1.Descriptor, err error) { - labels := map[string]string{} + labels := map[string]string{ + "containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339), + } for i, m := range index.Manifests { labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i)] = m.Digest.String() } @@ -590,3 +607,9 @@ func writeContent(ctx context.Context, store content.Store, mediaType, ref strin Size: size, }, nil } + +func clearRootGCLabel(ctx context.Context, client *Client, desc ocispec.Descriptor) error { + info := content.Info{Digest: desc.Digest} + _, err := client.ContentStore().Update(ctx, info, "labels.containerd.io/gc.root") + return err +}