From 804ae89be632a111d4cadee589b13b4b63ae7f86 Mon Sep 17 00:00:00 2001 From: Stephen Day Date: Mon, 15 Jul 2019 18:30:10 -0700 Subject: [PATCH] errors: use errdefs errors in client and commands This change moves from specific, global errors to the errdefs errors. This makes it easy to handle certain classes of errors while still adding context to the failure. Signed-off-by: Stephen Day --- client.go | 10 +++---- cmd/containerd/command/error.go | 32 ----------------------- cmd/containerd/command/main.go | 3 ++- cmd/containerd/command/publish.go | 2 +- cmd/containerd/command/service_windows.go | 6 +++-- cmd/ctr/commands/containers/containers.go | 14 +++++----- cmd/ctr/commands/error.go | 32 ----------------------- error.go | 32 ----------------------- 8 files changed, 20 insertions(+), 111 deletions(-) delete mode 100644 cmd/containerd/command/error.go delete mode 100644 cmd/ctr/commands/error.go delete mode 100644 error.go diff --git a/client.go b/client.go index be99e00b9..ceb8fdb7a 100644 --- a/client.go +++ b/client.go @@ -137,7 +137,7 @@ func New(address string, opts ...ClientOpt) (*Client, error) { c.conn, c.connector = conn, connector } if copts.services == nil && c.conn == nil { - return nil, ErrNoGRPCAndService + return nil, errors.Wrap(errdefs.ErrUnavailable, "no grpc connection or services is available") } // check namespace labels for default runtime @@ -196,7 +196,7 @@ type Client struct { // Reconnect re-establishes the GRPC connection to the containerd daemon func (c *Client) Reconnect() error { if c.connector == nil { - return ErrReconnectFailed + return errors.Wrap(errdefs.ErrUnavailable, "unable to reconnect to containerd, no connector available") } c.connMu.Lock() defer c.connMu.Unlock() @@ -219,7 +219,7 @@ func (c *Client) IsServing(ctx context.Context) (bool, error) { c.connMu.Lock() if c.conn == nil { c.connMu.Unlock() - return false, ErrNoGRPC + return false, errors.Wrap(errdefs.ErrUnavailable, "no grpc connection available") } c.connMu.Unlock() r, err := c.HealthService().Check(ctx, &grpc_health_v1.HealthCheckRequest{}, grpc.WaitForReady(true)) @@ -350,7 +350,7 @@ func (c *Client) Fetch(ctx context.Context, ref string, opts ...RemoteOpt) (imag } if fetchCtx.Unpack { - return images.Image{}, ErrUnpackNotSupported + return images.Image{}, errors.Wrap(errdefs.ErrNotImplemented, "unpack on fetch not supported, try pull") } if fetchCtx.PlatformMatcher == nil { @@ -656,7 +656,7 @@ func (c *Client) Version(ctx context.Context) (Version, error) { c.connMu.Lock() if c.conn == nil { c.connMu.Unlock() - return Version{}, ErrNoGRPC + return Version{}, errors.Wrap(errdefs.ErrUnavailable, "no grpc connection available") } c.connMu.Unlock() response, err := c.VersionService().Version(ctx, &ptypes.Empty{}) diff --git a/cmd/containerd/command/error.go b/cmd/containerd/command/error.go deleted file mode 100644 index 3e8572d63..000000000 --- a/cmd/containerd/command/error.go +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package command - -import ( - "github.com/pkg/errors" -) - -var ( - // ErrUnknownLevel is returned when an unknown debugging level is encountered - ErrUnknownLevel = errors.New("unknown level") - // ErrRegisterAndUnregisterService is returned when both register and unregister flags are specified - ErrRegisterAndUnregisterService = errors.New("--register-service and --unregister-service cannot be used together") - // ErrEmptyTopic is returned when no topic is provided - ErrEmptyTopic = errors.New("topic required to publish event") - // ErrEmptyGRCPAddress is returned when the grpc address is empty - ErrEmptyGRCPAddress = errors.New("grpc address cannot be empty") -) diff --git a/cmd/containerd/command/main.go b/cmd/containerd/command/main.go index ca0bc8d0b..d4e3dfee5 100644 --- a/cmd/containerd/command/main.go +++ b/cmd/containerd/command/main.go @@ -27,6 +27,7 @@ import ( "runtime" "time" + "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/log" "github.com/containerd/containerd/mount" "github.com/containerd/containerd/services/server" @@ -152,7 +153,7 @@ func App() *cli.App { ttrpcAddress = fmt.Sprintf("%s.ttrpc", config.GRPC.Address) ) if address == "" { - return ErrEmptyGRCPAddress + return errors.Wrap(errdefs.ErrInvalidArgument, "grpc address cannot be empty") } log.G(ctx).WithFields(logrus.Fields{ "version": version.Version, diff --git a/cmd/containerd/command/publish.go b/cmd/containerd/command/publish.go index 321ad43d0..fda424b18 100644 --- a/cmd/containerd/command/publish.go +++ b/cmd/containerd/command/publish.go @@ -51,7 +51,7 @@ var publishCommand = cli.Command{ ctx := namespaces.WithNamespace(gocontext.Background(), context.String("namespace")) topic := context.String("topic") if topic == "" { - return ErrEmptyTopic + return errors.Wrap(errdefs.ErrInvalidArgument, "topic required to publish event") } payload, err := getEventPayload(os.Stdin) if err != nil { diff --git a/cmd/containerd/command/service_windows.go b/cmd/containerd/command/service_windows.go index 4d70b9125..78bcb5e84 100644 --- a/cmd/containerd/command/service_windows.go +++ b/cmd/containerd/command/service_windows.go @@ -27,7 +27,9 @@ import ( "time" "unsafe" + "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/services/server" + "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/urfave/cli" "golang.org/x/sys/windows" @@ -161,7 +163,7 @@ func (h *etwHook) Fire(e *logrus.Entry) error { etype = windows.EVENTLOG_INFORMATION_TYPE eid = eventDebug default: - return ErrUnknownLevel + return errors.Wrap(errdefs.ErrInvalidArgument, "unknown level") } // If there is additional data, include it as a second string. @@ -310,7 +312,7 @@ func registerUnregisterService(root string) (bool, error) { if unregisterServiceFlag { if registerServiceFlag { - return true, ErrRegisterAndUnregisterService + return true, errors.Wrap(errdefs.ErrInvalidArgument, "--register-service and --unregister-service cannot be used together") } return true, unregisterService() } diff --git a/cmd/ctr/commands/containers/containers.go b/cmd/ctr/commands/containers/containers.go index 1a1fa9b5d..f087106cc 100644 --- a/cmd/ctr/commands/containers/containers.go +++ b/cmd/ctr/commands/containers/containers.go @@ -28,8 +28,10 @@ import ( "github.com/containerd/containerd/cmd/ctr/commands" "github.com/containerd/containerd/cmd/ctr/commands/run" "github.com/containerd/containerd/containers" + "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/log" "github.com/containerd/typeurl" + "github.com/pkg/errors" "github.com/urfave/cli" ) @@ -64,17 +66,17 @@ var createCommand = cli.Command{ if config { id = context.Args().First() if context.NArg() > 1 { - return commands.ErrArgConfigFile + return errors.Wrap(errdefs.ErrInvalidArgument, "with spec config file, only container id should be provided") } } else { id = context.Args().Get(1) ref = context.Args().First() if ref == "" { - return commands.ErrUnprovidedImageRef + return errors.Wrap(errdefs.ErrInvalidArgument, "image ref must be provided") } } if id == "" { - return commands.ErrEmptyContainerID + return errors.Wrap(errdefs.ErrInvalidArgument, "container id must be provided") } client, ctx, cancel, err := commands.NewClient(context) if err != nil { @@ -167,7 +169,7 @@ var deleteCommand = cli.Command{ } if context.NArg() == 0 { - return commands.ErrDeleteNoneContainer + return errors.Wrap(errdefs.ErrInvalidArgument, "must specify at least one container to delete") } for _, arg := range context.Args() { if err := deleteContainer(ctx, client, arg, deleteOpts...); err != nil { @@ -213,7 +215,7 @@ var setLabelsCommand = cli.Command{ Action: func(context *cli.Context) error { containerID, labels := commands.ObjectWithLabelArgs(context) if containerID == "" { - return commands.ErrEmptyContainerID + return errors.Wrap(errdefs.ErrInvalidArgument, "container id must be provided") } client, ctx, cancel, err := commands.NewClient(context) if err != nil { @@ -249,7 +251,7 @@ var infoCommand = cli.Command{ Action: func(context *cli.Context) error { id := context.Args().First() if id == "" { - return commands.ErrEmptyContainerID + return errors.Wrap(errdefs.ErrInvalidArgument, "container id must be provided") } client, ctx, cancel, err := commands.NewClient(context) if err != nil { diff --git a/cmd/ctr/commands/error.go b/cmd/ctr/commands/error.go deleted file mode 100644 index c5a1e9f90..000000000 --- a/cmd/ctr/commands/error.go +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package commands - -import ( - "github.com/pkg/errors" -) - -var ( - // ErrArgConfigFile is returned when the configuration for a spec is provided - ErrArgConfigFile = errors.New("with spec config file, only container id should be provided") - // ErrUnprovidedImageRef is returned when no image reference is provided - ErrUnprovidedImageRef = errors.New("image ref must be provided") - // ErrEmptyContainerID is returned when no container id is provided - ErrEmptyContainerID = errors.New("container id must be provided") - // ErrDeleteNoneContainer is returned when no container ids are provided for deletion - ErrDeleteNoneContainer = errors.New("must specify at least one container to delete") -) diff --git a/error.go b/error.go deleted file mode 100644 index e3ccba1b7..000000000 --- a/error.go +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package containerd - -import ( - "github.com/pkg/errors" -) - -var ( - // ErrNoGRPCAndService is returned when no connection or service is available - ErrNoGRPCAndService = errors.New("no grpc connection and service is available") - // ErrReconnectFailed is returned when no connector is available to reconnect - ErrReconnectFailed = errors.New("unable to reconnect to containerd, no connector available") - // ErrNoGRPC is returned when no grpc connect is available - ErrNoGRPC = errors.New("no grpc connection available") - // ErrUnpackNotSupported is returned when a fetch cannot unpack - ErrUnpackNotSupported = errors.New("unpack on fetch not supported, try pull") -)