cli: reduce uses of pkg/errors for stdlib errors

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2025-07-15 13:12:10 +02:00
parent 44eba133d6
commit e069ded4c3
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
15 changed files with 62 additions and 56 deletions

View File

@ -12,7 +12,6 @@ import (
"github.com/fvbommel/sortorder"
"github.com/moby/term"
"github.com/morikuni/aec"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
@ -204,7 +203,7 @@ var helpCommand = &cobra.Command{
RunE: func(c *cobra.Command, args []string) error {
cmd, args, e := c.Root().Find(args)
if cmd == nil || e != nil || len(args) > 0 {
return errors.Errorf("unknown help topic: %v", strings.Join(args, " "))
return fmt.Errorf("unknown help topic: %v", strings.Join(args, " "))
}
helpFunc := cmd.HelpFunc()
helpFunc(cmd, args)

View File

@ -5,6 +5,7 @@ package command
import (
"context"
"errors"
"fmt"
"io"
"os"
@ -26,7 +27,6 @@ import (
"github.com/moby/moby/api/types/build"
"github.com/moby/moby/api/types/swarm"
"github.com/moby/moby/client"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@ -168,7 +168,7 @@ func (cli *DockerCli) BuildKitEnabled() (bool, error) {
if v := os.Getenv("DOCKER_BUILDKIT"); v != "" {
enabled, err := strconv.ParseBool(v)
if err != nil {
return false, errors.Wrap(err, "DOCKER_BUILDKIT environment variable expects boolean value")
return false, fmt.Errorf("DOCKER_BUILDKIT environment variable expects boolean value: %w", err)
}
return enabled, nil
}
@ -299,7 +299,7 @@ func NewAPIClientFromFlags(opts *cliflags.ClientOptions, configFile *configfile.
}
endpoint, err := resolveDockerEndpoint(contextStore, resolveContextName(opts, configFile))
if err != nil {
return nil, errors.Wrap(err, "unable to resolve docker endpoint")
return nil, fmt.Errorf("unable to resolve docker endpoint: %w", err)
}
return newAPIClientFromEndpoint(endpoint, configFile)
}
@ -478,7 +478,7 @@ func (cli *DockerCli) initialize() error {
cli.init.Do(func() {
cli.dockerEndpoint, cli.initErr = cli.getDockerEndPoint()
if cli.initErr != nil {
cli.initErr = errors.Wrap(cli.initErr, "unable to resolve docker endpoint")
cli.initErr = fmt.Errorf("unable to resolve docker endpoint: %w", cli.initErr)
return
}
if cli.client == nil {
@ -546,7 +546,7 @@ func getServerHost(hosts []string, defaultToTLS bool) (string, error) {
case 1:
return dopts.ParseHost(defaultToTLS, hosts[0])
default:
return "", errors.New("Specify only one -H")
return "", errors.New("specify only one -H")
}
}

View File

@ -3,6 +3,7 @@ package command
import (
"context"
"encoding/csv"
"fmt"
"io"
"net/http"
"os"
@ -12,7 +13,6 @@ import (
"github.com/docker/cli/cli/streams"
"github.com/moby/moby/client"
"github.com/moby/term"
"github.com/pkg/errors"
)
// CLIOption is a functional argument to apply options to a [DockerCli]. These
@ -189,7 +189,7 @@ func withCustomHeadersFromEnv() client.Opt {
csvReader := csv.NewReader(strings.NewReader(value))
fields, err := csvReader.Read()
if err != nil {
return invalidParameter(errors.Errorf(
return invalidParameter(fmt.Errorf(
"failed to parse custom headers from %s environment variable: value must be formatted as comma-separated key=value pairs",
envOverrideHTTPHeaders,
))
@ -206,7 +206,7 @@ func withCustomHeadersFromEnv() client.Opt {
k = strings.TrimSpace(k)
if k == "" {
return invalidParameter(errors.Errorf(
return invalidParameter(fmt.Errorf(
`failed to set custom headers from %s environment variable: value contains a key=value pair with an empty key: '%s'`,
envOverrideHTTPHeaders, kv,
))
@ -217,7 +217,7 @@ func withCustomHeadersFromEnv() client.Opt {
// from an environment variable with the same name). In the meantime,
// produce an error to prevent users from depending on this.
if !hasValue {
return invalidParameter(errors.Errorf(
return invalidParameter(fmt.Errorf(
`failed to set custom headers from %s environment variable: missing "=" in key=value pair: '%s'`,
envOverrideHTTPHeaders, kv,
))

View File

@ -2,6 +2,7 @@ package config
import (
"context"
"errors"
"fmt"
"io"
@ -11,7 +12,6 @@ import (
"github.com/docker/cli/opts"
"github.com/moby/moby/api/types/swarm"
"github.com/moby/sys/sequential"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@ -53,7 +53,7 @@ func RunConfigCreate(ctx context.Context, dockerCLI command.Cli, options CreateO
configData, err := readConfigData(dockerCLI.In(), options.File)
if err != nil {
return errors.Errorf("Error reading content from %q: %v", options.File, err)
return fmt.Errorf("error reading content from %q: %v", options.File, err)
}
spec := swarm.ConfigSpec{

View File

@ -2,6 +2,7 @@ package container
import (
"context"
"errors"
"io"
"github.com/docker/cli/cli"
@ -10,7 +11,6 @@ import (
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/client"
"github.com/moby/sys/signal"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@ -28,13 +28,13 @@ func inspectContainerAndCheckState(ctx context.Context, apiClient client.APIClie
return nil, err
}
if !c.State.Running {
return nil, errors.New("You cannot attach to a stopped container, start it first")
return nil, errors.New("cannot attach to a stopped container, start it first")
}
if c.State.Paused {
return nil, errors.New("You cannot attach to a paused container, unpause it first")
return nil, errors.New("cannot attach to a paused container, unpause it first")
}
if c.State.Restarting {
return nil, errors.New("You cannot attach to a restarting container, wait until it is running")
return nil, errors.New("cannot attach to a restarting container, wait until it is running")
}
return &c, nil

View File

@ -29,7 +29,7 @@ func TestNewAttachCommandErrors(t *testing.T) {
{
name: "client-stopped",
args: []string{"5cb5bb5e4a3b"},
expectedError: "You cannot attach to a stopped container",
expectedError: "cannot attach to a stopped container",
containerInspectFunc: func(containerID string) (container.InspectResponse, error) {
return container.InspectResponse{
ContainerJSONBase: &container.ContainerJSONBase{
@ -43,7 +43,7 @@ func TestNewAttachCommandErrors(t *testing.T) {
{
name: "client-paused",
args: []string{"5cb5bb5e4a3b"},
expectedError: "You cannot attach to a paused container",
expectedError: "cannot attach to a paused container",
containerInspectFunc: func(containerID string) (container.InspectResponse, error) {
return container.InspectResponse{
ContainerJSONBase: &container.ContainerJSONBase{
@ -58,7 +58,7 @@ func TestNewAttachCommandErrors(t *testing.T) {
{
name: "client-restarting",
args: []string{"5cb5bb5e4a3b"},
expectedError: "You cannot attach to a restarting container",
expectedError: "cannot attach to a restarting container",
containerInspectFunc: func(containerID string) (container.InspectResponse, error) {
return container.InspectResponse{
ContainerJSONBase: &container.ContainerJSONBase{

View File

@ -3,6 +3,7 @@ package container
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"os"
@ -19,7 +20,6 @@ import (
"github.com/moby/go-archive"
"github.com/moby/moby/api/types/container"
"github.com/morikuni/aec"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@ -331,7 +331,7 @@ func copyToContainer(ctx context.Context, dockerCLI command.Cli, copyConfig cpCo
// Validate the destination path
if err := command.ValidateOutputPathFileMode(dstStat.Mode); err != nil {
return errors.Wrapf(err, `destination "%s:%s" must be a directory or a regular file`, copyConfig.container, dstPath)
return fmt.Errorf(`destination "%s:%s" must be a directory or a regular file: %w`, copyConfig.container, dstPath, err)
}
// Ignore any error and assume that the parent directory of the destination
@ -354,7 +354,7 @@ func copyToContainer(ctx context.Context, dockerCLI command.Cli, copyConfig cpCo
content = os.Stdin
resolvedDstPath = dstInfo.Path
if !dstInfo.IsDir {
return errors.Errorf("destination \"%s:%s\" must be a directory", copyConfig.container, dstPath)
return fmt.Errorf(`destination "%s:%s" must be a directory`, copyConfig.container, dstPath)
}
} else {
// Prepare source copy info.

View File

@ -4,6 +4,7 @@ import (
"archive/tar"
"bytes"
"context"
"errors"
"fmt"
"io"
"net/netip"
@ -30,7 +31,6 @@ import (
"github.com/moby/moby/api/types/versions"
"github.com/moby/moby/client"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
@ -80,7 +80,7 @@ func NewCreateCommand(dockerCli command.Cli) *cobra.Command {
flags.StringVar(&options.pull, "pull", PullImageMissing, `Pull image before creating ("`+PullImageAlways+`", "|`+PullImageMissing+`", "`+PullImageNever+`")`)
flags.BoolVarP(&options.quiet, "quiet", "q", false, "Suppress the pull output")
flags.BoolVarP(&options.useAPISocket, "use-api-socket", "", false, "Bind mount Docker API socket and required auth")
flags.SetAnnotation("use-api-socket", "experimentalCLI", nil) // Marks flag as experimental for now.
_ = flags.SetAnnotation("use-api-socket", "experimentalCLI", nil) // Mark flag as experimental for now.
// Add an explicit help that doesn't have a `-h` to prevent the conflict
// with hostname
@ -113,7 +113,7 @@ func runCreate(ctx context.Context, dockerCli command.Cli, flags *pflag.FlagSet,
}
}
proxyConfig := dockerCli.ConfigFile().ParseProxyConfig(dockerCli.Client().DaemonHost(), opts.ConvertKVStringsToMapWithNil(copts.env.GetSlice()))
newEnv := []string{}
newEnv := make([]string, 0, len(proxyConfig))
for k, v := range proxyConfig {
if v == nil {
newEnv = append(newEnv, k)
@ -151,7 +151,9 @@ func pullImage(ctx context.Context, dockerCli command.Cli, img string, options *
if err != nil {
return err
}
defer responseBody.Close()
defer func() {
_ = responseBody.Close()
}()
out := dockerCli.Err()
if options.quiet {
@ -170,13 +172,13 @@ func (cid *cidFile) Close() error {
if cid.file == nil {
return nil
}
cid.file.Close()
_ = cid.file.Close()
if cid.written {
return nil
}
if err := os.Remove(cid.path); err != nil {
return errors.Wrapf(err, "failed to remove the CID file '%s'", cid.path)
return fmt.Errorf("failed to remove the CID file '%s': %w", cid.path, err)
}
return nil
@ -187,7 +189,7 @@ func (cid *cidFile) Write(id string) error {
return nil
}
if _, err := cid.file.Write([]byte(id)); err != nil {
return errors.Wrap(err, "failed to write the container ID to the file")
return fmt.Errorf("failed to write the container ID to the file: %w", err)
}
cid.written = true
return nil
@ -198,12 +200,12 @@ func newCIDFile(cidPath string) (*cidFile, error) {
return &cidFile{}, nil
}
if _, err := os.Stat(cidPath); err == nil {
return nil, errors.Errorf("container ID file found, make sure the other container isn't running or delete %s", cidPath)
return nil, errors.New("container ID file found, make sure the other container isn't running or delete " + cidPath)
}
f, err := os.Create(cidPath)
if err != nil {
return nil, errors.Wrap(err, "failed to create the container ID file")
return nil, fmt.Errorf("failed to create the container ID file: %w", err)
}
return &cidFile{path: cidPath, file: f}, nil
@ -224,7 +226,9 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c
if err != nil {
return "", err
}
defer containerIDFile.Close()
defer func() {
_ = containerIDFile.Close()
}()
ref, err := reference.ParseAnyReference(config.Image)
if err != nil {
@ -318,7 +322,7 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c
if options.platform != "" && versions.GreaterThanOrEqualTo(dockerCli.Client().ClientVersion(), "1.41") {
p, err := platforms.Parse(options.platform)
if err != nil {
return "", errors.Wrap(invalidParameter(err), "error parsing specified platform")
return "", invalidParameter(fmt.Errorf("error parsing specified platform: %w", err))
}
platform = &p
}
@ -431,7 +435,7 @@ func copyDockerConfigIntoContainer(ctx context.Context, dockerAPI client.APIClie
// We don't need to get super fancy with the tar creation.
var tarBuf bytes.Buffer
tarWriter := tar.NewWriter(&tarBuf)
tarWriter.WriteHeader(&tar.Header{
_ = tarWriter.WriteHeader(&tar.Header{
Name: configPath,
Size: int64(configBuf.Len()),
Mode: 0o600,

View File

@ -4,10 +4,12 @@
package command
import (
"errors"
"fmt"
"github.com/docker/cli/cli/context/docker"
"github.com/docker/cli/cli/context/store"
cliflags "github.com/docker/cli/cli/flags"
"github.com/pkg/errors"
)
const (
@ -185,7 +187,7 @@ func (s *ContextStoreWithDefault) GetTLSData(contextName, endpointName, fileName
return nil, err
}
if defaultContext.TLS.Endpoints[endpointName].Files[fileName] == nil {
return nil, notFound(errors.Errorf("TLS data for %s/%s/%s does not exist", DefaultContextName, endpointName, fileName))
return nil, notFound(fmt.Errorf("TLS data for %s/%s/%s does not exist", DefaultContextName, endpointName, fileName))
}
return defaultContext.TLS.Endpoints[endpointName].Files[fileName], nil
}

View File

@ -2,6 +2,7 @@ package command
import (
"context"
"errors"
"fmt"
"os"
"runtime"
@ -17,7 +18,6 @@ import (
"github.com/docker/cli/internal/tui"
registrytypes "github.com/moby/moby/api/types/registry"
"github.com/morikuni/aec"
"github.com/pkg/errors"
)
const (
@ -151,7 +151,7 @@ func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword
argUser = defaultUsername
}
if argUser == "" {
return registrytypes.AuthConfig{}, errors.Errorf("Error: Non-null Username Required")
return registrytypes.AuthConfig{}, errors.New("error: username is required")
}
}
@ -183,7 +183,7 @@ func PromptUserForCredentials(ctx context.Context, cli Cli, argUser, argPassword
}
_, _ = fmt.Fprintln(cli.Out())
if argPassword == "" {
return registrytypes.AuthConfig{}, errors.Errorf("Error: Password Required")
return registrytypes.AuthConfig{}, errors.New("error: password is required")
}
}

View File

@ -14,7 +14,6 @@ import (
"strings"
"unicode"
"github.com/pkg/errors"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
@ -48,7 +47,7 @@ func dockerExporterOTLPEndpoint(cli Cli) (endpoint string, secure bool) {
if otelCfg != nil {
otelMap, ok := otelCfg.(map[string]any)
if !ok {
otel.Handle(errors.Errorf(
otel.Handle(fmt.Errorf(
"unexpected type for field %q: %T (expected: %T)",
otelContextFieldName,
otelCfg,
@ -76,7 +75,7 @@ func dockerExporterOTLPEndpoint(cli Cli) (endpoint string, secure bool) {
// We pretend we're the same as the environment reader.
u, err := url.Parse(endpoint)
if err != nil {
otel.Handle(errors.Errorf("docker otel endpoint is invalid: %s", err))
otel.Handle(fmt.Errorf("docker otel endpoint is invalid: %s", err))
return "", false
}

View File

@ -2,12 +2,12 @@ package command
import (
"context"
"errors"
"fmt"
"strings"
"time"
"github.com/docker/cli/cli/version"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"

View File

@ -4,13 +4,14 @@
package command
import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/docker/cli/cli/config"
"github.com/moby/moby/api/types/filters"
"github.com/pkg/errors"
)
// PruneFilters merges prune filters specified in config.json with those specified
@ -59,7 +60,7 @@ func ValidateOutputPath(path string) error {
dir := filepath.Dir(filepath.Clean(path))
if dir != "" && dir != "." {
if _, err := os.Stat(dir); os.IsNotExist(err) {
return errors.Errorf("invalid output path: directory %q does not exist", dir)
return fmt.Errorf("invalid output path: directory %q does not exist", dir)
}
}
// check whether `path` points to a regular file
@ -74,7 +75,7 @@ func ValidateOutputPath(path string) error {
}
if err := ValidateOutputPathFileMode(fileInfo.Mode()); err != nil {
return errors.Wrapf(err, "invalid output path: %q must be a directory or a regular file", path)
return fmt.Errorf("invalid output path: %q must be a directory or a regular file: %w", path, err)
}
}
return nil

View File

@ -1,7 +1,8 @@
package cli
import (
"github.com/pkg/errors"
"fmt"
"github.com/spf13/cobra"
)
@ -12,7 +13,7 @@ func NoArgs(cmd *cobra.Command, args []string) error {
}
if cmd.HasSubCommands() {
return errors.Errorf(
return fmt.Errorf(
"%[1]s: unknown command: %[2]s %[3]s\n\nUsage: %[4]s\n\nRun '%[2]s --help' for more information",
binName(cmd),
cmd.CommandPath(),
@ -21,7 +22,7 @@ func NoArgs(cmd *cobra.Command, args []string) error {
)
}
return errors.Errorf(
return fmt.Errorf(
"%[1]s: '%[2]s' accepts no arguments\n\nUsage: %[3]s\n\nRun '%[2]s --help' for more information",
binName(cmd),
cmd.CommandPath(),
@ -35,7 +36,7 @@ func RequiresMinArgs(minArgs int) cobra.PositionalArgs {
if len(args) >= minArgs {
return nil
}
return errors.Errorf(
return fmt.Errorf(
"%[1]s: '%[2]s' requires at least %[3]d %[4]s\n\nUsage: %[5]s\n\nSee '%[2]s --help' for more information",
binName(cmd),
cmd.CommandPath(),
@ -52,8 +53,8 @@ func RequiresMaxArgs(maxArgs int) cobra.PositionalArgs {
if len(args) <= maxArgs {
return nil
}
return errors.Errorf(
"%[1]s: '%[2]s' requires at most %[3]d %[4]s\n\nUsage: %[5]s\n\nSRun '%[2]s --help' for more information",
return fmt.Errorf(
"%[1]s: '%[2]s' requires at most %[3]d %[4]s\n\nUsage: %[5]s\n\nRun '%[2]s --help' for more information",
binName(cmd),
cmd.CommandPath(),
maxArgs,
@ -69,7 +70,7 @@ func RequiresRangeArgs(minArgs int, maxArgs int) cobra.PositionalArgs {
if len(args) >= minArgs && len(args) <= maxArgs {
return nil
}
return errors.Errorf(
return fmt.Errorf(
"%[1]s: '%[2]s' requires at least %[3]d and at most %[4]d %[5]s\n\nUsage: %[6]s\n\nRun '%[2]s --help' for more information",
binName(cmd),
cmd.CommandPath(),
@ -87,7 +88,7 @@ func ExactArgs(number int) cobra.PositionalArgs {
if len(args) == number {
return nil
}
return errors.Errorf(
return fmt.Errorf(
"%[1]s: '%[2]s' requires %[3]d %[4]s\n\nUsage: %[5]s\n\nRun '%[2]s --help' for more information",
binName(cmd),
cmd.CommandPath(),

View File

@ -93,7 +93,7 @@ func TestGlobalArgsOnlyParsedOnce(t *testing.T) {
args: []string{"-H", dh, "-H", dh, "version", "-f", "{{.Client.Version}}"},
expectedExitCode: 1,
expectedOut: icmd.None,
expectedErr: "Specify only one -H",
expectedErr: "specify only one -H",
},
{
name: "builtin",