Revert "Add shared content label to namespaces"

This reverts commit e692a01926.

Signed-off-by: Cody Roseborough <cdr@amazon.com>
This commit is contained in:
Cody Roseborough 2022-01-12 10:56:48 -08:00
parent 6e211a774f
commit 8dd36423b6
6 changed files with 1 additions and 253 deletions

View File

@ -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.

View File

@ -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"

View File

@ -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}
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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)
}