Merge pull request #1115 from stevvooe/consolidate-errors
errdefs: centralize error handling
This commit is contained in:
commit
eedcbc64cc
@ -8,8 +8,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/metadata"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
@ -183,7 +183,7 @@ var namespacesRemoveCommand = cli.Command{
|
|||||||
|
|
||||||
for _, target := range clicontext.Args() {
|
for _, target := range clicontext.Args() {
|
||||||
if err := namespaces.Delete(ctx, target); err != nil {
|
if err := namespaces.Delete(ctx, target); err != nil {
|
||||||
if !metadata.IsNotFound(err) {
|
if !errdefs.IsNotFound(err) {
|
||||||
if exitErr == nil {
|
if exitErr == nil {
|
||||||
exitErr = errors.Wrapf(err, "unable to delete %v", target)
|
exitErr = errors.Wrapf(err, "unable to delete %v", target)
|
||||||
}
|
}
|
||||||
|
4
cmd/dist/delete.go
vendored
4
cmd/dist/delete.go
vendored
@ -3,7 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
@ -43,7 +43,7 @@ var deleteCommand = cli.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := cs.Delete(ctx, dgst); err != nil {
|
if err := cs.Delete(ctx, dgst); err != nil {
|
||||||
if !content.IsNotFound(err) {
|
if !errdefs.IsNotFound(err) {
|
||||||
if exitError == nil {
|
if exitError == nil {
|
||||||
exitError = err
|
exitError = err
|
||||||
}
|
}
|
||||||
|
3
cmd/dist/fetch.go
vendored
3
cmd/dist/fetch.go
vendored
@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/progress"
|
"github.com/containerd/containerd/progress"
|
||||||
@ -153,7 +154,7 @@ outer:
|
|||||||
if !done && (!ok || status.Status == "downloading") {
|
if !done && (!ok || status.Status == "downloading") {
|
||||||
info, err := cs.Info(ctx, j.Digest)
|
info, err := cs.Info(ctx, j.Digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !content.IsNotFound(err) {
|
if !errdefs.IsNotFound(err) {
|
||||||
log.G(ctx).WithError(err).Errorf("failed to get content info")
|
log.G(ctx).WithError(err).Errorf("failed to get content info")
|
||||||
continue outer
|
continue outer
|
||||||
} else {
|
} else {
|
||||||
|
4
cmd/dist/images.go
vendored
4
cmd/dist/images.go
vendored
@ -5,8 +5,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/metadata"
|
|
||||||
"github.com/containerd/containerd/progress"
|
"github.com/containerd/containerd/progress"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
@ -83,7 +83,7 @@ var imageRemoveCommand = cli.Command{
|
|||||||
|
|
||||||
for _, target := range clicontext.Args() {
|
for _, target := range clicontext.Args() {
|
||||||
if err := imageStore.Delete(ctx, target); err != nil {
|
if err := imageStore.Delete(ctx, target); err != nil {
|
||||||
if !metadata.IsNotFound(err) {
|
if !errdefs.IsNotFound(err) {
|
||||||
if exitErr == nil {
|
if exitErr == nil {
|
||||||
exitErr = errors.Wrapf(err, "unable to delete %v", target)
|
exitErr = errors.Wrapf(err, "unable to delete %v", target)
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,8 @@ import (
|
|||||||
"github.com/containerd/containerd/api/services/tasks/v1"
|
"github.com/containerd/containerd/api/services/tasks/v1"
|
||||||
"github.com/containerd/containerd/api/types"
|
"github.com/containerd/containerd/api/types"
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/snapshot"
|
|
||||||
protobuf "github.com/gogo/protobuf/types"
|
protobuf "github.com/gogo/protobuf/types"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
"github.com/opencontainers/image-spec/identity"
|
"github.com/opencontainers/image-spec/identity"
|
||||||
@ -46,7 +46,7 @@ func WithCheckpoint(desc v1.Descriptor, rootfsID string) NewContainerOpts {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := client.SnapshotService().Prepare(ctx, rootfsID, identity.ChainID(diffIDs).String()); err != nil {
|
if _, err := client.SnapshotService().Prepare(ctx, rootfsID, identity.ChainID(diffIDs).String()); err != nil {
|
||||||
if !snapshot.IsExist(err) {
|
if !errdefs.IsAlreadyExists(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,98 +0,0 @@
|
|||||||
package content
|
|
||||||
|
|
||||||
import "github.com/pkg/errors"
|
|
||||||
|
|
||||||
type contentExistsErr struct {
|
|
||||||
desc string
|
|
||||||
}
|
|
||||||
|
|
||||||
type contentNotFoundErr struct {
|
|
||||||
desc string
|
|
||||||
}
|
|
||||||
|
|
||||||
type contentLockedErr struct {
|
|
||||||
desc string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrExists is returned when something exists when it may not be expected.
|
|
||||||
func ErrExists(msg string) error {
|
|
||||||
if msg == "" {
|
|
||||||
msg = "content: exists"
|
|
||||||
}
|
|
||||||
return errors.WithStack(contentExistsErr{
|
|
||||||
desc: msg,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrNotFound is returned when an item is not found.
|
|
||||||
func ErrNotFound(msg string) error {
|
|
||||||
if msg == "" {
|
|
||||||
msg = "content: not found"
|
|
||||||
}
|
|
||||||
return errors.WithStack(contentNotFoundErr{
|
|
||||||
desc: msg,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrLocked is returned when content is actively being uploaded, this
|
|
||||||
// indicates that another process is attempting to upload the same content.
|
|
||||||
func ErrLocked(msg string) error {
|
|
||||||
if msg == "" {
|
|
||||||
msg = "content: locked"
|
|
||||||
}
|
|
||||||
return errors.WithStack(contentLockedErr{
|
|
||||||
desc: msg,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c contentExistsErr) Error() string {
|
|
||||||
return c.desc
|
|
||||||
}
|
|
||||||
func (c contentNotFoundErr) Error() string {
|
|
||||||
return c.desc
|
|
||||||
}
|
|
||||||
func (c contentLockedErr) Error() string {
|
|
||||||
return c.desc
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c contentExistsErr) Exists() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c contentNotFoundErr) NotFound() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c contentLockedErr) Locked() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNotFound returns true if the error is due to a not found content item
|
|
||||||
func IsNotFound(err error) bool {
|
|
||||||
if err, ok := errors.Cause(err).(interface {
|
|
||||||
NotFound() bool
|
|
||||||
}); ok {
|
|
||||||
return err.NotFound()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsExists returns true if the error is due to an already existing content item
|
|
||||||
func IsExists(err error) bool {
|
|
||||||
if err, ok := errors.Cause(err).(interface {
|
|
||||||
Exists() bool
|
|
||||||
}); ok {
|
|
||||||
return err.Exists()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsLocked returns true if the error is due to a currently locked content item
|
|
||||||
func IsLocked(err error) bool {
|
|
||||||
if err, ok := errors.Cause(err).(interface {
|
|
||||||
Locked() bool
|
|
||||||
}); ok {
|
|
||||||
return err.Locked()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -33,7 +34,7 @@ func ReadBlob(ctx context.Context, provider Provider, dgst digest.Digest) ([]byt
|
|||||||
func WriteBlob(ctx context.Context, cs Ingester, ref string, r io.Reader, size int64, expected digest.Digest) error {
|
func WriteBlob(ctx context.Context, cs Ingester, ref string, r io.Reader, size int64, expected digest.Digest) error {
|
||||||
cw, err := cs.Writer(ctx, ref, size, expected)
|
cw, err := cs.Writer(ctx, ref, size, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !IsExists(err) {
|
if !errdefs.IsAlreadyExists(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +80,7 @@ func Copy(cw Writer, r io.Reader, size int64, expected digest.Digest) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := cw.Commit(size, expected); err != nil {
|
if err := cw.Commit(size, expected); err != nil {
|
||||||
if !IsExists(err) {
|
if !errdefs.IsAlreadyExists(err) {
|
||||||
return errors.Wrapf(err, "failed commit on ref %q", ws.Ref)
|
return errors.Wrapf(err, "failed commit on ref %q", ws.Ref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package content
|
package content
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Handles locking references
|
// Handles locking references
|
||||||
@ -19,7 +21,7 @@ func tryLock(ref string) error {
|
|||||||
defer locksMu.Unlock()
|
defer locksMu.Unlock()
|
||||||
|
|
||||||
if _, ok := locks[ref]; ok {
|
if _, ok := locks[ref]; ok {
|
||||||
return ErrLocked(fmt.Sprintf("key %s is locked", ref))
|
return errors.Wrapf(errdefs.ErrUnavailable, "ref %s locked", ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
locks[ref] = struct{}{}
|
locks[ref] = struct{}{}
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -40,7 +41,7 @@ func (s *store) Info(ctx context.Context, dgst digest.Digest) (Info, error) {
|
|||||||
fi, err := os.Stat(p)
|
fi, err := os.Stat(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
err = ErrNotFound("")
|
err = errors.Wrapf(errdefs.ErrNotFound, "content %v", dgst)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Info{}, err
|
return Info{}, err
|
||||||
@ -62,7 +63,7 @@ func (s *store) Reader(ctx context.Context, dgst digest.Digest) (io.ReadCloser,
|
|||||||
fp, err := os.Open(s.blobPath(dgst))
|
fp, err := os.Open(s.blobPath(dgst))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
err = ErrNotFound("")
|
err = errors.Wrapf(errdefs.ErrNotFound, "content %v", dgst)
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -85,7 +86,7 @@ func (cs *store) Delete(ctx context.Context, dgst digest.Digest) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrNotFound("")
|
return errors.Wrapf(errdefs.ErrNotFound, "content %v", dgst)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -232,7 +233,7 @@ func (s *store) Writer(ctx context.Context, ref string, total int64, expected di
|
|||||||
if expected != "" {
|
if expected != "" {
|
||||||
p := s.blobPath(expected)
|
p := s.blobPath(expected)
|
||||||
if _, err := os.Stat(p); err == nil {
|
if _, err := os.Stat(p); err == nil {
|
||||||
return nil, ErrExists("")
|
return nil, errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,7 +330,7 @@ func (s *store) Abort(ctx context.Context, ref string) error {
|
|||||||
root := s.ingestRoot(ref)
|
root := s.ingestRoot(ref)
|
||||||
if err := os.RemoveAll(root); err != nil {
|
if err := os.RemoveAll(root); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return ErrNotFound("")
|
return errors.Wrapf(errdefs.ErrNotFound, "ingest ref %q", ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -99,7 +100,7 @@ func (w *writer) Commit(size int64, expected digest.Digest) error {
|
|||||||
if err := os.Rename(ingest, target); err != nil {
|
if err := os.Rename(ingest, target); err != nil {
|
||||||
if os.IsExist(err) {
|
if os.IsExist(err) {
|
||||||
// collision with the target file!
|
// collision with the target file!
|
||||||
return ErrExists("")
|
return errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", dgst)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
54
errdefs/errors.go
Normal file
54
errdefs/errors.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// Package errdefs defines the common errors used throughout containerd
|
||||||
|
// packages.
|
||||||
|
//
|
||||||
|
// Use with errors.Wrap and error.Wrapf to add context to an error.
|
||||||
|
//
|
||||||
|
// To detect an error class, use the IsXXX functions to tell whether an error
|
||||||
|
// is of a certain type.
|
||||||
|
//
|
||||||
|
// The functions ToGRPC and FromGRPC can be used to map server-side and
|
||||||
|
// client-side errors to the correct types.
|
||||||
|
package errdefs
|
||||||
|
|
||||||
|
import "github.com/pkg/errors"
|
||||||
|
|
||||||
|
// Definitions of common error types used throughout containerd. All containerd
|
||||||
|
// errors returned by most packages will map into one of these errors classes.
|
||||||
|
// Packages should return errors of these types when they want to instruct a
|
||||||
|
// client to take a particular action.
|
||||||
|
//
|
||||||
|
// For the most part, we just try to provide local grpc errors. Most conditions
|
||||||
|
// map very well to those defined by grpc.
|
||||||
|
var (
|
||||||
|
ErrUnknown = errors.New("unknown") // used internally to represent a missed mapping.
|
||||||
|
ErrInvalidArgument = errors.New("invalid")
|
||||||
|
ErrNotFound = errors.New("not found")
|
||||||
|
ErrAlreadyExists = errors.New("already exists")
|
||||||
|
ErrFailedPrecondition = errors.New("failed precondition")
|
||||||
|
ErrUnavailable = errors.New("unavailable")
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsInvalidArgument(err error) bool {
|
||||||
|
return errors.Cause(err) == ErrInvalidArgument
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNotFound returns true if the error is due to a missing object
|
||||||
|
func IsNotFound(err error) bool {
|
||||||
|
return errors.Cause(err) == ErrNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsAlreadyExists returns true if the error is due to an already existing
|
||||||
|
// metadata item
|
||||||
|
func IsAlreadyExists(err error) bool {
|
||||||
|
return errors.Cause(err) == ErrAlreadyExists
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsFailedPrecondition returns true if an operation could not proceed to the
|
||||||
|
// lack of a particular condition.
|
||||||
|
func IsFailedPrecondition(err error) bool {
|
||||||
|
return errors.Cause(err) == ErrFailedPrecondition
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsUnavailable(err error) bool {
|
||||||
|
return errors.Cause(err) == ErrUnavailable
|
||||||
|
}
|
106
errdefs/grpc.go
Normal file
106
errdefs/grpc.go
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
package errdefs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ToGRPC will attempt to map the backend containerd error into a grpc error,
|
||||||
|
// using the original error message as a description.
|
||||||
|
//
|
||||||
|
// Further information may be extracted from certain errors depending on their
|
||||||
|
// type.
|
||||||
|
//
|
||||||
|
// If the error is unmapped, the original error will be returned to be handled
|
||||||
|
// by the regular grpc error handling stack.
|
||||||
|
func ToGRPC(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if isGRPCError(err) {
|
||||||
|
// error has already been mapped to grpc
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case IsInvalidArgument(err):
|
||||||
|
return grpc.Errorf(codes.InvalidArgument, err.Error())
|
||||||
|
case IsNotFound(err):
|
||||||
|
return grpc.Errorf(codes.NotFound, err.Error())
|
||||||
|
case IsAlreadyExists(err):
|
||||||
|
return grpc.Errorf(codes.AlreadyExists, err.Error())
|
||||||
|
case IsFailedPrecondition(err):
|
||||||
|
return grpc.Errorf(codes.FailedPrecondition, err.Error())
|
||||||
|
case IsUnavailable(err):
|
||||||
|
return grpc.Errorf(codes.Unavailable, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToGRPCf maps the error to grpc error codes, assembling the formatting string
|
||||||
|
// and combining it with the target error string.
|
||||||
|
//
|
||||||
|
// This is equivalent to errors.ToGRPC(errors.Wrapf(err, format, args...))
|
||||||
|
func ToGRPCf(err error, format string, args ...interface{}) error {
|
||||||
|
return ToGRPC(errors.Wrapf(err, format, args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromGRPC(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var cls error // divide these into error classes, becomes the cause
|
||||||
|
|
||||||
|
switch grpc.Code(err) {
|
||||||
|
case codes.InvalidArgument:
|
||||||
|
cls = ErrInvalidArgument
|
||||||
|
case codes.AlreadyExists:
|
||||||
|
cls = ErrAlreadyExists
|
||||||
|
case codes.NotFound:
|
||||||
|
cls = ErrNotFound
|
||||||
|
case codes.Unavailable:
|
||||||
|
cls = ErrUnavailable
|
||||||
|
case codes.FailedPrecondition:
|
||||||
|
cls = ErrFailedPrecondition
|
||||||
|
default:
|
||||||
|
cls = ErrUnknown
|
||||||
|
}
|
||||||
|
|
||||||
|
if cls != nil {
|
||||||
|
msg := rebaseMessage(cls, err)
|
||||||
|
if msg != "" {
|
||||||
|
err = errors.Wrapf(cls, msg)
|
||||||
|
} else {
|
||||||
|
err = cls
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// rebaseMessage removes the repeats for an error at the end of an error
|
||||||
|
// string. This will happen when taking an error over grpc then remapping it.
|
||||||
|
//
|
||||||
|
// Effectively, we just remove the string of cls from the end of err if it
|
||||||
|
// appears there.
|
||||||
|
func rebaseMessage(cls error, err error) string {
|
||||||
|
desc := grpc.ErrorDesc(err)
|
||||||
|
clss := cls.Error()
|
||||||
|
if desc == clss {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimSuffix(desc, ": "+clss)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isGRPCError(err error) bool {
|
||||||
|
_, ok := status.FromError(err)
|
||||||
|
return ok
|
||||||
|
}
|
@ -17,6 +17,7 @@ package identifiers
|
|||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,15 +33,8 @@ var (
|
|||||||
// Rules for domains, defined in RFC 1035, section 2.3.1, are used for
|
// Rules for domains, defined in RFC 1035, section 2.3.1, are used for
|
||||||
// identifiers.
|
// identifiers.
|
||||||
identifierRe = regexp.MustCompile(reAnchor(label + reGroup("[.]"+reGroup(label)) + "*"))
|
identifierRe = regexp.MustCompile(reAnchor(label + reGroup("[.]"+reGroup(label)) + "*"))
|
||||||
|
|
||||||
errIdentifierInvalid = errors.New("invalid identifier")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsInvalid return true if the error was due to an invalid identifer.
|
|
||||||
func IsInvalid(err error) bool {
|
|
||||||
return errors.Cause(err) == errIdentifierInvalid
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate return nil if the string s is a valid identifier.
|
// Validate return nil if the string s is a valid identifier.
|
||||||
//
|
//
|
||||||
// identifiers must be valid domain identifiers according to RFC 1035, section 2.3.1. To
|
// identifiers must be valid domain identifiers according to RFC 1035, section 2.3.1. To
|
||||||
@ -50,11 +44,11 @@ func IsInvalid(err error) bool {
|
|||||||
// a domain identifier or filesystem path component.
|
// a domain identifier or filesystem path component.
|
||||||
func Validate(s string) error {
|
func Validate(s string) error {
|
||||||
if len(s) > maxLength {
|
if len(s) > maxLength {
|
||||||
return errors.Wrapf(errIdentifierInvalid, "identifier %q greater than maximum length (%d characters)", s, maxLength)
|
return errors.Wrapf(errdefs.ErrInvalidArgument, "identifier %q greater than maximum length (%d characters)", s, maxLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !identifierRe.MatchString(s) {
|
if !identifierRe.MatchString(s) {
|
||||||
return errors.Wrapf(errIdentifierInvalid, "identifier %q must match %v", s, identifierRe)
|
return errors.Wrapf(errdefs.ErrInvalidArgument, "identifier %q must match %v", s, identifierRe)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ package identifiers
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestValidIdentifiers(t *testing.T) {
|
func TestValidIdentifiers(t *testing.T) {
|
||||||
@ -44,7 +46,7 @@ func TestInvalidIdentifiers(t *testing.T) {
|
|||||||
t.Run(input, func(t *testing.T) {
|
t.Run(input, func(t *testing.T) {
|
||||||
if err := Validate(input); err == nil {
|
if err := Validate(input); err == nil {
|
||||||
t.Fatal("expected invalid error")
|
t.Fatal("expected invalid error")
|
||||||
} else if !IsInvalid(err) {
|
} else if !errdefs.IsInvalidArgument(err) {
|
||||||
t.Fatal("error should be an invalid identifier error")
|
t.Fatal("error should be an invalid identifier error")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
"github.com/containerd/containerd/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/identifiers"
|
"github.com/containerd/containerd/identifiers"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -29,12 +30,12 @@ func (s *containerStore) Get(ctx context.Context, id string) (containers.Contain
|
|||||||
|
|
||||||
bkt := getContainerBucket(s.tx, namespace, id)
|
bkt := getContainerBucket(s.tx, namespace, id)
|
||||||
if bkt == nil {
|
if bkt == nil {
|
||||||
return containers.Container{}, ErrNotFound("bucket does not exist")
|
return containers.Container{}, errors.Wrapf(errdefs.ErrNotFound, "bucket name %q")
|
||||||
}
|
}
|
||||||
|
|
||||||
container := containers.Container{ID: id}
|
container := containers.Container{ID: id}
|
||||||
if err := readContainer(&container, bkt); err != nil {
|
if err := readContainer(&container, bkt); err != nil {
|
||||||
return containers.Container{}, errors.Wrap(err, "failed to read container")
|
return containers.Container{}, errors.Wrapf(err, "failed to read container %v", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
return container, nil
|
return container, nil
|
||||||
@ -90,7 +91,7 @@ func (s *containerStore) Create(ctx context.Context, container containers.Contai
|
|||||||
cbkt, err := bkt.CreateBucket([]byte(container.ID))
|
cbkt, err := bkt.CreateBucket([]byte(container.ID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == bolt.ErrBucketExists {
|
if err == bolt.ErrBucketExists {
|
||||||
err = ErrExists("content for id already exists")
|
err = errors.Wrapf(errdefs.ErrAlreadyExists, "content %q")
|
||||||
}
|
}
|
||||||
return containers.Container{}, err
|
return containers.Container{}, err
|
||||||
}
|
}
|
||||||
@ -110,14 +111,18 @@ func (s *containerStore) Update(ctx context.Context, container containers.Contai
|
|||||||
return containers.Container{}, err
|
return containers.Container{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if container.ID == "" {
|
||||||
|
return containers.Container{}, errors.Wrapf(errdefs.ErrInvalidArgument, "must specify a container id")
|
||||||
|
}
|
||||||
|
|
||||||
bkt := getContainersBucket(s.tx, namespace)
|
bkt := getContainersBucket(s.tx, namespace)
|
||||||
if bkt == nil {
|
if bkt == nil {
|
||||||
return containers.Container{}, ErrNotFound("no containers")
|
return containers.Container{}, errors.Wrapf(errdefs.ErrNotFound, "container %q", container.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
cbkt := bkt.Bucket([]byte(container.ID))
|
cbkt := bkt.Bucket([]byte(container.ID))
|
||||||
if cbkt == nil {
|
if cbkt == nil {
|
||||||
return containers.Container{}, ErrNotFound("no content for id")
|
return containers.Container{}, errors.Wrapf(errdefs.ErrNotFound, "container %q", container.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
container.UpdatedAt = time.Now()
|
container.UpdatedAt = time.Now()
|
||||||
@ -136,11 +141,11 @@ func (s *containerStore) Delete(ctx context.Context, id string) error {
|
|||||||
|
|
||||||
bkt := getContainersBucket(s.tx, namespace)
|
bkt := getContainersBucket(s.tx, namespace)
|
||||||
if bkt == nil {
|
if bkt == nil {
|
||||||
return ErrNotFound("no containers")
|
return errors.Wrapf(errdefs.ErrNotFound, "cannot delete container %v, bucket not present", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := bkt.DeleteBucket([]byte(id)); err == bolt.ErrBucketNotFound {
|
if err := bkt.DeleteBucket([]byte(id)); err == bolt.ErrBucketNotFound {
|
||||||
return ErrNotFound("no content for id")
|
return errors.Wrapf(errdefs.ErrNotFound, "container %v", id)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1,95 +0,0 @@
|
|||||||
package metadata
|
|
||||||
|
|
||||||
import "github.com/pkg/errors"
|
|
||||||
|
|
||||||
type metadataExistsErr struct {
|
|
||||||
desc string
|
|
||||||
}
|
|
||||||
type metadataNotFoundErr struct {
|
|
||||||
desc string
|
|
||||||
}
|
|
||||||
type metadataNotEmptyErr struct {
|
|
||||||
desc string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrExists is returned when an item already exists in metadata
|
|
||||||
func ErrExists(msg string) error {
|
|
||||||
if msg == "" {
|
|
||||||
msg = "metadata: exists"
|
|
||||||
}
|
|
||||||
return errors.WithStack(metadataExistsErr{
|
|
||||||
desc: msg,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrNotFound is returned when an item cannot be found in metadata
|
|
||||||
func ErrNotFound(msg string) error {
|
|
||||||
if msg == "" {
|
|
||||||
msg = "metadata: not found"
|
|
||||||
}
|
|
||||||
return errors.WithStack(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 errors.WithStack(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 {
|
|
||||||
if err, ok := errors.Cause(err).(interface {
|
|
||||||
NotFound() bool
|
|
||||||
}); ok {
|
|
||||||
return err.NotFound()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsExists returns true if the error is due to an already existing metadata item
|
|
||||||
func IsExists(err error) bool {
|
|
||||||
if err, ok := errors.Cause(err).(interface {
|
|
||||||
Exists() bool
|
|
||||||
}); ok {
|
|
||||||
return err.Exists()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNotEmpty returns true if the error is due to delete request of a non-empty metadata item
|
|
||||||
func IsNotEmpty(err error) bool {
|
|
||||||
if err, ok := errors.Cause(err).(interface {
|
|
||||||
NotEmpty() bool
|
|
||||||
}); ok {
|
|
||||||
return err.NotEmpty()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
@ -6,10 +6,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type imageStore struct {
|
type imageStore struct {
|
||||||
@ -30,12 +32,12 @@ func (s *imageStore) Get(ctx context.Context, name string) (images.Image, error)
|
|||||||
|
|
||||||
bkt := getImagesBucket(s.tx, namespace)
|
bkt := getImagesBucket(s.tx, namespace)
|
||||||
if bkt == nil {
|
if bkt == nil {
|
||||||
return images.Image{}, ErrNotFound("")
|
return images.Image{}, errors.Wrapf(errdefs.ErrNotFound, "image %q", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
ibkt := bkt.Bucket([]byte(name))
|
ibkt := bkt.Bucket([]byte(name))
|
||||||
if ibkt == nil {
|
if ibkt == nil {
|
||||||
return images.Image{}, ErrNotFound("")
|
return images.Image{}, errors.Wrapf(errdefs.ErrNotFound, "image %q", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
image.Name = name
|
image.Name = name
|
||||||
@ -124,7 +126,7 @@ func (s *imageStore) Delete(ctx context.Context, name string) error {
|
|||||||
return withImagesBucket(s.tx, namespace, func(bkt *bolt.Bucket) error {
|
return withImagesBucket(s.tx, namespace, func(bkt *bolt.Bucket) error {
|
||||||
err := bkt.DeleteBucket([]byte(name))
|
err := bkt.DeleteBucket([]byte(name))
|
||||||
if err == bolt.ErrBucketNotFound {
|
if err == bolt.ErrBucketNotFound {
|
||||||
return ErrNotFound("")
|
return errors.Wrapf(errdefs.ErrNotFound, "image %q", name)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
@ -4,8 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/identifiers"
|
"github.com/containerd/containerd/identifiers"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type namespaceStore struct {
|
type namespaceStore struct {
|
||||||
@ -30,7 +32,7 @@ func (s *namespaceStore) Create(ctx context.Context, namespace string, labels ma
|
|||||||
bkt, err := topbkt.CreateBucket([]byte(namespace))
|
bkt, err := topbkt.CreateBucket([]byte(namespace))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == bolt.ErrBucketExists {
|
if err == bolt.ErrBucketExists {
|
||||||
return ErrExists("")
|
return errors.Wrapf(errdefs.ErrAlreadyExists, "namespace %q")
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
@ -105,12 +107,12 @@ func (s *namespaceStore) Delete(ctx context.Context, namespace string) error {
|
|||||||
if empty, err := s.namespaceEmpty(ctx, namespace); err != nil {
|
if empty, err := s.namespaceEmpty(ctx, namespace); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if !empty {
|
} else if !empty {
|
||||||
return ErrNotEmpty("")
|
return errors.Wrapf(errdefs.ErrFailedPrecondition, "namespace %q must be empty", namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := bkt.DeleteBucket([]byte(namespace)); err != nil {
|
if err := bkt.DeleteBucket([]byte(namespace)); err != nil {
|
||||||
if err == bolt.ErrBucketNotFound {
|
if err == bolt.ErrBucketNotFound {
|
||||||
return ErrNotFound("")
|
return errors.Wrapf(errdefs.ErrNotFound, "namespace %q", namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
@ -3,6 +3,7 @@ package namespaces
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/identifiers"
|
"github.com/containerd/containerd/identifiers"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
@ -13,10 +14,6 @@ const (
|
|||||||
Default = "default"
|
Default = "default"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
errNamespaceRequired = errors.New("namespace is required")
|
|
||||||
)
|
|
||||||
|
|
||||||
type namespaceKey struct{}
|
type namespaceKey struct{}
|
||||||
|
|
||||||
// WithNamespace sets a given namespace on the context
|
// WithNamespace sets a given namespace on the context
|
||||||
@ -50,16 +47,11 @@ func Namespace(ctx context.Context) (string, bool) {
|
|||||||
return namespace, ok
|
return namespace, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNamespaceRequired returns whether an error is caused by a missing namespace
|
|
||||||
func IsNamespaceRequired(err error) bool {
|
|
||||||
return errors.Cause(err) == errNamespaceRequired
|
|
||||||
}
|
|
||||||
|
|
||||||
// NamespaceRequired returns the valid namepace from the context or an error.
|
// NamespaceRequired returns the valid namepace from the context or an error.
|
||||||
func NamespaceRequired(ctx context.Context) (string, error) {
|
func NamespaceRequired(ctx context.Context) (string, error) {
|
||||||
namespace, ok := Namespace(ctx)
|
namespace, ok := Namespace(ctx)
|
||||||
if !ok || namespace == "" {
|
if !ok || namespace == "" {
|
||||||
return "", errNamespaceRequired
|
return "", errors.Wrapf(errdefs.ErrFailedPrecondition, "namespace is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := identifiers.Validate(namespace); err != nil {
|
if err := identifiers.Validate(namespace); err != nil {
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/remotes"
|
"github.com/containerd/containerd/remotes"
|
||||||
@ -31,10 +32,10 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
|||||||
status, err := p.tracker.GetStatus(ref)
|
status, err := p.tracker.GetStatus(ref)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if status.Offset == status.Total {
|
if status.Offset == status.Total {
|
||||||
return nil, content.ErrExists("")
|
return nil, errors.Wrapf(errdefs.ErrAlreadyExists, "ref %v already exists", ref)
|
||||||
}
|
}
|
||||||
// TODO: Handle incomplete status
|
// TODO: Handle incomplete status
|
||||||
} else if !content.IsNotFound(err) {
|
} else if !errdefs.IsNotFound(err) {
|
||||||
return nil, errors.Wrap(err, "failed to get status")
|
return nil, errors.Wrap(err, "failed to get status")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +73,7 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
|||||||
// TODO: Set updated time?
|
// TODO: Set updated time?
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return nil, content.ErrExists("")
|
return nil, errors.Wrapf(errdefs.ErrAlreadyExists, "content %v on remote", desc.Digest)
|
||||||
}
|
}
|
||||||
if resp.StatusCode != http.StatusNotFound {
|
if resp.StatusCode != http.StatusNotFound {
|
||||||
// TODO: log error
|
// TODO: log error
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/remotes"
|
"github.com/containerd/containerd/remotes"
|
||||||
@ -202,7 +203,7 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro
|
|||||||
|
|
||||||
cw, err := c.contentStore.Writer(ctx, ref, desc.Size, desc.Digest)
|
cw, err := c.contentStore.Writer(ctx, ref, desc.Size, desc.Digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !content.IsExists(err) {
|
if !errdefs.IsAlreadyExists(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Status struct {
|
type Status struct {
|
||||||
@ -34,7 +36,7 @@ func (t *memoryStatusTracker) GetStatus(ref string) (Status, error) {
|
|||||||
defer t.m.Unlock()
|
defer t.m.Unlock()
|
||||||
status, ok := t.statuses[ref]
|
status, ok := t.statuses[ref]
|
||||||
if !ok {
|
if !ok {
|
||||||
return Status{}, content.ErrNotFound("")
|
return Status{}, errors.Wrapf(errdefs.ErrNotFound, "status for ref %v", ref)
|
||||||
}
|
}
|
||||||
return status, nil
|
return status, nil
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
@ -69,9 +70,9 @@ func fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc
|
|||||||
for {
|
for {
|
||||||
cw, err = ingester.Writer(ctx, ref, desc.Size, desc.Digest)
|
cw, err = ingester.Writer(ctx, ref, desc.Size, desc.Digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if content.IsExists(err) {
|
if errdefs.IsAlreadyExists(err) {
|
||||||
return nil
|
return nil
|
||||||
} else if !content.IsLocked(err) {
|
} else if !errdefs.IsUnavailable(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +123,7 @@ func push(ctx context.Context, provider content.Provider, pusher Pusher, desc oc
|
|||||||
|
|
||||||
cw, err := pusher.Push(ctx, desc)
|
cw, err := pusher.Push(ctx, desc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !content.IsExists(err) {
|
if !errdefs.IsAlreadyExists(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package rootfs
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
"github.com/containerd/containerd/snapshot"
|
"github.com/containerd/containerd/snapshot"
|
||||||
@ -46,7 +47,7 @@ func applyLayer(ctx context.Context, layer Layer, chain []digest.Digest, sn snap
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
log.G(ctx).Debugf("Extraction not needed, layer snapshot exists")
|
log.G(ctx).Debugf("Extraction not needed, layer snapshot exists")
|
||||||
return nil
|
return nil
|
||||||
} else if !snapshot.IsNotExist(err) {
|
} else if !errdefs.IsNotFound(err) {
|
||||||
return errors.Wrap(err, "failed to stat snapshot")
|
return errors.Wrap(err, "failed to stat snapshot")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,13 +3,8 @@ package containers
|
|||||||
import (
|
import (
|
||||||
api "github.com/containerd/containerd/api/services/containers/v1"
|
api "github.com/containerd/containerd/api/services/containers/v1"
|
||||||
"github.com/containerd/containerd/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
"github.com/containerd/containerd/identifiers"
|
|
||||||
"github.com/containerd/containerd/metadata"
|
|
||||||
"github.com/containerd/containerd/namespaces"
|
|
||||||
"github.com/gogo/protobuf/types"
|
"github.com/gogo/protobuf/types"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func containersToProto(containers []containers.Container) []api.Container {
|
func containersToProto(containers []containers.Container) []api.Container {
|
||||||
@ -52,18 +47,3 @@ func containerFromProto(containerpb *api.Container) containers.Container {
|
|||||||
RootFS: containerpb.RootFS,
|
RootFS: containerpb.RootFS,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapGRPCError(err error, id string) error {
|
|
||||||
switch {
|
|
||||||
case metadata.IsNotFound(err):
|
|
||||||
return grpc.Errorf(codes.NotFound, "container %v not found", id)
|
|
||||||
case metadata.IsExists(err):
|
|
||||||
return grpc.Errorf(codes.AlreadyExists, "container %v already exists", id)
|
|
||||||
case namespaces.IsNamespaceRequired(err):
|
|
||||||
return grpc.Errorf(codes.InvalidArgument, "namespace required, please set %q header", namespaces.GRPCHeader)
|
|
||||||
case identifiers.IsInvalid(err):
|
|
||||||
return grpc.Errorf(codes.InvalidArgument, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
api "github.com/containerd/containerd/api/services/containers/v1"
|
api "github.com/containerd/containerd/api/services/containers/v1"
|
||||||
eventsapi "github.com/containerd/containerd/api/services/events/v1"
|
eventsapi "github.com/containerd/containerd/api/services/events/v1"
|
||||||
"github.com/containerd/containerd/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/events"
|
"github.com/containerd/containerd/events"
|
||||||
"github.com/containerd/containerd/metadata"
|
"github.com/containerd/containerd/metadata"
|
||||||
"github.com/containerd/containerd/plugin"
|
"github.com/containerd/containerd/plugin"
|
||||||
@ -49,31 +50,30 @@ func (s *Service) Register(server *grpc.Server) error {
|
|||||||
func (s *Service) Get(ctx context.Context, req *api.GetContainerRequest) (*api.GetContainerResponse, error) {
|
func (s *Service) Get(ctx context.Context, req *api.GetContainerRequest) (*api.GetContainerResponse, error) {
|
||||||
var resp api.GetContainerResponse
|
var resp api.GetContainerResponse
|
||||||
|
|
||||||
return &resp, s.withStoreView(ctx, func(ctx context.Context, store containers.Store) error {
|
return &resp, errdefs.ToGRPC(s.withStoreView(ctx, func(ctx context.Context, store containers.Store) error {
|
||||||
container, err := store.Get(ctx, req.ID)
|
container, err := store.Get(ctx, req.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mapGRPCError(err, req.ID)
|
return err
|
||||||
}
|
}
|
||||||
containerpb := containerToProto(&container)
|
containerpb := containerToProto(&container)
|
||||||
resp.Container = containerpb
|
resp.Container = containerpb
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) List(ctx context.Context, req *api.ListContainersRequest) (*api.ListContainersResponse, error) {
|
func (s *Service) List(ctx context.Context, req *api.ListContainersRequest) (*api.ListContainersResponse, error) {
|
||||||
var resp api.ListContainersResponse
|
var resp api.ListContainersResponse
|
||||||
|
|
||||||
return &resp, s.withStoreView(ctx, func(ctx context.Context, store containers.Store) error {
|
return &resp, errdefs.ToGRPC(s.withStoreView(ctx, func(ctx context.Context, store containers.Store) error {
|
||||||
containers, err := store.List(ctx, req.Filter)
|
containers, err := store.List(ctx, req.Filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mapGRPCError(err, "")
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Containers = containersToProto(containers)
|
resp.Containers = containersToProto(containers)
|
||||||
return nil
|
return nil
|
||||||
})
|
}))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Create(ctx context.Context, req *api.CreateContainerRequest) (*api.CreateContainerResponse, error) {
|
func (s *Service) Create(ctx context.Context, req *api.CreateContainerRequest) (*api.CreateContainerResponse, error) {
|
||||||
@ -84,14 +84,14 @@ func (s *Service) Create(ctx context.Context, req *api.CreateContainerRequest) (
|
|||||||
|
|
||||||
created, err := store.Create(ctx, container)
|
created, err := store.Create(ctx, container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mapGRPCError(err, req.Container.ID)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Container = containerToProto(&created)
|
resp.Container = containerToProto(&created)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return &resp, err
|
return &resp, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
if err := s.emit(ctx, "/containers/create", &eventsapi.ContainerCreate{
|
if err := s.emit(ctx, "/containers/create", &eventsapi.ContainerCreate{
|
||||||
ContainerID: resp.Container.ID,
|
ContainerID: resp.Container.ID,
|
||||||
@ -115,7 +115,7 @@ func (s *Service) Update(ctx context.Context, req *api.UpdateContainerRequest) (
|
|||||||
|
|
||||||
current, err := store.Get(ctx, container.ID)
|
current, err := store.Get(ctx, container.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mapGRPCError(err, container.ID)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if current.ID != container.ID {
|
if current.ID != container.ID {
|
||||||
@ -150,14 +150,14 @@ func (s *Service) Update(ctx context.Context, req *api.UpdateContainerRequest) (
|
|||||||
|
|
||||||
created, err := store.Update(ctx, container)
|
created, err := store.Update(ctx, container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mapGRPCError(err, req.Container.ID)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Container = containerToProto(&created)
|
resp.Container = containerToProto(&created)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return &resp, err
|
return &resp, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.emit(ctx, "/containers/update", &eventsapi.ContainerUpdate{
|
if err := s.emit(ctx, "/containers/update", &eventsapi.ContainerUpdate{
|
||||||
@ -174,9 +174,9 @@ func (s *Service) Update(ctx context.Context, req *api.UpdateContainerRequest) (
|
|||||||
|
|
||||||
func (s *Service) Delete(ctx context.Context, req *api.DeleteContainerRequest) (*empty.Empty, error) {
|
func (s *Service) Delete(ctx context.Context, req *api.DeleteContainerRequest) (*empty.Empty, error) {
|
||||||
if err := s.withStoreUpdate(ctx, func(ctx context.Context, store containers.Store) error {
|
if err := s.withStoreUpdate(ctx, func(ctx context.Context, store containers.Store) error {
|
||||||
return mapGRPCError(store.Delete(ctx, req.ID), req.ID)
|
return store.Delete(ctx, req.ID)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return &empty.Empty{}, mapGRPCError(err, req.ID)
|
return &empty.Empty{}, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.emit(ctx, "/containers/delete", &eventsapi.ContainerDelete{
|
if err := s.emit(ctx, "/containers/delete", &eventsapi.ContainerDelete{
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
package content
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/containerd/containerd/content"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
)
|
|
||||||
|
|
||||||
func rewriteGRPCError(err error) error {
|
|
||||||
switch grpc.Code(errors.Cause(err)) {
|
|
||||||
case codes.AlreadyExists:
|
|
||||||
return content.ErrExists(grpc.ErrorDesc(err))
|
|
||||||
case codes.NotFound:
|
|
||||||
return content.ErrNotFound(grpc.ErrorDesc(err))
|
|
||||||
case codes.Unavailable:
|
|
||||||
return content.ErrLocked(grpc.ErrorDesc(err))
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func serverErrorToGRPC(err error, id string) error {
|
|
||||||
switch {
|
|
||||||
case content.IsNotFound(err):
|
|
||||||
return grpc.Errorf(codes.NotFound, "%v: not found", id)
|
|
||||||
case content.IsExists(err):
|
|
||||||
return grpc.Errorf(codes.AlreadyExists, "%v: exists", id)
|
|
||||||
case content.IsLocked(err):
|
|
||||||
return grpc.Errorf(codes.Unavailable, "%v: locked", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
@ -8,6 +8,7 @@ import (
|
|||||||
api "github.com/containerd/containerd/api/services/content/v1"
|
api "github.com/containerd/containerd/api/services/content/v1"
|
||||||
eventsapi "github.com/containerd/containerd/api/services/events/v1"
|
eventsapi "github.com/containerd/containerd/api/services/events/v1"
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/events"
|
"github.com/containerd/containerd/events"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/plugin"
|
"github.com/containerd/containerd/plugin"
|
||||||
@ -66,7 +67,7 @@ func (s *Service) Info(ctx context.Context, req *api.InfoRequest) (*api.InfoResp
|
|||||||
|
|
||||||
bi, err := s.store.Info(ctx, req.Digest)
|
bi, err := s.store.Info(ctx, req.Digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, serverErrorToGRPC(err, req.Digest.String())
|
return nil, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &api.InfoResponse{
|
return &api.InfoResponse{
|
||||||
@ -125,7 +126,7 @@ func (s *Service) Delete(ctx context.Context, req *api.DeleteContentRequest) (*e
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := s.store.Delete(ctx, req.Digest); err != nil {
|
if err := s.store.Delete(ctx, req.Digest); err != nil {
|
||||||
return nil, serverErrorToGRPC(err, req.Digest.String())
|
return nil, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.emit(ctx, "/content/delete", &eventsapi.ContentDelete{
|
if err := s.emit(ctx, "/content/delete", &eventsapi.ContentDelete{
|
||||||
@ -144,12 +145,12 @@ func (s *Service) Read(req *api.ReadContentRequest, session api.Content_ReadServ
|
|||||||
|
|
||||||
oi, err := s.store.Info(session.Context(), req.Digest)
|
oi, err := s.store.Info(session.Context(), req.Digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serverErrorToGRPC(err, req.Digest.String())
|
return errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, err := s.store.Reader(session.Context(), req.Digest)
|
rc, err := s.store.Reader(session.Context(), req.Digest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serverErrorToGRPC(err, req.Digest.String())
|
return errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
defer rc.Close() // TODO(stevvooe): Cache these file descriptors for performance.
|
defer rc.Close() // TODO(stevvooe): Cache these file descriptors for performance.
|
||||||
|
|
||||||
@ -217,7 +218,7 @@ func (rw *readResponseWriter) Write(p []byte) (n int, err error) {
|
|||||||
func (s *Service) Status(ctx context.Context, req *api.StatusRequest) (*api.StatusResponse, error) {
|
func (s *Service) Status(ctx context.Context, req *api.StatusRequest) (*api.StatusResponse, error) {
|
||||||
statuses, err := s.store.Status(ctx, req.Filter)
|
statuses, err := s.store.Status(ctx, req.Filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, serverErrorToGRPC(err, req.Filter)
|
return nil, errdefs.ToGRPCf(err, "could not get status for filter %q", req.Filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp api.StatusResponse
|
var resp api.StatusResponse
|
||||||
@ -295,7 +296,7 @@ func (s *Service) Write(session api.Content_WriteServer) (err error) {
|
|||||||
// this action locks the writer for the session.
|
// this action locks the writer for the session.
|
||||||
wr, err := s.store.Writer(ctx, ref, total, expected)
|
wr, err := s.store.Writer(ctx, ref, total, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serverErrorToGRPC(err, ref)
|
return errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
defer wr.Close()
|
defer wr.Close()
|
||||||
|
|
||||||
@ -303,7 +304,7 @@ func (s *Service) Write(session api.Content_WriteServer) (err error) {
|
|||||||
msg.Action = req.Action
|
msg.Action = req.Action
|
||||||
ws, err := wr.Status()
|
ws, err := wr.Status()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return serverErrorToGRPC(err, ref)
|
return errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.Offset = ws.Offset // always set the offset.
|
msg.Offset = ws.Offset // always set the offset.
|
||||||
@ -414,7 +415,7 @@ func (s *Service) Write(session api.Content_WriteServer) (err error) {
|
|||||||
|
|
||||||
func (s *Service) Abort(ctx context.Context, req *api.AbortRequest) (*empty.Empty, error) {
|
func (s *Service) Abort(ctx context.Context, req *api.AbortRequest) (*empty.Empty, error) {
|
||||||
if err := s.store.Abort(ctx, req.Ref); err != nil {
|
if err := s.store.Abort(ctx, req.Ref); err != nil {
|
||||||
return nil, serverErrorToGRPC(err, req.Ref)
|
return nil, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &empty.Empty{}, nil
|
return &empty.Empty{}, nil
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
contentapi "github.com/containerd/containerd/api/services/content/v1"
|
contentapi "github.com/containerd/containerd/api/services/content/v1"
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ func (rs *remoteStore) Info(ctx context.Context, dgst digest.Digest) (content.In
|
|||||||
Digest: dgst,
|
Digest: dgst,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return content.Info{}, rewriteGRPCError(err)
|
return content.Info{}, errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return content.Info{
|
return content.Info{
|
||||||
@ -37,14 +38,14 @@ func (rs *remoteStore) Info(ctx context.Context, dgst digest.Digest) (content.In
|
|||||||
func (rs *remoteStore) Walk(ctx context.Context, fn content.WalkFunc) error {
|
func (rs *remoteStore) Walk(ctx context.Context, fn content.WalkFunc) error {
|
||||||
session, err := rs.client.List(ctx, &contentapi.ListContentRequest{})
|
session, err := rs.client.List(ctx, &contentapi.ListContentRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rewriteGRPCError(err)
|
return errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
msg, err := session.Recv()
|
msg, err := session.Recv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != io.EOF {
|
if err != io.EOF {
|
||||||
return rewriteGRPCError(err)
|
return errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
@ -68,7 +69,7 @@ func (rs *remoteStore) Delete(ctx context.Context, dgst digest.Digest) error {
|
|||||||
if _, err := rs.client.Delete(ctx, &contentapi.DeleteContentRequest{
|
if _, err := rs.client.Delete(ctx, &contentapi.DeleteContentRequest{
|
||||||
Digest: dgst,
|
Digest: dgst,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return rewriteGRPCError(err)
|
return errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -98,7 +99,7 @@ func (rs *remoteStore) Status(ctx context.Context, filter string) ([]content.Sta
|
|||||||
Filter: filter,
|
Filter: filter,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, rewriteGRPCError(err)
|
return nil, errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var statuses []content.Status
|
var statuses []content.Status
|
||||||
@ -119,7 +120,7 @@ func (rs *remoteStore) Status(ctx context.Context, filter string) ([]content.Sta
|
|||||||
func (rs *remoteStore) Writer(ctx context.Context, ref string, size int64, expected digest.Digest) (content.Writer, error) {
|
func (rs *remoteStore) Writer(ctx context.Context, ref string, size int64, expected digest.Digest) (content.Writer, error) {
|
||||||
wrclient, offset, err := rs.negotiate(ctx, ref, size, expected)
|
wrclient, offset, err := rs.negotiate(ctx, ref, size, expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, rewriteGRPCError(err)
|
return nil, errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &remoteWriter{
|
return &remoteWriter{
|
||||||
@ -134,7 +135,7 @@ func (rs *remoteStore) Abort(ctx context.Context, ref string) error {
|
|||||||
if _, err := rs.client.Abort(ctx, &contentapi.AbortRequest{
|
if _, err := rs.client.Abort(ctx, &contentapi.AbortRequest{
|
||||||
Ref: ref,
|
Ref: ref,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return rewriteGRPCError(err)
|
return errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
contentapi "github.com/containerd/containerd/api/services/content/v1"
|
contentapi "github.com/containerd/containerd/api/services/content/v1"
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -86,7 +87,7 @@ func (rw *remoteWriter) Commit(size int64, expected digest.Digest) error {
|
|||||||
Expected: expected,
|
Expected: expected,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rewriteGRPCError(err)
|
return errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if size != 0 && resp.Offset != size {
|
if size != 0 && resp.Offset != size {
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
imagesapi "github.com/containerd/containerd/api/services/images/v1"
|
imagesapi "github.com/containerd/containerd/api/services/images/v1"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
@ -28,7 +29,7 @@ func (s *remoteStore) Update(ctx context.Context, name string, desc ocispec.Desc
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
return rewriteGRPCError(err)
|
return errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *remoteStore) Get(ctx context.Context, name string) (images.Image, error) {
|
func (s *remoteStore) Get(ctx context.Context, name string) (images.Image, error) {
|
||||||
@ -36,7 +37,7 @@ func (s *remoteStore) Get(ctx context.Context, name string) (images.Image, error
|
|||||||
Name: name,
|
Name: name,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return images.Image{}, rewriteGRPCError(err)
|
return images.Image{}, errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return imageFromProto(resp.Image), nil
|
return imageFromProto(resp.Image), nil
|
||||||
@ -45,7 +46,7 @@ func (s *remoteStore) Get(ctx context.Context, name string) (images.Image, error
|
|||||||
func (s *remoteStore) List(ctx context.Context) ([]images.Image, error) {
|
func (s *remoteStore) List(ctx context.Context) ([]images.Image, error) {
|
||||||
resp, err := s.client.List(ctx, &imagesapi.ListImagesRequest{})
|
resp, err := s.client.List(ctx, &imagesapi.ListImagesRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, rewriteGRPCError(err)
|
return nil, errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return imagesFromProto(resp.Images), nil
|
return imagesFromProto(resp.Images), nil
|
||||||
@ -56,5 +57,5 @@ func (s *remoteStore) Delete(ctx context.Context, name string) error {
|
|||||||
Name: name,
|
Name: name,
|
||||||
})
|
})
|
||||||
|
|
||||||
return rewriteGRPCError(err)
|
return errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,8 @@ package images
|
|||||||
import (
|
import (
|
||||||
imagesapi "github.com/containerd/containerd/api/services/images/v1"
|
imagesapi "github.com/containerd/containerd/api/services/images/v1"
|
||||||
"github.com/containerd/containerd/api/types"
|
"github.com/containerd/containerd/api/types"
|
||||||
"github.com/containerd/containerd/identifiers"
|
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/metadata"
|
|
||||||
"github.com/containerd/containerd/namespaces"
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func imagesToProto(images []images.Image) []imagesapi.Image {
|
func imagesToProto(images []images.Image) []imagesapi.Image {
|
||||||
@ -62,33 +56,3 @@ func descToProto(desc *ocispec.Descriptor) types.Descriptor {
|
|||||||
Digest: desc.Digest,
|
Digest: desc.Digest,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func rewriteGRPCError(err error) error {
|
|
||||||
if err == nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch grpc.Code(errors.Cause(err)) {
|
|
||||||
case codes.AlreadyExists:
|
|
||||||
return metadata.ErrExists(grpc.ErrorDesc(err))
|
|
||||||
case codes.NotFound:
|
|
||||||
return metadata.ErrNotFound(grpc.ErrorDesc(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func mapGRPCError(err error, id string) error {
|
|
||||||
switch {
|
|
||||||
case metadata.IsNotFound(err):
|
|
||||||
return grpc.Errorf(codes.NotFound, "image %v not found", id)
|
|
||||||
case metadata.IsExists(err):
|
|
||||||
return grpc.Errorf(codes.AlreadyExists, "image %v already exists", id)
|
|
||||||
case namespaces.IsNamespaceRequired(err):
|
|
||||||
return grpc.Errorf(codes.InvalidArgument, "namespace required, please set %q header", namespaces.GRPCHeader)
|
|
||||||
case identifiers.IsInvalid(err):
|
|
||||||
return grpc.Errorf(codes.InvalidArgument, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
eventsapi "github.com/containerd/containerd/api/services/events/v1"
|
eventsapi "github.com/containerd/containerd/api/services/events/v1"
|
||||||
imagesapi "github.com/containerd/containerd/api/services/images/v1"
|
imagesapi "github.com/containerd/containerd/api/services/images/v1"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/events"
|
"github.com/containerd/containerd/events"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/metadata"
|
"github.com/containerd/containerd/metadata"
|
||||||
@ -51,22 +52,22 @@ func (s *Service) Register(server *grpc.Server) error {
|
|||||||
func (s *Service) Get(ctx context.Context, req *imagesapi.GetImageRequest) (*imagesapi.GetImageResponse, error) {
|
func (s *Service) Get(ctx context.Context, req *imagesapi.GetImageRequest) (*imagesapi.GetImageResponse, error) {
|
||||||
var resp imagesapi.GetImageResponse
|
var resp imagesapi.GetImageResponse
|
||||||
|
|
||||||
return &resp, s.withStoreView(ctx, func(ctx context.Context, store images.Store) error {
|
return &resp, errdefs.ToGRPC(s.withStoreView(ctx, func(ctx context.Context, store images.Store) error {
|
||||||
image, err := store.Get(ctx, req.Name)
|
image, err := store.Get(ctx, req.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mapGRPCError(err, req.Name)
|
return err
|
||||||
}
|
}
|
||||||
imagepb := imageToProto(&image)
|
imagepb := imageToProto(&image)
|
||||||
resp.Image = &imagepb
|
resp.Image = &imagepb
|
||||||
return nil
|
return nil
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Update(ctx context.Context, req *imagesapi.UpdateImageRequest) (*imagesapi.UpdateImageResponse, error) {
|
func (s *Service) Update(ctx context.Context, req *imagesapi.UpdateImageRequest) (*imagesapi.UpdateImageResponse, error) {
|
||||||
if err := s.withStoreUpdate(ctx, func(ctx context.Context, store images.Store) error {
|
if err := s.withStoreUpdate(ctx, func(ctx context.Context, store images.Store) error {
|
||||||
return mapGRPCError(store.Update(ctx, req.Image.Name, descFromProto(&req.Image.Target)), req.Image.Name)
|
return store.Update(ctx, req.Image.Name, descFromProto(&req.Image.Target))
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.emit(ctx, "/images/update", &eventsapi.ImageUpdate{
|
if err := s.emit(ctx, "/images/update", &eventsapi.ImageUpdate{
|
||||||
@ -88,7 +89,7 @@ func (s *Service) List(ctx context.Context, _ *imagesapi.ListImagesRequest) (*im
|
|||||||
return &resp, s.withStoreView(ctx, func(ctx context.Context, store images.Store) error {
|
return &resp, s.withStoreView(ctx, func(ctx context.Context, store images.Store) error {
|
||||||
images, err := store.List(ctx)
|
images, err := store.List(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mapGRPCError(err, "")
|
return errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Images = imagesToProto(images)
|
resp.Images = imagesToProto(images)
|
||||||
@ -98,7 +99,7 @@ func (s *Service) List(ctx context.Context, _ *imagesapi.ListImagesRequest) (*im
|
|||||||
|
|
||||||
func (s *Service) Delete(ctx context.Context, req *imagesapi.DeleteImageRequest) (*empty.Empty, error) {
|
func (s *Service) Delete(ctx context.Context, req *imagesapi.DeleteImageRequest) (*empty.Empty, error) {
|
||||||
if err := s.withStoreUpdate(ctx, func(ctx context.Context, store images.Store) error {
|
if err := s.withStoreUpdate(ctx, func(ctx context.Context, store images.Store) error {
|
||||||
return mapGRPCError(store.Delete(ctx, req.Name), req.Name)
|
return errdefs.ToGRPC(store.Delete(ctx, req.Name))
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
api "github.com/containerd/containerd/api/services/namespaces/v1"
|
api "github.com/containerd/containerd/api/services/namespaces/v1"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
"github.com/gogo/protobuf/types"
|
"github.com/gogo/protobuf/types"
|
||||||
)
|
)
|
||||||
@ -27,7 +28,7 @@ func (r *remote) Create(ctx context.Context, namespace string, labels map[string
|
|||||||
|
|
||||||
_, err := r.client.Create(ctx, &req)
|
_, err := r.client.Create(ctx, &req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rewriteGRPCError(err)
|
return errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -39,7 +40,7 @@ func (r *remote) Labels(ctx context.Context, namespace string) (map[string]strin
|
|||||||
|
|
||||||
resp, err := r.client.Get(ctx, &req)
|
resp, err := r.client.Get(ctx, &req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, rewriteGRPCError(err)
|
return nil, errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp.Namespace.Labels, nil
|
return resp.Namespace.Labels, nil
|
||||||
@ -59,7 +60,7 @@ func (r *remote) SetLabel(ctx context.Context, namespace, key, value string) err
|
|||||||
|
|
||||||
_, err := r.client.Update(ctx, &req)
|
_, err := r.client.Update(ctx, &req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rewriteGRPCError(err)
|
return errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -70,7 +71,7 @@ func (r *remote) List(ctx context.Context) ([]string, error) {
|
|||||||
|
|
||||||
resp, err := r.client.List(ctx, &req)
|
resp, err := r.client.List(ctx, &req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, rewriteGRPCError(err)
|
return nil, errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var namespaces []string
|
var namespaces []string
|
||||||
@ -88,7 +89,7 @@ func (r *remote) Delete(ctx context.Context, namespace string) error {
|
|||||||
req.Name = namespace
|
req.Name = namespace
|
||||||
_, err := r.client.Delete(ctx, &req)
|
_, err := r.client.Delete(ctx, &req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rewriteGRPCError(err)
|
return errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
package namespaces
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/containerd/containerd/metadata"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
)
|
|
||||||
|
|
||||||
func mapGRPCError(err error, id string) error {
|
|
||||||
switch {
|
|
||||||
case metadata.IsNotFound(err):
|
|
||||||
return grpc.Errorf(codes.NotFound, "namespace %v not found", id)
|
|
||||||
case metadata.IsExists(err):
|
|
||||||
return grpc.Errorf(codes.AlreadyExists, "namespace %v already exists", id)
|
|
||||||
case metadata.IsNotEmpty(err):
|
|
||||||
return grpc.Errorf(codes.FailedPrecondition, "namespace %v must be empty", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func rewriteGRPCError(err error) error {
|
|
||||||
if err == nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch grpc.Code(errors.Cause(err)) {
|
|
||||||
case codes.AlreadyExists:
|
|
||||||
return metadata.ErrExists(grpc.ErrorDesc(err))
|
|
||||||
case codes.NotFound:
|
|
||||||
return metadata.ErrNotFound(grpc.ErrorDesc(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
eventsapi "github.com/containerd/containerd/api/services/events/v1"
|
eventsapi "github.com/containerd/containerd/api/services/events/v1"
|
||||||
api "github.com/containerd/containerd/api/services/namespaces/v1"
|
api "github.com/containerd/containerd/api/services/namespaces/v1"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/events"
|
"github.com/containerd/containerd/events"
|
||||||
"github.com/containerd/containerd/metadata"
|
"github.com/containerd/containerd/metadata"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
@ -59,7 +60,7 @@ func (s *Service) Get(ctx context.Context, req *api.GetNamespaceRequest) (*api.G
|
|||||||
return &resp, s.withStoreView(ctx, func(ctx context.Context, store namespaces.Store) error {
|
return &resp, s.withStoreView(ctx, func(ctx context.Context, store namespaces.Store) error {
|
||||||
labels, err := store.Labels(ctx, req.Name)
|
labels, err := store.Labels(ctx, req.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mapGRPCError(err, req.Name)
|
return errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Namespace = api.Namespace{
|
resp.Namespace = api.Namespace{
|
||||||
@ -85,7 +86,7 @@ func (s *Service) List(ctx context.Context, req *api.ListNamespacesRequest) (*ap
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
// In general, this should be unlikely, since we are holding a
|
// In general, this should be unlikely, since we are holding a
|
||||||
// transaction to service this request.
|
// transaction to service this request.
|
||||||
return mapGRPCError(err, namespace)
|
return errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Namespaces = append(resp.Namespaces, api.Namespace{
|
resp.Namespaces = append(resp.Namespaces, api.Namespace{
|
||||||
@ -103,7 +104,7 @@ func (s *Service) Create(ctx context.Context, req *api.CreateNamespaceRequest) (
|
|||||||
|
|
||||||
if err := s.withStoreUpdate(ctx, func(ctx context.Context, store namespaces.Store) error {
|
if err := s.withStoreUpdate(ctx, func(ctx context.Context, store namespaces.Store) error {
|
||||||
if err := store.Create(ctx, req.Namespace.Name, req.Namespace.Labels); err != nil {
|
if err := store.Create(ctx, req.Namespace.Name, req.Namespace.Labels); err != nil {
|
||||||
return mapGRPCError(err, req.Namespace.Name)
|
return errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range req.Namespace.Labels {
|
for k, v := range req.Namespace.Labels {
|
||||||
@ -149,7 +150,7 @@ func (s *Service) Update(ctx context.Context, req *api.UpdateNamespaceRequest) (
|
|||||||
// get current set of labels
|
// get current set of labels
|
||||||
labels, err := store.Labels(ctx, req.Namespace.Name)
|
labels, err := store.Labels(ctx, req.Namespace.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mapGRPCError(err, req.Namespace.Name)
|
return errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range labels {
|
for k := range labels {
|
||||||
@ -183,7 +184,7 @@ func (s *Service) Update(ctx context.Context, req *api.UpdateNamespaceRequest) (
|
|||||||
|
|
||||||
func (s *Service) Delete(ctx context.Context, req *api.DeleteNamespaceRequest) (*empty.Empty, error) {
|
func (s *Service) Delete(ctx context.Context, req *api.DeleteNamespaceRequest) (*empty.Empty, error) {
|
||||||
if err := s.withStoreUpdate(ctx, func(ctx context.Context, store namespaces.Store) error {
|
if err := s.withStoreUpdate(ctx, func(ctx context.Context, store namespaces.Store) error {
|
||||||
return mapGRPCError(store.Delete(ctx, req.Name), req.Name)
|
return errdefs.ToGRPC(store.Delete(ctx, req.Name))
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return &empty.Empty{}, err
|
return &empty.Empty{}, err
|
||||||
}
|
}
|
||||||
|
@ -3,16 +3,12 @@ package snapshot
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
|
|
||||||
snapshotapi "github.com/containerd/containerd/api/services/snapshot/v1"
|
snapshotapi "github.com/containerd/containerd/api/services/snapshot/v1"
|
||||||
"github.com/containerd/containerd/api/types"
|
"github.com/containerd/containerd/api/types"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
"github.com/containerd/containerd/snapshot"
|
"github.com/containerd/containerd/snapshot"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewSnapshotterFromClient returns a new Snapshotter which communicates
|
// NewSnapshotterFromClient returns a new Snapshotter which communicates
|
||||||
@ -30,7 +26,7 @@ type remoteSnapshotter struct {
|
|||||||
func (r *remoteSnapshotter) Stat(ctx context.Context, key string) (snapshot.Info, error) {
|
func (r *remoteSnapshotter) Stat(ctx context.Context, key string) (snapshot.Info, error) {
|
||||||
resp, err := r.client.Stat(ctx, &snapshotapi.StatSnapshotRequest{Key: key})
|
resp, err := r.client.Stat(ctx, &snapshotapi.StatSnapshotRequest{Key: key})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return snapshot.Info{}, rewriteGRPCError(err)
|
return snapshot.Info{}, errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
return toInfo(resp.Info), nil
|
return toInfo(resp.Info), nil
|
||||||
}
|
}
|
||||||
@ -38,7 +34,7 @@ func (r *remoteSnapshotter) Stat(ctx context.Context, key string) (snapshot.Info
|
|||||||
func (r *remoteSnapshotter) Usage(ctx context.Context, key string) (snapshot.Usage, error) {
|
func (r *remoteSnapshotter) Usage(ctx context.Context, key string) (snapshot.Usage, error) {
|
||||||
resp, err := r.client.Usage(ctx, &snapshotapi.UsageRequest{Key: key})
|
resp, err := r.client.Usage(ctx, &snapshotapi.UsageRequest{Key: key})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return snapshot.Usage{}, rewriteGRPCError(err)
|
return snapshot.Usage{}, errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
return toUsage(resp), nil
|
return toUsage(resp), nil
|
||||||
}
|
}
|
||||||
@ -46,7 +42,7 @@ func (r *remoteSnapshotter) Usage(ctx context.Context, key string) (snapshot.Usa
|
|||||||
func (r *remoteSnapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, error) {
|
func (r *remoteSnapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, error) {
|
||||||
resp, err := r.client.Mounts(ctx, &snapshotapi.MountsRequest{Key: key})
|
resp, err := r.client.Mounts(ctx, &snapshotapi.MountsRequest{Key: key})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, rewriteGRPCError(err)
|
return nil, errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
return toMounts(resp.Mounts), nil
|
return toMounts(resp.Mounts), nil
|
||||||
}
|
}
|
||||||
@ -54,7 +50,7 @@ func (r *remoteSnapshotter) Mounts(ctx context.Context, key string) ([]mount.Mou
|
|||||||
func (r *remoteSnapshotter) Prepare(ctx context.Context, key, parent string) ([]mount.Mount, error) {
|
func (r *remoteSnapshotter) Prepare(ctx context.Context, key, parent string) ([]mount.Mount, error) {
|
||||||
resp, err := r.client.Prepare(ctx, &snapshotapi.PrepareSnapshotRequest{Key: key, Parent: parent})
|
resp, err := r.client.Prepare(ctx, &snapshotapi.PrepareSnapshotRequest{Key: key, Parent: parent})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, rewriteGRPCError(err)
|
return nil, errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
return toMounts(resp.Mounts), nil
|
return toMounts(resp.Mounts), nil
|
||||||
}
|
}
|
||||||
@ -62,7 +58,7 @@ func (r *remoteSnapshotter) Prepare(ctx context.Context, key, parent string) ([]
|
|||||||
func (r *remoteSnapshotter) View(ctx context.Context, key, parent string) ([]mount.Mount, error) {
|
func (r *remoteSnapshotter) View(ctx context.Context, key, parent string) ([]mount.Mount, error) {
|
||||||
resp, err := r.client.View(ctx, &snapshotapi.ViewSnapshotRequest{Key: key, Parent: parent})
|
resp, err := r.client.View(ctx, &snapshotapi.ViewSnapshotRequest{Key: key, Parent: parent})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, rewriteGRPCError(err)
|
return nil, errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
return toMounts(resp.Mounts), nil
|
return toMounts(resp.Mounts), nil
|
||||||
}
|
}
|
||||||
@ -72,18 +68,18 @@ func (r *remoteSnapshotter) Commit(ctx context.Context, name, key string) error
|
|||||||
Name: name,
|
Name: name,
|
||||||
Key: key,
|
Key: key,
|
||||||
})
|
})
|
||||||
return rewriteGRPCError(err)
|
return errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *remoteSnapshotter) Remove(ctx context.Context, key string) error {
|
func (r *remoteSnapshotter) Remove(ctx context.Context, key string) error {
|
||||||
_, err := r.client.Remove(ctx, &snapshotapi.RemoveSnapshotRequest{Key: key})
|
_, err := r.client.Remove(ctx, &snapshotapi.RemoveSnapshotRequest{Key: key})
|
||||||
return rewriteGRPCError(err)
|
return errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *remoteSnapshotter) Walk(ctx context.Context, fn func(context.Context, snapshot.Info) error) error {
|
func (r *remoteSnapshotter) Walk(ctx context.Context, fn func(context.Context, snapshot.Info) error) error {
|
||||||
sc, err := r.client.List(ctx, &snapshotapi.ListSnapshotsRequest{})
|
sc, err := r.client.List(ctx, &snapshotapi.ListSnapshotsRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rewriteGRPCError(err)
|
errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
resp, err := sc.Recv()
|
resp, err := sc.Recv()
|
||||||
@ -91,7 +87,7 @@ func (r *remoteSnapshotter) Walk(ctx context.Context, fn func(context.Context, s
|
|||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return rewriteGRPCError(err)
|
return errdefs.FromGRPC(err)
|
||||||
}
|
}
|
||||||
if resp == nil {
|
if resp == nil {
|
||||||
return nil
|
return nil
|
||||||
@ -104,25 +100,6 @@ func (r *remoteSnapshotter) Walk(ctx context.Context, fn func(context.Context, s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func rewriteGRPCError(err error) error {
|
|
||||||
switch grpc.Code(errors.Cause(err)) {
|
|
||||||
case codes.AlreadyExists:
|
|
||||||
return snapshot.ErrSnapshotExist
|
|
||||||
case codes.NotFound:
|
|
||||||
return snapshot.ErrSnapshotNotExist
|
|
||||||
case codes.FailedPrecondition:
|
|
||||||
desc := grpc.ErrorDesc(errors.Cause(err))
|
|
||||||
if strings.Contains(desc, snapshot.ErrSnapshotNotActive.Error()) {
|
|
||||||
return snapshot.ErrSnapshotNotActive
|
|
||||||
}
|
|
||||||
if strings.Contains(desc, snapshot.ErrSnapshotNotCommitted.Error()) {
|
|
||||||
return snapshot.ErrSnapshotNotCommitted
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func toKind(kind snapshotapi.Kind) snapshot.Kind {
|
func toKind(kind snapshotapi.Kind) snapshot.Kind {
|
||||||
if kind == snapshotapi.KindActive {
|
if kind == snapshotapi.KindActive {
|
||||||
return snapshot.KindActive
|
return snapshot.KindActive
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
eventsapi "github.com/containerd/containerd/api/services/events/v1"
|
eventsapi "github.com/containerd/containerd/api/services/events/v1"
|
||||||
snapshotapi "github.com/containerd/containerd/api/services/snapshot/v1"
|
snapshotapi "github.com/containerd/containerd/api/services/snapshot/v1"
|
||||||
"github.com/containerd/containerd/api/types"
|
"github.com/containerd/containerd/api/types"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/events"
|
"github.com/containerd/containerd/events"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
@ -14,7 +15,6 @@ import (
|
|||||||
protoempty "github.com/golang/protobuf/ptypes/empty"
|
protoempty "github.com/golang/protobuf/ptypes/empty"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -60,7 +60,7 @@ func (s *service) Prepare(ctx context.Context, pr *snapshotapi.PrepareSnapshotRe
|
|||||||
// TODO: Lookup snapshot id from metadata store
|
// TODO: Lookup snapshot id from metadata store
|
||||||
mounts, err := s.snapshotter.Prepare(ctx, pr.Key, pr.Parent)
|
mounts, err := s.snapshotter.Prepare(ctx, pr.Key, pr.Parent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, grpcError(err)
|
return nil, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.emit(ctx, "/snapshot/prepare", &eventsapi.SnapshotPrepare{
|
if err := s.emit(ctx, "/snapshot/prepare", &eventsapi.SnapshotPrepare{
|
||||||
@ -80,7 +80,7 @@ func (s *service) View(ctx context.Context, pr *snapshotapi.ViewSnapshotRequest)
|
|||||||
// TODO: Lookup snapshot id from metadata store
|
// TODO: Lookup snapshot id from metadata store
|
||||||
mounts, err := s.snapshotter.View(ctx, pr.Key, pr.Parent)
|
mounts, err := s.snapshotter.View(ctx, pr.Key, pr.Parent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, grpcError(err)
|
return nil, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
return &snapshotapi.ViewSnapshotResponse{
|
return &snapshotapi.ViewSnapshotResponse{
|
||||||
Mounts: fromMounts(mounts),
|
Mounts: fromMounts(mounts),
|
||||||
@ -93,7 +93,7 @@ func (s *service) Mounts(ctx context.Context, mr *snapshotapi.MountsRequest) (*s
|
|||||||
// TODO: Lookup snapshot id from metadata store
|
// TODO: Lookup snapshot id from metadata store
|
||||||
mounts, err := s.snapshotter.Mounts(ctx, mr.Key)
|
mounts, err := s.snapshotter.Mounts(ctx, mr.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, grpcError(err)
|
return nil, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
return &snapshotapi.MountsResponse{
|
return &snapshotapi.MountsResponse{
|
||||||
Mounts: fromMounts(mounts),
|
Mounts: fromMounts(mounts),
|
||||||
@ -105,7 +105,7 @@ func (s *service) Commit(ctx context.Context, cr *snapshotapi.CommitSnapshotRequ
|
|||||||
// TODO: Apply namespace
|
// TODO: Apply namespace
|
||||||
// TODO: Lookup snapshot id from metadata store
|
// TODO: Lookup snapshot id from metadata store
|
||||||
if err := s.snapshotter.Commit(ctx, cr.Name, cr.Key); err != nil {
|
if err := s.snapshotter.Commit(ctx, cr.Name, cr.Key); err != nil {
|
||||||
return nil, grpcError(err)
|
return nil, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.emit(ctx, "/snapshot/commit", &eventsapi.SnapshotCommit{
|
if err := s.emit(ctx, "/snapshot/commit", &eventsapi.SnapshotCommit{
|
||||||
@ -122,7 +122,7 @@ func (s *service) Remove(ctx context.Context, rr *snapshotapi.RemoveSnapshotRequ
|
|||||||
// TODO: Apply namespace
|
// TODO: Apply namespace
|
||||||
// TODO: Lookup snapshot id from metadata store
|
// TODO: Lookup snapshot id from metadata store
|
||||||
if err := s.snapshotter.Remove(ctx, rr.Key); err != nil {
|
if err := s.snapshotter.Remove(ctx, rr.Key); err != nil {
|
||||||
return nil, grpcError(err)
|
return nil, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.emit(ctx, "/snapshot/remove", &eventsapi.SnapshotRemove{
|
if err := s.emit(ctx, "/snapshot/remove", &eventsapi.SnapshotRemove{
|
||||||
@ -138,7 +138,7 @@ func (s *service) Stat(ctx context.Context, sr *snapshotapi.StatSnapshotRequest)
|
|||||||
// TODO: Apply namespace
|
// TODO: Apply namespace
|
||||||
info, err := s.snapshotter.Stat(ctx, sr.Key)
|
info, err := s.snapshotter.Stat(ctx, sr.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, grpcError(err)
|
return nil, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &snapshotapi.StatSnapshotResponse{Info: fromInfo(info)}, nil
|
return &snapshotapi.StatSnapshotResponse{Info: fromInfo(info)}, nil
|
||||||
@ -184,26 +184,12 @@ func (s *service) Usage(ctx context.Context, ur *snapshotapi.UsageRequest) (*sna
|
|||||||
// TODO: Apply namespace
|
// TODO: Apply namespace
|
||||||
usage, err := s.snapshotter.Usage(ctx, ur.Key)
|
usage, err := s.snapshotter.Usage(ctx, ur.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, grpcError(err)
|
return nil, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fromUsage(usage), nil
|
return fromUsage(usage), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func grpcError(err error) error {
|
|
||||||
if snapshot.IsNotExist(err) {
|
|
||||||
return grpc.Errorf(codes.NotFound, err.Error())
|
|
||||||
}
|
|
||||||
if snapshot.IsExist(err) {
|
|
||||||
return grpc.Errorf(codes.AlreadyExists, err.Error())
|
|
||||||
}
|
|
||||||
if snapshot.IsNotActive(err) || snapshot.IsNotCommitted(err) {
|
|
||||||
return grpc.Errorf(codes.FailedPrecondition, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func fromKind(kind snapshot.Kind) snapshotapi.Kind {
|
func fromKind(kind snapshot.Kind) snapshotapi.Kind {
|
||||||
if kind == snapshot.KindActive {
|
if kind == snapshot.KindActive {
|
||||||
return snapshotapi.KindActive
|
return snapshotapi.KindActive
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/containerd/containerd/archive"
|
"github.com/containerd/containerd/archive"
|
||||||
"github.com/containerd/containerd/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/events"
|
"github.com/containerd/containerd/events"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
@ -37,6 +38,9 @@ var (
|
|||||||
empty = &google_protobuf.Empty{}
|
empty = &google_protobuf.Empty{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO(stevvooe): Clean up error mapping to avoid double mapping certain
|
||||||
|
// errors within helper methods.
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
plugin.Register(&plugin.Registration{
|
plugin.Register(&plugin.Registration{
|
||||||
Type: plugin.GRPCPlugin,
|
Type: plugin.GRPCPlugin,
|
||||||
@ -115,14 +119,7 @@ func (s *Service) Create(ctx context.Context, r *api.CreateTaskRequest) (*api.Cr
|
|||||||
|
|
||||||
container, err := s.getContainer(ctx, r.ContainerID)
|
container, err := s.getContainer(ctx, r.ContainerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch {
|
return nil, errdefs.ToGRPC(err)
|
||||||
case metadata.IsNotFound(err):
|
|
||||||
return nil, grpc.Errorf(codes.NotFound, "container %v not found", r.ContainerID)
|
|
||||||
case metadata.IsExists(err):
|
|
||||||
return nil, grpc.Errorf(codes.AlreadyExists, "container %v already exists", r.ContainerID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := runtime.CreateOpts{
|
opts := runtime.CreateOpts{
|
||||||
@ -484,7 +481,7 @@ func (s *Service) getContainer(ctx context.Context, id string) (containers.Conta
|
|||||||
container, err = store.Get(ctx, id)
|
container, err = store.Get(ctx, id)
|
||||||
return err
|
return err
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return containers.Container{}, err
|
return containers.Container{}, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return container, nil
|
return container, nil
|
||||||
@ -493,12 +490,12 @@ func (s *Service) getContainer(ctx context.Context, id string) (containers.Conta
|
|||||||
func (s *Service) getTask(ctx context.Context, id string) (runtime.Task, error) {
|
func (s *Service) getTask(ctx context.Context, id string) (runtime.Task, error) {
|
||||||
container, err := s.getContainer(ctx, id)
|
container, err := s.getContainer(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, grpc.Errorf(codes.InvalidArgument, "task %v not found: %s", id, err.Error())
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime, err := s.getRuntime(container.Runtime.Name)
|
runtime, err := s.getRuntime(container.Runtime.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, grpc.Errorf(codes.NotFound, "task %v not found: %s", id, err.Error())
|
return nil, errdefs.ToGRPCf(err, "runtime for task %v", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
t, err := runtime.Get(ctx, id)
|
t, err := runtime.Get(ctx, id)
|
||||||
@ -512,7 +509,7 @@ func (s *Service) getTask(ctx context.Context, id string) (runtime.Task, error)
|
|||||||
func (s *Service) getRuntime(name string) (runtime.Runtime, error) {
|
func (s *Service) getRuntime(name string) (runtime.Runtime, error) {
|
||||||
runtime, ok := s.runtimes[name]
|
runtime, ok := s.runtimes[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unknown runtime %q", name)
|
return nil, grpc.Errorf(codes.NotFound, "unknown runtime %q", name)
|
||||||
}
|
}
|
||||||
return runtime, nil
|
return runtime, nil
|
||||||
}
|
}
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
package snapshot
|
|
||||||
|
|
||||||
import "github.com/pkg/errors"
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrSnapshotNotExist is returned when a snapshot cannot be found
|
|
||||||
ErrSnapshotNotExist = errors.New("snapshot does not exist")
|
|
||||||
|
|
||||||
// ErrSnapshotExist is returned when an operation to create a snapshot
|
|
||||||
// encounters a snapshot with the same key
|
|
||||||
ErrSnapshotExist = errors.New("snapshot already exists")
|
|
||||||
|
|
||||||
// ErrSnapshotNotActive is returned when a request which requires an
|
|
||||||
// active snapshot encounters a non-active snapshot.
|
|
||||||
ErrSnapshotNotActive = errors.New("snapshot is not active")
|
|
||||||
|
|
||||||
// ErrSnapshotNotCommitted is returned when a request which requires a
|
|
||||||
// committed snapshot encounters a non-committed snapshot.
|
|
||||||
ErrSnapshotNotCommitted = errors.New("snapshot is not committed")
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsNotExist returns whether the error represents that a snapshot
|
|
||||||
// was not found.
|
|
||||||
func IsNotExist(err error) bool {
|
|
||||||
return errors.Cause(err) == ErrSnapshotNotExist
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsExist returns whether the error represents whether a snapshot
|
|
||||||
// already exists using a provided key.
|
|
||||||
func IsExist(err error) bool {
|
|
||||||
return errors.Cause(err) == ErrSnapshotExist
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNotActive returns whether the error represents a request
|
|
||||||
// for a non active snapshot when an active snapshot is expected.
|
|
||||||
func IsNotActive(err error) bool {
|
|
||||||
return errors.Cause(err) == ErrSnapshotNotActive
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNotCommitted returns whether the error represents a request
|
|
||||||
// for a non committed snapshot when a committed snapshot is expected.
|
|
||||||
func IsNotCommitted(err error) bool {
|
|
||||||
return errors.Cause(err) == ErrSnapshotNotCommitted
|
|
||||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
"github.com/containerd/containerd/snapshot"
|
"github.com/containerd/containerd/snapshot"
|
||||||
db "github.com/containerd/containerd/snapshot/storage/proto"
|
db "github.com/containerd/containerd/snapshot/storage/proto"
|
||||||
@ -129,12 +130,12 @@ func CreateActive(ctx context.Context, key, parent string, readonly bool) (a Act
|
|||||||
}
|
}
|
||||||
|
|
||||||
if parentS.Kind != db.KindCommitted {
|
if parentS.Kind != db.KindCommitted {
|
||||||
return errors.Wrap(snapshot.ErrSnapshotNotCommitted, "parent is not committed snapshot")
|
return errors.Wrap(errdefs.ErrInvalidArgument, "parent is not committed snapshot")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b := bkt.Get([]byte(key))
|
b := bkt.Get([]byte(key))
|
||||||
if len(b) != 0 {
|
if len(b) != 0 {
|
||||||
return snapshot.ErrSnapshotExist
|
return errors.Wrapf(errdefs.ErrAlreadyExists, "snapshot %v", key)
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := nextSequence(ctx)
|
id, err := nextSequence(ctx)
|
||||||
@ -183,7 +184,7 @@ func GetActive(ctx context.Context, key string) (a Active, err error) {
|
|||||||
err = withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error {
|
err = withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error {
|
||||||
b := bkt.Get([]byte(key))
|
b := bkt.Get([]byte(key))
|
||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
return snapshot.ErrSnapshotNotExist
|
return errors.Wrapf(errdefs.ErrNotFound, "snapshot %v", key)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ss db.Snapshot
|
var ss db.Snapshot
|
||||||
@ -191,7 +192,7 @@ func GetActive(ctx context.Context, key string) (a Active, err error) {
|
|||||||
return errors.Wrap(err, "failed to unmarshal snapshot")
|
return errors.Wrap(err, "failed to unmarshal snapshot")
|
||||||
}
|
}
|
||||||
if ss.Kind != db.KindActive {
|
if ss.Kind != db.KindActive {
|
||||||
return snapshot.ErrSnapshotNotActive
|
return errors.Wrapf(errdefs.ErrFailedPrecondition, "requested snapshot %v not active", key)
|
||||||
}
|
}
|
||||||
|
|
||||||
a.ID = fmt.Sprintf("%d", ss.ID)
|
a.ID = fmt.Sprintf("%d", ss.ID)
|
||||||
@ -225,7 +226,7 @@ func Remove(ctx context.Context, key string) (id string, k snapshot.Kind, err er
|
|||||||
var ss db.Snapshot
|
var ss db.Snapshot
|
||||||
b := bkt.Get([]byte(key))
|
b := bkt.Get([]byte(key))
|
||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
return snapshot.ErrSnapshotNotExist
|
return errors.Wrapf(errdefs.ErrNotFound, "snapshot %v", key)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := proto.Unmarshal(b, &ss); err != nil {
|
if err := proto.Unmarshal(b, &ss); err != nil {
|
||||||
@ -273,7 +274,7 @@ func CommitActive(ctx context.Context, key, name string, usage snapshot.Usage) (
|
|||||||
err = withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error {
|
err = withBucket(ctx, func(ctx context.Context, bkt, pbkt *bolt.Bucket) error {
|
||||||
b := bkt.Get([]byte(name))
|
b := bkt.Get([]byte(name))
|
||||||
if len(b) != 0 {
|
if len(b) != 0 {
|
||||||
return errors.Wrap(snapshot.ErrSnapshotExist, "committed name already exists")
|
return errors.Wrapf(errdefs.ErrAlreadyExists, "committed snapshot %v", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ss db.Snapshot
|
var ss db.Snapshot
|
||||||
@ -281,7 +282,7 @@ func CommitActive(ctx context.Context, key, name string, usage snapshot.Usage) (
|
|||||||
return errors.Wrap(err, "failed to get active snapshot")
|
return errors.Wrap(err, "failed to get active snapshot")
|
||||||
}
|
}
|
||||||
if ss.Kind != db.KindActive {
|
if ss.Kind != db.KindActive {
|
||||||
return snapshot.ErrSnapshotNotActive
|
return errors.Wrapf(errdefs.ErrFailedPrecondition, "snapshot %v is not active", name)
|
||||||
}
|
}
|
||||||
if ss.Readonly {
|
if ss.Readonly {
|
||||||
return errors.Errorf("active snapshot is readonly")
|
return errors.Errorf("active snapshot is readonly")
|
||||||
@ -340,12 +341,12 @@ func withBucket(ctx context.Context, fn func(context.Context, *bolt.Bucket, *bol
|
|||||||
}
|
}
|
||||||
nbkt := t.tx.Bucket(bucketKeyStorageVersion)
|
nbkt := t.tx.Bucket(bucketKeyStorageVersion)
|
||||||
if nbkt == nil {
|
if nbkt == nil {
|
||||||
return errors.Wrap(snapshot.ErrSnapshotNotExist, "bucket does not exist")
|
return errors.Wrapf(errdefs.ErrNotFound, "bucket does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
bkt := nbkt.Bucket([]byte(namespace))
|
bkt := nbkt.Bucket([]byte(namespace))
|
||||||
if bkt == nil {
|
if bkt == nil {
|
||||||
return errors.Wrap(snapshot.ErrSnapshotNotExist, "namespace not available in snapshotter")
|
return errors.Wrapf(errdefs.ErrNotFound, "namespace not available in snapshotter")
|
||||||
}
|
}
|
||||||
|
|
||||||
return fn(ctx, bkt.Bucket(bucketKeySnapshot), bkt.Bucket(bucketKeyParents))
|
return fn(ctx, bkt.Bucket(bucketKeySnapshot), bkt.Bucket(bucketKeyParents))
|
||||||
@ -409,7 +410,7 @@ func parents(bkt *bolt.Bucket, parent *db.Snapshot) (parents []string, err error
|
|||||||
func getSnapshot(bkt *bolt.Bucket, key string, ss *db.Snapshot) error {
|
func getSnapshot(bkt *bolt.Bucket, key string, ss *db.Snapshot) error {
|
||||||
b := bkt.Get([]byte(key))
|
b := bkt.Get([]byte(key))
|
||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
return snapshot.ErrSnapshotNotExist
|
return errors.Wrapf(errdefs.ErrNotFound, "snapshot %v", key)
|
||||||
}
|
}
|
||||||
if err := proto.Unmarshal(b, ss); err != nil {
|
if err := proto.Unmarshal(b, ss); err != nil {
|
||||||
return errors.Wrap(err, "failed to unmarshal snapshot")
|
return errors.Wrap(err, "failed to unmarshal snapshot")
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
"github.com/containerd/containerd/snapshot"
|
"github.com/containerd/containerd/snapshot"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -205,7 +206,7 @@ func assertNotExist(t *testing.T, err error) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("Expected not exist error")
|
t.Fatal("Expected not exist error")
|
||||||
}
|
}
|
||||||
if !snapshot.IsNotExist(err) {
|
if !errdefs.IsNotFound(err) {
|
||||||
t.Fatalf("Expected not exist error, got %+v", err)
|
t.Fatalf("Expected not exist error, got %+v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,7 +215,7 @@ func assertNotActive(t *testing.T, err error) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("Expected not active error")
|
t.Fatal("Expected not active error")
|
||||||
}
|
}
|
||||||
if !snapshot.IsNotActive(err) {
|
if !errdefs.IsFailedPrecondition(err) {
|
||||||
t.Fatalf("Expected not active error, got %+v", err)
|
t.Fatalf("Expected not active error, got %+v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -223,7 +224,7 @@ func assertNotCommitted(t *testing.T, err error) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("Expected active error")
|
t.Fatal("Expected active error")
|
||||||
}
|
}
|
||||||
if !snapshot.IsNotCommitted(err) {
|
if !errdefs.IsInvalidArgument(err) {
|
||||||
t.Fatalf("Expected active error, got %+v", err)
|
t.Fatalf("Expected active error, got %+v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,7 +233,7 @@ func assertExist(t *testing.T, err error) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("Expected exist error")
|
t.Fatal("Expected exist error")
|
||||||
}
|
}
|
||||||
if !snapshot.IsExist(err) {
|
if !errdefs.IsAlreadyExists(err) {
|
||||||
t.Fatalf("Expected exist error, got %+v", err)
|
t.Fatalf("Expected exist error, got %+v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user