Allow opts to flow to the backend snapshotter during snapshot creation.

Signed-off-by: Eric Hotinger <ehotinger@gmail.com>
This commit is contained in:
Eric Hotinger 2019-02-28 11:37:03 -08:00
parent 3e7c6f6a6b
commit 75f183887a
3 changed files with 75 additions and 7 deletions

View File

@ -34,6 +34,10 @@ import (
bolt "go.etcd.io/bbolt" bolt "go.etcd.io/bbolt"
) )
const (
inheritedLabelsPrefix = "containerd.io/snapshot/"
)
type snapshotter struct { type snapshotter struct {
snapshots.Snapshotter snapshots.Snapshotter
name string name string
@ -338,12 +342,14 @@ func (s *snapshotter) createSnapshot(ctx context.Context, key, parent string, re
return err return err
} }
inheritedOpt := snapshots.WithLabels(filterInheritedLabels(base.Labels))
// TODO: Consider doing this outside of transaction to lessen // TODO: Consider doing this outside of transaction to lessen
// metadata lock time // metadata lock time
if readonly { if readonly {
m, err = s.Snapshotter.View(ctx, bkey, bparent) m, err = s.Snapshotter.View(ctx, bkey, bparent, inheritedOpt)
} else { } else {
m, err = s.Snapshotter.Prepare(ctx, bkey, bparent) m, err = s.Snapshotter.Prepare(ctx, bkey, bparent, inheritedOpt)
} }
return err return err
}); err != nil { }); err != nil {
@ -445,9 +451,11 @@ func (s *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap
return err return err
} }
inheritedOpt := snapshots.WithLabels(filterInheritedLabels(base.Labels))
// TODO: Consider doing this outside of transaction to lessen // TODO: Consider doing this outside of transaction to lessen
// metadata lock time // metadata lock time
return s.Snapshotter.Commit(ctx, nameKey, bkey) return s.Snapshotter.Commit(ctx, nameKey, bkey, inheritedOpt)
}) })
} }
@ -761,3 +769,19 @@ func (s *snapshotter) pruneBranch(ctx context.Context, node *treeNode) error {
func (s *snapshotter) Close() error { func (s *snapshotter) Close() error {
return s.Snapshotter.Close() return s.Snapshotter.Close()
} }
// filterInheritedLabels filters the provided labels by removing any key which doesn't have
// a prefix of "containerd.io/snapshot/".
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 strings.HasPrefix(k, inheritedLabelsPrefix) {
filtered[k] = v
}
}
return filtered
}

View File

@ -20,6 +20,7 @@ import (
"context" "context"
"os" "os"
"path/filepath" "path/filepath"
"reflect"
"runtime" "runtime"
"testing" "testing"
@ -63,3 +64,41 @@ func TestMetadata(t *testing.T) {
testutil.RequiresRoot(t) testutil.RequiresRoot(t)
testsuite.SnapshotterSuite(t, "Metadata", newTestSnapshotter) testsuite.SnapshotterSuite(t, "Metadata", newTestSnapshotter)
} }
func TestFilterInheritedLabels(t *testing.T) {
tests := []struct {
labels map[string]string
expected map[string]string
}{
{
nil,
nil,
},
{
map[string]string{},
map[string]string{},
},
{
map[string]string{"": ""},
map[string]string{},
},
{
map[string]string{"foo": "bar"},
map[string]string{},
},
{
map[string]string{inheritedLabelsPrefix + "foo": "bar"},
map[string]string{inheritedLabelsPrefix + "foo": "bar"},
},
{
map[string]string{inheritedLabelsPrefix + "foo": "bar", "qux": "qaz"},
map[string]string{inheritedLabelsPrefix + "foo": "bar"},
},
}
for _, test := range tests {
if actual := filterInheritedLabels(test.labels); !reflect.DeepEqual(actual, test.expected) {
t.Fatalf("expected %v but got %v", test.expected, actual)
}
}
}

View File

@ -86,10 +86,15 @@ func (k *Kind) UnmarshalJSON(b []byte) error {
// Info provides information about a particular snapshot. // Info provides information about a particular snapshot.
// JSON marshallability is supported for interactive with tools like ctr, // JSON marshallability is supported for interactive with tools like ctr,
type Info struct { type Info struct {
Kind Kind // active or committed snapshot Kind Kind // active or committed snapshot
Name string // name or key of snapshot Name string // name or key of snapshot
Parent string `json:",omitempty"` // name of parent snapshot Parent string `json:",omitempty"` // name of parent snapshot
Labels map[string]string `json:",omitempty"` // Labels for snapshot
// Labels for a snapshot.
//
// Note: only labels prefixed with `containerd.io/snapshot/` will be inherited by the
// snapshotter's `Prepare`, `View`, or `Commit` calls.
Labels map[string]string `json:",omitempty"`
Created time.Time `json:",omitempty"` // Created time Created time.Time `json:",omitempty"` // Created time
Updated time.Time `json:",omitempty"` // Last update time Updated time.Time `json:",omitempty"` // Last update time
} }