moby/client/errors.go
Sebastiaan van Stijn e6907243af
client: negotiate api version before handling version-specific code
We try to perform API-version negotiation as lazy as possible (and only execute
when we are about to make an API request). However, some code requires API-version
dependent handling (to set options, or remove options based on the version of the
API we're using).

Currently this code depended on the caller code to perform API negotiation (or
to configure the API version) first, which may not happen, and because of that
we may be missing options (or set options that are not supported on older API
versions).

This patch:

- splits the code that triggered API-version negotiation to a separate
  Client.checkVersion() function.
- updates NewVersionError to accept a context
- updates NewVersionError to perform API-version negotiation (if enabled)
- updates various Client functions to manually trigger API-version negotiation

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-09-20 15:23:27 +02:00

68 lines
2.3 KiB
Go

package client // import "github.com/docker/docker/client"
import (
"context"
"fmt"
"github.com/docker/docker/api/types/versions"
"github.com/docker/docker/errdefs"
"github.com/pkg/errors"
)
// errConnectionFailed implements an error returned when connection failed.
type errConnectionFailed struct {
host string
}
// Error returns a string representation of an errConnectionFailed
func (err errConnectionFailed) Error() string {
if err.host == "" {
return "Cannot connect to the Docker daemon. Is the docker daemon running on this host?"
}
return fmt.Sprintf("Cannot connect to the Docker daemon at %s. Is the docker daemon running?", err.host)
}
// IsErrConnectionFailed returns true if the error is caused by connection failed.
func IsErrConnectionFailed(err error) bool {
return errors.As(err, &errConnectionFailed{})
}
// ErrorConnectionFailed returns an error with host in the error message when connection to docker daemon failed.
func ErrorConnectionFailed(host string) error {
return errConnectionFailed{host: host}
}
// IsErrNotFound returns true if the error is a NotFound error, which is returned
// by the API when some object is not found. It is an alias for [errdefs.IsNotFound].
func IsErrNotFound(err error) bool {
return errdefs.IsNotFound(err)
}
type objectNotFoundError struct {
object string
id string
}
func (e objectNotFoundError) NotFound() {}
func (e objectNotFoundError) Error() string {
return fmt.Sprintf("Error: No such %s: %s", e.object, e.id)
}
// NewVersionError returns an error if the APIVersion required is less than the
// current supported version.
//
// It performs API-version negotiation if the Client is configured with this
// option, otherwise it assumes the latest API version is used.
func (cli *Client) NewVersionError(ctx context.Context, APIrequired, feature string) error {
// Make sure we negotiated (if the client is configured to do so),
// as code below contains API-version specific handling of options.
//
// Normally, version-negotiation (if enabled) would not happen until
// the API request is made.
cli.checkVersion(ctx)
if cli.version != "" && versions.LessThan(cli.version, APIrequired) {
return fmt.Errorf("%q requires API version %s, but the Docker daemon API version is %s", feature, APIrequired, cli.version)
}
return nil
}