Revert "Add shared content label to namespaces"
This reverts commit e692a01926
.
Signed-off-by: Cody Roseborough <cdr@amazon.com>
This commit is contained in:
parent
6e211a774f
commit
8dd36423b6
@ -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.
|
||||
|
@ -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"
|
||||
|
@ -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}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user