Skip to content

Commit

Permalink
pkg/podman: Add error parsing method
Browse files Browse the repository at this point in the history
This new helper function parses the output of Podman in stderr into
a dedicated structure with defined methods for working with the error.

The most significant part is the method Is() that wraps around
errors.Is() and if that fails to find a match resorts to string
matching. This is needed because there are no defined errors to catch
errors coming from Podman.

The structure is only meant to be used internally.

containers#786
  • Loading branch information
HarryMichal committed Jun 21, 2021
1 parent 7d13300 commit 0f5868c
Showing 1 changed file with 66 additions and 0 deletions.
66 changes: 66 additions & 0 deletions src/pkg/podman/podman.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ package podman
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"strings"

"github.com/HarryMichal/go-version"
"github.com/containers/toolbox/pkg/shell"
Expand Down Expand Up @@ -332,3 +334,67 @@ func SystemMigrate(ociRuntimeRequired string) error {

return nil
}

type internalError struct {
Err error
}

func (e *internalError) Error() string {
if e.Err == nil {
return ""
}
return e.Err.Error()
}

func (e *internalError) Wrap(format string, a ...interface{}) {
errMsg := fmt.Sprintf(format, a...)
if e.Err == nil {
e.Err = errors.New(errMsg)
} else {
e.Err = fmt.Errorf("%v: %w", errMsg, e.Err)
}
}

// Is wraps around errors.Is() and add support for string comparison of errors
func (e internalError) Is(err error) bool {
if errors.Is(e.Err, err) {
return true
}

errMsgParts := strings.Split(e.Err.Error(), ": ")
for _, part := range errMsgParts {
if part == err.Error() {
return true
}
}

return false
}

// parseErrorMsg serves for converting error output of Podman into an error
// that can be further used in Go.
//
// The returned error can be examined using methods Unwrap, Is & As.
func parseErrorMsg(stderr *bytes.Buffer) internalError {
var err internalError
var errMsg string
var errMsgParts []string

errMsg = stderr.String()
errMsg = strings.TrimSpace(errMsg)
// Podman error messages are usually prepended with the "Error: " string
errMsg = strings.TrimPrefix(errMsg, "Error: ")
// Sometimes an error contains a newline (e.g. responses from Docker
// registry). Normlaize them into further parseable error message.
errMsg = strings.ReplaceAll(errMsg, "\n", ": ")
// Wrapped error messages are usually separated by a colon followed by
// a single space character
errMsgParts = strings.Split(errMsg, ": ")

// Wrapping happens from the first to the last error
for i := len(errMsgParts) - 1; i >= 0; i-- {
err.Wrap(errMsgParts[i])
}

return err
}

0 comments on commit 0f5868c

Please sign in to comment.