pkg/bindings: add new APIVersionError error type

When a new API call is added to the bindings we should guard it based on
the version and throw a useful error. Right now an old server that does
not implement a given endpoint would throw a "NOT FOUND" error which is
not good for callers.

Instead implement a custom error type to give a usefule error instead.
This allows bindings users to call errors.As() to know if they call and
to old version.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
Paul Holzinger
2023-11-29 15:27:25 +01:00
parent 93bcd2a25d
commit 86296ff8da
3 changed files with 31 additions and 1 deletions

View File

@ -118,7 +118,7 @@ func ExecRemove(ctx context.Context, sessionID string, options *ExecRemoveOption
// The exec remove endpoint was added in 4.8. // The exec remove endpoint was added in 4.8.
if v.Major < 4 || (v.Major == 4 && v.Minor < 8) { if v.Major < 4 || (v.Major == 4 && v.Minor < 8) {
// Do no call this endpoint as it will not be supported on the server and throw an "NOT FOUND" error. // Do no call this endpoint as it will not be supported on the server and throw an "NOT FOUND" error.
return nil return bindings.NewAPIVersionError("/exec/{id}/remove", v, "4.8.0")
} }
if options == nil { if options == nil {
options = new(ExecRemoveOptions) options = new(ExecRemoveOptions)

View File

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"io" "io"
"github.com/blang/semver/v4"
"github.com/containers/podman/v4/pkg/errorhandling" "github.com/containers/podman/v4/pkg/errorhandling"
) )
@ -61,3 +62,26 @@ func CheckResponseCode(inError error) (int, error) {
return -1, errors.New("is not type ErrorModel") return -1, errors.New("is not type ErrorModel")
} }
} }
type APIVersionError struct {
endpoint string
serverVersion *semver.Version
requiredVersion string
}
// NewAPIVersionError create bindings error when the endpoint on the server is not supported
// because the version is to old.
// - endpoint is the name fo the endpoint (e.g. /containers/json)
// - version is the server API version
// - requiredVersion is the server version need to use said endpoint
func NewAPIVersionError(endpoint string, version *semver.Version, requiredVersion string) *APIVersionError {
return &APIVersionError{
endpoint: endpoint,
serverVersion: version,
requiredVersion: requiredVersion,
}
}
func (e *APIVersionError) Error() string {
return fmt.Sprintf("API server version is %s, need at least %s to call %s", e.serverVersion.String(), e.requiredVersion, e.endpoint)
}

View File

@ -17,6 +17,7 @@ import (
"github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/libpod/events" "github.com/containers/podman/v4/libpod/events"
"github.com/containers/podman/v4/pkg/api/handlers" "github.com/containers/podman/v4/pkg/api/handlers"
"github.com/containers/podman/v4/pkg/bindings"
"github.com/containers/podman/v4/pkg/bindings/containers" "github.com/containers/podman/v4/pkg/bindings/containers"
"github.com/containers/podman/v4/pkg/bindings/images" "github.com/containers/podman/v4/pkg/bindings/images"
"github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/entities"
@ -588,6 +589,11 @@ func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrID string, o
} }
defer func() { defer func() {
if err := containers.ExecRemove(ic.ClientCtx, sessionID, nil); err != nil { if err := containers.ExecRemove(ic.ClientCtx, sessionID, nil); err != nil {
apiErr := new(bindings.APIVersionError)
if errors.As(err, &apiErr) {
// if the API is to old do not throw an error
return
}
if retErr == nil { if retErr == nil {
exitCode = -1 exitCode = -1
retErr = err retErr = err