From 4ccb7aa2213e09c21a4b320eec5b8b6d1ac32e48 Mon Sep 17 00:00:00 2001 From: Kohei Tokunaga Date: Mon, 23 Dec 2019 10:39:40 +0900 Subject: [PATCH 1/2] Enable to propagate necessary information to snapshotter during unpack Though containerd gives ChainID to backend snapshotters during unpack for searching snapshots to be skipped downloading the contents, ChainID isn't enough for some snapshotters which require additional information of layers. Some examples are remote snapshotters which is based on stargz filesystem (requires image-related information to query the contents to docker registry) and those which is based on CernVM-FS (requires manifest digest, etc. for providing squashed rootfs). This commit solves this issue by enabling a handler to inject additional information of layers to snapshotters during unpack. Signed-off-by: Kohei Tokunaga --- pull.go | 2 +- unpacker.go | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/pull.go b/pull.go index 2520639df..02d6f4e9b 100644 --- a/pull.go +++ b/pull.go @@ -81,7 +81,7 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (_ Ima if wrapper == nil { return unpackWrapper(h) } - return wrapper(unpackWrapper(h)) + return unpackWrapper(wrapper(h)) } } diff --git a/unpacker.go b/unpacker.go index 7d3a6d3d8..36a93e1f9 100644 --- a/unpacker.go +++ b/unpacker.go @@ -22,6 +22,7 @@ import ( "encoding/json" "fmt" "math/rand" + "strings" "sync" "sync/atomic" "time" @@ -41,6 +42,11 @@ import ( "golang.org/x/sync/semaphore" ) +const ( + inheritedLabelsPrefix = "containerd.io/snapshot/" + labelSnapshotRef = "containerd.io/snapshot.ref" +) + type unpacker struct { updateCh chan ocispec.Descriptor snapshotter string @@ -113,9 +119,16 @@ EachLayer: return errors.Wrapf(err, "failed to stat snapshot %s", chainID) } - labelOpt := snapshots.WithLabels(map[string]string{ - "containerd.io/snapshot.ref": chainID, - }) + // filters the provided annotations by removing any key which isn't a snapshot + // label. Snapshot labels have a prefix of "containerd.io/snapshot/". + labels := make(map[string]string) + for k, v := range desc.Annotations { + if strings.HasPrefix(k, inheritedLabelsPrefix) { + labels[k] = v + } + } + labels[labelSnapshotRef] = chainID + labelOpt := snapshots.WithLabels(labels) var ( key string From 493a36de9521c4a6a0e0cc2fd0495da1d5c08db7 Mon Sep 17 00:00:00 2001 From: ktock Date: Wed, 25 Dec 2019 10:21:57 +0900 Subject: [PATCH 2/2] Move label filter to snapshots package Signed-off-by: Kohei Tokunaga --- metadata/snapshot.go | 23 +++-------------------- metadata/snapshot_test.go | 2 +- snapshots/snapshotter.go | 22 ++++++++++++++++++++++ unpacker.go | 15 +++++---------- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/metadata/snapshot.go b/metadata/snapshot.go index 28fdb8442..73da78467 100644 --- a/metadata/snapshot.go +++ b/metadata/snapshot.go @@ -219,7 +219,7 @@ func (s *snapshotter) Update(ctx context.Context, info snapshots.Info, fieldpath inner := snapshots.Info{ Name: bkey, - Labels: filterInheritedLabels(local.Labels), + Labels: snapshots.FilterInheritedLabels(local.Labels), } // NOTE: Perform this inside the transaction to reduce the @@ -306,7 +306,7 @@ func (s *snapshotter) createSnapshot(ctx context.Context, key, parent string, re bparent string bkey string bopts = []snapshots.Opt{ - snapshots.WithLabels(filterInheritedLabels(base.Labels)), + snapshots.WithLabels(snapshots.FilterInheritedLabels(base.Labels)), } ) @@ -586,7 +586,7 @@ func (s *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap return err } - inheritedOpt := snapshots.WithLabels(filterInheritedLabels(base.Labels)) + inheritedOpt := snapshots.WithLabels(snapshots.FilterInheritedLabels(base.Labels)) // NOTE: Backend snapshotters should commit fast and reliably to // prevent metadata store locking and minimizing rollbacks. @@ -939,20 +939,3 @@ func (s *snapshotter) pruneBranch(ctx context.Context, node *treeNode) error { func (s *snapshotter) Close() error { return s.Snapshotter.Close() } - -// filterInheritedLabels filters the provided labels by removing any key which -// isn't a snapshot label. Snapshot labels have a prefix of "containerd.io/snapshot/" -// or are the "containerd.io/snapshot.ref" label. -func filterInheritedLabels(labels map[string]string) map[string]string { - if labels == nil { - return nil - } - - filtered := make(map[string]string) - for k, v := range labels { - if k == labelSnapshotRef || strings.HasPrefix(k, inheritedLabelsPrefix) { - filtered[k] = v - } - } - return filtered -} diff --git a/metadata/snapshot_test.go b/metadata/snapshot_test.go index 4ba280caf..93c3c9d72 100644 --- a/metadata/snapshot_test.go +++ b/metadata/snapshot_test.go @@ -227,7 +227,7 @@ func TestFilterInheritedLabels(t *testing.T) { } for _, test := range tests { - if actual := filterInheritedLabels(test.labels); !reflect.DeepEqual(actual, test.expected) { + if actual := snapshots.FilterInheritedLabels(test.labels); !reflect.DeepEqual(actual, test.expected) { t.Fatalf("expected %v but got %v", test.expected, actual) } } diff --git a/snapshots/snapshotter.go b/snapshots/snapshotter.go index 3a0a6589e..e884cd647 100644 --- a/snapshots/snapshotter.go +++ b/snapshots/snapshotter.go @@ -25,6 +25,11 @@ import ( "github.com/containerd/containerd/mount" ) +const ( + inheritedLabelsPrefix = "containerd.io/snapshot/" + labelSnapshotRef = "containerd.io/snapshot.ref" +) + // Kind identifies the kind of snapshot. type Kind uint8 @@ -346,3 +351,20 @@ func WithLabels(labels map[string]string) Opt { return nil } } + +// FilterInheritedLabels filters the provided labels by removing any key which +// isn't a snapshot label. Snapshot labels have a prefix of "containerd.io/snapshot/" +// or are the "containerd.io/snapshot.ref" label. +func FilterInheritedLabels(labels map[string]string) map[string]string { + if labels == nil { + return nil + } + + filtered := make(map[string]string) + for k, v := range labels { + if k == labelSnapshotRef || strings.HasPrefix(k, inheritedLabelsPrefix) { + filtered[k] = v + } + } + return filtered +} diff --git a/unpacker.go b/unpacker.go index 36a93e1f9..53630d886 100644 --- a/unpacker.go +++ b/unpacker.go @@ -22,7 +22,6 @@ import ( "encoding/json" "fmt" "math/rand" - "strings" "sync" "sync/atomic" "time" @@ -43,8 +42,7 @@ import ( ) const ( - inheritedLabelsPrefix = "containerd.io/snapshot/" - labelSnapshotRef = "containerd.io/snapshot.ref" + labelSnapshotRef = "containerd.io/snapshot.ref" ) type unpacker struct { @@ -119,13 +117,10 @@ EachLayer: return errors.Wrapf(err, "failed to stat snapshot %s", chainID) } - // filters the provided annotations by removing any key which isn't a snapshot - // label. Snapshot labels have a prefix of "containerd.io/snapshot/". - labels := make(map[string]string) - for k, v := range desc.Annotations { - if strings.HasPrefix(k, inheritedLabelsPrefix) { - labels[k] = v - } + // inherits annotations which are provided as snapshot labels. + labels := snapshots.FilterInheritedLabels(desc.Annotations) + if labels == nil { + labels = make(map[string]string) } labels[labelSnapshotRef] = chainID labelOpt := snapshots.WithLabels(labels)