diff --git a/docs/ops.md b/docs/ops.md index 2e14beda1..c884db083 100644 --- a/docs/ops.md +++ b/docs/ops.md @@ -232,7 +232,3 @@ The default is "shared". While this is largely the most desired policy, one can [plugins.bolt] content_sharing_policy = "isolated" ``` - -It is possible to share only the contents of a specific namespace by adding the label `containerd.io/namespace.shareable=true` to that namespace. -This will share the contents of the namespace even if the content sharing policy is set to isolated and make its images usable by all other namespaces. -If the label value is set to anything other than `true`, the namespace content will not be shared. diff --git a/labels/labels.go b/labels/labels.go index 6be006c3e..d76ff2cf9 100644 --- a/labels/labels.go +++ b/labels/labels.go @@ -19,7 +19,3 @@ package labels // LabelUncompressed is added to compressed layer contents. // The value is digest of the uncompressed content. const LabelUncompressed = "containerd.io/uncompressed" - -// LabelSharedNamespace is added to a namespace to allow that namespaces -// contents to be shared. -const LabelSharedNamespace = "containerd.io/namespace.shareable" diff --git a/metadata/buckets.go b/metadata/buckets.go index 9103d16ed..d23be84fe 100644 --- a/metadata/buckets.go +++ b/metadata/buckets.go @@ -115,7 +115,6 @@ package metadata import ( - "github.com/containerd/containerd/labels" digest "github.com/opencontainers/go-digest" bolt "go.etcd.io/bbolt" ) @@ -183,45 +182,6 @@ func createBucketIfNotExists(tx *bolt.Tx, keys ...[]byte) (*bolt.Bucket, error) return bkt, nil } -func namespacesBucketPath() []byte { - return bucketKeyVersion -} - -func getNamespacesBucket(tx *bolt.Tx) *bolt.Bucket { - return getBucket(tx, namespacesBucketPath()) -} - -// Given a namespace string and a bolt transaction -// return true if the ns has the shared label in it. -func hasSharedLabel(tx *bolt.Tx, ns string) bool { - labelsBkt := getNamespaceLabelsBucket(tx, ns) - if labelsBkt == nil { - return false - } - cur := labelsBkt.Cursor() - for k, v := cur.First(); k != nil; k, v = cur.Next() { - if string(k) == labels.LabelSharedNamespace && string(v) == "true" { - return true - } - } - return false -} - -func getShareableBucket(tx *bolt.Tx, dgst digest.Digest) *bolt.Bucket { - var bkt *bolt.Bucket - nsbkt := getNamespacesBucket(tx) - cur := nsbkt.Cursor() - for k, _ := cur.First(); k != nil; k, _ = cur.Next() { - // If this bucket has shared label - // get the bucket and return it. - if hasSharedLabel(tx, string(k)) { - bkt = getBlobBucket(tx, string(k), dgst) - break - } - } - return bkt -} - func namespaceLabelsBucketPath(namespace string) [][]byte { return [][]byte{bucketKeyVersion, []byte(namespace), bucketKeyObjectLabels} } diff --git a/metadata/buckets_test.go b/metadata/buckets_test.go deleted file mode 100644 index 991900e18..000000000 --- a/metadata/buckets_test.go +++ /dev/null @@ -1,171 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package metadata - -import ( - "errors" - "os" - "path/filepath" - "testing" - - "github.com/containerd/containerd/labels" - digest "github.com/opencontainers/go-digest" - bolt "go.etcd.io/bbolt" -) - -func TestHasSharedLabel(t *testing.T) { - tmpdir, err := os.MkdirTemp("", "bucket-testing-") - if err != nil { - t.Error(err) - } - - db, err := bolt.Open(filepath.Join(tmpdir, "metadata.db"), 0660, nil) - if err != nil { - t.Error(err) - } - - err = createNamespaceLabelsBucket(db, "testing-with-shareable", true) - if err != nil { - t.Error(err) - } - - err = createNamespaceLabelsBucket(db, "testing-without-shareable", false) - if err != nil { - t.Error(err) - } - - err = db.View(func(tx *bolt.Tx) error { - if !hasSharedLabel(tx, "testing-with-shareable") { - return errors.New("hasSharedLabel should return true when label is set") - } - if hasSharedLabel(tx, "testing-without-shareable") { - return errors.New("hasSharedLabel should return false when label is not set") - } - return nil - }) - - if err != nil { - t.Error(err) - } -} - -func TestGetShareableBucket(t *testing.T) { - tmpdir, err := os.MkdirTemp("", "bucket-testing-") - if err != nil { - t.Error(err) - } - - db, err := bolt.Open(filepath.Join(tmpdir, "metadata.db"), 0660, nil) - if err != nil { - t.Error(err) - } - - goodDigest := digest.FromString("gooddigest") - imagePresentNS := "has-image-is-shareable" - imageAbsentNS := "image-absent" - - // Create two namespaces, empty for now - err = db.Update(func(tx *bolt.Tx) error { - _, err := createImagesBucket(tx, imagePresentNS) - if err != nil { - return err - } - - _, err = createImagesBucket(tx, imageAbsentNS) - if err != nil { - return err - } - - return nil - }) - - if err != nil { - t.Error(err) - } - - // Test that getShareableBucket is correctly returning nothing when a - // a bucket with that digest is not present in any namespace. - err = db.View(func(tx *bolt.Tx) error { - if bkt := getShareableBucket(tx, goodDigest); bkt != nil { - return errors.New("getShareableBucket should return nil if digest is not present") - } - return nil - }) - - if err != nil { - t.Error(err) - } - - // Create a blob bucket in one of the namespaces with a well-known digest - err = db.Update(func(tx *bolt.Tx) error { - _, err = createBlobBucket(tx, imagePresentNS, goodDigest) - if err != nil { - return err - } - return nil - }) - - if err != nil { - t.Error(err) - } - - // Verify that it is still not retrievable if the shareable label is not present - err = db.View(func(tx *bolt.Tx) error { - if bkt := getShareableBucket(tx, goodDigest); bkt != nil { - return errors.New("getShareableBucket should return nil if digest is present but doesn't have shareable label") - } - return nil - }) - - if err != nil { - t.Error(err) - } - - // Create the namespace labels bucket and mark it as shareable - err = createNamespaceLabelsBucket(db, imagePresentNS, true) - if err != nil { - t.Error(err) - } - - // Verify that this digest is retrievable from getShareableBucket - err = db.View(func(tx *bolt.Tx) error { - if bkt := getShareableBucket(tx, goodDigest); bkt == nil { - return errors.New("getShareableBucket should not return nil if digest is present") - } - return nil - }) - - if err != nil { - t.Error(err) - } -} - -func createNamespaceLabelsBucket(db transactor, ns string, shareable bool) error { - err := db.Update(func(tx *bolt.Tx) error { - err := withNamespacesLabelsBucket(tx, ns, func(bkt *bolt.Bucket) error { - if shareable { - err := bkt.Put([]byte(labels.LabelSharedNamespace), []byte("true")) - if err != nil { - return err - } - } - return nil - }) - return err - }) - return err -} diff --git a/metadata/content.go b/metadata/content.go index c717d9892..e024f9a50 100644 --- a/metadata/content.go +++ b/metadata/content.go @@ -76,10 +76,6 @@ func (cs *contentStore) Info(ctx context.Context, dgst digest.Digest) (content.I var info content.Info if err := view(ctx, cs.db, func(tx *bolt.Tx) error { bkt := getBlobBucket(tx, ns, dgst) - if bkt == nil { - // try to find shareable bkt before erroring - bkt = getShareableBucket(tx, dgst) - } if bkt == nil { return fmt.Errorf("content digest %v: %w", dgst, errdefs.ErrNotFound) } @@ -107,13 +103,10 @@ func (cs *contentStore) Update(ctx context.Context, info content.Info, fieldpath } if err := update(ctx, cs.db, func(tx *bolt.Tx) error { bkt := getBlobBucket(tx, ns, info.Digest) - if bkt == nil { - // try to find a shareable bkt before erroring - bkt = getShareableBucket(tx, info.Digest) - } if bkt == nil { return fmt.Errorf("content digest %v: %w", info.Digest, errdefs.ErrNotFound) } + if err := readInfo(&updated, bkt); err != nil { return fmt.Errorf("info %q: %w", info.Digest, err) } @@ -706,10 +699,6 @@ func (cs *contentStore) checkAccess(ctx context.Context, dgst digest.Digest) err return view(ctx, cs.db, func(tx *bolt.Tx) error { bkt := getBlobBucket(tx, ns, dgst) - if bkt == nil { - // try to find shareable bkt before erroring - bkt = getShareableBucket(tx, dgst) - } if bkt == nil { return fmt.Errorf("content digest %v: %w", dgst, errdefs.ErrNotFound) } diff --git a/metadata/images.go b/metadata/images.go index de44c7284..8355b712e 100644 --- a/metadata/images.go +++ b/metadata/images.go @@ -55,28 +55,6 @@ func (s *imageStore) Get(ctx context.Context, name string) (images.Image, error) if err := view(ctx, s.db, func(tx *bolt.Tx) error { bkt := getImagesBucket(tx, namespace) - if bkt == nil || bkt.Bucket([]byte(name)) == nil { - nsbkt := getNamespacesBucket(tx) - cur := nsbkt.Cursor() - for k, _ := cur.First(); k != nil; k, _ = cur.Next() { - // If this namespace has the sharedlabel - if hasSharedLabel(tx, string(k)) { - // and has the image we are looking for - bkt = getImagesBucket(tx, string(k)) - if bkt == nil { - continue - } - - ibkt := bkt.Bucket([]byte(name)) - if ibkt == nil { - continue - } - // we are done - break - } - - } - } if bkt == nil { return fmt.Errorf("image %q: %w", name, errdefs.ErrNotFound) }