Use error interfaces for content/metadata
These interfaces allow us to preserve both the checking of error "cause" as well as messages returned from the gRPC API so that the client gets full error reason instead of a default "metadata: not found" in the case of a missing image. Signed-off-by: Phil Estes <estesp@linux.vnet.ibm.com>
This commit is contained in:
@@ -28,7 +28,7 @@ func (s *containerStore) Get(ctx context.Context, id string) (containers.Contain
|
||||
|
||||
bkt := getContainerBucket(s.tx, namespace, id)
|
||||
if bkt == nil {
|
||||
return containers.Container{}, errors.Wrap(ErrNotFound, "bucket does not exist")
|
||||
return containers.Container{}, ErrNotFound("bucket does not exist")
|
||||
}
|
||||
|
||||
container := containers.Container{ID: id}
|
||||
@@ -85,7 +85,7 @@ func (s *containerStore) Create(ctx context.Context, container containers.Contai
|
||||
cbkt, err := bkt.CreateBucket([]byte(container.ID))
|
||||
if err != nil {
|
||||
if err == bolt.ErrBucketExists {
|
||||
err = errors.Wrap(ErrExists, "content for id already exists")
|
||||
err = ErrExists("content for id already exists")
|
||||
}
|
||||
return containers.Container{}, err
|
||||
}
|
||||
@@ -107,12 +107,12 @@ func (s *containerStore) Update(ctx context.Context, container containers.Contai
|
||||
|
||||
bkt := getContainersBucket(s.tx, namespace)
|
||||
if bkt == nil {
|
||||
return containers.Container{}, errors.Wrap(ErrNotFound, "no containers")
|
||||
return containers.Container{}, ErrNotFound("no containers")
|
||||
}
|
||||
|
||||
cbkt := bkt.Bucket([]byte(container.ID))
|
||||
if cbkt == nil {
|
||||
return containers.Container{}, errors.Wrap(ErrNotFound, "no content for id")
|
||||
return containers.Container{}, ErrNotFound("no content for id")
|
||||
}
|
||||
|
||||
container.UpdatedAt = time.Now()
|
||||
@@ -131,11 +131,11 @@ func (s *containerStore) Delete(ctx context.Context, id string) error {
|
||||
|
||||
bkt := getContainersBucket(s.tx, namespace)
|
||||
if bkt == nil {
|
||||
return errors.Wrap(ErrNotFound, "no containers")
|
||||
return ErrNotFound("no containers")
|
||||
}
|
||||
|
||||
if err := bkt.DeleteBucket([]byte(id)); err == bolt.ErrBucketNotFound {
|
||||
return errors.Wrap(ErrNotFound, "no content for id")
|
||||
return ErrNotFound("no content for id")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,22 +1,117 @@
|
||||
package metadata
|
||||
|
||||
import "github.com/pkg/errors"
|
||||
type metadataExistsErr struct {
|
||||
desc string
|
||||
}
|
||||
type metadataNotFoundErr struct {
|
||||
desc string
|
||||
}
|
||||
type metadataNotEmptyErr struct {
|
||||
desc string
|
||||
}
|
||||
|
||||
var (
|
||||
ErrExists = errors.New("metadata: exists")
|
||||
ErrNotFound = errors.New("metadata: not found")
|
||||
ErrNotEmpty = errors.New("metadata: namespace not empty")
|
||||
)
|
||||
// ErrExists is returned when an item already exists in metadata
|
||||
func ErrExists(msg string) error {
|
||||
if msg == "" {
|
||||
msg = "metadata: exists"
|
||||
}
|
||||
return metadataExistsErr{
|
||||
desc: msg,
|
||||
}
|
||||
}
|
||||
|
||||
// IsNotFound returns true if the error is due to a missing image.
|
||||
// ErrNotFound is returned when an item cannot be found in metadata
|
||||
func ErrNotFound(msg string) error {
|
||||
if msg == "" {
|
||||
msg = "metadata: not found"
|
||||
}
|
||||
return metadataNotFoundErr{
|
||||
desc: msg,
|
||||
}
|
||||
}
|
||||
|
||||
// ErrNotEmpty is returned when a metadata item can't be deleted because it is not empty
|
||||
func ErrNotEmpty(msg string) error {
|
||||
if msg == "" {
|
||||
msg = "metadata: namespace not empty"
|
||||
}
|
||||
return metadataNotEmptyErr{
|
||||
desc: msg,
|
||||
}
|
||||
}
|
||||
|
||||
func (m metadataExistsErr) Error() string {
|
||||
return m.desc
|
||||
}
|
||||
func (m metadataNotFoundErr) Error() string {
|
||||
return m.desc
|
||||
}
|
||||
func (m metadataNotEmptyErr) Error() string {
|
||||
return m.desc
|
||||
}
|
||||
|
||||
func (m metadataExistsErr) Exists() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (m metadataNotFoundErr) NotFound() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (m metadataNotEmptyErr) NotEmpty() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsNotFound returns true if the error is due to a missing metadata item
|
||||
func IsNotFound(err error) bool {
|
||||
return errors.Cause(err) == ErrNotFound
|
||||
if err, ok := err.(interface {
|
||||
NotFound() bool
|
||||
}); ok {
|
||||
return err.NotFound()
|
||||
}
|
||||
|
||||
causal, ok := err.(interface {
|
||||
Cause() error
|
||||
})
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return IsNotFound(causal.Cause())
|
||||
}
|
||||
|
||||
// IsExists returns true if the error is due to an already existing metadata item
|
||||
func IsExists(err error) bool {
|
||||
return errors.Cause(err) == ErrExists
|
||||
if err, ok := err.(interface {
|
||||
Exists() bool
|
||||
}); ok {
|
||||
return err.Exists()
|
||||
}
|
||||
|
||||
causal, ok := err.(interface {
|
||||
Cause() error
|
||||
})
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return IsExists(causal.Cause())
|
||||
}
|
||||
|
||||
// IsNotEmpty returns true if the error is due to delete request of a non-empty metadata item
|
||||
func IsNotEmpty(err error) bool {
|
||||
return errors.Cause(err) == ErrNotEmpty
|
||||
if err, ok := err.(interface {
|
||||
NotEmpty() bool
|
||||
}); ok {
|
||||
return err.NotEmpty()
|
||||
}
|
||||
|
||||
causal, ok := err.(interface {
|
||||
Cause() error
|
||||
})
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return IsNotEmpty(causal.Cause())
|
||||
}
|
||||
|
||||
@@ -30,12 +30,12 @@ func (s *imageStore) Get(ctx context.Context, name string) (images.Image, error)
|
||||
|
||||
bkt := getImagesBucket(s.tx, namespace)
|
||||
if bkt == nil {
|
||||
return images.Image{}, ErrNotFound
|
||||
return images.Image{}, ErrNotFound("")
|
||||
}
|
||||
|
||||
ibkt := bkt.Bucket([]byte(name))
|
||||
if ibkt == nil {
|
||||
return images.Image{}, ErrNotFound
|
||||
return images.Image{}, ErrNotFound("")
|
||||
}
|
||||
|
||||
image.Name = name
|
||||
@@ -124,7 +124,7 @@ func (s *imageStore) Delete(ctx context.Context, name string) error {
|
||||
return withImagesBucket(s.tx, namespace, func(bkt *bolt.Bucket) error {
|
||||
err := bkt.DeleteBucket([]byte(name))
|
||||
if err == bolt.ErrBucketNotFound {
|
||||
return ErrNotFound
|
||||
return ErrNotFound("")
|
||||
}
|
||||
return err
|
||||
})
|
||||
|
||||
@@ -25,7 +25,7 @@ func (s *namespaceStore) Create(ctx context.Context, namespace string, labels ma
|
||||
bkt, err := topbkt.CreateBucket([]byte(namespace))
|
||||
if err != nil {
|
||||
if err == bolt.ErrBucketExists {
|
||||
return ErrExists
|
||||
return ErrExists("")
|
||||
}
|
||||
|
||||
return err
|
||||
@@ -100,12 +100,12 @@ func (s *namespaceStore) Delete(ctx context.Context, namespace string) error {
|
||||
if empty, err := s.namespaceEmpty(ctx, namespace); err != nil {
|
||||
return err
|
||||
} else if !empty {
|
||||
return ErrNotEmpty
|
||||
return ErrNotEmpty("")
|
||||
}
|
||||
|
||||
if err := bkt.DeleteBucket([]byte(namespace)); err != nil {
|
||||
if err == bolt.ErrBucketNotFound {
|
||||
return ErrNotFound
|
||||
return ErrNotFound("")
|
||||
}
|
||||
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user