github.com/demonoid81/containerd@v1.3.4/metadata/namespaces.go (about)

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package metadata
    18  
    19  import (
    20  	"context"
    21  
    22  	"github.com/containerd/containerd/errdefs"
    23  	l "github.com/containerd/containerd/labels"
    24  	"github.com/containerd/containerd/namespaces"
    25  	"github.com/pkg/errors"
    26  	bolt "go.etcd.io/bbolt"
    27  )
    28  
    29  type namespaceStore struct {
    30  	tx *bolt.Tx
    31  }
    32  
    33  // NewNamespaceStore returns a store backed by a bolt DB
    34  func NewNamespaceStore(tx *bolt.Tx) namespaces.Store {
    35  	return &namespaceStore{tx: tx}
    36  }
    37  
    38  func (s *namespaceStore) Create(ctx context.Context, namespace string, labels map[string]string) error {
    39  	topbkt, err := createBucketIfNotExists(s.tx, bucketKeyVersion)
    40  	if err != nil {
    41  		return err
    42  	}
    43  
    44  	if err := namespaces.Validate(namespace); err != nil {
    45  		return err
    46  	}
    47  
    48  	for k, v := range labels {
    49  		if err := l.Validate(k, v); err != nil {
    50  			return errors.Wrapf(err, "namespace.Labels")
    51  		}
    52  	}
    53  
    54  	// provides the already exists error.
    55  	bkt, err := topbkt.CreateBucket([]byte(namespace))
    56  	if err != nil {
    57  		if err == bolt.ErrBucketExists {
    58  			return errors.Wrapf(errdefs.ErrAlreadyExists, "namespace %q", namespace)
    59  		}
    60  
    61  		return err
    62  	}
    63  
    64  	lbkt, err := bkt.CreateBucketIfNotExists(bucketKeyObjectLabels)
    65  	if err != nil {
    66  		return err
    67  	}
    68  
    69  	for k, v := range labels {
    70  		if err := lbkt.Put([]byte(k), []byte(v)); err != nil {
    71  			return err
    72  		}
    73  	}
    74  
    75  	return nil
    76  }
    77  
    78  func (s *namespaceStore) Labels(ctx context.Context, namespace string) (map[string]string, error) {
    79  	labels := map[string]string{}
    80  
    81  	bkt := getNamespaceLabelsBucket(s.tx, namespace)
    82  	if bkt == nil {
    83  		return labels, nil
    84  	}
    85  
    86  	if err := bkt.ForEach(func(k, v []byte) error {
    87  		labels[string(k)] = string(v)
    88  		return nil
    89  	}); err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	return labels, nil
    94  }
    95  
    96  func (s *namespaceStore) SetLabel(ctx context.Context, namespace, key, value string) error {
    97  	if err := l.Validate(key, value); err != nil {
    98  		return errors.Wrapf(err, "namespace.Labels")
    99  	}
   100  
   101  	return withNamespacesLabelsBucket(s.tx, namespace, func(bkt *bolt.Bucket) error {
   102  		if value == "" {
   103  			return bkt.Delete([]byte(key))
   104  		}
   105  
   106  		return bkt.Put([]byte(key), []byte(value))
   107  	})
   108  
   109  }
   110  
   111  func (s *namespaceStore) List(ctx context.Context) ([]string, error) {
   112  	bkt := getBucket(s.tx, bucketKeyVersion)
   113  	if bkt == nil {
   114  		return nil, nil // no namespaces!
   115  	}
   116  
   117  	var namespaces []string
   118  	if err := bkt.ForEach(func(k, v []byte) error {
   119  		if v != nil {
   120  			return nil // not a bucket
   121  		}
   122  
   123  		namespaces = append(namespaces, string(k))
   124  		return nil
   125  	}); err != nil {
   126  		return nil, err
   127  	}
   128  
   129  	return namespaces, nil
   130  }
   131  
   132  func (s *namespaceStore) Delete(ctx context.Context, namespace string, opts ...namespaces.DeleteOpts) error {
   133  	i := &namespaces.DeleteInfo{
   134  		Name: namespace,
   135  	}
   136  	for _, o := range opts {
   137  		if err := o(ctx, i); err != nil {
   138  			return err
   139  		}
   140  	}
   141  	bkt := getBucket(s.tx, bucketKeyVersion)
   142  	if empty, err := s.namespaceEmpty(ctx, namespace); err != nil {
   143  		return err
   144  	} else if !empty {
   145  		return errors.Wrapf(errdefs.ErrFailedPrecondition, "namespace %q must be empty", namespace)
   146  	}
   147  
   148  	if err := bkt.DeleteBucket([]byte(namespace)); err != nil {
   149  		if err == bolt.ErrBucketNotFound {
   150  			return errors.Wrapf(errdefs.ErrNotFound, "namespace %q", namespace)
   151  		}
   152  
   153  		return err
   154  	}
   155  
   156  	return nil
   157  }
   158  
   159  func (s *namespaceStore) namespaceEmpty(ctx context.Context, namespace string) (bool, error) {
   160  	// Get all data buckets
   161  	buckets := []*bolt.Bucket{
   162  		getImagesBucket(s.tx, namespace),
   163  		getBlobsBucket(s.tx, namespace),
   164  		getContainersBucket(s.tx, namespace),
   165  	}
   166  	if snbkt := getSnapshottersBucket(s.tx, namespace); snbkt != nil {
   167  		if err := snbkt.ForEach(func(k, v []byte) error {
   168  			if v == nil {
   169  				buckets = append(buckets, snbkt.Bucket(k))
   170  			}
   171  			return nil
   172  		}); err != nil {
   173  			return false, err
   174  		}
   175  	}
   176  
   177  	// Ensure data buckets are empty
   178  	for _, bkt := range buckets {
   179  		if !isBucketEmpty(bkt) {
   180  			return false, nil
   181  		}
   182  	}
   183  
   184  	return true, nil
   185  }
   186  
   187  func isBucketEmpty(bkt *bolt.Bucket) bool {
   188  	if bkt == nil {
   189  		return true
   190  	}
   191  
   192  	k, _ := bkt.Cursor().First()
   193  	return k == nil
   194  }