diff options
Diffstat (limited to 'pkg')
148 files changed, 1172 insertions, 1222 deletions
diff --git a/pkg/api/handlers/compat/auth.go b/pkg/api/handlers/compat/auth.go index 7804c8230..37d2b784d 100644 --- a/pkg/api/handlers/compat/auth.go +++ b/pkg/api/handlers/compat/auth.go @@ -3,6 +3,7 @@ package compat import ( "context" "encoding/json" + "errors" "fmt" "net/http" "strings" @@ -14,7 +15,6 @@ import ( api "github.com/containers/podman/v4/pkg/api/types" "github.com/containers/podman/v4/pkg/domain/entities" docker "github.com/docker/docker/api/types" - "github.com/pkg/errors" ) func stripAddressOfScheme(address string) string { @@ -28,7 +28,7 @@ func Auth(w http.ResponseWriter, r *http.Request) { var authConfig docker.AuthConfig err := json.NewDecoder(r.Body).Decode(&authConfig) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse request")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to parse request: %w", err)) return } diff --git a/pkg/api/handlers/compat/changes.go b/pkg/api/handlers/compat/changes.go index af0143fcf..c3f612f04 100644 --- a/pkg/api/handlers/compat/changes.go +++ b/pkg/api/handlers/compat/changes.go @@ -1,6 +1,7 @@ package compat import ( + "fmt" "net/http" "github.com/containers/podman/v4/libpod" @@ -8,7 +9,6 @@ import ( "github.com/containers/podman/v4/pkg/api/handlers/utils" api "github.com/containers/podman/v4/pkg/api/types" "github.com/gorilla/schema" - "github.com/pkg/errors" ) func Changes(w http.ResponseWriter, r *http.Request) { @@ -20,7 +20,7 @@ func Changes(w http.ResponseWriter, r *http.Request) { DiffType string `schema:"diffType"` }{} if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } var diffType define.DiffType @@ -32,7 +32,7 @@ func Changes(w http.ResponseWriter, r *http.Request) { case "image": diffType = define.DiffImage default: - utils.Error(w, http.StatusBadRequest, errors.Errorf("invalid diffType value %q", query.DiffType)) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("invalid diffType value %q", query.DiffType)) return } diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index 38fe0196a..ae063dc9f 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -397,6 +397,15 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error }, nil } +func convertSecondaryIPPrefixLen(input *define.InspectNetworkSettings, output *types.NetworkSettings) { + for index, ip := range input.SecondaryIPAddresses { + output.SecondaryIPAddresses[index].PrefixLen = ip.PrefixLength + } + for index, ip := range input.SecondaryIPv6Addresses { + output.SecondaryIPv6Addresses[index].PrefixLen = ip.PrefixLength + } +} + func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, error) { _, imageName := l.Image() inspect, err := l.Inspect(sz) @@ -587,6 +596,9 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, if err := json.Unmarshal(n, &networkSettings); err != nil { return nil, err } + + convertSecondaryIPPrefixLen(inspect.NetworkSettings, &networkSettings) + // do not report null instead use an empty map if networkSettings.Networks == nil { networkSettings.Networks = map[string]*network.EndpointSettings{} diff --git a/pkg/api/handlers/compat/containers_attach.go b/pkg/api/handlers/compat/containers_attach.go index c8905808f..e804e628a 100644 --- a/pkg/api/handlers/compat/containers_attach.go +++ b/pkg/api/handlers/compat/containers_attach.go @@ -1,6 +1,8 @@ package compat import ( + "errors" + "fmt" "net/http" "github.com/containers/podman/v4/libpod" @@ -9,7 +11,6 @@ import ( "github.com/containers/podman/v4/pkg/api/server/idle" api "github.com/containers/podman/v4/pkg/api/types" "github.com/gorilla/schema" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -60,13 +61,13 @@ func AttachContainer(w http.ResponseWriter, r *http.Request) { streams = nil } if useStreams && !streams.Stdout && !streams.Stderr && !streams.Stdin { - utils.Error(w, http.StatusBadRequest, errors.Errorf("at least one of stdin, stdout, stderr must be true")) + utils.Error(w, http.StatusBadRequest, errors.New("at least one of stdin, stdout, stderr must be true")) return } // At least one of these must be set if !query.Stream && !query.Logs { - utils.Error(w, http.StatusBadRequest, errors.Errorf("at least one of Logs or Stream must be set")) + utils.Error(w, http.StatusBadRequest, errors.New("at least one of Logs or Stream must be set")) return } @@ -85,16 +86,16 @@ func AttachContainer(w http.ResponseWriter, r *http.Request) { // For Docker compatibility, we need to re-initialize containers in these states. if state == define.ContainerStateConfigured || state == define.ContainerStateExited || state == define.ContainerStateStopped { if err := ctr.Init(r.Context(), ctr.PodID() != ""); err != nil { - utils.Error(w, http.StatusConflict, errors.Wrapf(err, "error preparing container %s for attach", ctr.ID())) + utils.Error(w, http.StatusConflict, fmt.Errorf("error preparing container %s for attach: %w", ctr.ID(), err)) return } } else if !(state == define.ContainerStateCreated || state == define.ContainerStateRunning) { - utils.InternalServerError(w, errors.Wrapf(define.ErrCtrStateInvalid, "can only attach to created or running containers - currently in state %s", state.String())) + utils.InternalServerError(w, fmt.Errorf("can only attach to created or running containers - currently in state %s: %w", state.String(), define.ErrCtrStateInvalid)) return } logErr := func(e error) { - logrus.Error(errors.Wrapf(e, "error attaching to container %s", ctr.ID())) + logrus.Errorf("Error attaching to container %s: %v", ctr.ID(), e) } // Perform HTTP attach. diff --git a/pkg/api/handlers/compat/containers_export.go b/pkg/api/handlers/compat/containers_export.go index 743ce2d53..66e1dcca5 100644 --- a/pkg/api/handlers/compat/containers_export.go +++ b/pkg/api/handlers/compat/containers_export.go @@ -1,6 +1,7 @@ package compat import ( + "fmt" "io/ioutil" "net/http" "os" @@ -8,7 +9,6 @@ import ( "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/pkg/api/handlers/utils" api "github.com/containers/podman/v4/pkg/api/types" - "github.com/pkg/errors" ) func ExportContainer(w http.ResponseWriter, r *http.Request) { @@ -21,21 +21,21 @@ func ExportContainer(w http.ResponseWriter, r *http.Request) { } tmpfile, err := ioutil.TempFile("", "api.tar") if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to create tempfile: %w", err)) return } defer os.Remove(tmpfile.Name()) if err := tmpfile.Close(); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to close tempfile: %w", err)) return } if err := con.Export(tmpfile.Name()); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to save image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to save image: %w", err)) return } rdr, err := os.Open(tmpfile.Name()) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to read the exported tarfile: %w", err)) return } defer rdr.Close() diff --git a/pkg/api/handlers/compat/containers_logs.go b/pkg/api/handlers/compat/containers_logs.go index fc894d815..77c4fdd2a 100644 --- a/pkg/api/handlers/compat/containers_logs.go +++ b/pkg/api/handlers/compat/containers_logs.go @@ -16,7 +16,6 @@ import ( api "github.com/containers/podman/v4/pkg/api/types" "github.com/containers/podman/v4/pkg/util" "github.com/gorilla/schema" - "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) @@ -36,13 +35,13 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) { Tail: "all", } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } if !(query.Stdout || query.Stderr) { msg := fmt.Sprintf("%s: you must choose at least one stream", http.StatusText(http.StatusBadRequest)) - utils.Error(w, http.StatusBadRequest, errors.Errorf("%s for %s", msg, r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("%s for %s", msg, r.URL.String())) return } @@ -96,7 +95,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) { logChannel := make(chan *logs.LogLine, tail+1) if err := runtime.Log(r.Context(), []*libpod.Container{ctnr}, options, logChannel); err != nil { - utils.InternalServerError(w, errors.Wrapf(err, "failed to obtain logs for Container '%s'", name)) + utils.InternalServerError(w, fmt.Errorf("failed to obtain logs for Container '%s': %w", name, err)) return } go func() { @@ -114,7 +113,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) { if !utils.IsLibpodRequest(r) { inspectData, err := ctnr.Inspect(false) if err != nil { - utils.InternalServerError(w, errors.Wrapf(err, "failed to obtain logs for Container '%s'", name)) + utils.InternalServerError(w, fmt.Errorf("failed to obtain logs for Container '%s': %w", name, err)) return } writeHeader = !inspectData.Config.Tty diff --git a/pkg/api/handlers/compat/containers_prune.go b/pkg/api/handlers/compat/containers_prune.go index 9b5390d64..95d6a639f 100644 --- a/pkg/api/handlers/compat/containers_prune.go +++ b/pkg/api/handlers/compat/containers_prune.go @@ -2,6 +2,8 @@ package compat import ( "bytes" + "errors" + "fmt" "net/http" "github.com/containers/podman/v4/libpod" @@ -11,14 +13,13 @@ import ( "github.com/containers/podman/v4/pkg/domain/entities/reports" "github.com/containers/podman/v4/pkg/domain/filters" "github.com/containers/podman/v4/pkg/util" - "github.com/pkg/errors" ) func PruneContainers(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) filtersMap, err := util.PrepareFilters(r) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats.go index 12c5283fc..c115b4181 100644 --- a/pkg/api/handlers/compat/containers_stats.go +++ b/pkg/api/handlers/compat/containers_stats.go @@ -2,6 +2,7 @@ package compat import ( "encoding/json" + "fmt" "net/http" "time" @@ -13,7 +14,6 @@ import ( docker "github.com/docker/docker/api/types" "github.com/gorilla/schema" runccgroups "github.com/opencontainers/runc/libcontainer/cgroups" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -30,7 +30,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { Stream: true, } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } if query.Stream && query.OneShot { // mismatch. one-shot can only be passed with stream=false @@ -47,7 +47,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { stats, err := ctnr.GetContainerStats(nil) if err != nil { - utils.InternalServerError(w, errors.Wrapf(err, "failed to obtain Container %s stats", name)) + utils.InternalServerError(w, fmt.Errorf("failed to obtain Container %s stats: %w", name, err)) return } diff --git a/pkg/api/handlers/compat/containers_top.go b/pkg/api/handlers/compat/containers_top.go index 6ca178cf7..9f598cd73 100644 --- a/pkg/api/handlers/compat/containers_top.go +++ b/pkg/api/handlers/compat/containers_top.go @@ -12,7 +12,6 @@ import ( "github.com/containers/podman/v4/pkg/api/handlers/utils" api "github.com/containers/podman/v4/pkg/api/types" "github.com/gorilla/schema" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -33,7 +32,7 @@ func TopContainer(w http.ResponseWriter, r *http.Request) { PsArgs: psArgs, } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } diff --git a/pkg/api/handlers/compat/events.go b/pkg/api/handlers/compat/events.go index 6bcb7bd32..18fb35966 100644 --- a/pkg/api/handlers/compat/events.go +++ b/pkg/api/handlers/compat/events.go @@ -1,6 +1,7 @@ package compat import ( + "fmt" "net/http" "github.com/containers/podman/v4/libpod" @@ -11,7 +12,6 @@ import ( "github.com/containers/podman/v4/pkg/util" "github.com/gorilla/schema" jsoniter "github.com/json-iterator/go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -34,7 +34,7 @@ func GetEvents(w http.ResponseWriter, r *http.Request) { Stream: true, } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -44,7 +44,7 @@ func GetEvents(w http.ResponseWriter, r *http.Request) { libpodFilters, err := util.FiltersFromRequest(r) if err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } eventChannel := make(chan *events.Event) diff --git a/pkg/api/handlers/compat/exec.go b/pkg/api/handlers/compat/exec.go index c7990f6e8..1b4dead8b 100644 --- a/pkg/api/handlers/compat/exec.go +++ b/pkg/api/handlers/compat/exec.go @@ -7,6 +7,7 @@ import ( "net/http" "strings" + "github.com/containers/common/pkg/resize" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/api/handlers" @@ -176,9 +177,9 @@ func ExecStartHandler(w http.ResponseWriter, r *http.Request) { logrus.Error(fmt.Errorf("error attaching to container %s exec session %s: %w", sessionCtr.ID(), sessionID, e)) } - var size *define.TerminalSize + var size *resize.TerminalSize if bodyParams.Tty && (bodyParams.Height > 0 || bodyParams.Width > 0) { - size = &define.TerminalSize{ + size = &resize.TerminalSize{ Height: bodyParams.Height, Width: bodyParams.Width, } diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go index 80fc17f56..a9185c3d3 100644 --- a/pkg/api/handlers/compat/images_build.go +++ b/pkg/api/handlers/compat/images_build.go @@ -3,6 +3,7 @@ package compat import ( "context" "encoding/json" + "errors" "fmt" "io" "io/ioutil" @@ -27,7 +28,6 @@ import ( "github.com/docker/docker/pkg/jsonmessage" "github.com/gorilla/schema" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -65,7 +65,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { } err := os.RemoveAll(filepath.Dir(contextDirectory)) if err != nil { - logrus.Warn(errors.Wrapf(err, "failed to remove build scratch directory %q", filepath.Dir(contextDirectory))) + logrus.Warn(fmt.Errorf("failed to remove build scratch directory %q: %w", filepath.Dir(contextDirectory), err)) } }() @@ -338,7 +338,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { if len(tags) > 0 { possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, tags[0]) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error normalizing image: %w", err)) return } output = possiblyNormalizedName @@ -350,7 +350,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { var err error isolation, err = parseLibPodIsolation(query.Isolation) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to parse isolation")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to parse isolation: %w", err)) return } @@ -371,7 +371,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { for i := 1; i < len(tags); i++ { possiblyNormalizedTag, err := utils.NormalizeToDockerHub(r, tags[i]) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error normalizing image: %w", err)) return } additionalTags = append(additionalTags, possiblyNormalizedTag) @@ -487,7 +487,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { } con := strings.SplitN(opt, "=", 2) if len(con) != 2 { - utils.BadRequest(w, "securityopt", query.SecurityOpt, errors.Errorf("Invalid --security-opt name=value pair: %q", opt)) + utils.BadRequest(w, "securityopt", query.SecurityOpt, fmt.Errorf("invalid --security-opt name=value pair: %q", opt)) return } @@ -499,7 +499,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { case "seccomp": seccomp = con[1] default: - utils.BadRequest(w, "securityopt", query.SecurityOpt, errors.Errorf("Invalid --security-opt 2: %q", opt)) + utils.BadRequest(w, "securityopt", query.SecurityOpt, fmt.Errorf("invalid --security-opt 2: %q", opt)) return } } @@ -540,7 +540,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { if fromImage != "" { possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, fromImage) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error normalizing image: %w", err)) return } fromImage = possiblyNormalizedName diff --git a/pkg/api/handlers/compat/images_history.go b/pkg/api/handlers/compat/images_history.go index 70a11ddc5..ebb5acdd9 100644 --- a/pkg/api/handlers/compat/images_history.go +++ b/pkg/api/handlers/compat/images_history.go @@ -1,13 +1,13 @@ package compat import ( + "fmt" "net/http" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/pkg/api/handlers" "github.com/containers/podman/v4/pkg/api/handlers/utils" api "github.com/containers/podman/v4/pkg/api/types" - "github.com/pkg/errors" ) func HistoryImage(w http.ResponseWriter, r *http.Request) { @@ -16,13 +16,13 @@ func HistoryImage(w http.ResponseWriter, r *http.Request) { possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, name) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error normalizing image: %w", err)) return } newImage, _, err := runtime.LibimageRuntime().LookupImage(possiblyNormalizedName, nil) if err != nil { - utils.ImageNotFound(w, possiblyNormalizedName, errors.Wrapf(err, "failed to find image %s", possiblyNormalizedName)) + utils.ImageNotFound(w, possiblyNormalizedName, fmt.Errorf("failed to find image %s: %w", possiblyNormalizedName, err)) return } history, err := newImage.History(r.Context()) diff --git a/pkg/api/handlers/compat/images_prune.go b/pkg/api/handlers/compat/images_prune.go index 02cadbbbe..cc60ceb1c 100644 --- a/pkg/api/handlers/compat/images_prune.go +++ b/pkg/api/handlers/compat/images_prune.go @@ -2,6 +2,7 @@ package compat import ( "bytes" + "errors" "fmt" "net/http" @@ -13,7 +14,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/containers/podman/v4/pkg/util" "github.com/docker/docker/api/types" - "github.com/pkg/errors" ) func PruneImages(w http.ResponseWriter, r *http.Request) { @@ -22,7 +22,7 @@ func PruneImages(w http.ResponseWriter, r *http.Request) { filterMap, err := util.PrepareFilters(r) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } diff --git a/pkg/api/handlers/compat/images_push.go b/pkg/api/handlers/compat/images_push.go index 6765c30b6..bb82ef10d 100644 --- a/pkg/api/handlers/compat/images_push.go +++ b/pkg/api/handlers/compat/images_push.go @@ -2,6 +2,7 @@ package compat import ( "encoding/json" + "errors" "fmt" "io/ioutil" "net/http" @@ -17,7 +18,6 @@ import ( "github.com/containers/storage" "github.com/docker/docker/pkg/jsonmessage" "github.com/gorilla/schema" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -28,7 +28,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) { digestFile, err := ioutil.TempFile("", "digest.txt") if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to create tempfile: %w", err)) return } defer digestFile.Close() @@ -50,7 +50,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -63,19 +63,19 @@ func PushImage(w http.ResponseWriter, r *http.Request) { } if _, err := utils.ParseStorageReference(imageName); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "image source %q is not a containers-storage-transport reference", imageName)) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("image source %q is not a containers-storage-transport reference: %w", imageName, err)) return } possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, imageName) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error normalizing image: %w", err)) return } imageName = possiblyNormalizedName localImage, _, err := runtime.LibimageRuntime().LookupImage(possiblyNormalizedName, nil) if err != nil { - utils.ImageNotFound(w, imageName, errors.Wrapf(err, "failed to find image %s", imageName)) + utils.ImageNotFound(w, imageName, fmt.Errorf("failed to find image %s: %w", imageName, err)) return } rawManifest, _, err := localImage.Manifest(r.Context()) diff --git a/pkg/api/handlers/compat/images_search.go b/pkg/api/handlers/compat/images_search.go index 9f41c1b4f..a6fd3a3a1 100644 --- a/pkg/api/handlers/compat/images_search.go +++ b/pkg/api/handlers/compat/images_search.go @@ -13,7 +13,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/containers/storage" "github.com/gorilla/schema" - "github.com/pkg/errors" ) func SearchImages(w http.ResponseWriter, r *http.Request) { @@ -30,7 +29,7 @@ func SearchImages(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } diff --git a/pkg/api/handlers/compat/images_tag.go b/pkg/api/handlers/compat/images_tag.go index da0a04e84..a1da7a4b9 100644 --- a/pkg/api/handlers/compat/images_tag.go +++ b/pkg/api/handlers/compat/images_tag.go @@ -1,6 +1,7 @@ package compat import ( + "errors" "fmt" "net/http" @@ -8,7 +9,6 @@ import ( "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/pkg/api/handlers/utils" api "github.com/containers/podman/v4/pkg/api/types" - "github.com/pkg/errors" ) func TagImage(w http.ResponseWriter, r *http.Request) { @@ -17,7 +17,7 @@ func TagImage(w http.ResponseWriter, r *http.Request) { name := utils.GetName(r) possiblyNormalizedName, err := utils.NormalizeToDockerHub(r, name) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error normalizing image: %w", err)) return } @@ -25,7 +25,7 @@ func TagImage(w http.ResponseWriter, r *http.Request) { lookupOptions := &libimage.LookupImageOptions{ManifestList: true} newImage, _, err := runtime.LibimageRuntime().LookupImage(possiblyNormalizedName, lookupOptions) if err != nil { - utils.ImageNotFound(w, name, errors.Wrapf(err, "failed to find image %s", name)) + utils.ImageNotFound(w, name, fmt.Errorf("failed to find image %s: %w", name, err)) return } @@ -42,7 +42,7 @@ func TagImage(w http.ResponseWriter, r *http.Request) { possiblyNormalizedTag, err := utils.NormalizeToDockerHub(r, tagName) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error normalizing image")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error normalizing image: %w", err)) return } diff --git a/pkg/api/handlers/compat/info.go b/pkg/api/handlers/compat/info.go index 85547570a..d82513284 100644 --- a/pkg/api/handlers/compat/info.go +++ b/pkg/api/handlers/compat/info.go @@ -22,7 +22,6 @@ import ( "github.com/docker/docker/api/types/registry" "github.com/docker/docker/api/types/swarm" "github.com/google/uuid" - "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) @@ -33,18 +32,18 @@ func GetInfo(w http.ResponseWriter, r *http.Request) { infoData, err := runtime.Info() if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to obtain system memory info")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to obtain system memory info: %w", err)) return } configInfo, err := runtime.GetConfig() if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to obtain runtime config")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to obtain runtime config: %w", err)) return } versionInfo, err := define.GetVersion() if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to obtain podman versions")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to obtain podman versions: %w", err)) return } stateInfo := getContainersState(runtime) diff --git a/pkg/api/handlers/compat/resize.go b/pkg/api/handlers/compat/resize.go index f5da306da..a2caf6e35 100644 --- a/pkg/api/handlers/compat/resize.go +++ b/pkg/api/handlers/compat/resize.go @@ -6,6 +6,7 @@ import ( "net/http" "strings" + "github.com/containers/common/pkg/resize" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/api/handlers/utils" @@ -32,7 +33,7 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) { return } - sz := define.TerminalSize{ + sz := resize.TerminalSize{ Width: query.Width, Height: query.Height, } diff --git a/pkg/api/handlers/compat/version.go b/pkg/api/handlers/compat/version.go index cfc3468c2..0d34fbd98 100644 --- a/pkg/api/handlers/compat/version.go +++ b/pkg/api/handlers/compat/version.go @@ -13,7 +13,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/entities/types" "github.com/containers/podman/v4/version" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -28,7 +27,7 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) { info, err := runtime.Info() if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to obtain system memory info")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to obtain system memory info: %w", err)) return } diff --git a/pkg/api/handlers/libpod/containers_create.go b/pkg/api/handlers/libpod/containers_create.go index 4fff9e345..e4964d602 100644 --- a/pkg/api/handlers/libpod/containers_create.go +++ b/pkg/api/handlers/libpod/containers_create.go @@ -3,6 +3,7 @@ package libpod import ( "context" "encoding/json" + "fmt" "net/http" "strconv" @@ -13,7 +14,6 @@ import ( "github.com/containers/podman/v4/pkg/specgen" "github.com/containers/podman/v4/pkg/specgen/generate" "github.com/containers/podman/v4/pkg/specgenutil" - "github.com/pkg/errors" ) // CreateContainer takes a specgenerator and makes a container. It returns @@ -34,7 +34,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) { } if err := json.NewDecoder(r.Body).Decode(&sg); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("decode(): %w", err)) return } if sg.Passwd == nil { diff --git a/pkg/api/handlers/libpod/containers_stats.go b/pkg/api/handlers/libpod/containers_stats.go index 46d722a3d..687d61c12 100644 --- a/pkg/api/handlers/libpod/containers_stats.go +++ b/pkg/api/handlers/libpod/containers_stats.go @@ -2,6 +2,8 @@ package libpod import ( "encoding/json" + "errors" + "fmt" "net/http" "github.com/containers/common/pkg/cgroups" @@ -12,7 +14,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/containers/podman/v4/pkg/rootless" "github.com/gorilla/schema" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -24,8 +25,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { if rootless.IsRootless() { // if so, then verify cgroup v2 available (more expensive check) if isV2, _ := cgroups.IsCgroup2UnifiedMode(); !isV2 { - msg := "Container stats resource only available for cgroup v2" - utils.Error(w, http.StatusConflict, errors.New(msg)) + utils.Error(w, http.StatusConflict, errors.New("container stats resource only available for cgroup v2")) return } } @@ -39,7 +39,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) { Interval: 5, } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } diff --git a/pkg/api/handlers/libpod/generate.go b/pkg/api/handlers/libpod/generate.go index b1ac6a65a..48c4c59e1 100644 --- a/pkg/api/handlers/libpod/generate.go +++ b/pkg/api/handlers/libpod/generate.go @@ -1,6 +1,7 @@ package libpod import ( + "fmt" "net/http" "github.com/containers/podman/v4/libpod" @@ -10,7 +11,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/containers/podman/v4/pkg/util" "github.com/gorilla/schema" - "github.com/pkg/errors" ) func GenerateSystemd(w http.ResponseWriter, r *http.Request) { @@ -37,7 +37,7 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -76,7 +76,7 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) { report, err := containerEngine.GenerateSystemd(r.Context(), utils.GetName(r), options) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error generating systemd units")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error generating systemd units: %w", err)) return } @@ -94,7 +94,7 @@ func GenerateKube(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -102,7 +102,7 @@ func GenerateKube(w http.ResponseWriter, r *http.Request) { options := entities.GenerateKubeOptions{Service: query.Service} report, err := containerEngine.GenerateKube(r.Context(), query.Names, options) if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error generating YAML")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error generating YAML: %w", err)) return } diff --git a/pkg/api/handlers/libpod/images_pull.go b/pkg/api/handlers/libpod/images_pull.go index 2cd45fb63..7e24ae5ac 100644 --- a/pkg/api/handlers/libpod/images_pull.go +++ b/pkg/api/handlers/libpod/images_pull.go @@ -3,6 +3,8 @@ package libpod import ( "context" "encoding/json" + "errors" + "fmt" "net/http" "github.com/containers/common/libimage" @@ -15,7 +17,6 @@ import ( "github.com/containers/podman/v4/pkg/channel" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/gorilla/schema" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -41,7 +42,7 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go index bdf0162c7..3235a2972 100644 --- a/pkg/api/handlers/libpod/manifests.go +++ b/pkg/api/handlers/libpod/manifests.go @@ -3,6 +3,7 @@ package libpod import ( "context" "encoding/json" + "errors" "fmt" "io/ioutil" "net/http" @@ -24,7 +25,6 @@ import ( "github.com/gorilla/mux" "github.com/gorilla/schema" "github.com/opencontainers/go-digest" - "github.com/pkg/errors" ) func ManifestCreate(w http.ResponseWriter, r *http.Request) { @@ -45,7 +45,7 @@ func ManifestCreate(w http.ResponseWriter, r *http.Request) { if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusBadRequest, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -54,7 +54,7 @@ func ManifestCreate(w http.ResponseWriter, r *http.Request) { n, err := url.QueryUnescape(name) if err != nil { utils.Error(w, http.StatusBadRequest, - errors.Wrapf(err, "failed to parse name parameter %q", name)) + fmt.Errorf("failed to parse name parameter %q: %w", name, err)) return } query.Name = n @@ -62,7 +62,7 @@ func ManifestCreate(w http.ResponseWriter, r *http.Request) { if _, err := reference.ParseNormalizedNamed(query.Name); err != nil { utils.Error(w, http.StatusBadRequest, - errors.Wrapf(err, "invalid image name %s", query.Name)) + fmt.Errorf("invalid image name %s: %w", query.Name, err)) return } @@ -94,7 +94,7 @@ func ManifestCreate(w http.ResponseWriter, r *http.Request) { body := new(entities.ManifestModifyOptions) if err := json.Unmarshal(buffer, body); err != nil { - utils.InternalServerError(w, errors.Wrap(err, "Decode()")) + utils.InternalServerError(w, fmt.Errorf("Decode(): %w", err)) return } @@ -166,7 +166,7 @@ func ManifestAddV3(w http.ResponseWriter, r *http.Request) { TLSVerify bool `schema:"tlsVerify"` }{} if err := json.NewDecoder(r.Body).Decode(&query); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("Decode(): %w", err)) return } @@ -220,7 +220,7 @@ func ManifestRemoveDigestV3(w http.ResponseWriter, r *http.Request) { name := utils.GetName(r) if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusBadRequest, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } manifestList, err := runtime.LibimageRuntime().LookupManifestList(name) @@ -256,7 +256,7 @@ func ManifestPushV3(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusBadRequest, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } if err := utils.IsRegistryReference(query.Destination); err != nil { @@ -292,7 +292,7 @@ func ManifestPushV3(w http.ResponseWriter, r *http.Request) { imageEngine := abi.ImageEngine{Libpod: runtime} digest, err := imageEngine.ManifestPush(context.Background(), source, query.Destination, options) if err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "error pushing image %q", query.Destination)) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("error pushing image %q: %w", query.Destination, err)) return } utils.WriteResponse(w, http.StatusOK, entities.IDResponse{ID: digest}) @@ -313,7 +313,7 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusBadRequest, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -325,7 +325,7 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) { authconf, authfile, err := auth.GetCredentials(r) if err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse registry header for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse registry header for %s: %w", r.URL.String(), err)) return } defer auth.RemoveAuthfile(authfile) @@ -351,7 +351,7 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) { source := utils.GetName(r) digest, err := imageEngine.ManifestPush(context.Background(), source, destination, options) if err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "error pushing image %q", destination)) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("error pushing image %q: %w", destination, err)) return } utils.WriteResponse(w, http.StatusOK, entities.IDResponse{ID: digest}) @@ -364,7 +364,7 @@ func ManifestModify(w http.ResponseWriter, r *http.Request) { body := new(entities.ManifestModifyOptions) if err := json.NewDecoder(r.Body).Decode(body); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("Decode(): %w", err)) return } diff --git a/pkg/api/handlers/libpod/play.go b/pkg/api/handlers/libpod/play.go index 36e61c986..f8ce52a72 100644 --- a/pkg/api/handlers/libpod/play.go +++ b/pkg/api/handlers/libpod/play.go @@ -1,6 +1,7 @@ package libpod import ( + "fmt" "net" "net/http" @@ -12,7 +13,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/gorilla/schema" - "github.com/pkg/errors" ) func PlayKube(w http.ResponseWriter, r *http.Request) { @@ -34,7 +34,7 @@ func PlayKube(w http.ResponseWriter, r *http.Request) { } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } @@ -42,7 +42,7 @@ func PlayKube(w http.ResponseWriter, r *http.Request) { for _, ipString := range query.StaticIPs { ip := net.ParseIP(ipString) if ip == nil { - utils.Error(w, http.StatusBadRequest, errors.Errorf("Invalid IP address %s", ipString)) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("invalid IP address %s", ipString)) return } staticIPs = append(staticIPs, ip) @@ -103,7 +103,7 @@ func PlayKube(w http.ResponseWriter, r *http.Request) { report, err := containerEngine.PlayKube(r.Context(), r.Body, options) _ = r.Body.Close() if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error playing YAML file")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error playing YAML file: %w", err)) return } utils.WriteResponse(w, http.StatusOK, report) @@ -116,7 +116,7 @@ func PlayKubeDown(w http.ResponseWriter, r *http.Request) { report, err := containerEngine.PlayKubeDown(r.Context(), r.Body, *options) _ = r.Body.Close() if err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error tearing down YAML file")) + utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error tearing down YAML file: %w", err)) return } utils.WriteResponse(w, http.StatusOK, report) diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go index 92fd94390..8b1d456ec 100644 --- a/pkg/api/handlers/libpod/pods.go +++ b/pkg/api/handlers/libpod/pods.go @@ -530,8 +530,12 @@ func PodStats(w http.ResponseWriter, r *http.Request) { query := struct { NamesOrIDs []string `schema:"namesOrIDs"` All bool `schema:"all"` + Stream bool `schema:"stream"` + Delay int `schema:"delay"` }{ // default would go here + Delay: 5, + Stream: false, } if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) @@ -544,6 +548,10 @@ func PodStats(w http.ResponseWriter, r *http.Request) { utils.InternalServerError(w, err) } + var flush = func() {} + if flusher, ok := w.(http.Flusher); ok { + flush = flusher.Flush + } // Collect the stats and send them over the wire. containerEngine := abi.ContainerEngine{Libpod: runtime} reports, err := containerEngine.PodStats(r.Context(), query.NamesOrIDs, options) @@ -554,10 +562,35 @@ func PodStats(w http.ResponseWriter, r *http.Request) { utils.Error(w, http.StatusNotFound, err) return } - utils.InternalServerError(w, err) return } - utils.WriteResponse(w, http.StatusOK, reports) + w.Header().Set("Content-Type", "application/json") + coder := json.NewEncoder(w) + coder.SetEscapeHTML(true) + + if err := coder.Encode(reports); err != nil { + logrus.Infof("Error from %s %q : %v", r.Method, r.URL, err) + } + flush() + if query.Stream { + for { + select { + case <-r.Context().Done(): + return + default: + time.Sleep(time.Duration(query.Delay) * time.Second) + reports, err = containerEngine.PodStats(r.Context(), query.NamesOrIDs, options) + if err != nil { + return + } + if err := coder.Encode(reports); err != nil { + logrus.Infof("Error from %s %q : %v", r.Method, r.URL, err) + return + } + flush() + } + } + } } diff --git a/pkg/api/handlers/libpod/secrets.go b/pkg/api/handlers/libpod/secrets.go index 3ea2c2ea8..6eba65f2b 100644 --- a/pkg/api/handlers/libpod/secrets.go +++ b/pkg/api/handlers/libpod/secrets.go @@ -1,6 +1,7 @@ package libpod import ( + "fmt" "net/http" "github.com/containers/podman/v4/libpod" @@ -9,7 +10,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/gorilla/schema" - "github.com/pkg/errors" ) func CreateSecret(w http.ResponseWriter, r *http.Request) { @@ -27,7 +27,7 @@ func CreateSecret(w http.ResponseWriter, r *http.Request) { } opts := entities.SecretCreateOptions{} if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } diff --git a/pkg/api/handlers/libpod/swagger_spec.go b/pkg/api/handlers/libpod/swagger_spec.go index 8eeb041d2..bfe4ab9fd 100644 --- a/pkg/api/handlers/libpod/swagger_spec.go +++ b/pkg/api/handlers/libpod/swagger_spec.go @@ -1,11 +1,12 @@ package libpod import ( + "errors" + "fmt" "net/http" "os" "github.com/containers/podman/v4/pkg/api/handlers/utils" - "github.com/pkg/errors" ) // DefaultPodmanSwaggerSpec provides the default path to the podman swagger spec file @@ -18,7 +19,7 @@ func ServeSwagger(w http.ResponseWriter, r *http.Request) { } if _, err := os.Stat(path); err != nil { if errors.Is(err, os.ErrNotExist) { - utils.InternalServerError(w, errors.Errorf("swagger spec %q does not exist", path)) + utils.InternalServerError(w, fmt.Errorf("swagger spec %q does not exist", path)) return } utils.InternalServerError(w, err) diff --git a/pkg/api/handlers/libpod/system.go b/pkg/api/handlers/libpod/system.go index 9ceca99e8..7418dc4df 100644 --- a/pkg/api/handlers/libpod/system.go +++ b/pkg/api/handlers/libpod/system.go @@ -1,6 +1,7 @@ package libpod import ( + "fmt" "net/http" "github.com/containers/podman/v4/libpod" @@ -10,7 +11,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/infra/abi" "github.com/containers/podman/v4/pkg/util" "github.com/gorilla/schema" - "github.com/pkg/errors" ) // SystemPrune removes unused data @@ -25,13 +25,13 @@ func SystemPrune(w http.ResponseWriter, r *http.Request) { if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusBadRequest, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } filterMap, err := util.PrepareFilters(r) if err != nil { utils.Error(w, http.StatusBadRequest, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err)) return } diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index 9eb712c30..b533e131c 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -2,6 +2,7 @@ package handlers import ( "context" + "fmt" "time" "github.com/containers/common/libimage" @@ -10,7 +11,6 @@ import ( dockerContainer "github.com/docker/docker/api/types/container" dockerNetwork "github.com/docker/docker/api/types/network" "github.com/docker/go-connections/nat" - "github.com/pkg/errors" ) type AuthConfig struct { @@ -237,17 +237,17 @@ func portsToPortSet(input map[string]struct{}) (nat.PortSet, error) { case "tcp", "": p, err := nat.NewPort("tcp", port) if err != nil { - return nil, errors.Wrapf(err, "unable to create tcp port from %s", k) + return nil, fmt.Errorf("unable to create tcp port from %s: %w", k, err) } ports[p] = struct{}{} case "udp": p, err := nat.NewPort("udp", port) if err != nil { - return nil, errors.Wrapf(err, "unable to create tcp port from %s", k) + return nil, fmt.Errorf("unable to create tcp port from %s: %w", k, err) } ports[p] = struct{}{} default: - return nil, errors.Errorf("invalid port proto %q in %q", proto, k) + return nil, fmt.Errorf("invalid port proto %q in %q", proto, k) } } return ports, nil diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go index 80f8522fd..e198bdd6c 100644 --- a/pkg/api/handlers/utils/containers.go +++ b/pkg/api/handlers/utils/containers.go @@ -99,9 +99,8 @@ func WaitContainerDocker(w http.ResponseWriter, r *http.Request) { func WaitContainerLibpod(w http.ResponseWriter, r *http.Request) { var ( - err error - interval = time.Millisecond * 250 - conditions = []define.ContainerStatus{define.ContainerStateStopped, define.ContainerStateExited} + err error + interval = time.Millisecond * 250 ) decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder) query := waitQueryLibpod{} @@ -118,17 +117,10 @@ func WaitContainerLibpod(w http.ResponseWriter, r *http.Request) { } } - if _, found := r.URL.Query()["condition"]; found { - if len(query.Condition) > 0 { - conditions = query.Condition - } - } - name := GetName(r) waitFn := createContainerWaitFn(r.Context(), name, interval) - - exitCode, err := waitFn(conditions...) + exitCode, err := waitFn(query.Condition...) if err != nil { if errors.Is(err, define.ErrNoSuchCtr) { ContainerNotFound(w, name, err) diff --git a/pkg/api/handlers/utils/handler.go b/pkg/api/handlers/utils/handler.go index 338d5a84b..9562ebbbc 100644 --- a/pkg/api/handlers/utils/handler.go +++ b/pkg/api/handlers/utils/handler.go @@ -1,6 +1,7 @@ package utils import ( + "errors" "fmt" "io" "net/http" @@ -13,7 +14,6 @@ import ( "github.com/containers/podman/v4/version" "github.com/gorilla/mux" jsoniter "github.com/json-iterator/go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -42,11 +42,11 @@ func SupportedVersion(r *http.Request, condition string) (semver.Version, error) } safeVal, err := url.PathUnescape(val) if err != nil { - return version, errors.Wrapf(err, "unable to unescape given API version: %q", val) + return version, fmt.Errorf("unable to unescape given API version: %q: %w", val, err) } version, err = semver.ParseTolerant(safeVal) if err != nil { - return version, errors.Wrapf(err, "unable to parse given API version: %q from %q", safeVal, val) + return version, fmt.Errorf("unable to parse given API version: %q from %q: %w", safeVal, val, err) } inRange, err := semver.ParseRange(condition) @@ -178,7 +178,7 @@ func GetVar(r *http.Request, k string) string { val := mux.Vars(r)[k] safeVal, err := url.PathUnescape(val) if err != nil { - logrus.Error(errors.Wrapf(err, "failed to unescape mux key %s, value %s", k, val)) + logrus.Error(fmt.Errorf("failed to unescape mux key %s, value %s: %w", k, val, err)) return val } return safeVal diff --git a/pkg/api/server/listener_api.go b/pkg/api/server/listener_api.go index aaaf6688e..d1f3ea7a3 100644 --- a/pkg/api/server/listener_api.go +++ b/pkg/api/server/listener_api.go @@ -1,11 +1,10 @@ package server import ( + "fmt" "net" "os" "path/filepath" - - "github.com/pkg/errors" ) // ListenUnix follows stdlib net.Listen() API, providing a unix listener for given path @@ -14,18 +13,18 @@ func ListenUnix(network string, path string) (net.Listener, error) { // set up custom listener for API server err := os.MkdirAll(filepath.Dir(path), 0770) if err != nil { - return nil, errors.Wrapf(err, "api.ListenUnix() failed to create %s", filepath.Dir(path)) + return nil, fmt.Errorf("api.ListenUnix() failed to create %s: %w", filepath.Dir(path), err) } os.Remove(path) listener, err := net.Listen(network, path) if err != nil { - return nil, errors.Wrapf(err, "api.ListenUnix() failed to create net.Listen(%s, %s)", network, path) + return nil, fmt.Errorf("api.ListenUnix() failed to create net.Listen(%s, %s): %w", network, path, err) } _, err = os.Stat(path) if err != nil { - return nil, errors.Wrapf(err, "net.Listen(%s, %s) failed to report the failure to create socket", network, path) + return nil, fmt.Errorf("net.Listen(%s, %s) failed to report the failure to create socket: %w", network, path, err) } return listener, nil diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go index 3a78436d7..dd934fabd 100644 --- a/pkg/auth/auth.go +++ b/pkg/auth/auth.go @@ -3,6 +3,7 @@ package auth import ( "encoding/base64" "encoding/json" + "fmt" "io/ioutil" "net/http" "os" @@ -11,7 +12,6 @@ import ( imageAuth "github.com/containers/image/v5/pkg/docker/config" "github.com/containers/image/v5/types" dockerAPITypes "github.com/docker/docker/api/types" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -47,7 +47,7 @@ func GetCredentials(r *http.Request) (*types.DockerAuthConfig, string, error) { return nil, "", nil } if err != nil { - return nil, "", errors.Wrapf(err, "failed to parse %q header for %s", headerName, r.URL.String()) + return nil, "", fmt.Errorf("failed to parse %q header for %s: %w", headerName, r.URL.String(), err) } var authFile string @@ -56,7 +56,7 @@ func GetCredentials(r *http.Request) (*types.DockerAuthConfig, string, error) { } else { authFile, err = authConfigsToAuthFile(fileContents) if err != nil { - return nil, "", errors.Wrapf(err, "failed to parse %q header for %s", headerName, r.URL.String()) + return nil, "", fmt.Errorf("failed to parse %q header for %s: %w", headerName, r.URL.String(), err) } } return override, authFile, nil @@ -72,13 +72,13 @@ func getConfigCredentials(r *http.Request, headers []string) (*types.DockerAuthC for _, h := range headers { param, err := base64.URLEncoding.DecodeString(h) if err != nil { - return nil, nil, errors.Wrapf(err, "failed to decode %q", xRegistryConfigHeader) + return nil, nil, fmt.Errorf("failed to decode %q: %w", xRegistryConfigHeader, err) } ac := make(map[string]dockerAPITypes.AuthConfig) err = json.Unmarshal(param, &ac) if err != nil { - return nil, nil, errors.Wrapf(err, "failed to unmarshal %q", xRegistryConfigHeader) + return nil, nil, fmt.Errorf("failed to unmarshal %q: %w", xRegistryConfigHeader, err) } for k, v := range ac { @@ -238,10 +238,10 @@ func authConfigsToAuthFile(authConfigs map[string]types.DockerAuthConfig) (strin return "", err } if _, err := tmpFile.Write([]byte{'{', '}'}); err != nil { - return "", errors.Wrap(err, "error initializing temporary auth file") + return "", fmt.Errorf("error initializing temporary auth file: %w", err) } if err := tmpFile.Close(); err != nil { - return "", errors.Wrap(err, "error closing temporary auth file") + return "", fmt.Errorf("error closing temporary auth file: %w", err) } authFilePath := tmpFile.Name() @@ -255,7 +255,7 @@ func authConfigsToAuthFile(authConfigs map[string]types.DockerAuthConfig) (strin // that all credentials are valid. They'll be used on demand // later. if err := imageAuth.SetAuthentication(&sys, key, config.Username, config.Password); err != nil { - return "", errors.Wrapf(err, "error storing credentials in temporary auth file (key: %q / %q, user: %q)", authFileKey, key, config.Username) + return "", fmt.Errorf("error storing credentials in temporary auth file (key: %q / %q, user: %q): %w", authFileKey, key, config.Username, err) } } diff --git a/pkg/autoupdate/autoupdate.go b/pkg/autoupdate/autoupdate.go index 0c795faed..8d9991622 100644 --- a/pkg/autoupdate/autoupdate.go +++ b/pkg/autoupdate/autoupdate.go @@ -2,6 +2,7 @@ package autoupdate import ( "context" + "fmt" "os" "sort" @@ -17,7 +18,6 @@ import ( "github.com/containers/podman/v4/pkg/systemd" systemdDefine "github.com/containers/podman/v4/pkg/systemd/define" "github.com/coreos/go-systemd/v22/dbus" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -73,7 +73,7 @@ func LookupPolicy(s string) (Policy, error) { } sort.Strings(keys) - return "", errors.Errorf("invalid auto-update policy %q: valid policies are %+q", s, keys) + return "", fmt.Errorf("invalid auto-update policy %q: valid policies are %+q", s, keys) } // ValidateImageReference checks if the specified imageName is a fully-qualified @@ -85,17 +85,17 @@ func ValidateImageReference(imageName string) error { // Make sure the input image is a docker. imageRef, err := alltransports.ParseImageName(imageName) if err == nil && imageRef.Transport().Name() != docker.Transport.Name() { - return errors.Errorf("auto updates require the docker image transport but image is of transport %q", imageRef.Transport().Name()) + return fmt.Errorf("auto updates require the docker image transport but image is of transport %q", imageRef.Transport().Name()) } else if err != nil { repo, err := reference.Parse(imageName) if err != nil { - return errors.Wrap(err, "enforcing fully-qualified docker transport reference for auto updates") + return fmt.Errorf("enforcing fully-qualified docker transport reference for auto updates: %w", err) } if _, ok := repo.(reference.NamedTagged); !ok { - return errors.Errorf("auto updates require fully-qualified image references (no tag): %q", imageName) + return fmt.Errorf("auto updates require fully-qualified image references (no tag): %q", imageName) } if _, ok := repo.(reference.Digested); ok { - return errors.Errorf("auto updates require fully-qualified image references without digest: %q", imageName) + return fmt.Errorf("auto updates require fully-qualified image references without digest: %q", imageName) } } return nil @@ -151,7 +151,7 @@ func AutoUpdate(ctx context.Context, runtime *libpod.Runtime, options entities.A for imageID, policyMapper := range containerMap { image, exists := imageMap[imageID] if !exists { - errs = append(errs, errors.Errorf("container image ID %q not found in local storage", imageID)) + errs = append(errs, fmt.Errorf("container image ID %q not found in local storage", imageID)) return nil, errs } @@ -184,13 +184,13 @@ func autoUpdateRegistry(ctx context.Context, image *libimage.Image, ctr *libpod. cid := ctr.ID() rawImageName := ctr.RawImageName() if rawImageName == "" { - return nil, errors.Errorf("registry auto-updating container %q: raw-image name is empty", cid) + return nil, fmt.Errorf("registry auto-updating container %q: raw-image name is empty", cid) } labels := ctr.Labels() unit, exists := labels[systemdDefine.EnvVariable] if !exists { - return nil, errors.Errorf("auto-updating container %q: no %s label found", ctr.ID(), systemdDefine.EnvVariable) + return nil, fmt.Errorf("auto-updating container %q: no %s label found", ctr.ID(), systemdDefine.EnvVariable) } report := &entities.AutoUpdateReport{ @@ -214,7 +214,7 @@ func autoUpdateRegistry(ctx context.Context, image *libimage.Image, ctr *libpod. authfile := getAuthfilePath(ctr, options) needsUpdate, err := newerRemoteImageAvailable(ctx, image, rawImageName, authfile) if err != nil { - return report, errors.Wrapf(err, "registry auto-updating container %q: image check for %q failed", cid, rawImageName) + return report, fmt.Errorf("registry auto-updating container %q: image check for %q failed: %w", cid, rawImageName, err) } if !needsUpdate { @@ -228,7 +228,7 @@ func autoUpdateRegistry(ctx context.Context, image *libimage.Image, ctr *libpod. } if _, err := updateImage(ctx, runtime, rawImageName, authfile); err != nil { - return report, errors.Wrapf(err, "registry auto-updating container %q: image update for %q failed", cid, rawImageName) + return report, fmt.Errorf("registry auto-updating container %q: image update for %q failed: %w", cid, rawImageName, err) } updatedRawImages[rawImageName] = true @@ -245,10 +245,10 @@ func autoUpdateRegistry(ctx context.Context, image *libimage.Image, ctr *libpod. // To fallback, simply retag the old image and restart the service. if err := image.Tag(rawImageName); err != nil { - return report, errors.Wrap(err, "falling back to previous image") + return report, fmt.Errorf("falling back to previous image: %w", err) } if err := restartSystemdUnit(ctx, ctr, unit, conn); err != nil { - return report, errors.Wrap(err, "restarting unit with old image during fallback") + return report, fmt.Errorf("restarting unit with old image during fallback: %w", err) } report.Updated = "rolled back" @@ -260,13 +260,13 @@ func autoUpdateLocally(ctx context.Context, image *libimage.Image, ctr *libpod.C cid := ctr.ID() rawImageName := ctr.RawImageName() if rawImageName == "" { - return nil, errors.Errorf("locally auto-updating container %q: raw-image name is empty", cid) + return nil, fmt.Errorf("locally auto-updating container %q: raw-image name is empty", cid) } labels := ctr.Labels() unit, exists := labels[systemdDefine.EnvVariable] if !exists { - return nil, errors.Errorf("auto-updating container %q: no %s label found", ctr.ID(), systemdDefine.EnvVariable) + return nil, fmt.Errorf("auto-updating container %q: no %s label found", ctr.ID(), systemdDefine.EnvVariable) } report := &entities.AutoUpdateReport{ @@ -280,7 +280,7 @@ func autoUpdateLocally(ctx context.Context, image *libimage.Image, ctr *libpod.C needsUpdate, err := newerLocalImageAvailable(runtime, image, rawImageName) if err != nil { - return report, errors.Wrapf(err, "locally auto-updating container %q: image check for %q failed", cid, rawImageName) + return report, fmt.Errorf("locally auto-updating container %q: image check for %q failed: %w", cid, rawImageName, err) } if !needsUpdate { @@ -306,10 +306,10 @@ func autoUpdateLocally(ctx context.Context, image *libimage.Image, ctr *libpod.C // To fallback, simply retag the old image and restart the service. if err := image.Tag(rawImageName); err != nil { - return report, errors.Wrap(err, "falling back to previous image") + return report, fmt.Errorf("falling back to previous image: %w", err) } if err := restartSystemdUnit(ctx, ctr, unit, conn); err != nil { - return report, errors.Wrap(err, "restarting unit with old image during fallback") + return report, fmt.Errorf("restarting unit with old image during fallback: %w", err) } report.Updated = "rolled back" @@ -320,7 +320,7 @@ func autoUpdateLocally(ctx context.Context, image *libimage.Image, ctr *libpod.C func restartSystemdUnit(ctx context.Context, ctr *libpod.Container, unit string, conn *dbus.Conn) error { restartChan := make(chan string) if _, err := conn.RestartUnitContext(ctx, unit, "replace", restartChan); err != nil { - return errors.Wrapf(err, "auto-updating container %q: restarting systemd unit %q failed", ctr.ID(), unit) + return fmt.Errorf("auto-updating container %q: restarting systemd unit %q failed: %w", ctr.ID(), unit, err) } // Wait for the restart to finish and actually check if it was @@ -333,7 +333,7 @@ func restartSystemdUnit(ctx context.Context, ctr *libpod.Container, unit string, return nil default: - return errors.Errorf("auto-updating container %q: restarting systemd unit %q failed: expected %q but received %q", ctr.ID(), unit, "done", result) + return fmt.Errorf("auto-updating container %q: restarting systemd unit %q failed: expected %q but received %q", ctr.ID(), unit, "done", result) } } diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go index 6b3576f31..7dda955a2 100644 --- a/pkg/bindings/connection.go +++ b/pkg/bindings/connection.go @@ -2,6 +2,7 @@ package bindings import ( "context" + "errors" "fmt" "io" "net" @@ -15,7 +16,6 @@ import ( "github.com/blang/semver" "github.com/containers/podman/v4/pkg/terminal" "github.com/containers/podman/v4/version" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/agent" @@ -43,7 +43,7 @@ func GetClient(ctx context.Context) (*Connection, error) { if c, ok := ctx.Value(clientKey).(*Connection); ok { return c, nil } - return nil, errors.Errorf("%s not set in context", clientKey) + return nil, fmt.Errorf("%s not set in context", clientKey) } // ServiceVersion from context build by NewConnection() @@ -92,7 +92,7 @@ func NewConnectionWithIdentity(ctx context.Context, uri string, identity string) _url, err := url.Parse(uri) if err != nil { - return nil, errors.Wrapf(err, "Value of CONTAINER_HOST is not a valid url: %s", uri) + return nil, fmt.Errorf("value of CONTAINER_HOST is not a valid url: %s: %w", uri, err) } // Now we set up the http Client to use the connection above @@ -117,16 +117,16 @@ func NewConnectionWithIdentity(ctx context.Context, uri string, identity string) } connection = tcpClient(_url) default: - return nil, errors.Errorf("unable to create connection. %q is not a supported schema", _url.Scheme) + return nil, fmt.Errorf("unable to create connection. %q is not a supported schema", _url.Scheme) } if err != nil { - return nil, errors.Wrapf(err, "unable to connect to Podman. failed to create %sClient", _url.Scheme) + return nil, fmt.Errorf("unable to connect to Podman. failed to create %sClient: %w", _url.Scheme, err) } ctx = context.WithValue(ctx, clientKey, &connection) serviceVersion, err := pingNewConnection(ctx) if err != nil { - return nil, errors.Wrap(err, "unable to connect to Podman socket") + return nil, fmt.Errorf("unable to connect to Podman socket: %w", err) } ctx = context.WithValue(ctx, versionKey, serviceVersion) return ctx, nil @@ -177,11 +177,11 @@ func pingNewConnection(ctx context.Context) (*semver.Version, error) { // Server's job when Client version is equal or older return &versionSrv, nil case 1: - return nil, errors.Errorf("server API version is too old. Client %q server %q", + return nil, fmt.Errorf("server API version is too old. Client %q server %q", version.APIVersion[version.Libpod][version.MinimalAPI].String(), versionSrv.String()) } } - return nil, errors.Errorf("ping response was %d", response.StatusCode) + return nil, fmt.Errorf("ping response was %d", response.StatusCode) } func sshClient(_url *url.URL, secure bool, passPhrase string, identity string) (Connection, error) { @@ -193,7 +193,7 @@ func sshClient(_url *url.URL, secure bool, passPhrase string, identity string) ( if len(identity) > 0 { s, err := terminal.PublicKey(identity, []byte(passPhrase)) if err != nil { - return Connection{}, errors.Wrapf(err, "failed to parse identity %q", identity) + return Connection{}, fmt.Errorf("failed to parse identity %q: %w", identity, err) } signers = append(signers, s) @@ -289,7 +289,7 @@ func sshClient(_url *url.URL, secure bool, passPhrase string, identity string) ( }, ) if err != nil { - return Connection{}, errors.Wrapf(err, "connection to bastion host (%s) failed", _url.String()) + return Connection{}, fmt.Errorf("connection to bastion host (%s) failed: %w", _url.String(), err) } connection := Connection{URI: _url} @@ -379,7 +379,7 @@ func (c *Connection) GetDialer(ctx context.Context) (net.Conn, error) { return transport.DialContext(ctx, c.URI.Scheme, c.URI.String()) } - return nil, errors.New("Unable to get dial context") + return nil, errors.New("unable to get dial context") } // IsInformational returns true if the response code is 1xx diff --git a/pkg/bindings/containers/archive.go b/pkg/bindings/containers/archive.go index dd489d6f1..660d9da6b 100644 --- a/pkg/bindings/containers/archive.go +++ b/pkg/bindings/containers/archive.go @@ -2,6 +2,7 @@ package containers import ( "context" + "errors" "io" "net/http" "net/url" @@ -9,7 +10,6 @@ import ( "github.com/containers/podman/v4/pkg/bindings" "github.com/containers/podman/v4/pkg/copy" "github.com/containers/podman/v4/pkg/domain/entities" - "github.com/pkg/errors" ) // Stat checks if the specified path is on the container. Note that the stat diff --git a/pkg/bindings/containers/attach.go b/pkg/bindings/containers/attach.go index 303fc65bd..e23ee5ee9 100644 --- a/pkg/bindings/containers/attach.go +++ b/pkg/bindings/containers/attach.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/binary" + "errors" "fmt" "io" "net" @@ -14,11 +15,10 @@ import ( "strconv" "time" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/bindings" - "github.com/containers/podman/v4/utils" "github.com/moby/term" - "github.com/pkg/errors" "github.com/sirupsen/logrus" terminal "golang.org/x/term" ) @@ -75,7 +75,7 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri detachKeysInBytes, err = term.ToBytes(options.GetDetachKeys()) if err != nil { - return errors.Wrapf(err, "invalid detach keys") + return fmt.Errorf("invalid detach keys: %w", err) } } if isSet.stdin { @@ -159,7 +159,7 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri go func() { logrus.Debugf("Copying STDIN to socket") - _, err := utils.CopyDetachable(socket, stdin, detachKeysInBytes) + _, err := util.CopyDetachable(socket, stdin, detachKeysInBytes) if err != nil && err != define.ErrDetach { logrus.Errorf("Failed to write input to service: %v", err) } @@ -261,7 +261,7 @@ func DemuxHeader(r io.Reader, buffer []byte) (fd, sz int, err error) { fd = int(buffer[0]) if fd < 0 || fd > 3 { - err = errors.Wrapf(ErrLostSync, fmt.Sprintf(`channel "%d" found, 0-3 supported`, fd)) + err = fmt.Errorf(`channel "%d" found, 0-3 supported: %w`, fd, ErrLostSync) return } @@ -497,7 +497,7 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar if options.GetAttachInput() { go func() { logrus.Debugf("Copying STDIN to socket") - _, err := utils.CopyDetachable(socket, options.InputStream, []byte{}) + _, err := util.CopyDetachable(socket, options.InputStream, []byte{}) if err != nil { logrus.Errorf("Failed to write input to service: %v", err) } @@ -518,7 +518,7 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar return fmt.Errorf("exec session %s has a terminal and must have STDOUT enabled", sessionID) } // If not multiplex'ed, read from server and write to stdout - _, err := utils.CopyDetachable(options.GetOutputStream(), socket, []byte{}) + _, err := util.CopyDetachable(options.GetOutputStream(), socket, []byte{}) if err != nil { return err } diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go index ea01bc7d9..80ec7bc6f 100644 --- a/pkg/bindings/containers/containers.go +++ b/pkg/bindings/containers/containers.go @@ -2,6 +2,8 @@ package containers import ( "context" + "errors" + "fmt" "io" "net/http" "net/url" @@ -12,7 +14,6 @@ import ( "github.com/containers/podman/v4/pkg/bindings" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/entities/reports" - "github.com/pkg/errors" ) var ( @@ -447,7 +448,7 @@ func ContainerInit(ctx context.Context, nameOrID string, options *InitOptions) e defer response.Body.Close() if response.StatusCode == http.StatusNotModified { - return errors.Wrapf(define.ErrCtrStateInvalid, "container %s has already been created in runtime", nameOrID) + return fmt.Errorf("container %s has already been created in runtime: %w", nameOrID, define.ErrCtrStateInvalid) } return response.Process(nil) } diff --git a/pkg/bindings/containers/exec.go b/pkg/bindings/containers/exec.go index 3ad5d67d2..3d19fb812 100644 --- a/pkg/bindings/containers/exec.go +++ b/pkg/bindings/containers/exec.go @@ -3,6 +3,8 @@ package containers import ( "bytes" "context" + "errors" + "fmt" "net/http" "strings" @@ -11,7 +13,6 @@ import ( "github.com/containers/podman/v4/pkg/bindings" "github.com/containers/podman/v4/pkg/domain/entities" jsoniter "github.com/json-iterator/go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -27,12 +28,12 @@ func ExecCreate(ctx context.Context, nameOrID string, config *handlers.ExecCreat } if config == nil { - return "", errors.Errorf("must provide a configuration for exec session") + return "", errors.New("must provide a configuration for exec session") } requestJSON, err := json.Marshal(config) if err != nil { - return "", errors.Wrapf(err, "error marshalling exec config to JSON") + return "", fmt.Errorf("error marshalling exec config to JSON: %w", err) } jsonReader := strings.NewReader(string(requestJSON)) diff --git a/pkg/bindings/containers/logs.go b/pkg/bindings/containers/logs.go index 8ea8ed7fa..9ebfd90da 100644 --- a/pkg/bindings/containers/logs.go +++ b/pkg/bindings/containers/logs.go @@ -2,13 +2,13 @@ package containers import ( "context" + "errors" "fmt" "io" "net/http" "strconv" "github.com/containers/podman/v4/pkg/bindings" - "github.com/pkg/errors" ) // Logs obtains a container's logs given the options provided. The logs are then sent to the diff --git a/pkg/bindings/errors.go b/pkg/bindings/errors.go index eb95764ba..29f087c22 100644 --- a/pkg/bindings/errors.go +++ b/pkg/bindings/errors.go @@ -2,10 +2,11 @@ package bindings import ( "encoding/json" + "errors" + "fmt" "io/ioutil" "github.com/containers/podman/v4/pkg/errorhandling" - "github.com/pkg/errors" ) var ( @@ -30,7 +31,7 @@ func (h APIResponse) Process(unmarshalInto interface{}) error { func (h APIResponse) ProcessWithError(unmarshalInto interface{}, unmarshalErrorInto interface{}) error { data, err := ioutil.ReadAll(h.Response.Body) if err != nil { - return errors.Wrap(err, "unable to process API response") + return fmt.Errorf("unable to process API response: %w", err) } if h.IsSuccess() || h.IsRedirection() { if unmarshalInto != nil { diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go index f14f866dd..6883585e2 100644 --- a/pkg/bindings/images/build.go +++ b/pkg/bindings/images/build.go @@ -5,6 +5,7 @@ import ( "compress/gzip" "context" "encoding/json" + "errors" "fmt" "io" "io/fs" @@ -28,7 +29,6 @@ import ( "github.com/docker/go-units" "github.com/hashicorp/go-multierror" jsoniter "github.com/json-iterator/go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -543,14 +543,14 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO if err := dec.Decode(&s); err != nil { if errors.Is(err, io.ErrUnexpectedEOF) { - return nil, errors.Wrap(err, "server probably quit") + return nil, fmt.Errorf("server probably quit: %w", err) } // EOF means the stream is over in which case we need // to have read the id. if errors.Is(err, io.EOF) && id != "" { break } - return &entities.BuildReport{ID: id}, errors.Wrap(err, "decoding stream") + return &entities.BuildReport{ID: id}, fmt.Errorf("decoding stream: %w", err) } switch { @@ -574,11 +574,11 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO func nTar(excludes []string, sources ...string) (io.ReadCloser, error) { pm, err := fileutils.NewPatternMatcher(excludes) if err != nil { - return nil, errors.Wrapf(err, "error processing excludes list %v", excludes) + return nil, fmt.Errorf("error processing excludes list %v: %w", excludes, err) } if len(sources) == 0 { - return nil, errors.New("No source(s) provided for build") + return nil, errors.New("no source(s) provided for build") } pr, pw := io.Pipe() @@ -623,7 +623,7 @@ func nTar(excludes []string, sources ...string) (io.ReadCloser, error) { excluded, err := pm.Matches(name) //nolint:staticcheck if err != nil { - return errors.Wrapf(err, "error checking if %q is excluded", name) + return fmt.Errorf("error checking if %q is excluded: %w", name, err) } if excluded { // Note: filepath.SkipDir is not possible to use given .dockerignore semantics. @@ -726,7 +726,7 @@ func parseDockerignore(root string) ([]string, error) { var dockerIgnoreErr error ignore, dockerIgnoreErr = ioutil.ReadFile(filepath.Join(root, ".dockerignore")) if dockerIgnoreErr != nil && !os.IsNotExist(dockerIgnoreErr) { - return nil, errors.Wrapf(err, "error reading .containerignore: '%s'", root) + return nil, fmt.Errorf("error reading .containerignore: '%s': %w", root, err) } } rawexcludes := strings.Split(string(ignore), "\n") diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go index 57c8bd597..cd5147629 100644 --- a/pkg/bindings/images/images.go +++ b/pkg/bindings/images/images.go @@ -2,6 +2,7 @@ package images import ( "context" + "errors" "fmt" "io" "net/http" @@ -14,7 +15,6 @@ import ( "github.com/containers/podman/v4/pkg/bindings" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/entities/reports" - "github.com/pkg/errors" ) // Exists a lightweight way to determine if an image exists in local storage. It returns a diff --git a/pkg/bindings/images/pull.go b/pkg/bindings/images/pull.go index de02c62fd..1a4aa3038 100644 --- a/pkg/bindings/images/pull.go +++ b/pkg/bindings/images/pull.go @@ -3,6 +3,7 @@ package images import ( "context" "encoding/json" + "errors" "fmt" "io" "io/ioutil" @@ -15,7 +16,6 @@ import ( "github.com/containers/podman/v4/pkg/bindings" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/errorhandling" - "github.com/pkg/errors" ) // Pull is the binding for libpod's v2 endpoints for pulling images. Note that @@ -91,7 +91,7 @@ func Pull(ctx context.Context, rawImage string, options *PullOptions) ([]string, images = report.Images case report.ID != "": default: - return images, errors.Errorf("failed to parse pull results stream, unexpected input: %v", report) + return images, fmt.Errorf("failed to parse pull results stream, unexpected input: %v", report) } } return images, errorhandling.JoinErrors(pullErrors) diff --git a/pkg/bindings/manifests/manifests.go b/pkg/bindings/manifests/manifests.go index a68dd5a4e..80153c4b4 100644 --- a/pkg/bindings/manifests/manifests.go +++ b/pkg/bindings/manifests/manifests.go @@ -2,6 +2,8 @@ package manifests import ( "context" + "errors" + "fmt" "io/ioutil" "net/http" "strconv" @@ -15,7 +17,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/errorhandling" jsoniter "github.com/json-iterator/go" - "github.com/pkg/errors" ) // Create creates a manifest for the given name. Optional images to be associated with @@ -219,13 +220,13 @@ func Modify(ctx context.Context, name string, images []string, options *ModifyOp data, err := ioutil.ReadAll(response.Body) if err != nil { - return "", errors.Wrap(err, "unable to process API response") + return "", fmt.Errorf("unable to process API response: %w", err) } if response.IsSuccess() || response.IsRedirection() { var report entities.ManifestModifyReport if err = jsoniter.Unmarshal(data, &report); err != nil { - return "", errors.Wrap(err, "unable to decode API response") + return "", fmt.Errorf("unable to decode API response: %w", err) } err = errorhandling.JoinErrors(report.Errors) @@ -244,7 +245,7 @@ func Modify(ctx context.Context, name string, images []string, options *ModifyOp ResponseCode: response.StatusCode, } if err = jsoniter.Unmarshal(data, &errModel); err != nil { - return "", errors.Wrap(err, "unable to decode API response") + return "", fmt.Errorf("unable to decode API response: %w", err) } return "", &errModel } diff --git a/pkg/bindings/system/system.go b/pkg/bindings/system/system.go index 5ef78e444..dae80384b 100644 --- a/pkg/bindings/system/system.go +++ b/pkg/bindings/system/system.go @@ -3,6 +3,7 @@ package system import ( "context" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -11,7 +12,6 @@ import ( "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/bindings" "github.com/containers/podman/v4/pkg/domain/entities" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -37,7 +37,7 @@ func Events(ctx context.Context, eventChan chan entities.Event, cancelChan chan go func() { <-cancelChan err = response.Body.Close() - logrus.Error(errors.Wrap(err, "unable to close event response body")) + logrus.Errorf("Unable to close event response body: %v", err) }() } @@ -56,7 +56,7 @@ func Events(ctx context.Context, eventChan chan entities.Event, cancelChan chan case errors.Is(err, io.EOF): return nil default: - return errors.Wrap(err, "unable to decode event response") + return fmt.Errorf("unable to decode event response: %w", err) } } diff --git a/pkg/bindings/test/common_test.go b/pkg/bindings/test/common_test.go index 950fd21e6..6b0175f59 100644 --- a/pkg/bindings/test/common_test.go +++ b/pkg/bindings/test/common_test.go @@ -16,7 +16,6 @@ import ( "github.com/containers/podman/v4/pkg/specgen" "github.com/onsi/ginkgo" "github.com/onsi/gomega/gexec" - "github.com/pkg/errors" ) type testImage struct { @@ -127,7 +126,7 @@ func (b *bindingTest) runPodman(command []string) *gexec.Session { fmt.Printf("Running: %s %s\n", podmanBinary, strings.Join(cmd, " ")) session, err := gexec.Start(c, ginkgo.GinkgoWriter, ginkgo.GinkgoWriter) if err != nil { - panic(errors.Errorf("unable to run podman command: %q", cmd)) + panic(fmt.Errorf("unable to run podman command: %q", cmd)) } return session } diff --git a/pkg/channel/writer.go b/pkg/channel/writer.go index ecb68e906..f17486075 100644 --- a/pkg/channel/writer.go +++ b/pkg/channel/writer.go @@ -1,10 +1,9 @@ package channel import ( + "errors" "io" "sync" - - "github.com/pkg/errors" ) // WriteCloser is an io.WriteCloser that that proxies Write() calls to a channel diff --git a/pkg/checkpoint/checkpoint_restore.go b/pkg/checkpoint/checkpoint_restore.go index 396b521a1..e7c843143 100644 --- a/pkg/checkpoint/checkpoint_restore.go +++ b/pkg/checkpoint/checkpoint_restore.go @@ -2,6 +2,8 @@ package checkpoint import ( "context" + "errors" + "fmt" "io/ioutil" "os" @@ -16,7 +18,6 @@ import ( "github.com/containers/podman/v4/pkg/specgen/generate" "github.com/containers/podman/v4/pkg/specgenutil" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -65,7 +66,7 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt // This should not happen as checkpoints with these options are not exported. if len(ctrConfig.Dependencies) > 0 { - return nil, errors.Errorf("Cannot import checkpoints of containers with dependencies") + return nil, errors.New("cannot import checkpoints of containers with dependencies") } // Volumes included in the checkpoint should not exist @@ -76,7 +77,7 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt return nil, err } if exists { - return nil, errors.Errorf("volume with name %s already exists. Use --ignore-volumes to not restore content of volumes", vol.Name) + return nil, fmt.Errorf("volume with name %s already exists. Use --ignore-volumes to not restore content of volumes", vol.Name) } } } @@ -106,11 +107,11 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt if restoreOptions.Pod != "" { // Restoring into a Pod requires much newer versions of CRIU if !criu.CheckForCriu(criu.PodCriuVersion) { - return nil, errors.Errorf("restoring containers into pods requires at least CRIU %d", criu.PodCriuVersion) + return nil, fmt.Errorf("restoring containers into pods requires at least CRIU %d", criu.PodCriuVersion) } // The runtime also has to support it if !crutils.CRRuntimeSupportsPodCheckpointRestore(runtime.GetOCIRuntimePath()) { - return nil, errors.Errorf("runtime %s does not support pod restore", runtime.GetOCIRuntimePath()) + return nil, fmt.Errorf("runtime %s does not support pod restore", runtime.GetOCIRuntimePath()) } // Restoring into an existing Pod ctrConfig.Pod = restoreOptions.Pod @@ -120,12 +121,12 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt // Let's make sure we a restoring into a pod with the same shared namespaces. pod, err := runtime.LookupPod(ctrConfig.Pod) if err != nil { - return nil, errors.Wrapf(err, "pod %q cannot be retrieved", ctrConfig.Pod) + return nil, fmt.Errorf("pod %q cannot be retrieved: %w", ctrConfig.Pod, err) } infraContainer, err := pod.InfraContainer() if err != nil { - return nil, errors.Wrapf(err, "cannot retrieve infra container from pod %q", ctrConfig.Pod) + return nil, fmt.Errorf("cannot retrieve infra container from pod %q: %w", ctrConfig.Pod, err) } // If a namespaces was shared (!= "") it needs to be set to the new infrastructure container @@ -133,14 +134,14 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt // container we abort. if ctrConfig.IPCNsCtr != "" { if !pod.SharesIPC() { - return nil, errors.Errorf("pod %s does not share the IPC namespace", ctrConfig.Pod) + return nil, fmt.Errorf("pod %s does not share the IPC namespace", ctrConfig.Pod) } ctrConfig.IPCNsCtr = infraContainer.ID() } if ctrConfig.NetNsCtr != "" { if !pod.SharesNet() { - return nil, errors.Errorf("pod %s does not share the network namespace", ctrConfig.Pod) + return nil, fmt.Errorf("pod %s does not share the network namespace", ctrConfig.Pod) } ctrConfig.NetNsCtr = infraContainer.ID() for net, opts := range ctrConfig.Networks { @@ -154,21 +155,21 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt if ctrConfig.PIDNsCtr != "" { if !pod.SharesPID() { - return nil, errors.Errorf("pod %s does not share the PID namespace", ctrConfig.Pod) + return nil, fmt.Errorf("pod %s does not share the PID namespace", ctrConfig.Pod) } ctrConfig.PIDNsCtr = infraContainer.ID() } if ctrConfig.UTSNsCtr != "" { if !pod.SharesUTS() { - return nil, errors.Errorf("pod %s does not share the UTS namespace", ctrConfig.Pod) + return nil, fmt.Errorf("pod %s does not share the UTS namespace", ctrConfig.Pod) } ctrConfig.UTSNsCtr = infraContainer.ID() } if ctrConfig.CgroupNsCtr != "" { if !pod.SharesCgroup() { - return nil, errors.Errorf("pod %s does not share the cgroup namespace", ctrConfig.Pod) + return nil, fmt.Errorf("pod %s does not share the cgroup namespace", ctrConfig.Pod) } ctrConfig.CgroupNsCtr = infraContainer.ID() } @@ -180,7 +181,7 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt // Fix parent cgroup cgroupPath, err := pod.CgroupPath() if err != nil { - return nil, errors.Wrapf(err, "cannot retrieve cgroup path from pod %q", ctrConfig.Pod) + return nil, fmt.Errorf("cannot retrieve cgroup path from pod %q: %w", ctrConfig.Pod, err) } ctrConfig.CgroupParent = cgroupPath @@ -228,14 +229,14 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt containerConfig := container.Config() ctrName := ctrConfig.Name if containerConfig.Name != ctrName { - return nil, errors.Errorf("Name of restored container (%s) does not match requested name (%s)", containerConfig.Name, ctrName) + return nil, fmt.Errorf("name of restored container (%s) does not match requested name (%s)", containerConfig.Name, ctrName) } if !newName { // Only check ID for a restore with the same name. // Using -n to request a new name for the restored container, will also create a new ID if containerConfig.ID != ctrID { - return nil, errors.Errorf("ID of restored container (%s) does not match requested ID (%s)", containerConfig.ID, ctrID) + return nil, fmt.Errorf("ID of restored container (%s) does not match requested ID (%s)", containerConfig.ID, ctrID) } } diff --git a/pkg/checkpoint/crutils/checkpoint_restore_utils.go b/pkg/checkpoint/crutils/checkpoint_restore_utils.go index 76c868cee..1437a09df 100644 --- a/pkg/checkpoint/crutils/checkpoint_restore_utils.go +++ b/pkg/checkpoint/crutils/checkpoint_restore_utils.go @@ -2,6 +2,8 @@ package crutils import ( "bytes" + "errors" + "fmt" "io" "io/ioutil" "os" @@ -12,7 +14,6 @@ import ( "github.com/checkpoint-restore/go-criu/v5/stats" "github.com/containers/storage/pkg/archive" "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" ) // This file mainly exist to make the checkpoint/restore functions @@ -23,7 +24,7 @@ import ( func CRImportCheckpointWithoutConfig(destination, input string) error { archiveFile, err := os.Open(input) if err != nil { - return errors.Wrapf(err, "Failed to open checkpoint archive %s for import", input) + return fmt.Errorf("failed to open checkpoint archive %s for import: %w", input, err) } defer archiveFile.Close() @@ -35,7 +36,7 @@ func CRImportCheckpointWithoutConfig(destination, input string) error { }, } if err = archive.Untar(archiveFile, destination, options); err != nil { - return errors.Wrapf(err, "Unpacking of checkpoint archive %s failed", input) + return fmt.Errorf("unpacking of checkpoint archive %s failed: %w", input, err) } return nil @@ -47,7 +48,7 @@ func CRImportCheckpointWithoutConfig(destination, input string) error { func CRImportCheckpointConfigOnly(destination, input string) error { archiveFile, err := os.Open(input) if err != nil { - return errors.Wrapf(err, "Failed to open checkpoint archive %s for import", input) + return fmt.Errorf("failed to open checkpoint archive %s for import: %w", input, err) } defer archiveFile.Close() @@ -65,7 +66,7 @@ func CRImportCheckpointConfigOnly(destination, input string) error { }, } if err = archive.Untar(archiveFile, destination, options); err != nil { - return errors.Wrapf(err, "Unpacking of checkpoint archive %s failed", input) + return fmt.Errorf("unpacking of checkpoint archive %s failed: %w", input, err) } return nil @@ -81,14 +82,14 @@ func CRRemoveDeletedFiles(id, baseDirectory, containerRootDirectory string) erro } if err != nil { - return errors.Wrapf(err, "failed to read deleted files file") + return fmt.Errorf("failed to read deleted files file: %w", err) } for _, deleteFile := range deletedFiles { // Using RemoveAll as deletedFiles, which is generated from 'podman diff' // lists completely deleted directories as a single entry: 'D /root'. if err := os.RemoveAll(filepath.Join(containerRootDirectory, deleteFile)); err != nil { - return errors.Wrapf(err, "failed to delete files from container %s during restore", id) + return fmt.Errorf("failed to delete files from container %s during restore: %w", id, err) } } @@ -105,12 +106,12 @@ func CRApplyRootFsDiffTar(baseDirectory, containerRootDirectory string) error { if errors.Is(err, os.ErrNotExist) { return nil } - return errors.Wrap(err, "failed to open root file-system diff file") + return fmt.Errorf("failed to open root file-system diff file: %w", err) } defer rootfsDiffFile.Close() if err := archive.Untar(rootfsDiffFile, containerRootDirectory, nil); err != nil { - return errors.Wrapf(err, "failed to apply root file-system diff file %s", rootfsDiffPath) + return fmt.Errorf("failed to apply root file-system diff file %s: %w", rootfsDiffPath, err) } return nil @@ -158,11 +159,11 @@ func CRCreateRootFsDiffTar(changes *[]archive.Change, mountPoint, destination st IncludeFiles: rootfsIncludeFiles, }) if err != nil { - return includeFiles, errors.Wrapf(err, "error exporting root file-system diff to %q", rootfsDiffPath) + return includeFiles, fmt.Errorf("error exporting root file-system diff to %q: %w", rootfsDiffPath, err) } rootfsDiffFile, err := os.Create(rootfsDiffPath) if err != nil { - return includeFiles, errors.Wrapf(err, "error creating root file-system diff file %q", rootfsDiffPath) + return includeFiles, fmt.Errorf("error creating root file-system diff file %q: %w", rootfsDiffPath, err) } defer rootfsDiffFile.Close() if _, err = io.Copy(rootfsDiffFile, rootfsTar); err != nil { @@ -195,11 +196,11 @@ func CRCreateFileWithLabel(directory, fileName, fileLabel string) error { logFile, err := os.OpenFile(logFileName, os.O_CREATE, 0o600) if err != nil { - return errors.Wrapf(err, "failed to create file %q", logFileName) + return fmt.Errorf("failed to create file %q: %w", logFileName, err) } defer logFile.Close() if err = label.SetFileLabel(logFileName, fileLabel); err != nil { - return errors.Wrapf(err, "failed to label file %q", logFileName) + return fmt.Errorf("failed to label file %q: %w", logFileName, err) } return nil diff --git a/pkg/copy/fileinfo.go b/pkg/copy/fileinfo.go index 0ccca5b6e..7d4e67896 100644 --- a/pkg/copy/fileinfo.go +++ b/pkg/copy/fileinfo.go @@ -3,13 +3,14 @@ package copy import ( "encoding/base64" "encoding/json" + "errors" + "fmt" "net/http" "os" "path/filepath" "strings" "github.com/containers/podman/v4/libpod/define" - "github.com/pkg/errors" ) // XDockerContainerPathStatHeader is the *key* in http headers pointing to the @@ -18,7 +19,7 @@ const XDockerContainerPathStatHeader = "X-Docker-Container-Path-Stat" // ErrENOENT mimics the stdlib's ErrENOENT and can be used to implement custom logic // while preserving the user-visible error message. -var ErrENOENT = errors.New("No such file or directory") +var ErrENOENT = errors.New("no such file or directory") // FileInfo describes a file or directory and is returned by // (*CopyItem).Stat(). @@ -29,7 +30,7 @@ type FileInfo = define.FileInfo func EncodeFileInfo(info *FileInfo) (string, error) { buf, err := json.Marshal(&info) if err != nil { - return "", errors.Wrap(err, "failed to serialize file stats") + return "", fmt.Errorf("failed to serialize file stats: %w", err) } return base64.URLEncoding.EncodeToString(buf), nil } diff --git a/pkg/copy/parse.go b/pkg/copy/parse.go index 93edec5fa..50f1d211d 100644 --- a/pkg/copy/parse.go +++ b/pkg/copy/parse.go @@ -1,9 +1,8 @@ package copy import ( + "fmt" "strings" - - "github.com/pkg/errors" ) // ParseSourceAndDestination parses the source and destination input into a @@ -19,7 +18,7 @@ func ParseSourceAndDestination(source, destination string) (string, string, stri destContainer, destPath := parseUserInput(destination) if len(sourcePath) == 0 || len(destPath) == 0 { - return "", "", "", "", errors.Errorf("invalid arguments %q, %q: you must specify paths", source, destination) + return "", "", "", "", fmt.Errorf("invalid arguments %q, %q: you must specify paths", source, destination) } return sourceContainer, sourcePath, destContainer, destPath, nil diff --git a/pkg/domain/entities/container_ps.go b/pkg/domain/entities/container_ps.go index a5562e7c9..519d2b7da 100644 --- a/pkg/domain/entities/container_ps.go +++ b/pkg/domain/entities/container_ps.go @@ -1,13 +1,13 @@ package entities import ( + "errors" "sort" "strings" "time" "github.com/containers/common/libnetwork/types" "github.com/containers/podman/v4/pkg/ps/define" - "github.com/pkg/errors" ) // ListContainer describes a container suitable for listing @@ -166,7 +166,7 @@ func SortPsOutput(sortBy string, psOutput SortListContainers) (SortListContainer case "pod": sort.Sort(psSortedPod{psOutput}) default: - return nil, errors.Errorf("invalid option for --sort, options are: command, created, id, image, names, runningfor, size, or status") + return nil, errors.New("invalid option for --sort, options are: command, created, id, image, names, runningfor, size, or status") } return psOutput, nil } diff --git a/pkg/domain/entities/machine.go b/pkg/domain/entities/machine.go new file mode 100644 index 000000000..6ba53dbd1 --- /dev/null +++ b/pkg/domain/entities/machine.go @@ -0,0 +1,18 @@ +package entities + +type ListReporter struct { + Name string + Default bool + Created string + Running bool + Starting bool + LastUp string + Stream string + VMType string + CPUs uint64 + Memory string + DiskSize string + Port int + RemoteUsername string + IdentityPath string +} diff --git a/pkg/domain/entities/network.go b/pkg/domain/entities/network.go index d375c2e20..9e59953c6 100644 --- a/pkg/domain/entities/network.go +++ b/pkg/domain/entities/network.go @@ -81,8 +81,7 @@ type NetworkPruneReport struct { Error error } -// NetworkPruneOptions describes options for pruning -// unused cni networks +// NetworkPruneOptions describes options for pruning unused networks type NetworkPruneOptions struct { Filters map[string][]string } diff --git a/pkg/domain/entities/system.go b/pkg/domain/entities/system.go index 331d2bcdc..8dd0a61be 100644 --- a/pkg/domain/entities/system.go +++ b/pkg/domain/entities/system.go @@ -28,7 +28,7 @@ type SystemPruneReport struct { PodPruneReport []*PodPruneReport ContainerPruneReports []*reports.PruneReport ImagePruneReports []*reports.PruneReport - NetworkPruneReports []*reports.PruneReport + NetworkPruneReports []*NetworkPruneReport VolumePruneReports []*reports.PruneReport ReclaimedSpace uint64 } diff --git a/pkg/domain/filters/pods.go b/pkg/domain/filters/pods.go index c2ed359f5..78b97db64 100644 --- a/pkg/domain/filters/pods.go +++ b/pkg/domain/filters/pods.go @@ -1,6 +1,8 @@ package filters import ( + "errors" + "fmt" "strconv" "strings" @@ -8,7 +10,6 @@ import ( "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/util" - "github.com/pkg/errors" ) // GeneratePodFilterFunc takes a filter and filtervalue (key, value) @@ -59,7 +60,7 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti case "ctr-status": for _, filterValue := range filterValues { if !cutil.StringInSlice(filterValue, []string{"created", "running", "paused", "stopped", "exited", "unknown"}) { - return nil, errors.Errorf("%s is not a valid status", filterValue) + return nil, fmt.Errorf("%s is not a valid status", filterValue) } } return func(p *libpod.Pod) bool { @@ -96,7 +97,7 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti case "status": for _, filterValue := range filterValues { if !cutil.StringInSlice(filterValue, []string{"stopped", "running", "paused", "exited", "dead", "created", "degraded"}) { - return nil, errors.Errorf("%s is not a valid pod status", filterValue) + return nil, fmt.Errorf("%s is not a valid pod status", filterValue) } } return func(p *libpod.Pod) bool { @@ -158,5 +159,5 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti return false }, nil } - return nil, errors.Errorf("%s is an invalid filter", filter) + return nil, fmt.Errorf("%s is an invalid filter", filter) } diff --git a/pkg/domain/filters/volumes.go b/pkg/domain/filters/volumes.go index a18e6332c..7c5047225 100644 --- a/pkg/domain/filters/volumes.go +++ b/pkg/domain/filters/volumes.go @@ -1,13 +1,13 @@ package filters import ( + "fmt" "net/url" "regexp" "strings" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/pkg/util" - "github.com/pkg/errors" ) func GenerateVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, error) { @@ -72,7 +72,7 @@ func GenerateVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, error) { // invert the result of IsDangling. invert = true default: - return nil, errors.Errorf("%q is not a valid value for the \"dangling\" filter - must be true or false", danglingVal) + return nil, fmt.Errorf("%q is not a valid value for the \"dangling\" filter - must be true or false", danglingVal) } vf = append(vf, func(v *libpod.Volume) bool { dangling, err := v.IsDangling() @@ -85,7 +85,7 @@ func GenerateVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, error) { return dangling }) default: - return nil, errors.Errorf("%q is an invalid volume filter", filter) + return nil, fmt.Errorf("%q is an invalid volume filter", filter) } } } @@ -109,7 +109,7 @@ func GeneratePruneVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, erro } vf = append(vf, f) default: - return nil, errors.Errorf("%q is an invalid volume filter", filter) + return nil, fmt.Errorf("%q is an invalid volume filter", filter) } } } diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 1688be57e..23a591604 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -101,6 +101,9 @@ func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []strin responses := make([]entities.WaitReport, 0, len(ctrs)) for _, c := range ctrs { response := entities.WaitReport{Id: c.ID()} + if options.Condition == nil { + options.Condition = []define.ContainerStatus{define.ContainerStateStopped, define.ContainerStateExited} + } exitCode, err := c.WaitForConditionWithInterval(ctx, options.Interval, options.Condition...) if err != nil { response.Error = err diff --git a/pkg/domain/infra/abi/generate.go b/pkg/domain/infra/abi/generate.go index 8b2193cb2..31885ce54 100644 --- a/pkg/domain/infra/abi/generate.go +++ b/pkg/domain/infra/abi/generate.go @@ -12,7 +12,6 @@ import ( k8sAPI "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1" "github.com/containers/podman/v4/pkg/systemd/generate" "github.com/ghodss/yaml" - "github.com/pkg/errors" ) func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string, options entities.GenerateSystemdOptions) (*entities.GenerateSystemdReport, error) { @@ -30,8 +29,8 @@ func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string, // If it's not a container, we either have a pod or garbage. pod, err := ic.Libpod.LookupPod(nameOrID) if err != nil { - err = errors.Wrap(ctrErr, err.Error()) - return nil, errors.Wrapf(err, "%s does not refer to a container or pod", nameOrID) + err = fmt.Errorf("%v: %w", err.Error(), ctrErr) + return nil, fmt.Errorf("%s does not refer to a container or pod: %w", nameOrID, err) } // Generate the units for the pod and all its containers. @@ -64,7 +63,7 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string, // now that infra holds NS data, we need to support dependencies. // we cannot deal with ctrs already in a pod. if len(ctr.PodID()) > 0 { - return nil, errors.Errorf("container %s is associated with pod %s: use generate on the pod itself", ctr.ID(), ctr.PodID()) + return nil, fmt.Errorf("container %s is associated with pod %s: use generate on the pod itself", ctr.ID(), ctr.PodID()) } ctrs = append(ctrs, ctr) continue @@ -104,7 +103,7 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string, } // If it reaches here is because the name or id did not exist. - return nil, errors.Errorf("Name or ID %q not found", nameOrID) + return nil, fmt.Errorf("name or ID %q not found", nameOrID) } if !defaultKubeNS { diff --git a/pkg/domain/infra/abi/images_list.go b/pkg/domain/infra/abi/images_list.go index 8f5591e92..96e99fbf0 100644 --- a/pkg/domain/infra/abi/images_list.go +++ b/pkg/domain/infra/abi/images_list.go @@ -2,10 +2,10 @@ package abi import ( "context" + "fmt" "github.com/containers/common/libimage" "github.com/containers/podman/v4/pkg/domain/entities" - "github.com/pkg/errors" ) func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) ([]*entities.ImageSummary, error) { @@ -28,11 +28,11 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) for _, img := range images { repoDigests, err := img.RepoDigests() if err != nil { - return nil, errors.Wrapf(err, "getting repoDigests from image %q", img.ID()) + return nil, fmt.Errorf("getting repoDigests from image %q: %w", img.ID(), err) } isDangling, err := img.IsDangling(ctx) if err != nil { - return nil, errors.Wrapf(err, "error checking if image %q is dangling", img.ID()) + return nil, fmt.Errorf("error checking if image %q is dangling: %w", img.ID(), err) } e := entities.ImageSummary{ @@ -49,18 +49,18 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) } e.Labels, err = img.Labels(ctx) if err != nil { - return nil, errors.Wrapf(err, "error retrieving label for image %q: you may need to remove the image to resolve the error", img.ID()) + return nil, fmt.Errorf("error retrieving label for image %q: you may need to remove the image to resolve the error: %w", img.ID(), err) } ctnrs, err := img.Containers() if err != nil { - return nil, errors.Wrapf(err, "error retrieving containers for image %q: you may need to remove the image to resolve the error", img.ID()) + return nil, fmt.Errorf("error retrieving containers for image %q: you may need to remove the image to resolve the error: %w", img.ID(), err) } e.Containers = len(ctnrs) sz, err := img.Size() if err != nil { - return nil, errors.Wrapf(err, "error retrieving size of image %q: you may need to remove the image to resolve the error", img.ID()) + return nil, fmt.Errorf("error retrieving size of image %q: you may need to remove the image to resolve the error: %w", img.ID(), err) } e.Size = sz // This is good enough for now, but has to be @@ -69,7 +69,7 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) parent, err := img.Parent(ctx) if err != nil { - return nil, errors.Wrapf(err, "error retrieving parent of image %q: you may need to remove the image to resolve the error", img.ID()) + return nil, fmt.Errorf("error retrieving parent of image %q: you may need to remove the image to resolve the error: %w", img.ID(), err) } if parent != nil { e.ParentId = parent.ID() diff --git a/pkg/domain/infra/abi/parse/parse.go b/pkg/domain/infra/abi/parse/parse.go index 4e8c2e508..19699589b 100644 --- a/pkg/domain/infra/abi/parse/parse.go +++ b/pkg/domain/infra/abi/parse/parse.go @@ -1,13 +1,13 @@ package parse import ( + "fmt" "strconv" "strings" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" units "github.com/docker/go-units" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -32,7 +32,7 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) case "size": size, err := units.FromHumanSize(splitO[1]) if err != nil { - return nil, errors.Wrapf(err, "cannot convert size %s to integer", splitO[1]) + return nil, fmt.Errorf("cannot convert size %s to integer: %w", splitO[1], err) } libpodOptions = append(libpodOptions, libpod.WithVolumeSize(uint64(size))) finalVal = append(finalVal, o) @@ -41,7 +41,7 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) case "inodes": inodes, err := strconv.ParseUint(splitO[1], 10, 64) if err != nil { - return nil, errors.Wrapf(err, "cannot convert inodes %s to integer", splitO[1]) + return nil, fmt.Errorf("cannot convert inodes %s to integer: %w", splitO[1], err) } libpodOptions = append(libpodOptions, libpod.WithVolumeInodes(inodes)) finalVal = append(finalVal, o) @@ -49,11 +49,11 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) volumeOptions["INODES"] = splitO[1] case "uid": if len(splitO) != 2 { - return nil, errors.Wrapf(define.ErrInvalidArg, "uid option must provide a UID") + return nil, fmt.Errorf("uid option must provide a UID: %w", define.ErrInvalidArg) } intUID, err := strconv.Atoi(splitO[1]) if err != nil { - return nil, errors.Wrapf(err, "cannot convert UID %s to integer", splitO[1]) + return nil, fmt.Errorf("cannot convert UID %s to integer: %w", splitO[1], err) } logrus.Debugf("Removing uid= from options and adding WithVolumeUID for UID %d", intUID) libpodOptions = append(libpodOptions, libpod.WithVolumeUID(intUID), libpod.WithVolumeNoChown()) @@ -62,11 +62,11 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) volumeOptions["UID"] = splitO[1] case "gid": if len(splitO) != 2 { - return nil, errors.Wrapf(define.ErrInvalidArg, "gid option must provide a GID") + return nil, fmt.Errorf("gid option must provide a GID: %w", define.ErrInvalidArg) } intGID, err := strconv.Atoi(splitO[1]) if err != nil { - return nil, errors.Wrapf(err, "cannot convert GID %s to integer", splitO[1]) + return nil, fmt.Errorf("cannot convert GID %s to integer: %w", splitO[1], err) } logrus.Debugf("Removing gid= from options and adding WithVolumeGID for GID %d", intGID) libpodOptions = append(libpodOptions, libpod.WithVolumeGID(intGID), libpod.WithVolumeNoChown()) @@ -80,11 +80,11 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) volumeOptions["NOQUOTA"] = "true" case "timeout": if len(splitO) != 2 { - return nil, errors.Wrapf(define.ErrInvalidArg, "timeout option must provide a valid timeout in seconds") + return nil, fmt.Errorf("timeout option must provide a valid timeout in seconds: %w", define.ErrInvalidArg) } intTimeout, err := strconv.Atoi(splitO[1]) if err != nil { - return nil, errors.Wrapf(err, "cannot convert Timeout %s to an integer", splitO[1]) + return nil, fmt.Errorf("cannot convert Timeout %s to an integer: %w", splitO[1], err) } logrus.Debugf("Removing timeout from options and adding WithTimeout for Timeout %d", intTimeout) libpodOptions = append(libpodOptions, libpod.WithVolumeDriverTimeout(intTimeout)) diff --git a/pkg/domain/infra/abi/pods_stats.go b/pkg/domain/infra/abi/pods_stats.go index 6123027b8..a270db769 100644 --- a/pkg/domain/infra/abi/pods_stats.go +++ b/pkg/domain/infra/abi/pods_stats.go @@ -2,6 +2,7 @@ package abi import ( "context" + "errors" "fmt" "github.com/containers/common/pkg/cgroups" @@ -10,7 +11,6 @@ import ( "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/podman/v4/utils" "github.com/docker/go-units" - "github.com/pkg/errors" ) // PodStats implements printing stats about pods. @@ -28,7 +28,7 @@ func (ic *ContainerEngine) PodStats(ctx context.Context, namesOrIds []string, op // Get the (running) pods and convert them to the entities format. pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod) if err != nil { - return nil, errors.Wrap(err, "unable to get list of pods") + return nil, fmt.Errorf("unable to get list of pods: %w", err) } return ic.podsToStatsReport(pods) } diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go index 96690afef..0faae01c8 100644 --- a/pkg/domain/infra/abi/system.go +++ b/pkg/domain/infra/abi/system.go @@ -157,15 +157,15 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys // TODO: Figure out cleaner way to handle all of the different PruneOptions // Remove all unused pods. - podPruneReport, err := ic.prunePodHelper(ctx) + podPruneReports, err := ic.prunePodHelper(ctx) if err != nil { return nil, err } - if len(podPruneReport) > 0 { + if len(podPruneReports) > 0 { found = true } - systemPruneReport.PodPruneReport = append(systemPruneReport.PodPruneReport, podPruneReport...) + systemPruneReport.PodPruneReport = append(systemPruneReport.PodPruneReport, podPruneReports...) // Remove all unused containers. containerPruneOptions := entities.ContainerPruneOptions{} @@ -201,38 +201,35 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys networkPruneOptions := entities.NetworkPruneOptions{} networkPruneOptions.Filters = options.Filters - networkPruneReport, err := ic.NetworkPrune(ctx, networkPruneOptions) + networkPruneReports, err := ic.NetworkPrune(ctx, networkPruneOptions) if err != nil { return nil, err } - if len(networkPruneReport) > 0 { + if len(networkPruneReports) > 0 { found = true } - for _, net := range networkPruneReport { - systemPruneReport.NetworkPruneReports = append(systemPruneReport.NetworkPruneReports, &reports.PruneReport{ - Id: net.Name, - Err: net.Error, - Size: 0, - }) - } + + // Networks reclaimedSpace are always '0'. + systemPruneReport.NetworkPruneReports = append(systemPruneReport.NetworkPruneReports, networkPruneReports...) // Remove unused volume data. if options.Volume { volumePruneOptions := entities.VolumePruneOptions{} volumePruneOptions.Filters = (url.Values)(options.Filters) - volumePruneReport, err := ic.VolumePrune(ctx, volumePruneOptions) + volumePruneReports, err := ic.VolumePrune(ctx, volumePruneOptions) if err != nil { return nil, err } - if len(volumePruneReport) > 0 { + if len(volumePruneReports) > 0 { found = true } - reclaimedSpace += reports.PruneReportsSize(volumePruneReport) - systemPruneReport.VolumePruneReports = append(systemPruneReport.VolumePruneReports, volumePruneReport...) + reclaimedSpace += reports.PruneReportsSize(volumePruneReports) + systemPruneReport.VolumePruneReports = append(systemPruneReport.VolumePruneReports, volumePruneReports...) } } + systemPruneReport.ReclaimedSpace = reclaimedSpace return systemPruneReport, nil } diff --git a/pkg/domain/infra/abi/terminal/terminal.go b/pkg/domain/infra/abi/terminal/terminal.go index 692f8dcd5..37dadd92a 100644 --- a/pkg/domain/infra/abi/terminal/terminal.go +++ b/pkg/domain/infra/abi/terminal/terminal.go @@ -2,13 +2,13 @@ package terminal import ( "context" + "fmt" "os" "os/signal" - "github.com/containers/podman/v4/libpod/define" + "github.com/containers/common/pkg/resize" lsignal "github.com/containers/podman/v4/pkg/signal" "github.com/moby/term" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -18,20 +18,20 @@ type RawTtyFormatter struct { // getResize returns a TerminalSize command matching stdin's current // size on success, and nil on errors. -func getResize() *define.TerminalSize { +func getResize() *resize.TerminalSize { winsize, err := term.GetWinsize(os.Stdin.Fd()) if err != nil { logrus.Warnf("Could not get terminal size %v", err) return nil } - return &define.TerminalSize{ + return &resize.TerminalSize{ Width: winsize.Width, Height: winsize.Height, } } // Helper for prepareAttach - set up a goroutine to generate terminal resize events -func resizeTty(ctx context.Context, resize chan define.TerminalSize) { +func resizeTty(ctx context.Context, resize chan resize.TerminalSize) { sigchan := make(chan os.Signal, 1) signal.Notify(sigchan, lsignal.SIGWINCH) go func() { @@ -78,7 +78,7 @@ func (f *RawTtyFormatter) Format(entry *logrus.Entry) ([]byte, error) { return bytes, err } -func handleTerminalAttach(ctx context.Context, resize chan define.TerminalSize) (context.CancelFunc, *term.State, error) { +func handleTerminalAttach(ctx context.Context, resize chan resize.TerminalSize) (context.CancelFunc, *term.State, error) { logrus.Debugf("Handling terminal attach") subCtx, cancel := context.WithCancel(ctx) @@ -89,7 +89,7 @@ func handleTerminalAttach(ctx context.Context, resize chan define.TerminalSize) if err != nil { // allow caller to not have to do any cleaning up if we error here cancel() - return nil, nil, errors.Wrapf(err, "unable to save terminal state") + return nil, nil, fmt.Errorf("unable to save terminal state: %w", err) } logrus.SetFormatter(&RawTtyFormatter{}) diff --git a/pkg/domain/infra/abi/terminal/terminal_linux.go b/pkg/domain/infra/abi/terminal/terminal_linux.go index 62d36f28d..222590871 100644 --- a/pkg/domain/infra/abi/terminal/terminal_linux.go +++ b/pkg/domain/infra/abi/terminal/terminal_linux.go @@ -6,23 +6,23 @@ import ( "fmt" "os" + "github.com/containers/common/pkg/resize" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/term" ) // ExecAttachCtr execs and attaches to a container func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpod.ExecConfig, streams *define.AttachStreams) (int, error) { - var resize chan define.TerminalSize + var resizechan chan resize.TerminalSize haveTerminal := term.IsTerminal(int(os.Stdin.Fd())) // Check if we are attached to a terminal. If we are, generate resize // events, and set the terminal to raw mode if haveTerminal && execConfig.Terminal { - resize = make(chan define.TerminalSize) - cancel, oldTermState, err := handleTerminalAttach(ctx, resize) + resizechan = make(chan resize.TerminalSize) + cancel, oldTermState, err := handleTerminalAttach(ctx, resizechan) if err != nil { return -1, err } @@ -33,14 +33,14 @@ func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpo } }() } - return ctr.Exec(execConfig, streams, resize) + return ctr.Exec(execConfig, streams, resizechan) } // StartAttachCtr starts and (if required) attaches to a container // if you change the signature of this function from os.File to io.Writer, it will trigger a downstream // error. we may need to just lint disable this one. func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool) error { //nolint: interfacer - resize := make(chan define.TerminalSize) + resize := make(chan resize.TerminalSize) haveTerminal := term.IsTerminal(int(os.Stdin.Fd())) @@ -103,7 +103,7 @@ func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, err = <-attachChan if err != nil { - return errors.Wrapf(err, "error attaching to container %s", ctr.ID()) + return fmt.Errorf("error attaching to container %s: %w", ctr.ID(), err) } return nil diff --git a/pkg/domain/infra/abi/trust.go b/pkg/domain/infra/abi/trust.go index 58f099bb6..0e3d8fad9 100644 --- a/pkg/domain/infra/abi/trust.go +++ b/pkg/domain/infra/abi/trust.go @@ -3,13 +3,14 @@ package abi import ( "context" "encoding/json" + "errors" + "fmt" "io/ioutil" "os" "strings" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/trust" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -35,11 +36,11 @@ func (ir *ImageEngine) ShowTrust(ctx context.Context, args []string, options ent } policyContentStruct, err := trust.GetPolicy(policyPath) if err != nil { - return nil, errors.Wrapf(err, "could not read trust policies") + return nil, fmt.Errorf("could not read trust policies: %w", err) } report.Policies, err = getPolicyShowOutput(policyContentStruct, report.SystemRegistriesDirPath) if err != nil { - return nil, errors.Wrapf(err, "could not show trust policies") + return nil, fmt.Errorf("could not show trust policies: %w", err) } return &report, nil } @@ -56,7 +57,7 @@ func (ir *ImageEngine) SetTrust(ctx context.Context, args []string, options enti pubkeysfile := options.PubKeysFile if len(pubkeysfile) == 0 && trustType == "signedBy" { - return errors.Errorf("At least one public key must be defined for type 'signedBy'") + return errors.New("at least one public key must be defined for type 'signedBy'") } policyPath := trust.DefaultPolicyPath(ir.Libpod.SystemContext()) @@ -70,7 +71,7 @@ func (ir *ImageEngine) SetTrust(ctx context.Context, args []string, options enti return err } if err := json.Unmarshal(policyContent, &policyContentStruct); err != nil { - return errors.Errorf("could not read trust policies") + return errors.New("could not read trust policies") } } if len(pubkeysfile) != 0 { @@ -84,7 +85,7 @@ func (ir *ImageEngine) SetTrust(ctx context.Context, args []string, options enti policyContentStruct.Default = newReposContent } else { if len(policyContentStruct.Default) == 0 { - return errors.Errorf("default trust policy must be set") + return errors.New("default trust policy must be set") } registryExists := false for transport, transportval := range policyContentStruct.Transports { @@ -107,7 +108,7 @@ func (ir *ImageEngine) SetTrust(ctx context.Context, args []string, options enti data, err := json.MarshalIndent(policyContentStruct, "", " ") if err != nil { - return errors.Wrapf(err, "error setting trust policy") + return fmt.Errorf("error setting trust policy: %w", err) } return ioutil.WriteFile(policyPath, data, 0644) } diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go index 162025969..f76fab4ea 100644 --- a/pkg/domain/infra/runtime_libpod.go +++ b/pkg/domain/infra/runtime_libpod.go @@ -5,6 +5,7 @@ package infra import ( "context" + "errors" "fmt" "os" "os/signal" @@ -18,7 +19,6 @@ import ( "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/storage/pkg/idtools" "github.com/containers/storage/types" - "github.com/pkg/errors" "github.com/sirupsen/logrus" flag "github.com/spf13/pflag" ) @@ -316,7 +316,7 @@ func ParseIDMapping(mode namespaces.UsernsMode, uidMapSlice, gidMapSlice []strin uids, gids, err := rootless.GetConfiguredMappings() if err != nil { - return nil, errors.Wrapf(err, "cannot read mappings") + return nil, fmt.Errorf("cannot read mappings: %w", err) } maxUID, maxGID := 0, 0 for _, u := range uids { diff --git a/pkg/domain/infra/tunnel/auto-update.go b/pkg/domain/infra/tunnel/auto-update.go index ba41f0378..469da5a7a 100644 --- a/pkg/domain/infra/tunnel/auto-update.go +++ b/pkg/domain/infra/tunnel/auto-update.go @@ -2,9 +2,9 @@ package tunnel import ( "context" + "errors" "github.com/containers/podman/v4/pkg/domain/entities" - "github.com/pkg/errors" ) func (ic *ContainerEngine) AutoUpdate(ctx context.Context, options entities.AutoUpdateOptions) ([]*entities.AutoUpdateReport, []error) { diff --git a/pkg/domain/infra/tunnel/events.go b/pkg/domain/infra/tunnel/events.go index b472ad03a..30be92e23 100644 --- a/pkg/domain/infra/tunnel/events.go +++ b/pkg/domain/infra/tunnel/events.go @@ -2,13 +2,12 @@ package tunnel import ( "context" + "fmt" "strings" "github.com/containers/podman/v4/libpod/events" "github.com/containers/podman/v4/pkg/bindings/system" "github.com/containers/podman/v4/pkg/domain/entities" - - "github.com/pkg/errors" ) func (ic *ContainerEngine) Events(ctx context.Context, opts entities.EventsOptions) error { @@ -17,7 +16,7 @@ func (ic *ContainerEngine) Events(ctx context.Context, opts entities.EventsOptio for _, filter := range opts.Filter { split := strings.Split(filter, "=") if len(split) < 2 { - return errors.Errorf("invalid filter %q", filter) + return fmt.Errorf("invalid filter %q", filter) } filters[split[0]] = append(filters[split[0]], strings.Join(split[1:], "=")) } @@ -56,7 +55,7 @@ func (ic *ContainerEngine) GetLastContainerEvent(ctx context.Context, nameOrID s return nil, err } if len(containerEvents) < 1 { - return nil, errors.Wrapf(events.ErrEventNotFound, "%s not found", containerEvent.String()) + return nil, fmt.Errorf("%s not found: %w", containerEvent.String(), events.ErrEventNotFound) } // return the last element in the slice return containerEvents[len(containerEvents)-1], nil diff --git a/pkg/domain/infra/tunnel/helpers.go b/pkg/domain/infra/tunnel/helpers.go index 6c043465c..24b2b619d 100644 --- a/pkg/domain/infra/tunnel/helpers.go +++ b/pkg/domain/infra/tunnel/helpers.go @@ -2,13 +2,14 @@ package tunnel import ( "context" + "errors" + "fmt" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/bindings/containers" "github.com/containers/podman/v4/pkg/bindings/pods" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/errorhandling" - "github.com/pkg/errors" ) // FIXME: the `ignore` parameter is very likely wrong here as it should rather @@ -69,7 +70,7 @@ func getContainersAndInputByContext(contextWithConnection context.Context, all, } if !found && !ignore { - return nil, nil, errors.Wrapf(define.ErrNoSuchCtr, "unable to find container %q", nameOrID) + return nil, nil, fmt.Errorf("unable to find container %q: %w", nameOrID, define.ErrNoSuchCtr) } } return filtered, rawInputs, nil @@ -102,7 +103,7 @@ func getPodsByContext(contextWithConnection context.Context, all bool, namesOrID inspectData, err := pods.Inspect(contextWithConnection, nameOrID, nil) if err != nil { if errorhandling.Contains(err, define.ErrNoSuchPod) { - return nil, errors.Wrapf(define.ErrNoSuchPod, "unable to find pod %q", nameOrID) + return nil, fmt.Errorf("unable to find pod %q: %w", nameOrID, define.ErrNoSuchPod) } return nil, err } @@ -120,7 +121,7 @@ func getPodsByContext(contextWithConnection context.Context, all bool, namesOrID } if !found { - return nil, errors.Wrapf(define.ErrNoSuchPod, "unable to find pod %q", nameOrID) + return nil, fmt.Errorf("unable to find pod %q: %w", nameOrID, define.ErrNoSuchPod) } } return filtered, nil diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go index 09f8ac4c3..18f750dcc 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -2,6 +2,7 @@ package tunnel import ( "context" + "errors" "fmt" "io/ioutil" "os" @@ -19,7 +20,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/utils" "github.com/containers/podman/v4/pkg/errorhandling" utils2 "github.com/containers/podman/v4/utils" - "github.com/pkg/errors" ) func (ir *ImageEngine) Exists(_ context.Context, nameOrID string) (*entities.BoolReport, error) { @@ -131,7 +131,7 @@ func (ir *ImageEngine) Tag(ctx context.Context, nameOrID string, tags []string, ) ref, err := reference.Parse(newTag) if err != nil { - return errors.Wrapf(err, "error parsing reference %q", newTag) + return fmt.Errorf("error parsing reference %q: %w", newTag, err) } if t, ok := ref.(reference.Tagged); ok { tag = t.Tag() @@ -140,7 +140,7 @@ func (ir *ImageEngine) Tag(ctx context.Context, nameOrID string, tags []string, repo = r.Name() } if len(repo) < 1 { - return errors.Errorf("invalid image name %q", nameOrID) + return fmt.Errorf("invalid image name %q", nameOrID) } if err := images.Tag(ir.ClientCtx, nameOrID, tag, repo, options); err != nil { return err @@ -161,7 +161,7 @@ func (ir *ImageEngine) Untag(ctx context.Context, nameOrID string, tags []string ) ref, err := reference.Parse(newTag) if err != nil { - return errors.Wrapf(err, "error parsing reference %q", newTag) + return fmt.Errorf("error parsing reference %q: %w", newTag, err) } if t, ok := ref.(reference.Tagged); ok { tag = t.Tag() @@ -173,7 +173,7 @@ func (ir *ImageEngine) Untag(ctx context.Context, nameOrID string, tags []string repo = r.Name() } if len(repo) < 1 { - return errors.Errorf("invalid image name %q", nameOrID) + return fmt.Errorf("invalid image name %q", nameOrID) } if err := images.Untag(ir.ClientCtx, nameOrID, tag, repo, options); err != nil { return err @@ -194,7 +194,7 @@ func (ir *ImageEngine) Inspect(ctx context.Context, namesOrIDs []string, opts en return nil, nil, err } if errModel.ResponseCode == 404 { - errs = append(errs, errors.Wrapf(err, "unable to inspect %q", i)) + errs = append(errs, fmt.Errorf("unable to inspect %q: %w", i, err)) continue } return nil, nil, err @@ -215,7 +215,7 @@ func (ir *ImageEngine) Load(ctx context.Context, opts entities.ImageLoadOptions) return nil, err } if fInfo.IsDir() { - return nil, errors.Errorf("remote client supports archives only but %q is a directory", opts.Input) + return nil, fmt.Errorf("remote client supports archives only but %q is a directory", opts.Input) } return images.Load(ir.ClientCtx, f) } @@ -296,7 +296,7 @@ func (ir *ImageEngine) Save(ctx context.Context, nameOrID string, tags []string, switch { case err == nil: if info.Mode().IsRegular() { - return errors.Errorf("%q already exists as a regular file", opts.Output) + return fmt.Errorf("%q already exists as a regular file", opts.Output) } case os.IsNotExist(err): if err := os.Mkdir(opts.Output, 0755); err != nil { diff --git a/pkg/domain/infra/tunnel/manifest.go b/pkg/domain/infra/tunnel/manifest.go index 09c37b896..d2554f198 100644 --- a/pkg/domain/infra/tunnel/manifest.go +++ b/pkg/domain/infra/tunnel/manifest.go @@ -3,6 +3,7 @@ package tunnel import ( "context" "encoding/json" + "errors" "fmt" "strings" @@ -10,7 +11,6 @@ import ( "github.com/containers/podman/v4/pkg/bindings/images" "github.com/containers/podman/v4/pkg/bindings/manifests" "github.com/containers/podman/v4/pkg/domain/entities" - "github.com/pkg/errors" ) // ManifestCreate implements manifest create via ImageEngine @@ -18,7 +18,7 @@ func (ir *ImageEngine) ManifestCreate(ctx context.Context, name string, images [ options := new(manifests.CreateOptions).WithAll(opts.All) imageID, err := manifests.Create(ir.ClientCtx, name, images, options) if err != nil { - return imageID, errors.Wrapf(err, "error creating manifest") + return imageID, fmt.Errorf("error creating manifest: %w", err) } return imageID, err } @@ -36,12 +36,12 @@ func (ir *ImageEngine) ManifestExists(ctx context.Context, name string) (*entiti func (ir *ImageEngine) ManifestInspect(_ context.Context, name string) ([]byte, error) { list, err := manifests.Inspect(ir.ClientCtx, name, nil) if err != nil { - return nil, errors.Wrapf(err, "error getting content of manifest list or image %s", name) + return nil, fmt.Errorf("error getting content of manifest list or image %s: %w", name, err) } buf, err := json.MarshalIndent(list, "", " ") if err != nil { - return buf, errors.Wrapf(err, "error rendering manifest for display") + return buf, fmt.Errorf("error rendering manifest for display: %w", err) } return buf, err } @@ -56,7 +56,7 @@ func (ir *ImageEngine) ManifestAdd(_ context.Context, name string, imageNames [] for _, annotationSpec := range opts.Annotation { spec := strings.SplitN(annotationSpec, "=", 2) if len(spec) != 2 { - return "", errors.Errorf("no value given for annotation %q", spec[0]) + return "", fmt.Errorf("no value given for annotation %q", spec[0]) } annotations[spec[0]] = spec[1] } @@ -72,7 +72,7 @@ func (ir *ImageEngine) ManifestAdd(_ context.Context, name string, imageNames [] id, err := manifests.Add(ir.ClientCtx, name, options) if err != nil { - return id, errors.Wrapf(err, "error adding to manifest list %s", name) + return id, fmt.Errorf("error adding to manifest list %s: %w", name, err) } return id, nil } @@ -86,7 +86,7 @@ func (ir *ImageEngine) ManifestAnnotate(ctx context.Context, name, images string func (ir *ImageEngine) ManifestRemoveDigest(ctx context.Context, name string, image string) (string, error) { updatedListID, err := manifests.Remove(ir.ClientCtx, name, image, nil) if err != nil { - return updatedListID, errors.Wrapf(err, "error removing from manifest %s", name) + return updatedListID, fmt.Errorf("error removing from manifest %s: %w", name, err) } return fmt.Sprintf("%s :%s\n", updatedListID, image), nil } diff --git a/pkg/domain/infra/tunnel/network.go b/pkg/domain/infra/tunnel/network.go index 415999a96..6e27b8e56 100644 --- a/pkg/domain/infra/tunnel/network.go +++ b/pkg/domain/infra/tunnel/network.go @@ -2,13 +2,14 @@ package tunnel import ( "context" + "errors" + "fmt" "github.com/containers/common/libnetwork/types" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/bindings/network" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/errorhandling" - "github.com/pkg/errors" ) func (ic *ContainerEngine) NetworkList(ctx context.Context, opts entities.NetworkListOptions) ([]types.Network, error) { @@ -30,7 +31,7 @@ func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []stri return nil, nil, err } if errModel.ResponseCode == 404 { - errs = append(errs, errors.Wrapf(define.ErrNoSuchNetwork, "network %s", name)) + errs = append(errs, fmt.Errorf("network %s: %w", name, define.ErrNoSuchNetwork)) continue } return nil, nil, err @@ -95,7 +96,7 @@ func (ic *ContainerEngine) NetworkExists(ctx context.Context, networkname string }, nil } -// Network prune removes unused cni networks +// Network prune removes unused networks func (ic *ContainerEngine) NetworkPrune(ctx context.Context, options entities.NetworkPruneOptions) ([]*entities.NetworkPruneReport, error) { opts := new(network.PruneOptions).WithFilters(options.Filters) return network.Prune(ic.ClientCtx, opts) diff --git a/pkg/domain/infra/tunnel/secrets.go b/pkg/domain/infra/tunnel/secrets.go index 2412ed0a2..d26718b12 100644 --- a/pkg/domain/infra/tunnel/secrets.go +++ b/pkg/domain/infra/tunnel/secrets.go @@ -2,12 +2,12 @@ package tunnel import ( "context" + "fmt" "io" "github.com/containers/podman/v4/pkg/bindings/secrets" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/errorhandling" - "github.com/pkg/errors" ) func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader io.Reader, options entities.SecretCreateOptions) (*entities.SecretCreateReport, error) { @@ -33,7 +33,7 @@ func (ic *ContainerEngine) SecretInspect(ctx context.Context, nameOrIDs []string return nil, nil, err } if errModel.ResponseCode == 404 { - errs = append(errs, errors.Errorf("no such secret %q", name)) + errs = append(errs, fmt.Errorf("no such secret %q", name)) continue } return nil, nil, err @@ -73,7 +73,7 @@ func (ic *ContainerEngine) SecretRm(ctx context.Context, nameOrIDs []string, opt } if errModel.ResponseCode == 404 { allRm = append(allRm, &entities.SecretRmReport{ - Err: errors.Errorf("no secret with name or id %q: no such secret ", name), + Err: fmt.Errorf("no secret with name or id %q: no such secret ", name), ID: "", }) continue diff --git a/pkg/domain/infra/tunnel/volumes.go b/pkg/domain/infra/tunnel/volumes.go index 6ec35e836..b70d29783 100644 --- a/pkg/domain/infra/tunnel/volumes.go +++ b/pkg/domain/infra/tunnel/volumes.go @@ -2,12 +2,13 @@ package tunnel import ( "context" + "errors" + "fmt" "github.com/containers/podman/v4/pkg/bindings/volumes" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/entities/reports" "github.com/containers/podman/v4/pkg/errorhandling" - "github.com/pkg/errors" ) func (ic *ContainerEngine) VolumeCreate(ctx context.Context, opts entities.VolumeCreateOptions) (*entities.IDOrNameResponse, error) { @@ -64,7 +65,7 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin return nil, nil, err } if errModel.ResponseCode == 404 { - errs = append(errs, errors.Errorf("no such volume %q", id)) + errs = append(errs, fmt.Errorf("no such volume %q", id)) continue } return nil, nil, err diff --git a/pkg/domain/utils/scp.go b/pkg/domain/utils/scp.go index a4ff6b950..3c73cddd1 100644 --- a/pkg/domain/utils/scp.go +++ b/pkg/domain/utils/scp.go @@ -20,7 +20,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/terminal" "github.com/docker/distribution/reference" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/agent" @@ -44,7 +43,7 @@ func ExecuteTransfer(src, dst string, parentFlags []string, quiet bool) (*entiti confR, err := config.NewConfig("") // create a hand made config for the remote engine since we might use remote and native at once if err != nil { - return nil, nil, nil, nil, errors.Wrapf(err, "could not make config") + return nil, nil, nil, nil, fmt.Errorf("could not make config: %w", err) } cfg, err := config.ReadCustomConfig() // get ready to set ssh destination if necessary @@ -75,9 +74,9 @@ func ExecuteTransfer(src, dst string, parentFlags []string, quiet bool) (*entiti case len(locations) == 1: switch { case len(locations[0].Image) == 0: - return nil, nil, nil, nil, errors.Wrapf(define.ErrInvalidArg, "no source image specified") + return nil, nil, nil, nil, fmt.Errorf("no source image specified: %w", define.ErrInvalidArg) case len(locations[0].Image) > 0 && !locations[0].Remote && len(locations[0].User) == 0: // if we have podman image scp $IMAGE - return nil, nil, nil, nil, errors.Wrapf(define.ErrInvalidArg, "must specify a destination") + return nil, nil, nil, nil, fmt.Errorf("must specify a destination: %w", define.ErrInvalidArg) } } @@ -158,7 +157,7 @@ func ExecuteTransfer(src, dst string, parentFlags []string, quiet bool) (*entiti if source.User == "" { u, err := user.Current() if err != nil { - return nil, nil, nil, nil, errors.Wrapf(err, "could not obtain user, make sure the environmental variable $USER is set") + return nil, nil, nil, nil, fmt.Errorf("could not obtain user, make sure the environmental variable $USER is set: %w", err) } source.User = u.Username } @@ -231,11 +230,11 @@ func LoadToRemote(dest entities.ImageScpOptions, localFile string, tag string, u n, err := scpD.CopyTo(dial, localFile, remoteFile) if err != nil { errOut := strconv.Itoa(int(n)) + " Bytes copied before error" - return " ", "", errors.Wrapf(err, errOut) + return " ", "", fmt.Errorf("%v: %w", errOut, err) } var run string if tag != "" { - return "", "", errors.Wrapf(define.ErrInvalidArg, "Renaming of an image is currently not supported") + return "", "", fmt.Errorf("renaming of an image is currently not supported: %w", define.ErrInvalidArg) } podman := os.Args[0] run = podman + " image load --input=" + remoteFile + ";rm " + remoteFile // run ssh image load of the file copied via scp @@ -268,7 +267,7 @@ func SaveToRemote(image, localFile string, tag string, uri *url.URL, iden string defer dial.Close() if tag != "" { - return errors.Wrapf(define.ErrInvalidArg, "Renaming of an image is currently not supported") + return fmt.Errorf("renaming of an image is currently not supported: %w", define.ErrInvalidArg) } podman := os.Args[0] run := podman + " image save " + image + " --format=oci-archive --output=" + remoteFile // run ssh image load of the file copied via scp. Files are reverse in this case... @@ -282,7 +281,7 @@ func SaveToRemote(image, localFile string, tag string, uri *url.URL, iden string } if err != nil { errOut := strconv.Itoa(int(n)) + " Bytes copied before error" - return errors.Wrapf(err, errOut) + return fmt.Errorf("%v: %w", errOut, err) } return nil } @@ -307,7 +306,7 @@ func CreateConnection(url *url.URL, iden string) (*ssh.Client, string, error) { } dialAdd, err := ssh.Dial("tcp", url.Host, cfg) // dial the client if err != nil { - return nil, "", errors.Wrapf(err, "failed to connect") + return nil, "", fmt.Errorf("failed to connect: %w", err) } file, err := MakeRemoteFile(dialAdd) if err != nil { @@ -429,14 +428,14 @@ func ValidateImagePortion(location entities.ImageScpOptions, arg string) (entiti // validateSCPArgs takes the array of source and destination options and checks for common errors func ValidateSCPArgs(locations []*entities.ImageScpOptions) error { if len(locations) > 2 { - return errors.Wrapf(define.ErrInvalidArg, "cannot specify more than two arguments") + return fmt.Errorf("cannot specify more than two arguments: %w", define.ErrInvalidArg) } switch { case len(locations[0].Image) > 0 && len(locations[1].Image) > 0: locations[1].Tag = locations[1].Image locations[1].Image = "" case len(locations[0].Image) == 0 && len(locations[1].Image) == 0: - return errors.Wrapf(define.ErrInvalidArg, "a source image must be specified") + return fmt.Errorf("a source image must be specified: %w", define.ErrInvalidArg) } return nil } @@ -475,7 +474,7 @@ func ExecRemoteCommand(dial *ssh.Client, run string) ([]byte, error) { sess.Stdout = &buffer // output from client funneled into buffer sess.Stderr = &bufferErr // err form client funneled into buffer if err := sess.Run(run); err != nil { // run the command on the ssh client - return nil, errors.Wrapf(err, bufferErr.String()) + return nil, fmt.Errorf("%v: %w", bufferErr.String(), err) } return buffer.Bytes(), nil } @@ -488,12 +487,12 @@ func GetUserInfo(uri *url.URL) (*url.Userinfo, error) { if u, found := os.LookupEnv("_CONTAINERS_ROOTLESS_UID"); found { usr, err = user.LookupId(u) if err != nil { - return nil, errors.Wrapf(err, "failed to lookup rootless user") + return nil, fmt.Errorf("failed to lookup rootless user: %w", err) } } else { usr, err = user.Current() if err != nil { - return nil, errors.Wrapf(err, "failed to obtain current user") + return nil, fmt.Errorf("failed to obtain current user: %w", err) } } @@ -514,7 +513,7 @@ func ValidateAndConfigure(uri *url.URL, iden string) (*ssh.ClientConfig, error) value := iden s, err := terminal.PublicKey(value, []byte(passwd)) if err != nil { - return nil, errors.Wrapf(err, "failed to read identity %q", value) + return nil, fmt.Errorf("failed to read identity %q: %w", value, err) } signers = append(signers, s) logrus.Debugf("SSH Ident Key %q %s %s", value, ssh.FingerprintSHA256(s.PublicKey()), s.PublicKey().Type()) diff --git a/pkg/domain/utils/secrets_filters.go b/pkg/domain/utils/secrets_filters.go index e76bc592f..ab9b681ec 100644 --- a/pkg/domain/utils/secrets_filters.go +++ b/pkg/domain/utils/secrets_filters.go @@ -1,11 +1,11 @@ package utils import ( + "fmt" "strings" "github.com/containers/common/pkg/secrets" "github.com/containers/podman/v4/pkg/util" - "github.com/pkg/errors" ) func IfPassesSecretsFilter(s secrets.Secret, filters map[string][]string) (bool, error) { @@ -17,7 +17,7 @@ func IfPassesSecretsFilter(s secrets.Secret, filters map[string][]string) (bool, case "id": result = util.StringMatchRegexSlice(s.ID, filterValues) default: - return false, errors.Errorf("invalid filter %q", key) + return false, fmt.Errorf("invalid filter %q", key) } } return result, nil diff --git a/pkg/env/env.go b/pkg/env/env.go index 5989d0da5..8af9fd77c 100644 --- a/pkg/env/env.go +++ b/pkg/env/env.go @@ -8,8 +8,6 @@ import ( "fmt" "os" "strings" - - "github.com/pkg/errors" ) const whiteSpaces = " \t" @@ -56,7 +54,7 @@ func ParseFile(path string) (_ map[string]string, err error) { env := make(map[string]string) defer func() { if err != nil { - err = errors.Wrapf(err, "error parsing env file %q", path) + err = fmt.Errorf("error parsing env file %q: %w", path, err) } }() @@ -85,12 +83,12 @@ func parseEnv(env map[string]string, line string) error { // catch invalid variables such as "=" or "=A" if data[0] == "" { - return errors.Errorf("invalid environment variable: %q", line) + return fmt.Errorf("invalid environment variable: %q", line) } // trim the front of a variable, but nothing else name := strings.TrimLeft(data[0], whiteSpaces) if strings.ContainsAny(name, whiteSpaces) { - return errors.Errorf("name %q has white spaces, poorly formatted name", name) + return fmt.Errorf("name %q has white spaces, poorly formatted name", name) } if len(data) > 1 { diff --git a/pkg/hooks/1.0.0/hook.go b/pkg/hooks/1.0.0/hook.go index 244e8800f..71f940a64 100644 --- a/pkg/hooks/1.0.0/hook.go +++ b/pkg/hooks/1.0.0/hook.go @@ -3,12 +3,12 @@ package hook import ( "encoding/json" + "errors" "fmt" "os" "regexp" rspec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" ) // Version is the hook configuration version defined in this package. @@ -50,16 +50,16 @@ func (hook *Hook) Validate(extensionStages []string) (err error) { for key, value := range hook.When.Annotations { if _, err = regexp.Compile(key); err != nil { - return errors.Wrapf(err, "invalid annotation key %q", key) + return fmt.Errorf("invalid annotation key %q: %w", key, err) } if _, err = regexp.Compile(value); err != nil { - return errors.Wrapf(err, "invalid annotation value %q", value) + return fmt.Errorf("invalid annotation value %q: %w", value, err) } } for _, command := range hook.When.Commands { if _, err = regexp.Compile(command); err != nil { - return errors.Wrapf(err, "invalid command %q", command) + return fmt.Errorf("invalid command %q: %w", command, err) } } diff --git a/pkg/hooks/1.0.0/when.go b/pkg/hooks/1.0.0/when.go index a65af048e..a1351890f 100644 --- a/pkg/hooks/1.0.0/when.go +++ b/pkg/hooks/1.0.0/when.go @@ -1,10 +1,11 @@ package hook import ( + "errors" + "fmt" "regexp" rspec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" ) // When holds hook-injection conditions. @@ -52,12 +53,12 @@ func (when *When) Match(config *rspec.Spec, annotations map[string]string, hasBi for key, value := range annotations { match, err = regexp.MatchString(keyPattern, key) if err != nil { - return false, errors.Wrap(err, "annotation key") + return false, fmt.Errorf("annotation key: %w", err) } if match { match, err = regexp.MatchString(valuePattern, value) if err != nil { - return false, errors.Wrap(err, "annotation value") + return false, fmt.Errorf("annotation value: %w", err) } if match { break @@ -82,7 +83,7 @@ func (when *When) Match(config *rspec.Spec, annotations map[string]string, hasBi for _, cmdPattern := range when.Commands { match, err := regexp.MatchString(cmdPattern, command) if err != nil { - return false, errors.Wrap(err, "command") + return false, fmt.Errorf("command: %w", err) } if match { return true, nil diff --git a/pkg/hooks/exec/exec.go b/pkg/hooks/exec/exec.go index 2b7bc5f31..bc639245f 100644 --- a/pkg/hooks/exec/exec.go +++ b/pkg/hooks/exec/exec.go @@ -10,7 +10,6 @@ import ( "time" rspec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -46,7 +45,7 @@ func Run(ctx context.Context, hook *rspec.Hook, state []byte, stdout io.Writer, go func() { err := cmd.Wait() if err != nil { - err = errors.Wrapf(err, "executing %v", cmd.Args) + err = fmt.Errorf("executing %v: %w", cmd.Args, err) } exit <- err }() diff --git a/pkg/hooks/exec/runtimeconfigfilter.go b/pkg/hooks/exec/runtimeconfigfilter.go index 3ab3073b2..72d4b8979 100644 --- a/pkg/hooks/exec/runtimeconfigfilter.go +++ b/pkg/hooks/exec/runtimeconfigfilter.go @@ -4,12 +4,12 @@ import ( "bytes" "context" "encoding/json" + "fmt" "reflect" "time" "github.com/davecgh/go-spew/spew" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/pmezard/go-difflib/difflib" "github.com/sirupsen/logrus" ) @@ -43,7 +43,7 @@ func RuntimeConfigFilter(ctx context.Context, hooks []spec.Hook, config *spec.Sp err = json.Unmarshal(data, &newConfig) if err != nil { logrus.Debugf("invalid JSON from config-filter hook %d:\n%s", i, string(data)) - return nil, errors.Wrapf(err, "unmarshal output from config-filter hook %d", i) + return nil, fmt.Errorf("unmarshal output from config-filter hook %d: %w", i, err) } if !reflect.DeepEqual(config, &newConfig) { diff --git a/pkg/hooks/hooks.go b/pkg/hooks/hooks.go index ecd5b7dfc..14f98b1de 100644 --- a/pkg/hooks/hooks.go +++ b/pkg/hooks/hooks.go @@ -11,7 +11,6 @@ import ( current "github.com/containers/podman/v4/pkg/hooks/1.0.0" rspec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -105,7 +104,7 @@ func (m *Manager) Hooks(config *rspec.Spec, annotations map[string]string, hasBi for _, namedHook := range hooks { match, err := namedHook.hook.When.Match(config, annotations, hasBindMounts) if err != nil { - return extensionStageHooks, errors.Wrapf(err, "matching hook %q", namedHook.name) + return extensionStageHooks, fmt.Errorf("matching hook %q: %w", namedHook.name, err) } if match { logrus.Debugf("hook %s matched; adding to stages %v", namedHook.name, namedHook.hook.Stages) diff --git a/pkg/hooks/read.go b/pkg/hooks/read.go index c48d51f7d..379ed67ef 100644 --- a/pkg/hooks/read.go +++ b/pkg/hooks/read.go @@ -3,6 +3,8 @@ package hooks import ( "encoding/json" + "errors" + "fmt" "io/ioutil" "os" "path/filepath" @@ -10,7 +12,6 @@ import ( old "github.com/containers/podman/v4/pkg/hooks/0.1.0" current "github.com/containers/podman/v4/pkg/hooks/1.0.0" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -36,7 +37,7 @@ func Read(path string, extensionStages []string) (*current.Hook, error) { } hook, err := read(content) if err != nil { - return nil, errors.Wrapf(err, "parsing hook %q", path) + return nil, fmt.Errorf("parsing hook %q: %w", path, err) } err = hook.Validate(extensionStages) return hook, err @@ -45,16 +46,16 @@ func Read(path string, extensionStages []string) (*current.Hook, error) { func read(content []byte) (hook *current.Hook, err error) { var ver version if err := json.Unmarshal(content, &ver); err != nil { - return nil, errors.Wrap(err, "version check") + return nil, fmt.Errorf("version check: %w", err) } reader, ok := Readers[ver.Version] if !ok { - return nil, errors.Errorf("unrecognized hook version: %q", ver.Version) + return nil, fmt.Errorf("unrecognized hook version: %q", ver.Version) } hook, err = reader(content) if err != nil { - return hook, errors.Wrap(err, ver.Version) + return hook, fmt.Errorf("%v: %w", ver.Version, err) } return hook, err } @@ -83,7 +84,7 @@ func ReadDir(path string, extensionStages []string, hooks map[string]*current.Ho if res == nil { res = err } else { - res = errors.Wrapf(res, "%v", err) + res = fmt.Errorf("%v: %w", err, res) } continue } diff --git a/pkg/kubeutils/LICENSE b/pkg/kubeutils/LICENSE deleted file mode 100644 index 9b259bdfc..000000000 --- a/pkg/kubeutils/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - 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 - - https://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. diff --git a/pkg/kubeutils/resize.go b/pkg/kubeutils/resize.go deleted file mode 100644 index a744c66cc..000000000 --- a/pkg/kubeutils/resize.go +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright 2015 The Kubernetes 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 - - https://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 kubeutils - -import ( - "github.com/containers/podman/v4/libpod/define" -) - -// HandleResizing spawns a goroutine that processes the resize channel, calling resizeFunc for each -// remotecommand.TerminalSize received from the channel. The resize channel must be closed elsewhere to stop the -// goroutine. -func HandleResizing(resize <-chan define.TerminalSize, resizeFunc func(size define.TerminalSize)) { - if resize == nil { - return - } - - go func() { - for { - size, ok := <-resize - if !ok { - return - } - if size.Height < 1 || size.Width < 1 { - continue - } - resizeFunc(size) - } - }() -} diff --git a/pkg/machine/config.go b/pkg/machine/config.go index fcc129338..29cd7bc00 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -4,7 +4,7 @@ package machine import ( - errors2 "errors" + "errors" "io/ioutil" "net" "net/url" @@ -13,7 +13,6 @@ import ( "time" "github.com/containers/storage/pkg/homedir" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -55,6 +54,7 @@ type Provider interface { IsValidVMName(name string) (bool, error) CheckExclusiveActiveVM() (bool, string, error) RemoveAndCleanMachines() error + VMType() string } type RemoteConnectionType string @@ -255,11 +255,11 @@ func (m *VMFile) GetPath() string { // the actual path func (m *VMFile) Delete() error { if m.Symlink != nil { - if err := os.Remove(*m.Symlink); err != nil && !errors2.Is(err, os.ErrNotExist) { + if err := os.Remove(*m.Symlink); err != nil && !errors.Is(err, os.ErrNotExist) { logrus.Errorf("unable to remove symlink %q", *m.Symlink) } } - if err := os.Remove(m.Path); err != nil && !errors2.Is(err, os.ErrNotExist) { + if err := os.Remove(m.Path); err != nil && !errors.Is(err, os.ErrNotExist) { return err } return nil @@ -273,14 +273,14 @@ func (m *VMFile) Read() ([]byte, error) { // NewMachineFile is a constructor for VMFile func NewMachineFile(path string, symlink *string) (*VMFile, error) { if len(path) < 1 { - return nil, errors2.New("invalid machine file path") + return nil, errors.New("invalid machine file path") } if symlink != nil && len(*symlink) < 1 { - return nil, errors2.New("invalid symlink path") + return nil, errors.New("invalid symlink path") } mf := VMFile{Path: path} if symlink != nil && len(path) > maxSocketPathLength { - if err := mf.makeSymlink(symlink); err != nil && !errors2.Is(err, os.ErrExist) { + if err := mf.makeSymlink(symlink); err != nil && !errors.Is(err, os.ErrExist) { return nil, err } } @@ -296,7 +296,7 @@ func (m *VMFile) makeSymlink(symlink *string) error { } sl := filepath.Join(homeDir, ".podman", *symlink) // make the symlink dir and throw away if it already exists - if err := os.MkdirAll(filepath.Dir(sl), 0700); err != nil && !errors2.Is(err, os.ErrNotExist) { + if err := os.MkdirAll(filepath.Dir(sl), 0700); err != nil && !errors.Is(err, os.ErrNotExist) { return err } m.Symlink = &sl diff --git a/pkg/machine/connection.go b/pkg/machine/connection.go index 841b2afa6..6ff761a92 100644 --- a/pkg/machine/connection.go +++ b/pkg/machine/connection.go @@ -4,10 +4,10 @@ package machine import ( + "errors" "fmt" "github.com/containers/common/pkg/config" - "github.com/pkg/errors" ) func AddConnection(uri fmt.Stringer, name, identity string, isDefault bool) error { @@ -72,7 +72,7 @@ func RemoveConnection(name string) error { if _, ok := cfg.Engine.ServiceDestinations[name]; ok { delete(cfg.Engine.ServiceDestinations, name) } else { - return errors.Errorf("unable to find connection named %q", name) + return fmt.Errorf("unable to find connection named %q", name) } return cfg.Write() } diff --git a/pkg/machine/e2e/config.go b/pkg/machine/e2e/config.go index 248a2f0ad..b3fe74b0c 100644 --- a/pkg/machine/e2e/config.go +++ b/pkg/machine/e2e/config.go @@ -3,7 +3,6 @@ package e2e import ( "encoding/json" "fmt" - "math/rand" "os" "os/exec" "path/filepath" @@ -13,6 +12,7 @@ import ( "github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine/qemu" "github.com/containers/podman/v4/pkg/util" + "github.com/containers/storage/pkg/stringid" . "github.com/onsi/ginkgo" //nolint:golint,stylecheck . "github.com/onsi/gomega" "github.com/onsi/gomega/gexec" @@ -136,14 +136,14 @@ func (m *machineTestBuilder) setTimeout(timeout time.Duration) *machineTestBuild // toQemuInspectInfo is only for inspecting qemu machines. Other providers will need // to make their own. -func (mb *machineTestBuilder) toQemuInspectInfo() ([]qemuMachineInspectInfo, int, error) { +func (mb *machineTestBuilder) toQemuInspectInfo() ([]machine.InspectInfo, int, error) { args := []string{"machine", "inspect"} args = append(args, mb.names...) session, err := runWrapper(mb.podmanBinary, args, defaultTimeout, true) if err != nil { return nil, -1, err } - mii := []qemuMachineInspectInfo{} + mii := []machine.InspectInfo{} err = json.Unmarshal(session.Bytes(), &mii) return mii, session.ExitCode(), err } @@ -179,10 +179,5 @@ func (m *machineTestBuilder) init() {} // randomString returns a string of given length composed of random characters func randomString(n int) string { - var randomLetters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") - b := make([]rune, n) - for i := range b { - b[i] = randomLetters[rand.Intn(len(randomLetters))] - } - return string(b) + return stringid.GenerateRandomID()[0:12] } diff --git a/pkg/machine/e2e/config_info.go b/pkg/machine/e2e/config_info.go new file mode 100644 index 000000000..410c7e518 --- /dev/null +++ b/pkg/machine/e2e/config_info.go @@ -0,0 +1,20 @@ +package e2e + +type infoMachine struct { + format string + cmd []string +} + +func (i *infoMachine) buildCmd(m *machineTestBuilder) []string { + cmd := []string{"machine", "info"} + if len(i.format) > 0 { + cmd = append(cmd, "--format", i.format) + } + i.cmd = cmd + return cmd +} + +func (i *infoMachine) withFormat(format string) *infoMachine { + i.format = format + return i +} diff --git a/pkg/machine/e2e/info_test.go b/pkg/machine/e2e/info_test.go new file mode 100644 index 000000000..eeabb78af --- /dev/null +++ b/pkg/machine/e2e/info_test.go @@ -0,0 +1,58 @@ +package e2e + +import ( + "github.com/containers/podman/v4/cmd/podman/machine" + jsoniter "github.com/json-iterator/go" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gexec" +) + +var _ = Describe("podman machine info", func() { + var ( + mb *machineTestBuilder + testDir string + ) + + BeforeEach(func() { + testDir, mb = setup() + }) + AfterEach(func() { + teardown(originalHomeDir, testDir, mb) + }) + + It("machine info", func() { + info := new(infoMachine) + infoSession, err := mb.setCmd(info).run() + Expect(err).NotTo(HaveOccurred()) + Expect(infoSession).Should(Exit(0)) + + // Verify go template works and check for no running machines + info = new(infoMachine) + infoSession, err = mb.setCmd(info.withFormat("{{.Host.NumberOfMachines}}")).run() + Expect(err).NotTo(HaveOccurred()) + Expect(infoSession).Should(Exit(0)) + Expect(infoSession.outputToString()).To(Equal("0")) + + // Create a machine and check if info has been updated + i := new(initMachine) + initSession, err := mb.setCmd(i.withImagePath(mb.imagePath)).run() + Expect(err).To(BeNil()) + Expect(initSession).To(Exit(0)) + + info = new(infoMachine) + infoSession, err = mb.setCmd(info.withFormat("{{.Host.NumberOfMachines}}")).run() + Expect(err).NotTo(HaveOccurred()) + Expect(infoSession).Should(Exit(0)) + Expect(infoSession.outputToString()).To(Equal("1")) + + // Check if json is in correct format + infoSession, err = mb.setCmd(info.withFormat("json")).run() + Expect(err).NotTo(HaveOccurred()) + Expect(infoSession).Should(Exit(0)) + + infoReport := &machine.Info{} + err = jsoniter.Unmarshal(infoSession.Bytes(), infoReport) + Expect(err).To(BeNil()) + }) +}) diff --git a/pkg/machine/e2e/init_test.go b/pkg/machine/e2e/init_test.go index 6949eb0af..40f140cae 100644 --- a/pkg/machine/e2e/init_test.go +++ b/pkg/machine/e2e/init_test.go @@ -3,6 +3,7 @@ package e2e import ( "io/ioutil" "os" + "runtime" "time" "github.com/containers/podman/v4/pkg/machine" @@ -44,9 +45,9 @@ var _ = Describe("podman machine init", func() { Expect(len(inspectBefore)).To(BeNumerically(">", 0)) testMachine := inspectBefore[0] - Expect(testMachine.VM.Name).To(Equal(mb.names[0])) - Expect(testMachine.VM.CPUs).To(Equal(uint64(1))) - Expect(testMachine.VM.Memory).To(Equal(uint64(2048))) + Expect(testMachine.Name).To(Equal(mb.names[0])) + Expect(testMachine.Resources.CPUs).To(Equal(uint64(1))) + Expect(testMachine.Resources.Memory).To(Equal(uint64(2048))) }) @@ -61,7 +62,7 @@ var _ = Describe("podman machine init", func() { Expect(len(inspectBefore)).To(BeNumerically(">", 0)) Expect(err).To(BeNil()) Expect(len(inspectBefore)).To(BeNumerically(">", 0)) - Expect(inspectBefore[0].VM.Name).To(Equal(mb.names[0])) + Expect(inspectBefore[0].Name).To(Equal(mb.names[0])) s := startMachine{} ssession, err := mb.setCmd(s).setTimeout(time.Minute * 10).run() @@ -104,7 +105,15 @@ var _ = Describe("podman machine init", func() { memorySession, err := mb.setName(name).setCmd(sshMemory.withSSHComand([]string{"cat", "/proc/meminfo", "|", "numfmt", "--field", "2", "--from-unit=Ki", "--to-unit=Mi", "|", "sed", "'s/ kB/M/g'", "|", "grep", "MemTotal"})).run() Expect(err).To(BeNil()) Expect(memorySession).To(Exit(0)) - Expect(memorySession.outputToString()).To(ContainSubstring("3824")) + switch runtime.GOOS { + // os's handle memory differently + case "linux": + Expect(memorySession.outputToString()).To(ContainSubstring("3821")) + case "darwin": + Expect(memorySession.outputToString()).To(ContainSubstring("3824")) + default: + // add windows when testing on that platform + } sshTimezone := sshMachine{} timezoneSession, err := mb.setName(name).setCmd(sshTimezone.withSSHComand([]string{"date"})).run() diff --git a/pkg/machine/e2e/inspect_test.go b/pkg/machine/e2e/inspect_test.go index cdf13bb1a..93fb8cc2b 100644 --- a/pkg/machine/e2e/inspect_test.go +++ b/pkg/machine/e2e/inspect_test.go @@ -1,11 +1,9 @@ package e2e import ( - "encoding/json" "strings" "github.com/containers/podman/v4/pkg/machine" - "github.com/containers/podman/v4/pkg/machine/qemu" jsoniter "github.com/json-iterator/go" . "github.com/onsi/ginkgo" @@ -51,24 +49,6 @@ var _ = Describe("podman machine stop", func() { Expect(err).To(BeNil()) Expect(inspectSession).To(Exit(0)) Expect(inspectSession.Bytes()).To(ContainSubstring("foo1")) - - type fakeInfos struct { - Status string - VM qemu.MachineVM - } - infos := make([]fakeInfos, 0, 2) - err = json.Unmarshal(inspectSession.Bytes(), &infos) - Expect(err).ToNot(HaveOccurred()) - Expect(len(infos)).To(Equal(2)) - - // rm := new(rmMachine) - // // Must manually clean up due to multiple names - // for _, name := range []string{"foo1", "foo2"} { - // mb.setName(name).setCmd(rm.withForce()).run() - // mb.names = []string{} - // } - // mb.names = []string{} - }) It("inspect with go format", func() { diff --git a/pkg/machine/e2e/list_test.go b/pkg/machine/e2e/list_test.go index e2121e7bf..fb855c61e 100644 --- a/pkg/machine/e2e/list_test.go +++ b/pkg/machine/e2e/list_test.go @@ -2,9 +2,10 @@ package e2e import ( "strings" + "time" "github.com/containers/common/pkg/util" - "github.com/containers/podman/v4/cmd/podman/machine" + "github.com/containers/podman/v4/pkg/domain/entities" jsoniter "github.com/json-iterator/go" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -87,7 +88,7 @@ var _ = Describe("podman machine list", func() { startSession, err := mb.setCmd(s).runWithoutWait() Expect(err).To(BeNil()) l := new(listMachine) - for { // needs to be infinite because we need to check if running when inspect returns to avoid race conditions. + for i := 0; i < 30; i++ { listSession, err := mb.setCmd(l).run() Expect(listSession).To(Exit(0)) Expect(err).To(BeNil()) @@ -96,6 +97,7 @@ var _ = Describe("podman machine list", func() { } else { break } + time.Sleep(3 * time.Second) } Expect(startSession).To(Exit(0)) listSession, err := mb.setCmd(l).run() @@ -128,11 +130,11 @@ var _ = Describe("podman machine list", func() { // --format json list2 := new(listMachine) list2 = list2.withFormat("json") - listSession2, err := mb.setName("foo1").setCmd(list2).run() + listSession2, err := mb.setCmd(list2).run() Expect(err).To(BeNil()) Expect(listSession2).To(Exit(0)) - var listResponse []*machine.ListReporter + var listResponse []*entities.ListReporter err = jsoniter.Unmarshal(listSession.Bytes(), &listResponse) Expect(err).To(BeNil()) @@ -143,7 +145,6 @@ var _ = Describe("podman machine list", func() { Expect(listSession3).To(Exit(0)) listNames3 := listSession3.outputToStringSlice() Expect(listNames3).To(HaveLen(2)) - Expect(listNames3).To(ContainSubstring("NAME")) }) }) diff --git a/pkg/machine/e2e/machine_test.go b/pkg/machine/e2e/machine_test.go index 657014b05..7b063937d 100644 --- a/pkg/machine/e2e/machine_test.go +++ b/pkg/machine/e2e/machine_test.go @@ -22,7 +22,7 @@ func TestMain(m *testing.M) { } const ( - defaultStream string = "podman-testing" + defaultStream string = "testing" ) var ( @@ -97,6 +97,9 @@ func setup() (string, *machineTestBuilder) { if err := os.Setenv("HOME", homeDir); err != nil { Fail("failed to set home dir") } + if err := os.Setenv("XDG_RUNTIME_DIR", homeDir); err != nil { + Fail("failed to set xdg_runtime dir") + } if err := os.Unsetenv("SSH_AUTH_SOCK"); err != nil { Fail("unable to unset SSH_AUTH_SOCK") } @@ -120,9 +123,9 @@ func setup() (string, *machineTestBuilder) { } func teardown(origHomeDir string, testDir string, mb *machineTestBuilder) { - s := new(stopMachine) + r := new(rmMachine) for _, name := range mb.names { - if _, err := mb.setName(name).setCmd(s).run(); err != nil { + if _, err := mb.setName(name).setCmd(r.withForce()).run(); err != nil { fmt.Printf("error occurred rm'ing machine: %q\n", err) } } diff --git a/pkg/machine/e2e/set_test.go b/pkg/machine/e2e/set_test.go index 15215a44d..80cb89488 100644 --- a/pkg/machine/e2e/set_test.go +++ b/pkg/machine/e2e/set_test.go @@ -1,6 +1,8 @@ package e2e import ( + "runtime" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gexec" @@ -57,8 +59,15 @@ var _ = Describe("podman machine set", func() { memorySession, err := mb.setName(name).setCmd(sshMemory.withSSHComand([]string{"cat", "/proc/meminfo", "|", "numfmt", "--field", "2", "--from-unit=Ki", "--to-unit=Mi", "|", "sed", "'s/ kB/M/g'", "|", "grep", "MemTotal"})).run() Expect(err).To(BeNil()) Expect(memorySession).To(Exit(0)) - Expect(memorySession.outputToString()).To(ContainSubstring("3824")) - + switch runtime.GOOS { + // it seems macos and linux handle memory differently + case "linux": + Expect(memorySession.outputToString()).To(ContainSubstring("3821")) + case "darwin": + Expect(memorySession.outputToString()).To(ContainSubstring("3824")) + default: + // windows can go here if we ever run tests there + } // Setting a running machine results in 125 runner, err := mb.setName(name).setCmd(set.withCPUs(4)).run() Expect(err).To(BeNil()) diff --git a/pkg/machine/fcos.go b/pkg/machine/fcos.go index 59ef6d975..4ccb99e96 100644 --- a/pkg/machine/fcos.go +++ b/pkg/machine/fcos.go @@ -17,7 +17,6 @@ import ( "github.com/coreos/stream-metadata-go/fedoracoreos" "github.com/coreos/stream-metadata-go/release" "github.com/coreos/stream-metadata-go/stream" - "github.com/pkg/errors" digest "github.com/opencontainers/go-digest" "github.com/sirupsen/logrus" @@ -156,7 +155,7 @@ func GetFCOSDownload(imageStream string) (*FcosDownloadInfo, error) { case "stable": streamType = fedoracoreos.StreamStable default: - return nil, errors.Errorf("invalid stream %s: valid streams are `testing` and `stable`", imageStream) + return nil, fmt.Errorf("invalid stream %s: valid streams are `testing` and `stable`", imageStream) } streamurl := getStreamURL(streamType) resp, err := http.Get(streamurl.String()) diff --git a/pkg/machine/fedora.go b/pkg/machine/fedora.go index 14a173da6..46e450418 100644 --- a/pkg/machine/fedora.go +++ b/pkg/machine/fedora.go @@ -4,6 +4,7 @@ package machine import ( + "errors" "fmt" "io" "io/ioutil" @@ -13,7 +14,6 @@ import ( "path/filepath" "regexp" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -107,12 +107,12 @@ func getFedoraDownload(releaseStream string) (string, *url.URL, int64, error) { newLocation := rawURL + file downloadURL, err := url.Parse(newLocation) if err != nil { - return "", nil, -1, errors.Wrapf(err, "invalid URL generated from discovered Fedora file: %s", newLocation) + return "", nil, -1, fmt.Errorf("invalid URL generated from discovered Fedora file: %s: %w", newLocation, err) } resp, err := http.Head(newLocation) if err != nil { - return "", nil, -1, errors.Wrapf(err, "head request failed: %s", newLocation) + return "", nil, -1, fmt.Errorf("head request failed: %s: %w", newLocation, err) } _ = resp.Body.Close() diff --git a/pkg/machine/keys.go b/pkg/machine/keys.go index 463271427..0c7d7114e 100644 --- a/pkg/machine/keys.go +++ b/pkg/machine/keys.go @@ -4,6 +4,7 @@ package machine import ( + "errors" "fmt" "io" "io/ioutil" @@ -12,7 +13,6 @@ import ( "path/filepath" "strings" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 879ed5109..6134e69e1 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -5,6 +5,7 @@ package qemu import ( "bufio" + "bytes" "context" "encoding/base64" "encoding/json" @@ -138,8 +139,10 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) { cmd = append(cmd, []string{ "-device", "virtio-serial", // qemu needs to establish the long name; other connections can use the symlink'd - "-chardev", "socket,path=" + vm.ReadySocket.Path + ",server=on,wait=off,id=" + vm.Name + "_ready", - "-device", "virtserialport,chardev=" + vm.Name + "_ready" + ",name=org.fedoraproject.port.0", + // Note both id and chardev start with an extra "a" because qemu requires that it + // starts with an letter but users can also use numbers + "-chardev", "socket,path=" + vm.ReadySocket.Path + ",server=on,wait=off,id=a" + vm.Name + "_ready", + "-device", "virtserialport,chardev=a" + vm.Name + "_ready" + ",name=org.fedoraproject.port.0", "-pidfile", vm.VMPidFilePath.GetPath()}...) vm.CmdLine = cmd return vm, nil @@ -318,6 +321,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { source := paths[0] target := source readonly := false + securityModel := "mapped-xattr" if len(paths) > 1 { target = paths[1] } @@ -325,18 +329,20 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) { options := paths[2] volopts := strings.Split(options, ",") for _, o := range volopts { - switch o { - case "rw": + switch { + case o == "rw": readonly = false - case "ro": + case o == "ro": readonly = true + case strings.HasPrefix(o, "security_model="): + securityModel = strings.Split(o, "=")[1] default: fmt.Printf("Unknown option: %s\n", o) } } } if volumeType == VolumeTypeVirtfs { - virtfsOptions := fmt.Sprintf("local,path=%s,mount_tag=%s,security_model=mapped-xattr", source, tag) + virtfsOptions := fmt.Sprintf("local,path=%s,mount_tag=%s,security_model=%s", source, tag, securityModel) if readonly { virtfsOptions += ",readonly" } @@ -568,15 +574,25 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { files := []*os.File{dnr, dnw, dnw, fd} attr.Files = files logrus.Debug(v.CmdLine) - cmd := v.CmdLine + cmdLine := v.CmdLine // Disable graphic window when not in debug mode // Done in start, so we're not suck with the debug level we used on init if !logrus.IsLevelEnabled(logrus.DebugLevel) { - cmd = append(cmd, "-display", "none") + cmdLine = append(cmdLine, "-display", "none") } - _, err = os.StartProcess(v.CmdLine[0], cmd, attr) + stderrBuf := &bytes.Buffer{} + + cmd := &exec.Cmd{ + Args: cmdLine, + Path: cmdLine[0], + Stdin: dnr, + Stdout: dnw, + Stderr: stderrBuf, + ExtraFiles: []*os.File{fd}, + } + err = cmd.Start() if err != nil { // check if qemu was not found if !errors.Is(err, os.ErrNotExist) { @@ -587,15 +603,17 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { if err != nil { return err } - cmd[0], err = cfg.FindHelperBinary(QemuCommand, true) + cmdLine[0], err = cfg.FindHelperBinary(QemuCommand, true) if err != nil { return err } - _, err = os.StartProcess(cmd[0], cmd, attr) + cmd.Path = cmdLine[0] + err = cmd.Start() if err != nil { return fmt.Errorf("unable to execute %q: %w", cmd, err) } } + defer cmd.Process.Release() //nolint:errcheck fmt.Println("Waiting for VM ...") socketPath, err := getRuntimeDir() if err != nil { @@ -610,6 +628,16 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { if err == nil { break } + // check if qemu is still alive + var status syscall.WaitStatus + pid, err := syscall.Wait4(cmd.Process.Pid, &status, syscall.WNOHANG, nil) + if err != nil { + return fmt.Errorf("failed to read qemu process status: %w", err) + } + if pid > 0 { + // child exited + return fmt.Errorf("qemu exited unexpectedly with exit code %d, stderr: %s", status.ExitStatus(), stderrBuf.String()) + } time.Sleep(wait) wait++ } @@ -1217,7 +1245,10 @@ func (v *MachineVM) startHostNetworking() (string, apiForwardingState, error) { fmt.Println(cmd) } _, err = os.StartProcess(cmd[0], cmd, attr) - return forwardSock, state, fmt.Errorf("unable to execute: %q: %w", cmd, err) + if err != nil { + return "", 0, fmt.Errorf("unable to execute: %q: %w", cmd, err) + } + return forwardSock, state, nil } func (v *MachineVM) setupAPIForwarding(cmd []string) ([]string, string, apiForwardingState) { @@ -1698,6 +1729,9 @@ func isProcessAlive(pid int) bool { if err == nil || err == unix.EPERM { return true } - return false } + +func (p *Provider) VMType() string { + return vmtype +} diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go index 04215d545..450d8b877 100644 --- a/pkg/machine/wsl/machine.go +++ b/pkg/machine/wsl/machine.go @@ -6,6 +6,7 @@ package wsl import ( "bufio" "encoding/json" + "errors" "fmt" "io" "io/fs" @@ -22,7 +23,6 @@ import ( "github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/utils" "github.com/containers/storage/pkg/homedir" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/text/encoding/unicode" "golang.org/x/text/transform" @@ -277,7 +277,7 @@ func readAndMigrate(configPath string, name string) (*MachineVM, error) { b, err := os.ReadFile(configPath) if err != nil { if errors.Is(err, os.ErrNotExist) { - return nil, errors.Wrap(machine.ErrNoSuchVM, name) + return nil, fmt.Errorf("%v: %w", name, machine.ErrNoSuchVM) } return vm, err } @@ -407,7 +407,7 @@ func (v *MachineVM) writeConfig() error { return err } if err := ioutil.WriteFile(jsonFile, b, 0644); err != nil { - return errors.Wrap(err, "could not write machine json config") + return fmt.Errorf("could not write machine json config: %w", err) } return nil @@ -445,38 +445,38 @@ func provisionWSLDist(v *MachineVM) (string, error) { distDir := filepath.Join(vmDataDir, "wsldist") distTarget := filepath.Join(distDir, v.Name) if err := os.MkdirAll(distDir, 0755); err != nil { - return "", errors.Wrap(err, "could not create wsldist directory") + return "", fmt.Errorf("could not create wsldist directory: %w", err) } dist := toDist(v.Name) fmt.Println("Importing operating system into WSL (this may take 5+ minutes on a new WSL install)...") if err = runCmdPassThrough("wsl", "--import", dist, distTarget, v.ImagePath); err != nil { - return "", errors.Wrap(err, "WSL import of guest OS failed") + return "", fmt.Errorf("the WSL import of guest OS failed: %w", err) } fmt.Println("Installing packages (this will take awhile)...") if err = runCmdPassThrough("wsl", "-d", dist, "dnf", "upgrade", "-y"); err != nil { - return "", errors.Wrap(err, "package upgrade on guest OS failed") + return "", fmt.Errorf("package upgrade on guest OS failed: %w", err) } fmt.Println("Enabling Copr") if err = runCmdPassThrough("wsl", "-d", dist, "dnf", "install", "-y", "'dnf-command(copr)'"); err != nil { - return "", errors.Wrap(err, "enabling copr failed") + return "", fmt.Errorf("enabling copr failed: %w", err) } fmt.Println("Enabling podman4 repo") if err = runCmdPassThrough("wsl", "-d", dist, "dnf", "-y", "copr", "enable", "rhcontainerbot/podman4"); err != nil { - return "", errors.Wrap(err, "enabling copr failed") + return "", fmt.Errorf("enabling copr failed: %w", err) } if err = runCmdPassThrough("wsl", "-d", dist, "dnf", "install", "podman", "podman-docker", "openssh-server", "procps-ng", "-y"); err != nil { - return "", errors.Wrap(err, "package installation on guest OS failed") + return "", fmt.Errorf("package installation on guest OS failed: %w", err) } // Fixes newuidmap if err = runCmdPassThrough("wsl", "-d", dist, "dnf", "reinstall", "shadow-utils", "-y"); err != nil { - return "", errors.Wrap(err, "package reinstallation of shadow-utils on guest OS failed") + return "", fmt.Errorf("package reinstallation of shadow-utils on guest OS failed: %w", err) } // Windows 11 (NT Version = 10, Build 22000) generates harmless but scary messages on every @@ -495,28 +495,28 @@ func createKeys(v *MachineVM, dist string, sshDir string) error { user := v.RemoteUsername if err := os.MkdirAll(sshDir, 0700); err != nil { - return errors.Wrap(err, "could not create ssh directory") + return fmt.Errorf("could not create ssh directory: %w", err) } if err := runCmdPassThrough("wsl", "--terminate", dist); err != nil { - return errors.Wrap(err, "could not cycle WSL dist") + return fmt.Errorf("could not cycle WSL dist: %w", err) } key, err := machine.CreateSSHKeysPrefix(sshDir, v.Name, true, true, "wsl", "-d", dist) if err != nil { - return errors.Wrap(err, "could not create ssh keys") + return fmt.Errorf("could not create ssh keys: %w", err) } if err := pipeCmdPassThrough("wsl", key+"\n", "-d", dist, "sh", "-c", "mkdir -p /root/.ssh;"+ "cat >> /root/.ssh/authorized_keys; chmod 600 /root/.ssh/authorized_keys"); err != nil { - return errors.Wrap(err, "could not create root authorized keys on guest OS") + return fmt.Errorf("could not create root authorized keys on guest OS: %w", err) } userAuthCmd := withUser("mkdir -p /home/[USER]/.ssh;"+ "cat >> /home/[USER]/.ssh/authorized_keys; chown -R [USER]:[USER] /home/[USER]/.ssh;"+ "chmod 600 /home/[USER]/.ssh/authorized_keys", user) if err := pipeCmdPassThrough("wsl", key+"\n", "-d", dist, "sh", "-c", userAuthCmd); err != nil { - return errors.Wrapf(err, "could not create '%s' authorized keys on guest OS", v.RemoteUsername) + return fmt.Errorf("could not create '%s' authorized keys on guest OS: %w", v.RemoteUsername, err) } return nil @@ -525,25 +525,25 @@ func createKeys(v *MachineVM, dist string, sshDir string) error { func configureSystem(v *MachineVM, dist string) error { user := v.RemoteUsername if err := runCmdPassThrough("wsl", "-d", dist, "sh", "-c", fmt.Sprintf(appendPort, v.Port, v.Port)); err != nil { - return errors.Wrap(err, "could not configure SSH port for guest OS") + return fmt.Errorf("could not configure SSH port for guest OS: %w", err) } if err := pipeCmdPassThrough("wsl", withUser(configServices, user), "-d", dist, "sh"); err != nil { - return errors.Wrap(err, "could not configure systemd settings for guest OS") + return fmt.Errorf("could not configure systemd settings for guest OS: %w", err) } if err := pipeCmdPassThrough("wsl", sudoers, "-d", dist, "sh", "-c", "cat >> /etc/sudoers"); err != nil { - return errors.Wrap(err, "could not add wheel to sudoers") + return fmt.Errorf("could not add wheel to sudoers: %w", err) } if err := pipeCmdPassThrough("wsl", overrideSysusers, "-d", dist, "sh", "-c", "cat > /etc/systemd/system/systemd-sysusers.service.d/override.conf"); err != nil { - return errors.Wrap(err, "could not generate systemd-sysusers override for guest OS") + return fmt.Errorf("could not generate systemd-sysusers override for guest OS: %w", err) } lingerCmd := withUser("cat > /home/[USER]/.config/systemd/[USER]/linger-example.service", user) if err := pipeCmdPassThrough("wsl", lingerService, "-d", dist, "sh", "-c", lingerCmd); err != nil { - return errors.Wrap(err, "could not generate linger service for guest OS") + return fmt.Errorf("could not generate linger service for guest OS: %w", err) } if err := enableUserLinger(v, dist); err != nil { @@ -551,15 +551,15 @@ func configureSystem(v *MachineVM, dist string) error { } if err := pipeCmdPassThrough("wsl", withUser(lingerSetup, user), "-d", dist, "sh"); err != nil { - return errors.Wrap(err, "could not configure systemd settomgs for guest OS") + return fmt.Errorf("could not configure systemd settomgs for guest OS: %w", err) } if err := pipeCmdPassThrough("wsl", containersConf, "-d", dist, "sh", "-c", "cat > /etc/containers/containers.conf"); err != nil { - return errors.Wrap(err, "could not create containers.conf for guest OS") + return fmt.Errorf("could not create containers.conf for guest OS: %w", err) } if err := runCmdPassThrough("wsl", "-d", dist, "sh", "-c", "echo wsl > /etc/containers/podman-machine"); err != nil { - return errors.Wrap(err, "could not create podman-machine file for guest OS") + return fmt.Errorf("could not create podman-machine file for guest OS: %w", err) } return nil @@ -584,7 +584,7 @@ func configureProxy(dist string, useProxy bool) error { if err := pipeCmdPassThrough("wsl", content, "-d", dist, "sh", "-c", proxyConfigAttempt); err != nil { const failMessage = "Failure creating proxy configuration" if exitErr, isExit := err.(*exec.ExitError); isExit && exitErr.ExitCode() != 42 { - return errors.Wrap(err, failMessage) + return fmt.Errorf("%v: %w", failMessage, err) } fmt.Println("Installing proxy support") @@ -592,7 +592,7 @@ func configureProxy(dist string, useProxy bool) error { "cat > /usr/local/bin/proxyinit; chmod 755 /usr/local/bin/proxyinit") if err = pipeCmdPassThrough("wsl", content, "-d", dist, "/usr/local/bin/proxyinit"); err != nil { - return errors.Wrap(err, failMessage) + return fmt.Errorf("%v: %w", failMessage, err) } } @@ -602,7 +602,7 @@ func configureProxy(dist string, useProxy bool) error { func enableUserLinger(v *MachineVM, dist string) error { lingerCmd := "mkdir -p /var/lib/systemd/linger; touch /var/lib/systemd/linger/" + v.RemoteUsername if err := runCmdPassThrough("wsl", "-d", dist, "sh", "-c", lingerCmd); err != nil { - return errors.Wrap(err, "could not enable linger for remote user on guest OS") + return fmt.Errorf("could not enable linger for remote user on guest OS: %w", err) } return nil @@ -611,26 +611,26 @@ func enableUserLinger(v *MachineVM, dist string) error { func installScripts(dist string) error { if err := pipeCmdPassThrough("wsl", enterns, "-d", dist, "sh", "-c", "cat > /usr/local/bin/enterns; chmod 755 /usr/local/bin/enterns"); err != nil { - return errors.Wrap(err, "could not create enterns script for guest OS") + return fmt.Errorf("could not create enterns script for guest OS: %w", err) } if err := pipeCmdPassThrough("wsl", profile, "-d", dist, "sh", "-c", "cat > /etc/profile.d/enterns.sh"); err != nil { - return errors.Wrap(err, "could not create motd profile script for guest OS") + return fmt.Errorf("could not create motd profile script for guest OS: %w", err) } if err := pipeCmdPassThrough("wsl", wslmotd, "-d", dist, "sh", "-c", "cat > /etc/wslmotd"); err != nil { - return errors.Wrap(err, "could not create a WSL MOTD for guest OS") + return fmt.Errorf("could not create a WSL MOTD for guest OS: %w", err) } if err := pipeCmdPassThrough("wsl", bootstrap, "-d", dist, "sh", "-c", "cat > /root/bootstrap; chmod 755 /root/bootstrap"); err != nil { - return errors.Wrap(err, "could not create bootstrap script for guest OS") + return fmt.Errorf("could not create bootstrap script for guest OS: %w", err) } if err := pipeCmdPassThrough("wsl", proxyConfigSetup, "-d", dist, "sh", "-c", "cat > /usr/local/bin/proxyinit; chmod 755 /usr/local/bin/proxyinit"); err != nil { - return errors.Wrap(err, "could not create proxyinit script for guest OS") + return fmt.Errorf("could not create proxyinit script for guest OS: %w", err) } return nil @@ -673,10 +673,10 @@ func checkAndInstallWSL(opts machine.InitOptions) (bool, error) { func attemptFeatureInstall(opts machine.InitOptions, admin bool) error { if !winVersionAtLeast(10, 0, 18362) { - return errors.Errorf("Your version of Windows does not support WSL. Update to Windows 10 Build 19041 or later") + return errors.New("your version of Windows does not support WSL. Update to Windows 10 Build 19041 or later") } else if !winVersionAtLeast(10, 0, 19041) { fmt.Fprint(os.Stderr, wslOldVersion) - return errors.Errorf("WSL can not be automatically installed") + return errors.New("the WSL can not be automatically installed") } message := "WSL is not installed on this system, installing it.\n\n" @@ -690,7 +690,7 @@ func attemptFeatureInstall(opts machine.InitOptions, admin bool) error { "If you prefer, you may abort now, and perform a manual installation using the \"wsl --install\" command." if !opts.ReExec && MessageBox(message, "Podman Machine", false) != 1 { - return errors.Errorf("WSL installation aborted") + return errors.New("the WSL installation aborted") } if !opts.ReExec && !admin { @@ -726,12 +726,12 @@ func installWsl() error { defer log.Close() if err := runCmdPassThroughTee(log, "dism", "/online", "/enable-feature", "/featurename:Microsoft-Windows-Subsystem-Linux", "/all", "/norestart"); isMsiError(err) { - return errors.Wrap(err, "could not enable WSL Feature") + return fmt.Errorf("could not enable WSL Feature: %w", err) } if err = runCmdPassThroughTee(log, "dism", "/online", "/enable-feature", "/featurename:VirtualMachinePlatform", "/all", "/norestart"); isMsiError(err) { - return errors.Wrap(err, "could not enable Virtual Machine Feature") + return fmt.Errorf("could not enable Virtual Machine Feature: %w", err) } log.Close() @@ -765,7 +765,7 @@ func installWslKernel() error { } if err != nil { - return errors.Wrap(err, "could not install WSL Kernel") + return fmt.Errorf("could not install WSL Kernel: %w", err) } return nil @@ -922,23 +922,23 @@ func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) { if opts.Rootful != nil && v.Rootful != *opts.Rootful { err := v.setRootful(*opts.Rootful) if err != nil { - setErrors = append(setErrors, errors.Wrapf(err, "error setting rootful option")) + setErrors = append(setErrors, fmt.Errorf("error setting rootful option: %w", err)) } else { v.Rootful = *opts.Rootful } } if opts.CPUs != nil { - setErrors = append(setErrors, errors.Errorf("changing CPUs not supported for WSL machines")) + setErrors = append(setErrors, errors.New("changing CPUs not supported for WSL machines")) } if opts.Memory != nil { - setErrors = append(setErrors, errors.Errorf("changing memory not supported for WSL machines")) + setErrors = append(setErrors, errors.New("changing memory not supported for WSL machines")) } if opts.DiskSize != nil { - setErrors = append(setErrors, errors.Errorf("changing Disk Size not supported for WSL machines")) + setErrors = append(setErrors, errors.New("changing Disk Size not supported for WSL machines")) } return setErrors, v.writeConfig() @@ -946,7 +946,7 @@ func (v *MachineVM) Set(_ string, opts machine.SetOptions) ([]error, error) { func (v *MachineVM) Start(name string, _ machine.StartOptions) error { if v.isRunning() { - return errors.Errorf("%q is already running", name) + return fmt.Errorf("%q is already running", name) } dist := toDist(name) @@ -957,7 +957,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { err := runCmdPassThrough("wsl", "-d", dist, "/root/bootstrap") if err != nil { - return errors.Wrap(err, "WSL bootstrap script failed") + return fmt.Errorf("the WSL bootstrap script failed: %w", err) } if !v.Rootful { @@ -999,7 +999,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error { func launchWinProxy(v *MachineVM) (bool, string, error) { machinePipe := toDist(v.Name) if !pipeAvailable(machinePipe) { - return false, "", errors.Errorf("could not start api proxy since expected pipe is not available: %s", machinePipe) + return false, "", fmt.Errorf("could not start api proxy since expected pipe is not available: %s", machinePipe) } globalName := false @@ -1047,7 +1047,7 @@ func launchWinProxy(v *MachineVM) (bool, string, error) { return globalName, pipePrefix + waitPipe, waitPipeExists(waitPipe, 30, func() error { active, exitCode := getProcessState(cmd.Process.Pid) if !active { - return errors.Errorf("win-sshproxy.exe failed to start, exit code: %d (see windows event logs)", exitCode) + return fmt.Errorf("win-sshproxy.exe failed to start, exit code: %d (see windows event logs)", exitCode) } return nil @@ -1185,7 +1185,7 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error { } if !wsl || !sysd { - return errors.Errorf("%q is not running", v.Name) + return fmt.Errorf("%q is not running", v.Name) } _, _, _ = v.updateTimeStamps(true) @@ -1197,12 +1197,12 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error { cmd := exec.Command("wsl", "-d", dist, "sh") cmd.Stdin = strings.NewReader(waitTerm) if err = cmd.Start(); err != nil { - return errors.Wrap(err, "Error executing wait command") + return fmt.Errorf("executing wait command: %w", err) } exitCmd := exec.Command("wsl", "-d", dist, "/usr/local/bin/enterns", "systemctl", "exit", "0") if err = exitCmd.Run(); err != nil { - return errors.Wrap(err, "Error stopping sysd") + return fmt.Errorf("stopping sysd: %w", err) } if err = cmd.Wait(); err != nil { @@ -1283,7 +1283,7 @@ func (v *MachineVM) Remove(name string, opts machine.RemoveOptions) (string, fun var files []string if v.isRunning() { - return "", nil, errors.Errorf("running vm %q cannot be destroyed", v.Name) + return "", nil, fmt.Errorf("running vm %q cannot be destroyed", v.Name) } // Collect all the files that need to be destroyed @@ -1355,7 +1355,7 @@ func (v *MachineVM) isRunning() bool { // Added ssh function to VM interface: pkg/machine/config/go : line 58 func (v *MachineVM) SSH(name string, opts machine.SSHOptions) error { if !v.isRunning() { - return errors.Errorf("vm %q is not running.", v.Name) + return fmt.Errorf("vm %q is not running.", v.Name) } username := opts.Username @@ -1655,3 +1655,7 @@ func (p *Provider) RemoveAndCleanMachines() error { } return prevErr } + +func (p *Provider) VMType() string { + return vmtype +} diff --git a/pkg/machine/wsl/util_windows.go b/pkg/machine/wsl/util_windows.go index b5c28e015..43f54fdd4 100644 --- a/pkg/machine/wsl/util_windows.go +++ b/pkg/machine/wsl/util_windows.go @@ -2,6 +2,7 @@ package wsl import ( "encoding/base64" + "errors" "fmt" "io/ioutil" "os" @@ -11,7 +12,6 @@ import ( "unicode/utf16" "unsafe" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" @@ -157,9 +157,9 @@ func relaunchElevatedWait() error { case syscall.WAIT_OBJECT_0: break case syscall.WAIT_FAILED: - return errors.Wrap(err, "could not wait for process, failed") + return fmt.Errorf("could not wait for process, failed: %w", err) default: - return errors.Errorf("could not wait for process, unknown error") + return errors.New("could not wait for process, unknown error") } var code uint32 if err := syscall.GetExitCodeProcess(handle, &code); err != nil { @@ -174,7 +174,7 @@ func relaunchElevatedWait() error { func wrapMaybe(err error, message string) error { if err != nil { - return errors.Wrap(err, message) + return fmt.Errorf("%v: %w", message, err) } return errors.New(message) @@ -182,10 +182,10 @@ func wrapMaybe(err error, message string) error { func wrapMaybef(err error, format string, args ...interface{}) error { if err != nil { - return errors.Wrapf(err, format, args...) + return fmt.Errorf(format+": %w", append(args, err)...) } - return errors.Errorf(format, args...) + return fmt.Errorf(format, args...) } func reboot() error { @@ -202,14 +202,14 @@ func reboot() error { dataDir, err := homedir.GetDataHome() if err != nil { - return errors.Wrap(err, "could not determine data directory") + return fmt.Errorf("could not determine data directory: %w", err) } if err := os.MkdirAll(dataDir, 0755); err != nil { - return errors.Wrap(err, "could not create data directory") + return fmt.Errorf("could not create data directory: %w", err) } commFile := filepath.Join(dataDir, "podman-relaunch.dat") if err := ioutil.WriteFile(commFile, []byte(encoded), 0600); err != nil { - return errors.Wrap(err, "could not serialize command state") + return fmt.Errorf("could not serialize command state: %w", err) } command := fmt.Sprintf(pShellLaunch, commFile) @@ -244,7 +244,7 @@ func reboot() error { procExit := user32.NewProc("ExitWindowsEx") if ret, _, err := procExit.Call(EWX_REBOOT|EWX_RESTARTAPPS|EWX_FORCEIFHUNG, SHTDN_REASON_MAJOR_APPLICATION|SHTDN_REASON_MINOR_INSTALLATION|SHTDN_REASON_FLAG_PLANNED); ret != 1 { - return errors.Wrap(err, "reboot failed") + return fmt.Errorf("reboot failed: %w", err) } return nil @@ -262,19 +262,19 @@ func obtainShutdownPrivilege() error { var hToken uintptr if ret, _, err := OpenProcessToken.Call(uintptr(proc), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, uintptr(unsafe.Pointer(&hToken))); ret != 1 { - return errors.Wrap(err, "error opening process token") + return fmt.Errorf("error opening process token: %w", err) } var privs TokenPrivileges if ret, _, err := LookupPrivilegeValue.Call(uintptr(0), uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(SeShutdownName))), uintptr(unsafe.Pointer(&(privs.privileges[0].luid)))); ret != 1 { - return errors.Wrap(err, "error looking up shutdown privilege") + return fmt.Errorf("error looking up shutdown privilege: %w", err) } privs.privilegeCount = 1 privs.privileges[0].attributes = SE_PRIVILEGE_ENABLED if ret, _, err := AdjustTokenPrivileges.Call(hToken, 0, uintptr(unsafe.Pointer(&privs)), 0, uintptr(0), 0); ret != 1 { - return errors.Wrap(err, "error enabling shutdown privilege on token") + return fmt.Errorf("error enabling shutdown privilege on token: %w", err) } return nil @@ -295,13 +295,13 @@ func getProcessState(pid int) (active bool, exitCode int) { func addRunOnceRegistryEntry(command string) error { k, _, err := registry.CreateKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\RunOnce`, registry.WRITE) if err != nil { - return errors.Wrap(err, "could not open RunOnce registry entry") + return fmt.Errorf("could not open RunOnce registry entry: %w", err) } defer k.Close() if err := k.SetExpandStringValue("podman-machine", command); err != nil { - return errors.Wrap(err, "could not open RunOnce registry entry") + return fmt.Errorf("could not open RunOnce registry entry: %w", err) } return nil diff --git a/pkg/parallel/parallel.go b/pkg/parallel/parallel.go index 4da7e0f89..7209f8aca 100644 --- a/pkg/parallel/parallel.go +++ b/pkg/parallel/parallel.go @@ -2,9 +2,10 @@ package parallel import ( "context" + "errors" + "fmt" "sync" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sync/semaphore" ) @@ -59,7 +60,7 @@ func Enqueue(ctx context.Context, fn func() error) <-chan error { defer close(retChan) if err := jobControl.Acquire(ctx, 1); err != nil { - retChan <- errors.Wrapf(err, "error acquiring job control semaphore") + retChan <- fmt.Errorf("error acquiring job control semaphore: %w", err) return } diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index fde621b72..b0012b32b 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -6,6 +6,7 @@ package rootless import ( "bufio" "bytes" + "errors" "fmt" "io" "io/ioutil" @@ -23,7 +24,6 @@ import ( "github.com/containers/storage/pkg/idtools" pmount "github.com/containers/storage/pkg/mount" "github.com/containers/storage/pkg/unshare" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/syndtr/gocapability/capability" "golang.org/x/sys/unix" @@ -126,7 +126,7 @@ func tryMappingTool(uid bool, pid int, hostID int, mappings []idtools.IDMap) err } path, err := exec.LookPath(tool) if err != nil { - return errors.Wrapf(err, "command required for rootless mode with multiple IDs") + return fmt.Errorf("command required for rootless mode with multiple IDs: %w", err) } appendTriplet := func(l []string, a, b, c int) []string { @@ -143,7 +143,7 @@ func tryMappingTool(uid bool, pid int, hostID int, mappings []idtools.IDMap) err what = "GID" where = "/etc/subgid" } - return errors.Errorf("invalid configuration: the specified mapping %d:%d in %q includes the user %s", i.HostID, i.Size, where, what) + return fmt.Errorf("invalid configuration: the specified mapping %d:%d in %q includes the user %s", i.HostID, i.Size, where, what) } args = appendTriplet(args, i.ContainerID+1, i.HostID, i.Size) } @@ -160,7 +160,7 @@ func tryMappingTool(uid bool, pid int, hostID int, mappings []idtools.IDMap) err } else if !isSet { errorStr = fmt.Sprintf("%s: should have %s or have filecaps %s", errorStr, idtype, idtype) } - return errors.Wrapf(err, errorStr) + return fmt.Errorf("%v: %w", errorStr, err) } return nil } @@ -182,7 +182,7 @@ func joinUserAndMountNS(pid uint, pausePid string) (bool, int, error) { pidC := C.reexec_userns_join(C.int(pid), cPausePid) if int(pidC) < 0 { - return false, -1, errors.Errorf("cannot re-exec process to join the existing user namespace") + return false, -1, fmt.Errorf("cannot re-exec process to join the existing user namespace") } ret := C.reexec_in_user_namespace_wait(pidC, 0) @@ -313,7 +313,7 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo pidC := C.reexec_in_user_namespace(C.int(r.Fd()), cPausePid, cFileToRead, fileOutputFD) pid = int(pidC) if pid < 0 { - return false, -1, errors.Errorf("cannot re-exec process") + return false, -1, fmt.Errorf("cannot re-exec process") } uids, gids, err := GetConfiguredMappings() @@ -343,13 +343,13 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo setgroups := fmt.Sprintf("/proc/%d/setgroups", pid) err = ioutil.WriteFile(setgroups, []byte("deny\n"), 0666) if err != nil { - return false, -1, errors.Wrapf(err, "cannot write setgroups file") + return false, -1, fmt.Errorf("cannot write setgroups file: %w", err) } logrus.Debugf("write setgroups file exited with 0") err = ioutil.WriteFile(uidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Geteuid())), 0666) if err != nil { - return false, -1, errors.Wrapf(err, "cannot write uid_map") + return false, -1, fmt.Errorf("cannot write uid_map: %w", err) } logrus.Debugf("write uid_map exited with 0") } @@ -369,19 +369,19 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo if !gidsMapped { err = ioutil.WriteFile(gidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Getegid())), 0666) if err != nil { - return false, -1, errors.Wrapf(err, "cannot write gid_map") + return false, -1, fmt.Errorf("cannot write gid_map: %w", err) } } _, err = w.Write([]byte("0")) if err != nil { - return false, -1, errors.Wrapf(err, "write to sync pipe") + return false, -1, fmt.Errorf("write to sync pipe: %w", err) } b := make([]byte, 1) _, err = w.Read(b) if err != nil { - return false, -1, errors.Wrapf(err, "read from sync pipe") + return false, -1, fmt.Errorf("read from sync pipe: %w", err) } if fileOutput != nil { @@ -474,7 +474,7 @@ func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []st pausePid, err = strconv.Atoi(string(data)) if err != nil { - lastErr = errors.Wrapf(err, "cannot parse file %q", path) + lastErr = fmt.Errorf("cannot parse file %q: %w", path, err) continue } } else { @@ -503,7 +503,7 @@ func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []st n, err := r.Read(b) if err != nil { - lastErr = errors.Wrapf(err, "cannot read %q", path) + lastErr = fmt.Errorf("cannot read %q: %w", path, err) continue } @@ -525,7 +525,7 @@ func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []st if lastErr != nil { return false, 0, lastErr } - return false, 0, errors.Wrapf(unix.ESRCH, "could not find any running process") + return false, 0, fmt.Errorf("could not find any running process: %w", unix.ESRCH) } // ReadMappingsProc parses and returns the ID mappings at the specified path. @@ -545,7 +545,7 @@ func ReadMappingsProc(path string) ([]idtools.IDMap, error) { if err == io.EOF { return mappings, nil } - return nil, errors.Wrapf(err, "cannot read line from %s", path) + return nil, fmt.Errorf("cannot read line from %s: %w", path, err) } if line == nil { return mappings, nil @@ -553,7 +553,7 @@ func ReadMappingsProc(path string) ([]idtools.IDMap, error) { containerID, hostID, size := 0, 0, 0 if _, err := fmt.Sscanf(string(line), "%d %d %d", &containerID, &hostID, &size); err != nil { - return nil, errors.Wrapf(err, "cannot parse %s", string(line)) + return nil, fmt.Errorf("cannot parse %s: %w", string(line), err) } mappings = append(mappings, idtools.IDMap{ContainerID: containerID, HostID: hostID, Size: size}) } diff --git a/pkg/rootless/rootless_unsupported.go b/pkg/rootless/rootless_unsupported.go index fe164e235..a77e7e077 100644 --- a/pkg/rootless/rootless_unsupported.go +++ b/pkg/rootless/rootless_unsupported.go @@ -4,10 +4,10 @@ package rootless import ( + "errors" "os" "github.com/containers/storage/pkg/idtools" - "github.com/pkg/errors" ) // IsRootless returns whether the user is rootless diff --git a/pkg/seccomp/seccomp.go b/pkg/seccomp/seccomp.go index 4502c608f..d19d45960 100644 --- a/pkg/seccomp/seccomp.go +++ b/pkg/seccomp/seccomp.go @@ -1,9 +1,8 @@ package seccomp import ( + "fmt" "sort" - - "github.com/pkg/errors" ) // ContainerImageLabel is the key of the image annotation embedding a seccomp @@ -50,5 +49,5 @@ func LookupPolicy(s string) (Policy, error) { } sort.Strings(keys) - return -1, errors.Errorf("invalid seccomp policy %q: valid policies are %+q", s, keys) + return -1, fmt.Errorf("invalid seccomp policy %q: valid policies are %+q", s, keys) } diff --git a/pkg/specgen/config_unsupported.go b/pkg/specgen/config_unsupported.go index a6bf77277..becfd2eaf 100644 --- a/pkg/specgen/config_unsupported.go +++ b/pkg/specgen/config_unsupported.go @@ -4,9 +4,10 @@ package specgen import ( + "errors" + "github.com/containers/common/libimage" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" ) func (s *SpecGenerator) getSeccompConfig(configSpec *spec.Spec, img *libimage.Image) (*spec.LinuxSeccomp, error) { diff --git a/pkg/specgen/container_validate.go b/pkg/specgen/container_validate.go index 5616a4511..63d94b6b3 100644 --- a/pkg/specgen/container_validate.go +++ b/pkg/specgen/container_validate.go @@ -1,6 +1,8 @@ package specgen import ( + "errors" + "fmt" "strconv" "strings" @@ -8,7 +10,6 @@ import ( "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/rootless" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" ) var ( @@ -23,7 +24,7 @@ var ( ) func exclusiveOptions(opt1, opt2 string) error { - return errors.Errorf("%s and %s are mutually exclusive options", opt1, opt2) + return fmt.Errorf("%s and %s are mutually exclusive options", opt1, opt2) } // Validate verifies that the given SpecGenerator is valid and satisfies required @@ -33,18 +34,18 @@ func (s *SpecGenerator) Validate() error { // associated with them because those should be on the infra container. if len(s.Pod) > 0 && s.NetNS.NSMode == FromPod { if len(s.Networks) > 0 { - return errors.Wrap(define.ErrNetworkOnPodContainer, "networks must be defined when the pod is created") + return fmt.Errorf("networks must be defined when the pod is created: %w", define.ErrNetworkOnPodContainer) } if len(s.PortMappings) > 0 || s.PublishExposedPorts { - return errors.Wrap(define.ErrNetworkOnPodContainer, "published or exposed ports must be defined when the pod is created") + return fmt.Errorf("published or exposed ports must be defined when the pod is created: %w", define.ErrNetworkOnPodContainer) } if len(s.HostAdd) > 0 { - return errors.Wrap(define.ErrNetworkOnPodContainer, "extra host entries must be specified on the pod") + return fmt.Errorf("extra host entries must be specified on the pod: %w", define.ErrNetworkOnPodContainer) } } if s.NetNS.IsContainer() && len(s.HostAdd) > 0 { - return errors.Wrap(ErrInvalidSpecConfig, "cannot set extra host entries when the container is joined to another containers network namespace") + return fmt.Errorf("cannot set extra host entries when the container is joined to another containers network namespace: %w", ErrInvalidSpecConfig) } // @@ -52,22 +53,23 @@ func (s *SpecGenerator) Validate() error { // // Rootfs and Image cannot both populated if len(s.ContainerStorageConfig.Image) > 0 && len(s.ContainerStorageConfig.Rootfs) > 0 { - return errors.Wrap(ErrInvalidSpecConfig, "both image and rootfs cannot be simultaneously") + return fmt.Errorf("both image and rootfs cannot be simultaneously: %w", ErrInvalidSpecConfig) } // Cannot set hostname and utsns if len(s.ContainerBasicConfig.Hostname) > 0 && !s.ContainerBasicConfig.UtsNS.IsPrivate() { if s.ContainerBasicConfig.UtsNS.IsPod() { - return errors.Wrap(ErrInvalidSpecConfig, "cannot set hostname when joining the pod UTS namespace") + return fmt.Errorf("cannot set hostname when joining the pod UTS namespace: %w", ErrInvalidSpecConfig) } - return errors.Wrap(ErrInvalidSpecConfig, "cannot set hostname when running in the host UTS namespace") + + return fmt.Errorf("cannot set hostname when running in the host UTS namespace: %w", ErrInvalidSpecConfig) } // systemd values must be true, false, or always if len(s.ContainerBasicConfig.Systemd) > 0 && !util.StringInSlice(strings.ToLower(s.ContainerBasicConfig.Systemd), SystemDValues) { - return errors.Wrapf(ErrInvalidSpecConfig, "--systemd values must be one of %q", strings.Join(SystemDValues, ", ")) + return fmt.Errorf("--systemd values must be one of %q: %w", strings.Join(SystemDValues, ", "), ErrInvalidSpecConfig) } // sdnotify values must be container, conmon, or ignore if len(s.ContainerBasicConfig.SdNotifyMode) > 0 && !util.StringInSlice(strings.ToLower(s.ContainerBasicConfig.SdNotifyMode), SdNotifyModeValues) { - return errors.Wrapf(ErrInvalidSpecConfig, "--sdnotify values must be one of %q", strings.Join(SdNotifyModeValues, ", ")) + return fmt.Errorf("--sdnotify values must be one of %q: %w", strings.Join(SdNotifyModeValues, ", "), ErrInvalidSpecConfig) } // @@ -79,12 +81,12 @@ func (s *SpecGenerator) Validate() error { } // imagevolumemode must be one of ignore, tmpfs, or anonymous if given if len(s.ContainerStorageConfig.ImageVolumeMode) > 0 && !util.StringInSlice(strings.ToLower(s.ContainerStorageConfig.ImageVolumeMode), ImageVolumeModeValues) { - return errors.Errorf("invalid ImageVolumeMode %q, value must be one of %s", + return fmt.Errorf("invalid ImageVolumeMode %q, value must be one of %s", s.ContainerStorageConfig.ImageVolumeMode, strings.Join(ImageVolumeModeValues, ",")) } // shmsize conflicts with IPC namespace if s.ContainerStorageConfig.ShmSize != nil && (s.ContainerStorageConfig.IpcNS.IsHost() || s.ContainerStorageConfig.IpcNS.IsNone()) { - return errors.Errorf("cannot set shmsize when running in the %s IPC Namespace", s.ContainerStorageConfig.IpcNS) + return fmt.Errorf("cannot set shmsize when running in the %s IPC Namespace", s.ContainerStorageConfig.IpcNS) } // @@ -92,7 +94,7 @@ func (s *SpecGenerator) Validate() error { // // userns and idmappings conflict if s.UserNS.IsPrivate() && s.IDMappings == nil { - return errors.Wrap(ErrInvalidSpecConfig, "IDMappings are required when not creating a User namespace") + return fmt.Errorf("IDMappings are required when not creating a User namespace: %w", ErrInvalidSpecConfig) } // @@ -142,11 +144,11 @@ func (s *SpecGenerator) Validate() error { for _, limit := range tmpnproc { limitSplit := strings.SplitN(limit, "=", 2) if len(limitSplit) < 2 { - return errors.Wrapf(invalidUlimitFormatError, "missing = in %s", limit) + return fmt.Errorf("missing = in %s: %w", limit, invalidUlimitFormatError) } valueSplit := strings.SplitN(limitSplit[1], ":", 2) if len(valueSplit) < 2 { - return errors.Wrapf(invalidUlimitFormatError, "missing : in %s", limit) + return fmt.Errorf("missing : in %s: %w", limit, invalidUlimitFormatError) } hard, err := strconv.Atoi(valueSplit[0]) if err != nil { @@ -196,7 +198,7 @@ func (s *SpecGenerator) Validate() error { } if s.NetNS.NSMode != Bridge && len(s.Networks) > 0 { // Note that we also get the ip and mac in the networks map - return errors.New("Networks and static ip/mac address can only be used with Bridge mode networking") + return errors.New("networks and static ip/mac address can only be used with Bridge mode networking") } return nil diff --git a/pkg/specgen/generate/config_linux.go b/pkg/specgen/generate/config_linux.go index 60d87a8fd..a46966161 100644 --- a/pkg/specgen/generate/config_linux.go +++ b/pkg/specgen/generate/config_linux.go @@ -13,7 +13,6 @@ import ( "github.com/containers/podman/v4/pkg/util" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -46,7 +45,7 @@ func DevicesFromPath(g *generate.Generator, devicePath string) error { } if len(devs) > 2 { if devmode != "" { - return errors.Wrapf(unix.EINVAL, "invalid device specification %s", devicePath) + return fmt.Errorf("invalid device specification %s: %w", devicePath, unix.EINVAL) } devmode = devs[2] } @@ -60,7 +59,7 @@ func DevicesFromPath(g *generate.Generator, devicePath string) error { device = fmt.Sprintf("%s:%s", device, devmode) } if err := addDevice(g, device); err != nil { - return errors.Wrapf(err, "failed to add %s device", dpath) + return fmt.Errorf("failed to add %s device: %w", dpath, err) } } return nil @@ -68,7 +67,7 @@ func DevicesFromPath(g *generate.Generator, devicePath string) error { return err } if !found { - return errors.Wrapf(unix.EINVAL, "no devices found in %s", devicePath) + return fmt.Errorf("no devices found in %s: %w", devicePath, unix.EINVAL) } return nil } @@ -131,7 +130,7 @@ func addDevice(g *generate.Generator, device string) error { } dev, err := util.DeviceFromPath(src) if err != nil { - return errors.Wrapf(err, "%s is not a valid device", src) + return fmt.Errorf("%s is not a valid device: %w", src, err) } if rootless.IsRootless() { if _, err := os.Stat(src); err != nil { diff --git a/pkg/specgen/generate/config_linux_cgo.go b/pkg/specgen/generate/config_linux_cgo.go index efab6679a..74ba4aeeb 100644 --- a/pkg/specgen/generate/config_linux_cgo.go +++ b/pkg/specgen/generate/config_linux_cgo.go @@ -5,6 +5,8 @@ package generate import ( "context" + "errors" + "fmt" "io/ioutil" "github.com/containers/common/libimage" @@ -12,7 +14,6 @@ import ( "github.com/containers/podman/v4/pkg/seccomp" "github.com/containers/podman/v4/pkg/specgen" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -39,7 +40,7 @@ func getSeccompConfig(s *specgen.SpecGenerator, configSpec *spec.Spec, img *libi logrus.Debug("Loading seccomp profile from the security config") seccompConfig, err = goSeccomp.LoadProfile(imagePolicy, configSpec) if err != nil { - return nil, errors.Wrap(err, "loading seccomp profile failed") + return nil, fmt.Errorf("loading seccomp profile failed: %w", err) } return seccompConfig, nil } @@ -48,17 +49,17 @@ func getSeccompConfig(s *specgen.SpecGenerator, configSpec *spec.Spec, img *libi logrus.Debugf("Loading seccomp profile from %q", s.SeccompProfilePath) seccompProfile, err := ioutil.ReadFile(s.SeccompProfilePath) if err != nil { - return nil, errors.Wrap(err, "opening seccomp profile failed") + return nil, fmt.Errorf("opening seccomp profile failed: %w", err) } seccompConfig, err = goSeccomp.LoadProfile(string(seccompProfile), configSpec) if err != nil { - return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", s.SeccompProfilePath) + return nil, fmt.Errorf("loading seccomp profile (%s) failed: %w", s.SeccompProfilePath, err) } } else { logrus.Debug("Loading default seccomp profile") seccompConfig, err = goSeccomp.GetDefaultProfile(configSpec) if err != nil { - return nil, errors.Wrapf(err, "loading seccomp profile (%s) failed", s.SeccompProfilePath) + return nil, fmt.Errorf("loading seccomp profile (%s) failed: %w", s.SeccompProfilePath, err) } } diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go index 8fdd87adf..2248c9235 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -3,6 +3,7 @@ package generate import ( "context" "encoding/json" + "errors" "fmt" "os" "strings" @@ -17,7 +18,6 @@ import ( "github.com/containers/podman/v4/pkg/signal" "github.com/containers/podman/v4/pkg/specgen" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -115,7 +115,7 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat // Get Default Environment from containers.conf defaultEnvs, err := envLib.ParseSlice(rtc.GetDefaultEnvEx(s.EnvHost, s.HTTPProxy)) if err != nil { - return nil, errors.Wrap(err, "error parsing fields in containers.conf") + return nil, fmt.Errorf("error parsing fields in containers.conf: %w", err) } var envs map[string]string @@ -125,7 +125,7 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat // already, overriding the default environments envs, err = envLib.ParseSlice(inspectData.Config.Env) if err != nil { - return nil, errors.Wrap(err, "Env fields from image failed to parse") + return nil, fmt.Errorf("env fields from image failed to parse: %w", err) } defaultEnvs = envLib.Join(envLib.DefaultEnvVariables(), envLib.Join(defaultEnvs, envs)) } @@ -141,7 +141,7 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat // any case. osEnv, err := envLib.ParseSlice(os.Environ()) if err != nil { - return nil, errors.Wrap(err, "error parsing host environment variables") + return nil, fmt.Errorf("error parsing host environment variables: %w", err) } // Caller Specified defaults if s.EnvHost { diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index 6b2e90b22..51d290bb4 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -3,6 +3,8 @@ package generate import ( "context" "encoding/json" + "errors" + "fmt" "path/filepath" "strings" @@ -15,7 +17,6 @@ import ( "github.com/containers/podman/v4/pkg/util" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -34,7 +35,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener if s.Pod != "" { pod, err = rt.LookupPod(s.Pod) if err != nil { - return nil, nil, nil, errors.Wrapf(err, "error retrieving pod %s", s.Pod) + return nil, nil, nil, fmt.Errorf("error retrieving pod %s: %w", s.Pod, err) } if pod.HasInfraContainer() { infra, err = pod.InfraContainer() @@ -133,8 +134,14 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener options = append(options, libpod.WithRootFSFromImage(newImage.ID(), resolvedImageName, s.RawImageName)) } + + _, err = rt.LookupPod(s.Hostname) + if len(s.Hostname) > 0 && !s.UtsNS.IsPrivate() && err == nil { + // ok, we are incorrectly setting the pod as the hostname, lets undo that before validation + s.Hostname = "" + } if err := s.Validate(); err != nil { - return nil, nil, nil, errors.Wrap(err, "invalid config provided") + return nil, nil, nil, fmt.Errorf("invalid config provided: %w", err) } finalMounts, finalVolumes, finalOverlays, err := finalizeMounts(ctx, s, rt, rtc, newImage) @@ -326,7 +333,7 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l } } default: - return nil, errors.Wrapf(err, "invalid value %q systemd option requires 'true, false, always'", s.Systemd) + return nil, fmt.Errorf("invalid value %q systemd option requires 'true, false, always': %w", s.Systemd, err) } logrus.Debugf("using systemd mode: %t", useSystemd) if useSystemd { @@ -335,7 +342,7 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l if s.StopSignal == nil { stopSignal, err := util.ParseSignal("RTMIN+3") if err != nil { - return nil, errors.Wrapf(err, "error parsing systemd signal") + return nil, fmt.Errorf("error parsing systemd signal: %w", err) } s.StopSignal = &stopSignal } @@ -530,7 +537,7 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l for _, ctr := range s.DependencyContainers { depCtr, err := rt.LookupContainer(ctr) if err != nil { - return nil, errors.Wrapf(err, "%q is not a valid container, cannot be used as a dependency", ctr) + return nil, fmt.Errorf("%q is not a valid container, cannot be used as a dependency: %w", ctr, err) } deps = append(deps, depCtr) } diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go index c254b8192..454a1e1d0 100644 --- a/pkg/specgen/generate/kube/kube.go +++ b/pkg/specgen/generate/kube/kube.go @@ -3,6 +3,7 @@ package kube import ( "context" "encoding/json" + "errors" "fmt" "math" "net" @@ -29,7 +30,6 @@ import ( "github.com/docker/docker/pkg/system" "github.com/docker/go-units" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -146,7 +146,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener // pod name should be non-empty for Deployment objects to be able to create // multiple pods having containers with unique names if len(opts.PodName) < 1 { - return nil, errors.Errorf("got empty pod name on container creation when playing kube") + return nil, errors.New("got empty pod name on container creation when playing kube") } s.Name = fmt.Sprintf("%s-%s", opts.PodName, opts.Container.Name) @@ -163,7 +163,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener for _, o := range opts.LogOptions { split := strings.SplitN(o, "=", 2) if len(split) < 2 { - return nil, errors.Errorf("invalid log option %q", o) + return nil, fmt.Errorf("invalid log option %q", o) } switch strings.ToLower(split[0]) { case "driver": @@ -179,7 +179,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener default: switch len(split[1]) { case 0: - return nil, errors.Wrapf(define.ErrInvalidArg, "invalid log option") + return nil, fmt.Errorf("invalid log option: %w", define.ErrInvalidArg) default: // tags for journald only if s.LogConfiguration.Driver == "" || s.LogConfiguration.Driver == define.JournaldLogging { @@ -196,7 +196,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener setupSecurityContext(s, opts.Container.SecurityContext, opts.PodSecurityContext) err := setupLivenessProbe(s, opts.Container, opts.RestartPolicy) if err != nil { - return nil, errors.Wrap(err, "Failed to configure livenessProbe") + return nil, fmt.Errorf("failed to configure livenessProbe: %w", err) } // Since we prefix the container name with pod name to work-around the uniqueness requirement, @@ -207,7 +207,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener s.ResourceLimits = &spec.LinuxResources{} milliCPU, err := quantityToInt64(opts.Container.Resources.Limits.Cpu()) if err != nil { - return nil, errors.Wrap(err, "Failed to set CPU quota") + return nil, fmt.Errorf("failed to set CPU quota: %w", err) } if milliCPU > 0 { period, quota := util.CoresToPeriodAndQuota(float64(milliCPU)) @@ -219,12 +219,12 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener limit, err := quantityToInt64(opts.Container.Resources.Limits.Memory()) if err != nil { - return nil, errors.Wrap(err, "Failed to set memory limit") + return nil, fmt.Errorf("failed to set memory limit: %w", err) } memoryRes, err := quantityToInt64(opts.Container.Resources.Requests.Memory()) if err != nil { - return nil, errors.Wrap(err, "Failed to set memory reservation") + return nil, fmt.Errorf("failed to set memory reservation: %w", err) } if limit > 0 || memoryRes > 0 { @@ -337,7 +337,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener for _, volume := range opts.Container.VolumeMounts { volumeSource, exists := opts.Volumes[volume.Name] if !exists { - return nil, errors.Errorf("Volume mount %s specified for container but not configured in volumes", volume.Name) + return nil, fmt.Errorf("volume mount %s specified for container but not configured in volumes", volume.Name) } // Skip if the volume is optional. This means that a configmap for a configmap volume was not found but it was // optional so we can move on without throwing an error @@ -399,7 +399,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener } s.Devices = append(s.Devices, device) default: - return nil, errors.Errorf("Unsupported volume source type") + return nil, errors.New("unsupported volume source type") } } @@ -432,21 +432,21 @@ func parseMountPath(mountPath string, readOnly bool, propagationMode *v1.MountPr options := []string{} splitVol := strings.Split(mountPath, ":") if len(splitVol) > 2 { - return "", options, errors.Errorf("%q incorrect volume format, should be ctr-dir[:option]", mountPath) + return "", options, fmt.Errorf("%q incorrect volume format, should be ctr-dir[:option]", mountPath) } dest := splitVol[0] if len(splitVol) > 1 { options = strings.Split(splitVol[1], ",") } if err := parse.ValidateVolumeCtrDir(dest); err != nil { - return "", options, errors.Wrapf(err, "parsing MountPath") + return "", options, fmt.Errorf("parsing MountPath: %w", err) } if readOnly { options = append(options, "ro") } opts, err := parse.ValidateVolumeOpts(options) if err != nil { - return "", opts, errors.Wrapf(err, "parsing MountOptions") + return "", opts, fmt.Errorf("parsing MountOptions: %w", err) } if propagationMode != nil { switch *propagationMode { @@ -457,7 +457,7 @@ func parseMountPath(mountPath string, readOnly bool, propagationMode *v1.MountPr case v1.MountPropagationBidirectional: opts = append(opts, "rshared") default: - return "", opts, errors.Errorf("unknown propagation mode %q", *propagationMode) + return "", opts, fmt.Errorf("unknown propagation mode %q", *propagationMode) } } return dest, opts, nil @@ -504,7 +504,7 @@ func setupLivenessProbe(s *specgen.SpecGenerator, containerYAML v1.Container, re func makeHealthCheck(inCmd string, interval int32, retries int32, timeout int32, startPeriod int32) (*manifest.Schema2HealthConfig, error) { // Every healthcheck requires a command if len(inCmd) == 0 { - return nil, errors.New("Must define a healthcheck command for all healthchecks") + return nil, errors.New("must define a healthcheck command for all healthchecks") } // first try to parse option value as JSON array of strings... @@ -630,7 +630,7 @@ func quantityToInt64(quantity *resource.Quantity) (int64, error) { return i, nil } - return 0, errors.Errorf("Quantity cannot be represented as int64: %v", quantity) + return 0, fmt.Errorf("quantity cannot be represented as int64: %v", quantity) } // read a k8s secret in JSON format from the secret manager @@ -642,7 +642,7 @@ func k8sSecretFromSecretManager(name string, secretsManager *secrets.SecretsMana var secrets map[string][]byte if err := json.Unmarshal(jsonSecret, &secrets); err != nil { - return nil, errors.Errorf("Secret %v is not valid JSON: %v", name, err) + return nil, fmt.Errorf("secret %v is not valid JSON: %v", name, err) } return secrets, nil } @@ -653,7 +653,7 @@ func envVarsFrom(envFrom v1.EnvFromSource, opts *CtrSpecGenOptions) (map[string] if envFrom.ConfigMapRef != nil { cmRef := envFrom.ConfigMapRef - err := errors.Errorf("Configmap %v not found", cmRef.Name) + err := fmt.Errorf("configmap %v not found", cmRef.Name) for _, c := range opts.ConfigMaps { if cmRef.Name == c.Name { @@ -689,14 +689,14 @@ func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (*string, error) { if env.ValueFrom != nil { if env.ValueFrom.ConfigMapKeyRef != nil { cmKeyRef := env.ValueFrom.ConfigMapKeyRef - err := errors.Errorf("Cannot set env %v: configmap %v not found", env.Name, cmKeyRef.Name) + err := fmt.Errorf("cannot set env %v: configmap %v not found", env.Name, cmKeyRef.Name) for _, c := range opts.ConfigMaps { if cmKeyRef.Name == c.Name { if value, ok := c.Data[cmKeyRef.Key]; ok { return &value, nil } - err = errors.Errorf("Cannot set env %v: key %s not found in configmap %v", env.Name, cmKeyRef.Key, cmKeyRef.Name) + err = fmt.Errorf("cannot set env %v: key %s not found in configmap %v", env.Name, cmKeyRef.Key, cmKeyRef.Name) break } } @@ -714,10 +714,10 @@ func envVarValue(env v1.EnvVar, opts *CtrSpecGenOptions) (*string, error) { value := string(val) return &value, nil } - err = errors.Errorf("Secret %v has not %v key", secKeyRef.Name, secKeyRef.Key) + err = fmt.Errorf("secret %v has not %v key", secKeyRef.Name, secKeyRef.Key) } if secKeyRef.Optional == nil || !*secKeyRef.Optional { - return nil, errors.Errorf("Cannot set env %v: %v", env.Name, err) + return nil, fmt.Errorf("cannot set env %v: %v", env.Name, err) } return nil, nil } @@ -761,8 +761,8 @@ func envVarValueFieldRef(env v1.EnvVar, opts *CtrSpecGenOptions) (*string, error return &annotationValue, nil } - return nil, errors.Errorf( - "Can not set env %v. Reason: fieldPath %v is either not valid or not supported", + return nil, fmt.Errorf( + "can not set env %v. Reason: fieldPath %v is either not valid or not supported", env.Name, fieldPath, ) } @@ -796,15 +796,15 @@ func envVarValueResourceFieldRef(env v1.EnvVar, opts *CtrSpecGenOptions) (*strin value = resources.Requests.Cpu() isValidDivisor = isCPUDivisor(divisor) default: - return nil, errors.Errorf( - "Can not set env %v. Reason: resource %v is either not valid or not supported", + return nil, fmt.Errorf( + "can not set env %v. Reason: resource %v is either not valid or not supported", env.Name, resourceName, ) } if !isValidDivisor { - return nil, errors.Errorf( - "Can not set env %s. Reason: divisor value %s is not valid", + return nil, fmt.Errorf( + "can not set env %s. Reason: divisor value %s is not valid", env.Name, divisor.String(), ) } diff --git a/pkg/specgen/generate/kube/seccomp.go b/pkg/specgen/generate/kube/seccomp.go index 8f93b34ff..6e3accd8b 100644 --- a/pkg/specgen/generate/kube/seccomp.go +++ b/pkg/specgen/generate/kube/seccomp.go @@ -1,12 +1,12 @@ package kube import ( + "fmt" "path/filepath" "strings" "github.com/containers/podman/v4/libpod" v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1" - "github.com/pkg/errors" ) // KubeSeccompPaths holds information about a pod YAML's seccomp configuration @@ -42,7 +42,7 @@ func InitializeSeccompPaths(annotations map[string]string, profileRoot string) ( // this could be caused by a user inputting either of // container.seccomp.security.alpha.kubernetes.io{,/} // both of which are invalid - return nil, errors.Errorf("Invalid seccomp path: %s", prefixAndCtr[0]) + return nil, fmt.Errorf("invalid seccomp path: %s", prefixAndCtr[0]) } path, err := verifySeccompPath(seccomp, profileRoot) @@ -80,6 +80,6 @@ func verifySeccompPath(path string, profileRoot string) (string, error) { if parts[0] == "localhost" { return filepath.Join(profileRoot, parts[1]), nil } - return "", errors.Errorf("invalid seccomp path: %s", path) + return "", fmt.Errorf("invalid seccomp path: %s", path) } } diff --git a/pkg/specgen/generate/kube/volume.go b/pkg/specgen/generate/kube/volume.go index 1d6d49b9d..f5c0c241d 100644 --- a/pkg/specgen/generate/kube/volume.go +++ b/pkg/specgen/generate/kube/volume.go @@ -1,12 +1,13 @@ package kube import ( + "errors" + "fmt" "os" "github.com/containers/common/pkg/parse" "github.com/containers/podman/v4/libpod" v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -56,13 +57,13 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error) } // Label a newly created volume if err := libpod.LabelVolumePath(hostPath.Path); err != nil { - return nil, errors.Wrapf(err, "error giving %s a label", hostPath.Path) + return nil, fmt.Errorf("error giving %s a label: %w", hostPath.Path, err) } case v1.HostPathFileOrCreate: if _, err := os.Stat(hostPath.Path); os.IsNotExist(err) { f, err := os.OpenFile(hostPath.Path, os.O_RDONLY|os.O_CREATE, kubeFilePermission) if err != nil { - return nil, errors.Wrap(err, "error creating HostPath") + return nil, fmt.Errorf("error creating HostPath: %w", err) } if err := f.Close(); err != nil { logrus.Warnf("Error in closing newly created HostPath file: %v", err) @@ -70,23 +71,23 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error) } // unconditionally label a newly created volume if err := libpod.LabelVolumePath(hostPath.Path); err != nil { - return nil, errors.Wrapf(err, "error giving %s a label", hostPath.Path) + return nil, fmt.Errorf("error giving %s a label: %w", hostPath.Path, err) } case v1.HostPathSocket: st, err := os.Stat(hostPath.Path) if err != nil { - return nil, errors.Wrap(err, "error checking HostPathSocket") + return nil, fmt.Errorf("error checking HostPathSocket: %w", err) } if st.Mode()&os.ModeSocket != os.ModeSocket { - return nil, errors.Errorf("checking HostPathSocket: path %s is not a socket", hostPath.Path) + return nil, fmt.Errorf("checking HostPathSocket: path %s is not a socket", hostPath.Path) } case v1.HostPathBlockDev: dev, err := os.Stat(hostPath.Path) if err != nil { - return nil, errors.Wrap(err, "error checking HostPathBlockDevice") + return nil, fmt.Errorf("error checking HostPathBlockDevice: %w", err) } if dev.Mode()&os.ModeCharDevice == os.ModeCharDevice { - return nil, errors.Errorf("checking HostPathDevice: path %s is not a block device", hostPath.Path) + return nil, fmt.Errorf("checking HostPathDevice: path %s is not a block device", hostPath.Path) } return &KubeVolume{ Type: KubeVolumeTypeBlockDevice, @@ -95,10 +96,10 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error) case v1.HostPathCharDev: dev, err := os.Stat(hostPath.Path) if err != nil { - return nil, errors.Wrap(err, "error checking HostPathCharDevice") + return nil, fmt.Errorf("error checking HostPathCharDevice: %w", err) } if dev.Mode()&os.ModeCharDevice != os.ModeCharDevice { - return nil, errors.Errorf("checking HostPathCharDevice: path %s is not a character device", hostPath.Path) + return nil, fmt.Errorf("checking HostPathCharDevice: path %s is not a character device", hostPath.Path) } return &KubeVolume{ Type: KubeVolumeTypeCharDevice, @@ -110,12 +111,12 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error) // do nothing here because we will verify the path exists in validateVolumeHostDir break default: - return nil, errors.Errorf("Invalid HostPath type %v", hostPath.Type) + return nil, fmt.Errorf("invalid HostPath type %v", hostPath.Type) } } if err := parse.ValidateVolumeHostDir(hostPath.Path); err != nil { - return nil, errors.Wrapf(err, "error in parsing HostPath in YAML") + return nil, fmt.Errorf("error in parsing HostPath in YAML: %w", err) } return &KubeVolume{ @@ -152,7 +153,7 @@ func VolumeFromConfigMap(configMapVolumeSource *v1.ConfigMapVolumeSource, config kv.Optional = *configMapVolumeSource.Optional return kv, nil } - return nil, errors.Errorf("no such ConfigMap %q", configMapVolumeSource.Name) + return nil, fmt.Errorf("no such ConfigMap %q", configMapVolumeSource.Name) } // If there are Items specified in the volumeSource, that overwrites the Data from the configmap @@ -180,7 +181,7 @@ func VolumeFromSource(volumeSource v1.VolumeSource, configMaps []v1.ConfigMap) ( case volumeSource.ConfigMap != nil: return VolumeFromConfigMap(volumeSource.ConfigMap, configMaps) default: - return nil, errors.Errorf("HostPath, ConfigMap, and PersistentVolumeClaim are currently the only supported VolumeSource") + return nil, errors.New("HostPath, ConfigMap, and PersistentVolumeClaim are currently the only supported VolumeSource") } } @@ -191,7 +192,7 @@ func InitializeVolumes(specVolumes []v1.Volume, configMaps []v1.ConfigMap) (map[ for _, specVolume := range specVolumes { volume, err := VolumeFromSource(specVolume.VolumeSource, configMaps) if err != nil { - return nil, errors.Wrapf(err, "failed to create volume %q", specVolume.Name) + return nil, fmt.Errorf("failed to create volume %q: %w", specVolume.Name, err) } volumes[specVolume.Name] = volume diff --git a/pkg/specgen/generate/namespaces.go b/pkg/specgen/generate/namespaces.go index 4224d16ce..f0d4e9153 100644 --- a/pkg/specgen/generate/namespaces.go +++ b/pkg/specgen/generate/namespaces.go @@ -1,6 +1,7 @@ package generate import ( + "errors" "fmt" "os" "strings" @@ -15,7 +16,6 @@ import ( "github.com/containers/podman/v4/pkg/util" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -94,7 +94,7 @@ func GetDefaultNamespaceMode(nsType string, cfg *config.Config, pod *libpod.Pod) return ns, err } - return toReturn, errors.Wrapf(define.ErrInvalidArg, "invalid namespace type %q passed", nsType) + return toReturn, fmt.Errorf("invalid namespace type %q passed: %w", nsType, define.ErrInvalidArg) } // namespaceOptions generates container creation options for all @@ -113,18 +113,18 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod. if err != nil { // This is likely to be of the fatal kind (pod was // removed) so hard fail - return nil, errors.Wrapf(err, "error looking up pod %s infra container", pod.ID()) + return nil, fmt.Errorf("error looking up pod %s infra container: %w", pod.ID(), err) } if infraID != "" { ctr, err := rt.GetContainer(infraID) if err != nil { - return nil, errors.Wrapf(err, "error retrieving pod %s infra container %s", pod.ID(), infraID) + return nil, fmt.Errorf("error retrieving pod %s infra container %s: %w", pod.ID(), infraID, err) } infraCtr = ctr } } - errNoInfra := errors.Wrapf(define.ErrInvalidArg, "cannot use pod namespace as container is not joining a pod or pod has no infra container") + errNoInfra := fmt.Errorf("cannot use pod namespace as container is not joining a pod or pod has no infra container: %w", define.ErrInvalidArg) // PID switch s.PidNS.NSMode { @@ -136,7 +136,7 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod. case specgen.FromContainer: pidCtr, err := rt.LookupContainer(s.PidNS.Value) if err != nil { - return nil, errors.Wrapf(err, "error looking up container to share pid namespace with") + return nil, fmt.Errorf("error looking up container to share pid namespace with: %w", err) } toReturn = append(toReturn, libpod.WithPIDNSFrom(pidCtr)) } @@ -155,10 +155,10 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod. case specgen.FromContainer: ipcCtr, err := rt.LookupContainer(s.IpcNS.Value) if err != nil { - return nil, errors.Wrapf(err, "error looking up container to share ipc namespace with") + return nil, fmt.Errorf("error looking up container to share ipc namespace with: %w", err) } if ipcCtr.ConfigNoCopy().NoShmShare { - return nil, errors.Errorf("joining IPC of container %s is not allowed: non-shareable IPC (hint: use IpcMode:shareable for the donor container)", ipcCtr.ID()) + return nil, fmt.Errorf("joining IPC of container %s is not allowed: non-shareable IPC (hint: use IpcMode:shareable for the donor container)", ipcCtr.ID()) } toReturn = append(toReturn, libpod.WithIPCNSFrom(ipcCtr)) if !ipcCtr.ConfigNoCopy().NoShm { @@ -176,11 +176,18 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod. if pod == nil || infraCtr == nil { return nil, errNoInfra } - toReturn = append(toReturn, libpod.WithUTSNSFrom(infraCtr)) + if pod.NamespaceMode(spec.UTSNamespace) == host { + // adding infra as a nsCtr is not what we want to do when uts == host + // this leads the new ctr to try to add an ns path which is should not in this mode + logrus.Debug("pod has host uts, not adding infra as a nsCtr") + s.UtsNS = specgen.Namespace{NSMode: specgen.Host} + } else { + toReturn = append(toReturn, libpod.WithUTSNSFrom(infraCtr)) + } case specgen.FromContainer: utsCtr, err := rt.LookupContainer(s.UtsNS.Value) if err != nil { - return nil, errors.Wrapf(err, "error looking up container to share uts namespace with") + return nil, fmt.Errorf("error looking up container to share uts namespace with: %w", err) } toReturn = append(toReturn, libpod.WithUTSNSFrom(utsCtr)) } @@ -215,7 +222,7 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod. case specgen.FromContainer: userCtr, err := rt.LookupContainer(s.UserNS.Value) if err != nil { - return nil, errors.Wrapf(err, "error looking up container to share user namespace with") + return nil, fmt.Errorf("error looking up container to share user namespace with: %w", err) } toReturn = append(toReturn, libpod.WithUserNSFrom(userCtr)) } @@ -227,7 +234,7 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod. if pod == nil { toReturn = append(toReturn, libpod.WithIDMappings(*s.IDMappings)) } else if pod.HasInfraContainer() && (len(s.IDMappings.UIDMap) > 0 || len(s.IDMappings.GIDMap) > 0) { - return nil, errors.Wrapf(define.ErrInvalidArg, "cannot specify a new uid/gid map when entering a pod with an infra container") + return nil, fmt.Errorf("cannot specify a new uid/gid map when entering a pod with an infra container: %w", define.ErrInvalidArg) } } if s.User != "" { @@ -247,7 +254,7 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod. case specgen.FromContainer: cgroupCtr, err := rt.LookupContainer(s.CgroupNS.Value) if err != nil { - return nil, errors.Wrapf(err, "error looking up container to share cgroup namespace with") + return nil, fmt.Errorf("error looking up container to share cgroup namespace with: %w", err) } toReturn = append(toReturn, libpod.WithCgroupNSFrom(cgroupCtr)) } @@ -275,7 +282,7 @@ func namespaceOptions(s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod. case specgen.FromContainer: netCtr, err := rt.LookupContainer(s.NetNS.Value) if err != nil { - return nil, errors.Wrapf(err, "error looking up container to share net namespace with") + return nil, fmt.Errorf("error looking up container to share net namespace with: %w", err) } toReturn = append(toReturn, libpod.WithNetNSFrom(netCtr)) case specgen.Slirp: @@ -355,7 +362,7 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt switch s.PidNS.NSMode { case specgen.Path: if _, err := os.Stat(s.PidNS.Value); err != nil { - return errors.Wrap(err, "cannot find specified PID namespace path") + return fmt.Errorf("cannot find specified PID namespace path: %w", err) } if err := g.AddOrReplaceLinuxNamespace(string(spec.PIDNamespace), s.PidNS.Value); err != nil { return err @@ -374,7 +381,7 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt switch s.IpcNS.NSMode { case specgen.Path: if _, err := os.Stat(s.IpcNS.Value); err != nil { - return errors.Wrap(err, "cannot find specified IPC namespace path") + return fmt.Errorf("cannot find specified IPC namespace path: %w", err) } if err := g.AddOrReplaceLinuxNamespace(string(spec.IPCNamespace), s.IpcNS.Value); err != nil { return err @@ -393,7 +400,7 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt switch s.UtsNS.NSMode { case specgen.Path: if _, err := os.Stat(s.UtsNS.Value); err != nil { - return errors.Wrap(err, "cannot find specified UTS namespace path") + return fmt.Errorf("cannot find specified UTS namespace path: %w", err) } if err := g.AddOrReplaceLinuxNamespace(string(spec.UTSNamespace), s.UtsNS.Value); err != nil { return err @@ -416,13 +423,13 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt case s.UtsNS.NSMode == specgen.FromContainer: utsCtr, err := rt.LookupContainer(s.UtsNS.Value) if err != nil { - return errors.Wrapf(err, "error looking up container to share uts namespace with") + return fmt.Errorf("error looking up container to share uts namespace with: %w", err) } hostname = utsCtr.Hostname() case (s.NetNS.NSMode == specgen.Host && hostname == "") || s.UtsNS.NSMode == specgen.Host: tmpHostname, err := os.Hostname() if err != nil { - return errors.Wrap(err, "unable to retrieve hostname of the host") + return fmt.Errorf("unable to retrieve hostname of the host: %w", err) } hostname = tmpHostname default: @@ -451,7 +458,7 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt switch s.CgroupNS.NSMode { case specgen.Path: if _, err := os.Stat(s.CgroupNS.Value); err != nil { - return errors.Wrap(err, "cannot find specified cgroup namespace path") + return fmt.Errorf("cannot find specified cgroup namespace path: %w", err) } if err := g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), s.CgroupNS.Value); err != nil { return err @@ -470,7 +477,7 @@ func specConfigureNamespaces(s *specgen.SpecGenerator, g *generate.Generator, rt switch s.NetNS.NSMode { case specgen.Path: if _, err := os.Stat(s.NetNS.Value); err != nil { - return errors.Wrap(err, "cannot find specified network namespace path") + return fmt.Errorf("cannot find specified network namespace path: %w", err) } if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), s.NetNS.Value); err != nil { return err @@ -514,7 +521,7 @@ func GetNamespaceOptions(ns []string, netnsIsHost bool) ([]libpod.PodCreateOptio case "net": options = append(options, libpod.WithPodNet()) case "mnt": - return erroredOptions, errors.Errorf("Mount sharing functionality not supported on pod level") + return erroredOptions, fmt.Errorf("mount sharing functionality not supported on pod level") case "pid": options = append(options, libpod.WithPodPID()) case "user": @@ -527,7 +534,7 @@ func GetNamespaceOptions(ns []string, netnsIsHost bool) ([]libpod.PodCreateOptio case "none": return erroredOptions, nil default: - return erroredOptions, errors.Errorf("Invalid kernel namespace to share: %s. Options are: cgroup, ipc, net, pid, uts or none", toShare) + return erroredOptions, fmt.Errorf("invalid kernel namespace to share: %s. Options are: cgroup, ipc, net, pid, uts or none", toShare) } } return options, nil diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go index 1044854f4..bb5f2d0ec 100644 --- a/pkg/specgen/generate/oci.go +++ b/pkg/specgen/generate/oci.go @@ -3,6 +3,7 @@ package generate import ( "context" "encoding/json" + "fmt" "path" "strings" @@ -15,7 +16,6 @@ import ( "github.com/containers/podman/v4/pkg/specgen" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -117,7 +117,7 @@ func makeCommand(s *specgen.SpecGenerator, imageData *libimage.ImageData, rtc *c finalCommand = append(finalCommand, command...) if len(finalCommand) == 0 { - return nil, errors.Errorf("no command or entrypoint provided, and no CMD or ENTRYPOINT from image") + return nil, fmt.Errorf("no command or entrypoint provided, and no CMD or ENTRYPOINT from image") } if s.Init { @@ -126,7 +126,7 @@ func makeCommand(s *specgen.SpecGenerator, imageData *libimage.ImageData, rtc *c initPath = rtc.Engine.InitPath } if initPath == "" { - return nil, errors.Errorf("no path to init binary found but container requested an init") + return nil, fmt.Errorf("no path to init binary found but container requested an init") } finalCommand = append([]string{define.ContainerInitPath, "--"}, finalCommand...) } @@ -348,7 +348,7 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt for k, v := range s.WeightDevice { statT := unix.Stat_t{} if err := unix.Stat(k, &statT); err != nil { - return nil, errors.Wrapf(err, "failed to inspect '%s' in --blkio-weight-device", k) + return nil, fmt.Errorf("failed to inspect '%s' in --blkio-weight-device: %w", k, err) } g.AddLinuxResourcesBlockIOWeightDevice((int64(unix.Major(uint64(statT.Rdev)))), (int64(unix.Minor(uint64(statT.Rdev)))), *v.Weight) //nolint: unconvert } diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go index 4ac8a0aa2..212d613fe 100644 --- a/pkg/specgen/generate/pod_create.go +++ b/pkg/specgen/generate/pod_create.go @@ -13,7 +13,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/specgen" "github.com/containers/podman/v4/pkg/specgenutil" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -60,6 +59,7 @@ func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (*libpod.Pod, error) { if err != nil { return nil, err } + spec.Pod = pod.ID() opts = append(opts, rt.WithPod(pod)) spec.CgroupParent = pod.CgroupParent() @@ -154,7 +154,7 @@ func MapSpec(p *specgen.PodSpecGenerator) (*specgen.SpecGenerator, error) { if len(p.InfraContainerSpec.PortMappings) > 0 || len(p.InfraContainerSpec.Networks) > 0 || p.InfraContainerSpec.NetNS.NSMode == specgen.NoNetwork { - return nil, errors.Wrapf(define.ErrInvalidArg, "cannot set host network if network-related configuration is specified") + return nil, fmt.Errorf("cannot set host network if network-related configuration is specified: %w", define.ErrInvalidArg) } p.InfraContainerSpec.NetNS.NSMode = specgen.Host case specgen.Slirp: @@ -168,11 +168,11 @@ func MapSpec(p *specgen.PodSpecGenerator) (*specgen.SpecGenerator, error) { if len(p.InfraContainerSpec.PortMappings) > 0 || len(p.InfraContainerSpec.Networks) > 0 || p.InfraContainerSpec.NetNS.NSMode == specgen.Host { - return nil, errors.Wrapf(define.ErrInvalidArg, "cannot disable pod network if network-related configuration is specified") + return nil, fmt.Errorf("cannot disable pod network if network-related configuration is specified: %w", define.ErrInvalidArg) } p.InfraContainerSpec.NetNS.NSMode = specgen.NoNetwork default: - return nil, errors.Errorf("pods presently do not support network mode %s", p.NetNS.NSMode) + return nil, fmt.Errorf("pods presently do not support network mode %s", p.NetNS.NSMode) } if len(p.InfraCommand) > 0 { diff --git a/pkg/specgen/generate/ports.go b/pkg/specgen/generate/ports.go index 4243630e2..572f256c1 100644 --- a/pkg/specgen/generate/ports.go +++ b/pkg/specgen/generate/ports.go @@ -13,7 +13,6 @@ import ( "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/pkg/specgen" "github.com/containers/podman/v4/pkg/specgenutil" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -46,7 +45,7 @@ func joinTwoPortsToRangePortIfPossible(ports *[]types.PortMapping, allHostPorts, // if both host port ranges overlap and the container port range did not match // we have to error because we cannot assign the same host port to more than one container port if previousPort.HostPort+previousPort.Range-1 > port.HostPort { - return nil, errors.Errorf("conflicting port mappings for host port %d (protocol %s)", port.HostPort, port.Protocol) + return nil, fmt.Errorf("conflicting port mappings for host port %d (protocol %s)", port.HostPort, port.Protocol) } } // we could not join the ports so we append the old one to the list @@ -127,7 +126,7 @@ outer: rangePort = fmt.Sprintf("with range %d ", port.Range) } - return port, errors.Errorf("failed to find an open port to expose container port %d %son the host", port.ContainerPort, rangePort) + return port, fmt.Errorf("failed to find an open port to expose container port %d %son the host", port.ContainerPort, rangePort) } // Parse port maps to port mappings. @@ -163,7 +162,7 @@ func ParsePortMapping(portMappings []types.PortMapping, exposePorts map[uint16][ } if port.HostIP != "" { if ip := net.ParseIP(port.HostIP); ip == nil { - return nil, errors.Errorf("invalid IP address %q in port mapping", port.HostIP) + return nil, fmt.Errorf("invalid IP address %q in port mapping", port.HostIP) } } @@ -174,14 +173,14 @@ func ParsePortMapping(portMappings []types.PortMapping, exposePorts map[uint16][ } containerPort := port.ContainerPort if containerPort == 0 { - return nil, errors.Errorf("container port number must be non-0") + return nil, fmt.Errorf("container port number must be non-0") } hostPort := port.HostPort if uint32(portRange-1)+uint32(containerPort) > 65535 { - return nil, errors.Errorf("container port range exceeds maximum allowable port number") + return nil, fmt.Errorf("container port range exceeds maximum allowable port number") } if uint32(portRange-1)+uint32(hostPort) > 65535 { - return nil, errors.Errorf("host port range exceeds maximum allowable port number") + return nil, fmt.Errorf("host port range exceeds maximum allowable port number") } hostProtoMap, ok := portMap[port.HostIP] @@ -351,11 +350,11 @@ func createPortMappings(s *specgen.SpecGenerator, imageData *libimage.ImageData) for _, expose := range []map[uint16]string{expose, s.Expose} { for port, proto := range expose { if port == 0 { - return nil, nil, errors.Errorf("cannot expose 0 as it is not a valid port number") + return nil, nil, fmt.Errorf("cannot expose 0 as it is not a valid port number") } protocols, err := checkProtocol(proto, false) if err != nil { - return nil, nil, errors.Wrapf(err, "error validating protocols for exposed port %d", port) + return nil, nil, fmt.Errorf("error validating protocols for exposed port %d: %w", port, err) } toExpose[port] = appendProtocolsNoDuplicates(toExpose[port], protocols) } @@ -387,11 +386,11 @@ func checkProtocol(protocol string, allowSCTP bool) ([]string, error) { protocols[protoUDP] = struct{}{} case protoSCTP: if !allowSCTP { - return nil, errors.Errorf("protocol SCTP is not allowed for exposed ports") + return nil, fmt.Errorf("protocol SCTP is not allowed for exposed ports") } protocols[protoSCTP] = struct{}{} default: - return nil, errors.Errorf("unrecognized protocol %q in port mapping", p) + return nil, fmt.Errorf("unrecognized protocol %q in port mapping", p) } } @@ -402,7 +401,7 @@ func checkProtocol(protocol string, allowSCTP bool) ([]string, error) { // This shouldn't be possible, but check anyways if len(finalProto) == 0 { - return nil, errors.Errorf("no valid protocols specified for port mapping") + return nil, fmt.Errorf("no valid protocols specified for port mapping") } return finalProto, nil @@ -415,7 +414,7 @@ func GenExposedPorts(exposedPorts map[string]struct{}) (map[uint16]string, error } toReturn, err := specgenutil.CreateExpose(expose) if err != nil { - return nil, errors.Wrapf(err, "unable to convert image EXPOSE") + return nil, fmt.Errorf("unable to convert image EXPOSE: %w", err) } return toReturn, nil } diff --git a/pkg/specgen/generate/security.go b/pkg/specgen/generate/security.go index 7268ec318..aacefcbac 100644 --- a/pkg/specgen/generate/security.go +++ b/pkg/specgen/generate/security.go @@ -1,6 +1,7 @@ package generate import ( + "fmt" "strings" "github.com/containers/common/libimage" @@ -14,7 +15,6 @@ import ( "github.com/containers/podman/v4/pkg/util" "github.com/opencontainers/runtime-tools/generate" "github.com/opencontainers/selinux/go-selinux/label" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -32,11 +32,11 @@ func setLabelOpts(s *specgen.SpecGenerator, runtime *libpod.Runtime, pidConfig s } else if pidConfig.IsContainer() { ctr, err := runtime.LookupContainer(pidConfig.Value) if err != nil { - return errors.Wrapf(err, "container %q not found", pidConfig.Value) + return fmt.Errorf("container %q not found: %w", pidConfig.Value, err) } secopts, err := label.DupSecOpt(ctr.ProcessLabel()) if err != nil { - return errors.Wrapf(err, "failed to duplicate label %q ", ctr.ProcessLabel()) + return fmt.Errorf("failed to duplicate label %q : %w", ctr.ProcessLabel(), err) } labelOpts = append(labelOpts, secopts...) } @@ -46,11 +46,11 @@ func setLabelOpts(s *specgen.SpecGenerator, runtime *libpod.Runtime, pidConfig s } else if ipcConfig.IsContainer() { ctr, err := runtime.LookupContainer(ipcConfig.Value) if err != nil { - return errors.Wrapf(err, "container %q not found", ipcConfig.Value) + return fmt.Errorf("container %q not found: %w", ipcConfig.Value, err) } secopts, err := label.DupSecOpt(ctr.ProcessLabel()) if err != nil { - return errors.Wrapf(err, "failed to duplicate label %q ", ctr.ProcessLabel()) + return fmt.Errorf("failed to duplicate label %q : %w", ctr.ProcessLabel(), err) } labelOpts = append(labelOpts, secopts...) } @@ -63,7 +63,7 @@ func setupApparmor(s *specgen.SpecGenerator, rtc *config.Config, g *generate.Gen hasProfile := len(s.ApparmorProfile) > 0 if !apparmor.IsEnabled() { if hasProfile && s.ApparmorProfile != "unconfined" { - return errors.Errorf("Apparmor profile %q specified, but Apparmor is not enabled on this system", s.ApparmorProfile) + return fmt.Errorf("apparmor profile %q specified, but Apparmor is not enabled on this system", s.ApparmorProfile) } return nil } @@ -129,7 +129,7 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, // Pass capRequiredRequested in CapAdd field to normalize capabilities names capsRequired, err := capabilities.MergeCapabilities(nil, capsRequiredRequested, nil) if err != nil { - return errors.Wrapf(err, "capabilities requested by user or image are not valid: %q", strings.Join(capsRequired, ",")) + return fmt.Errorf("capabilities requested by user or image are not valid: %q: %w", strings.Join(capsRequired, ","), err) } // Verify all capRequired are in the capList for _, cap := range capsRequired { @@ -161,7 +161,7 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, } else { mergedCaps, err := capabilities.MergeCapabilities(nil, s.CapAdd, nil) if err != nil { - return errors.Wrapf(err, "capabilities requested by user are not valid: %q", strings.Join(s.CapAdd, ",")) + return fmt.Errorf("capabilities requested by user are not valid: %q: %w", strings.Join(s.CapAdd, ","), err) } boundingSet, err := capabilities.BoundingSet() if err != nil { @@ -245,17 +245,17 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, for sysctlKey, sysctlVal := range s.Sysctl { if s.IpcNS.IsHost() && strings.HasPrefix(sysctlKey, "fs.mqueue.") { - return errors.Wrapf(define.ErrInvalidArg, "sysctl %s=%s can't be set since IPC Namespace set to host", sysctlKey, sysctlVal) + return fmt.Errorf("sysctl %s=%s can't be set since IPC Namespace set to host: %w", sysctlKey, sysctlVal, define.ErrInvalidArg) } // Ignore net sysctls if --net=host if s.NetNS.IsHost() && strings.HasPrefix(sysctlKey, "net.") { - return errors.Wrapf(define.ErrInvalidArg, "sysctl %s=%s can't be set since Network Namespace set to host", sysctlKey, sysctlVal) + return fmt.Errorf("sysctl %s=%s can't be set since Network Namespace set to host: %w", sysctlKey, sysctlVal, define.ErrInvalidArg) } // Ignore uts sysctls if --uts=host if s.UtsNS.IsHost() && (strings.HasPrefix(sysctlKey, "kernel.domainname") || strings.HasPrefix(sysctlKey, "kernel.hostname")) { - return errors.Wrapf(define.ErrInvalidArg, "sysctl %s=%s can't be set since UTS Namespace set to host", sysctlKey, sysctlVal) + return fmt.Errorf("sysctl %s=%s can't be set since UTS Namespace set to host: %w", sysctlKey, sysctlVal, define.ErrInvalidArg) } g.AddLinuxSysctl(sysctlKey, sysctlVal) diff --git a/pkg/specgen/generate/storage.go b/pkg/specgen/generate/storage.go index 0a4d03780..867bb4b79 100644 --- a/pkg/specgen/generate/storage.go +++ b/pkg/specgen/generate/storage.go @@ -2,6 +2,7 @@ package generate import ( "context" + "errors" "fmt" "os" "path" @@ -16,11 +17,10 @@ import ( "github.com/containers/podman/v4/pkg/specgen" "github.com/containers/podman/v4/pkg/util" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) -var errDuplicateDest = errors.Errorf("duplicate mount destination") +var errDuplicateDest = errors.New("duplicate mount destination") // Produce final mounts and named volumes for a container func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, rtc *config.Config, img *libimage.Image) ([]spec.Mount, []*specgen.NamedVolume, []*specgen.OverlayVolume, error) { @@ -63,7 +63,7 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru } cleanDestination := filepath.Clean(m.Destination) if _, ok := unifiedMounts[cleanDestination]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified mounts - multiple mounts at %q", cleanDestination) + return nil, nil, nil, fmt.Errorf("conflict in specified mounts - multiple mounts at %q: %w", cleanDestination, errDuplicateDest) } unifiedMounts[cleanDestination] = m } @@ -84,7 +84,7 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru } cleanDestination := filepath.Clean(v.Dest) if _, ok := unifiedVolumes[cleanDestination]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", cleanDestination) + return nil, nil, nil, fmt.Errorf("conflict in specified volumes - multiple volumes at %q: %w", cleanDestination, errDuplicateDest) } unifiedVolumes[cleanDestination] = v } @@ -105,7 +105,7 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru } cleanDestination := filepath.Clean(v.Destination) if _, ok := unifiedOverlays[cleanDestination]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", cleanDestination) + return nil, nil, nil, fmt.Errorf("conflict in specified volumes - multiple volumes at %q: %w", cleanDestination, errDuplicateDest) } unifiedOverlays[cleanDestination] = v } @@ -131,7 +131,7 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru return nil, nil, nil, err } if _, ok := unifiedMounts[initMount.Destination]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict with mount added by --init to %q", initMount.Destination) + return nil, nil, nil, fmt.Errorf("conflict with mount added by --init to %q: %w", initMount.Destination, errDuplicateDest) } unifiedMounts[initMount.Destination] = initMount } @@ -161,12 +161,12 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru // Check for conflicts between named volumes and mounts for dest := range baseMounts { if _, ok := baseVolumes[dest]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict at mount destination %v", dest) + return nil, nil, nil, fmt.Errorf("conflict at mount destination %v: %w", dest, errDuplicateDest) } } for dest := range baseVolumes { if _, ok := baseMounts[dest]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict at mount destination %v", dest) + return nil, nil, nil, fmt.Errorf("conflict at mount destination %v: %w", dest, errDuplicateDest) } } // Final step: maps to arrays @@ -175,7 +175,7 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru if mount.Type == define.TypeBind { absSrc, err := filepath.Abs(mount.Source) if err != nil { - return nil, nil, nil, errors.Wrapf(err, "error getting absolute path of %s", mount.Source) + return nil, nil, nil, fmt.Errorf("error getting absolute path of %s: %w", mount.Source, err) } mount.Source = absSrc } @@ -208,7 +208,7 @@ func getImageVolumes(ctx context.Context, img *libimage.Image, s *specgen.SpecGe inspect, err := img.Inspect(ctx, nil) if err != nil { - return nil, nil, errors.Wrapf(err, "error inspecting image to get image volumes") + return nil, nil, fmt.Errorf("error inspecting image to get image volumes: %w", err) } for volume := range inspect.Config.Volumes { logrus.Debugf("Image has volume at %q", volume) @@ -252,16 +252,16 @@ func getVolumesFrom(volumesFrom []string, runtime *libpod.Runtime) (map[string]s switch opt { case "z": if setZ { - return nil, nil, errors.Errorf("cannot set :z more than once in mount options") + return nil, nil, errors.New("cannot set :z more than once in mount options") } setZ = true case "ro", "rw": if setRORW { - return nil, nil, errors.Errorf("cannot set ro or rw options more than once") + return nil, nil, errors.New("cannot set ro or rw options more than once") } setRORW = true default: - return nil, nil, errors.Errorf("invalid option %q specified - volumes from another container can only use z,ro,rw options", opt) + return nil, nil, fmt.Errorf("invalid option %q specified - volumes from another container can only use z,ro,rw options", opt) } } options = splitOpts @@ -269,7 +269,7 @@ func getVolumesFrom(volumesFrom []string, runtime *libpod.Runtime) (map[string]s ctr, err := runtime.LookupContainer(splitVol[0]) if err != nil { - return nil, nil, errors.Wrapf(err, "error looking up container %q for volumes-from", splitVol[0]) + return nil, nil, fmt.Errorf("error looking up container %q for volumes-from: %w", splitVol[0], err) } logrus.Debugf("Adding volumes from container %s", ctr.ID()) @@ -290,7 +290,7 @@ func getVolumesFrom(volumesFrom []string, runtime *libpod.Runtime) (map[string]s // and append them in if we can find them. spec := ctr.Spec() if spec == nil { - return nil, nil, errors.Errorf("retrieving container %s spec for volumes-from", ctr.ID()) + return nil, nil, fmt.Errorf("retrieving container %s spec for volumes-from", ctr.ID()) } for _, mnt := range spec.Mounts { if mnt.Type != define.TypeBind { @@ -364,16 +364,16 @@ func addContainerInitBinary(s *specgen.SpecGenerator, path string) (spec.Mount, } if path == "" { - return mount, fmt.Errorf("please specify a path to the container-init binary") + return mount, errors.New("please specify a path to the container-init binary") } if !s.PidNS.IsPrivate() { - return mount, fmt.Errorf("cannot add init binary as PID 1 (PID namespace isn't private)") + return mount, errors.New("cannot add init binary as PID 1 (PID namespace isn't private)") } if s.Systemd == "always" { - return mount, fmt.Errorf("cannot use container-init binary with systemd=always") + return mount, errors.New("cannot use container-init binary with systemd=always") } if _, err := os.Stat(path); os.IsNotExist(err) { - return mount, errors.Wrap(err, "container-init binary not found on the host") + return mount, fmt.Errorf("container-init binary not found on the host: %w", err) } return mount, nil } diff --git a/pkg/specgen/generate/validate.go b/pkg/specgen/generate/validate.go index a1affef31..9c933d747 100644 --- a/pkg/specgen/generate/validate.go +++ b/pkg/specgen/generate/validate.go @@ -1,6 +1,8 @@ package generate import ( + "errors" + "fmt" "io/ioutil" "os" "path/filepath" @@ -9,7 +11,6 @@ import ( "github.com/containers/common/pkg/sysinfo" "github.com/containers/podman/v4/pkg/specgen" "github.com/containers/podman/v4/utils" - "github.com/pkg/errors" ) // Verify resource limits are sanely set when running on cgroup v1. @@ -23,7 +24,7 @@ func verifyContainerResourcesCgroupV1(s *specgen.SpecGenerator) ([]string, error } if s.ResourceLimits.Unified != nil { - return nil, errors.New("Cannot use --cgroup-conf without cgroup v2") + return nil, errors.New("cannot use --cgroup-conf without cgroup v2") } // Memory checks @@ -49,7 +50,7 @@ func verifyContainerResourcesCgroupV1(s *specgen.SpecGenerator) ([]string, error warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, or the cgroup is not mounted. Memory swappiness discarded.") memory.Swappiness = nil } else if *memory.Swappiness > 100 { - return warnings, errors.Errorf("invalid value: %v, valid memory swappiness range is 0-100", *memory.Swappiness) + return warnings, fmt.Errorf("invalid value: %v, valid memory swappiness range is 0-100", *memory.Swappiness) } } if memory.Reservation != nil && !sysInfo.MemoryReservation { @@ -104,18 +105,18 @@ func verifyContainerResourcesCgroupV1(s *specgen.SpecGenerator) ([]string, error cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(cpu.Cpus) if err != nil { - return warnings, errors.Errorf("invalid value %s for cpuset cpus", cpu.Cpus) + return warnings, fmt.Errorf("invalid value %s for cpuset cpus", cpu.Cpus) } if !cpusAvailable { - return warnings, errors.Errorf("requested CPUs are not available - requested %s, available: %s", cpu.Cpus, sysInfo.Cpus) + return warnings, fmt.Errorf("requested CPUs are not available - requested %s, available: %s", cpu.Cpus, sysInfo.Cpus) } memsAvailable, err := sysInfo.IsCpusetMemsAvailable(cpu.Mems) if err != nil { - return warnings, errors.Errorf("invalid value %s for cpuset mems", cpu.Mems) + return warnings, fmt.Errorf("invalid value %s for cpuset mems", cpu.Mems) } if !memsAvailable { - return warnings, errors.Errorf("requested memory nodes are not available - requested %s, available: %s", cpu.Mems, sysInfo.Mems) + return warnings, fmt.Errorf("requested memory nodes are not available - requested %s, available: %s", cpu.Mems, sysInfo.Mems) } } diff --git a/pkg/specgen/namespaces.go b/pkg/specgen/namespaces.go index f1343f6e2..03a2049f6 100644 --- a/pkg/specgen/namespaces.go +++ b/pkg/specgen/namespaces.go @@ -1,6 +1,7 @@ package specgen import ( + "errors" "fmt" "net" "os" @@ -14,7 +15,6 @@ import ( "github.com/containers/storage" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" - "github.com/pkg/errors" ) type NamespaceMode string @@ -158,18 +158,18 @@ func validateNetNS(n *Namespace) error { case "", Default, Host, Path, FromContainer, FromPod, Private, NoNetwork, Bridge: break default: - return errors.Errorf("invalid network %q", n.NSMode) + return fmt.Errorf("invalid network %q", n.NSMode) } // Path and From Container MUST have a string value set if n.NSMode == Path || n.NSMode == FromContainer { if len(n.Value) < 1 { - return errors.Errorf("namespace mode %s requires a value", n.NSMode) + return fmt.Errorf("namespace mode %s requires a value", n.NSMode) } } else if n.NSMode != Slirp { // All others except must NOT set a string value if len(n.Value) > 0 { - return errors.Errorf("namespace value %s cannot be provided with namespace mode %s", n.Value, n.NSMode) + return fmt.Errorf("namespace value %s cannot be provided with namespace mode %s", n.Value, n.NSMode) } } @@ -197,20 +197,20 @@ func (n *Namespace) validate() error { case "", Default, Host, Path, FromContainer, FromPod, Private: // Valid, do nothing case NoNetwork, Bridge, Slirp: - return errors.Errorf("cannot use network modes with non-network namespace") + return errors.New("cannot use network modes with non-network namespace") default: - return errors.Errorf("invalid namespace type %s specified", n.NSMode) + return fmt.Errorf("invalid namespace type %s specified", n.NSMode) } // Path and From Container MUST have a string value set if n.NSMode == Path || n.NSMode == FromContainer { if len(n.Value) < 1 { - return errors.Errorf("namespace mode %s requires a value", n.NSMode) + return fmt.Errorf("namespace mode %s requires a value", n.NSMode) } } else { // All others must NOT set a string value if len(n.Value) > 0 { - return errors.Errorf("namespace value %s cannot be provided with namespace mode %s", n.Value, n.NSMode) + return fmt.Errorf("namespace value %s cannot be provided with namespace mode %s", n.Value, n.NSMode) } } return nil @@ -231,19 +231,19 @@ func ParseNamespace(ns string) (Namespace, error) { case strings.HasPrefix(ns, "ns:"): split := strings.SplitN(ns, ":", 2) if len(split) != 2 { - return toReturn, errors.Errorf("must provide a path to a namespace when specifying \"ns:\"") + return toReturn, fmt.Errorf("must provide a path to a namespace when specifying \"ns:\"") } toReturn.NSMode = Path toReturn.Value = split[1] case strings.HasPrefix(ns, "container:"): split := strings.SplitN(ns, ":", 2) if len(split) != 2 { - return toReturn, errors.Errorf("must provide name or ID or a container when specifying \"container:\"") + return toReturn, fmt.Errorf("must provide name or ID or a container when specifying \"container:\"") } toReturn.NSMode = FromContainer toReturn.Value = split[1] default: - return toReturn, errors.Errorf("unrecognized namespace mode %s passed", ns) + return toReturn, fmt.Errorf("unrecognized namespace mode %s passed", ns) } return toReturn, nil @@ -266,7 +266,7 @@ func ParseCgroupNamespace(ns string) (Namespace, error) { case "private", "": toReturn.NSMode = Private default: - return toReturn, errors.Errorf("unrecognized cgroup namespace mode %s passed", ns) + return toReturn, fmt.Errorf("unrecognized cgroup namespace mode %s passed", ns) } } else { toReturn.NSMode = Host @@ -300,7 +300,7 @@ func ParseUserNamespace(ns string) (Namespace, error) { case strings.HasPrefix(ns, "auto:"): split := strings.SplitN(ns, ":", 2) if len(split) != 2 { - return toReturn, errors.Errorf("invalid setting for auto: mode") + return toReturn, errors.New("invalid setting for auto: mode") } toReturn.NSMode = Auto toReturn.Value = split[1] @@ -365,14 +365,14 @@ func ParseNetworkFlag(networks []string) (Namespace, map[string]types.PerNetwork case strings.HasPrefix(ns, "ns:"): split := strings.SplitN(ns, ":", 2) if len(split) != 2 { - return toReturn, nil, nil, errors.Errorf("must provide a path to a namespace when specifying \"ns:\"") + return toReturn, nil, nil, errors.New("must provide a path to a namespace when specifying \"ns:\"") } toReturn.NSMode = Path toReturn.Value = split[1] case strings.HasPrefix(ns, string(FromContainer)+":"): split := strings.SplitN(ns, ":", 2) if len(split) != 2 { - return toReturn, nil, nil, errors.Errorf("must provide name or ID or a container when specifying \"container:\"") + return toReturn, nil, nil, errors.New("must provide name or ID or a container when specifying \"container:\"") } toReturn.NSMode = FromContainer toReturn.Value = split[1] @@ -391,7 +391,7 @@ func ParseNetworkFlag(networks []string) (Namespace, map[string]types.PerNetwork } netOpts, err := parseBridgeNetworkOptions(parts[1]) if err != nil { - return toReturn, nil, nil, errors.Wrapf(err, "invalid option for network %s", parts[0]) + return toReturn, nil, nil, fmt.Errorf("invalid option for network %s: %w", parts[0], err) } podmanNetworks[parts[0]] = netOpts } @@ -402,24 +402,24 @@ func ParseNetworkFlag(networks []string) (Namespace, map[string]types.PerNetwork if len(networks) > 1 { if !toReturn.IsBridge() { - return toReturn, nil, nil, errors.Wrapf(define.ErrInvalidArg, "cannot set multiple networks without bridge network mode, selected mode %s", toReturn.NSMode) + return toReturn, nil, nil, fmt.Errorf("cannot set multiple networks without bridge network mode, selected mode %s: %w", toReturn.NSMode, define.ErrInvalidArg) } for _, network := range networks[1:] { parts := strings.SplitN(network, ":", 2) if parts[0] == "" { - return toReturn, nil, nil, errors.Wrapf(define.ErrInvalidArg, "network name cannot be empty") + return toReturn, nil, nil, fmt.Errorf("network name cannot be empty: %w", define.ErrInvalidArg) } if cutil.StringInSlice(parts[0], []string{string(Bridge), string(Slirp), string(FromPod), string(NoNetwork), string(Default), string(Private), string(Path), string(FromContainer), string(Host)}) { - return toReturn, nil, nil, errors.Wrapf(define.ErrInvalidArg, "can only set extra network names, selected mode %s conflicts with bridge", parts[0]) + return toReturn, nil, nil, fmt.Errorf("can only set extra network names, selected mode %s conflicts with bridge: %w", parts[0], define.ErrInvalidArg) } netOpts := types.PerNetworkOptions{} if len(parts) > 1 { var err error netOpts, err = parseBridgeNetworkOptions(parts[1]) if err != nil { - return toReturn, nil, nil, errors.Wrapf(err, "invalid option for network %s", parts[0]) + return toReturn, nil, nil, fmt.Errorf("invalid option for network %s: %w", parts[0], err) } } podmanNetworks[parts[0]] = netOpts @@ -441,7 +441,7 @@ func parseBridgeNetworkOptions(opts string) (types.PerNetworkOptions, error) { case "ip", "ip6": ip := net.ParseIP(split[1]) if ip == nil { - return netOpts, errors.Errorf("invalid ip address %q", split[1]) + return netOpts, fmt.Errorf("invalid ip address %q", split[1]) } netOpts.StaticIPs = append(netOpts.StaticIPs, ip) @@ -465,7 +465,7 @@ func parseBridgeNetworkOptions(opts string) (types.PerNetworkOptions, error) { netOpts.InterfaceName = split[1] default: - return netOpts, errors.Errorf("unknown bridge network option: %s", split[0]) + return netOpts, fmt.Errorf("unknown bridge network option: %s", split[0]) } } return netOpts, nil @@ -477,7 +477,7 @@ func SetupUserNS(idmappings *storage.IDMappingOptions, userns Namespace, g *gene switch userns.NSMode { case Path: if _, err := os.Stat(userns.Value); err != nil { - return user, errors.Wrap(err, "cannot find specified user namespace path") + return user, fmt.Errorf("cannot find specified user namespace path: %w", err) } if err := g.AddOrReplaceLinuxNamespace(string(spec.UserNamespace), userns.Value); err != nil { return user, err @@ -526,7 +526,7 @@ func privateUserNamespace(idmappings *storage.IDMappingOptions, g *generate.Gene return err } if idmappings == nil || (len(idmappings.UIDMap) == 0 && len(idmappings.GIDMap) == 0) { - return errors.Errorf("must provide at least one UID or GID mapping to configure a user namespace") + return errors.New("must provide at least one UID or GID mapping to configure a user namespace") } for _, uidmap := range idmappings.UIDMap { g.AddLinuxUIDMapping(uint32(uidmap.HostID), uint32(uidmap.ContainerID), uint32(uidmap.Size)) diff --git a/pkg/specgen/pod_validate.go b/pkg/specgen/pod_validate.go index 8d971a25e..724be213f 100644 --- a/pkg/specgen/pod_validate.go +++ b/pkg/specgen/pod_validate.go @@ -1,8 +1,10 @@ package specgen import ( + "errors" + "fmt" + "github.com/containers/podman/v4/pkg/util" - "github.com/pkg/errors" ) var ( @@ -13,7 +15,7 @@ var ( ) func exclusivePodOptions(opt1, opt2 string) error { - return errors.Wrapf(ErrInvalidPodSpecConfig, "%s and %s are mutually exclusive pod options", opt1, opt2) + return fmt.Errorf("%s and %s are mutually exclusive pod options: %w", opt1, opt2, ErrInvalidPodSpecConfig) } // Validate verifies the input is valid diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go index 02ba06be1..64a79f4ee 100644 --- a/pkg/specgen/podspecgen.go +++ b/pkg/specgen/podspecgen.go @@ -77,6 +77,8 @@ type PodBasicConfig struct { // Any containers created within the pod will inherit the pod's userns settings. // Optional Userns Namespace `json:"userns,omitempty"` + // UtsNs is used to indicate the UTS mode the pod is in + UtsNs Namespace `json:"utsns,omitempty"` // Devices contains user specified Devices to be added to the Pod Devices []string `json:"pod_devices,omitempty"` // Sysctl sets kernel parameters for the pod diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index 42b89ece1..c31c3f035 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -1,6 +1,7 @@ package specgen import ( + "errors" "net" "strings" "syscall" @@ -10,7 +11,6 @@ import ( "github.com/containers/image/v5/manifest" "github.com/containers/storage/types" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" ) // LogConfig describes the logging characteristics for a container @@ -571,10 +571,10 @@ type Secret struct { var ( // ErrNoStaticIPRootless is used when a rootless user requests to assign a static IP address // to a pod or container - ErrNoStaticIPRootless error = errors.New("rootless containers and pods cannot be assigned static IP addresses") + ErrNoStaticIPRootless = errors.New("rootless containers and pods cannot be assigned static IP addresses") // ErrNoStaticMACRootless is used when a rootless user requests to assign a static MAC address // to a pod or container - ErrNoStaticMACRootless error = errors.New("rootless containers and pods cannot be assigned static MAC addresses") + ErrNoStaticMACRootless = errors.New("rootless containers and pods cannot be assigned static MAC addresses") ) // NewSpecGenerator returns a SpecGenerator struct given one of two mandatory inputs diff --git a/pkg/specgen/volumes.go b/pkg/specgen/volumes.go index c9f944abf..84de4fdd1 100644 --- a/pkg/specgen/volumes.go +++ b/pkg/specgen/volumes.go @@ -1,12 +1,13 @@ package specgen import ( + "errors" + "fmt" "path/filepath" "strings" "github.com/containers/common/pkg/parse" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -50,13 +51,13 @@ type ImageVolume struct { // GenVolumeMounts parses user input into mounts, volumes and overlay volumes func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*NamedVolume, map[string]*OverlayVolume, error) { - errDuplicateDest := errors.Errorf("duplicate mount destination") + errDuplicateDest := errors.New("duplicate mount destination") mounts := make(map[string]spec.Mount) volumes := make(map[string]*NamedVolume) overlayVolumes := make(map[string]*OverlayVolume) - volumeFormatErr := errors.Errorf("incorrect volume format, should be [host-dir:]ctr-dir[:option]") + volumeFormatErr := errors.New("incorrect volume format, should be [host-dir:]ctr-dir[:option]") for _, vol := range volumeFlag { var ( options []string @@ -67,7 +68,7 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na splitVol := SplitVolumeString(vol) if len(splitVol) > 3 { - return nil, nil, nil, errors.Wrapf(volumeFormatErr, vol) + return nil, nil, nil, fmt.Errorf("%v: %w", vol, volumeFormatErr) } src = splitVol[0] @@ -143,13 +144,13 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na // relative values as lowerdir for overlay mounts source, err := filepath.Abs(src) if err != nil { - return nil, nil, nil, errors.Wrapf(err, "failed while resolving absolute path for source %v for overlay mount", src) + return nil, nil, nil, fmt.Errorf("failed while resolving absolute path for source %v for overlay mount: %w", src, err) } newOverlayVol.Source = source newOverlayVol.Options = options if _, ok := overlayVolumes[newOverlayVol.Destination]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, newOverlayVol.Destination) + return nil, nil, nil, fmt.Errorf("%v: %w", newOverlayVol.Destination, errDuplicateDest) } overlayVolumes[newOverlayVol.Destination] = newOverlayVol } else { @@ -160,7 +161,7 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na Options: options, } if _, ok := mounts[newMount.Destination]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, newMount.Destination) + return nil, nil, nil, fmt.Errorf("%v: %w", newMount.Destination, errDuplicateDest) } mounts[newMount.Destination] = newMount } @@ -172,7 +173,7 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na newNamedVol.Options = options if _, ok := volumes[newNamedVol.Dest]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, newNamedVol.Dest) + return nil, nil, nil, fmt.Errorf("%v: %w", newNamedVol.Dest, errDuplicateDest) } volumes[newNamedVol.Dest] = newNamedVol } diff --git a/pkg/specgen/winpath.go b/pkg/specgen/winpath.go index 0df4ebdd7..5c19aeb4b 100644 --- a/pkg/specgen/winpath.go +++ b/pkg/specgen/winpath.go @@ -1,11 +1,10 @@ package specgen import ( + "errors" "fmt" "strings" "unicode" - - "github.com/pkg/errors" ) func isHostWinPath(path string) bool { diff --git a/pkg/specgenutil/createparse.go b/pkg/specgenutil/createparse.go index 132f93771..373fb6faa 100644 --- a/pkg/specgenutil/createparse.go +++ b/pkg/specgenutil/createparse.go @@ -1,9 +1,10 @@ package specgenutil import ( + "errors" + "github.com/containers/common/pkg/config" "github.com/containers/podman/v4/pkg/domain/entities" - "github.com/pkg/errors" ) // validate determines if the flags and values given by the user are valid. things checked @@ -11,7 +12,7 @@ import ( func validate(c *entities.ContainerCreateOptions) error { var () if c.Rm && (c.Restart != "" && c.Restart != "no" && c.Restart != "on-failure") { - return errors.Errorf(`the --rm option conflicts with --restart, when the restartPolicy is not "" and "no"`) + return errors.New(`the --rm option conflicts with --restart, when the restartPolicy is not "" and "no"`) } if _, err := config.ParsePullPolicy(c.Pull); err != nil { diff --git a/pkg/specgenutil/ports.go b/pkg/specgenutil/ports.go index 6cc4de1ed..23ee9b4d3 100644 --- a/pkg/specgenutil/ports.go +++ b/pkg/specgenutil/ports.go @@ -1,8 +1,9 @@ package specgenutil import ( + "fmt" + "github.com/docker/go-connections/nat" - "github.com/pkg/errors" ) func verifyExpose(expose []string) error { @@ -15,7 +16,7 @@ func verifyExpose(expose []string) error { // if expose a port, the start and end port are the same _, _, err := nat.ParsePortRange(port) if err != nil { - return errors.Wrapf(err, "invalid range format for --expose: %s", expose) + return fmt.Errorf("invalid range format for --expose: %s: %w", expose, err) } } return nil diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go index 34350579d..9a7d50947 100644 --- a/pkg/specgenutil/specgen.go +++ b/pkg/specgenutil/specgen.go @@ -2,6 +2,7 @@ package specgenutil import ( "encoding/json" + "errors" "fmt" "os" "strconv" @@ -22,7 +23,6 @@ import ( "github.com/docker/docker/opts" "github.com/docker/go-units" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" ) func getCPULimits(c *entities.ContainerCreateOptions) *specs.LinuxCPU { @@ -78,7 +78,7 @@ func getIOLimits(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions) ( if b := c.BlkIOWeight; len(b) > 0 { u, err := strconv.ParseUint(b, 10, 16) if err != nil { - return nil, errors.Wrapf(err, "invalid value for blkio-weight") + return nil, fmt.Errorf("invalid value for blkio-weight: %w", err) } nu := uint16(u) io.Weight = &nu @@ -143,7 +143,7 @@ func getMemoryLimits(c *entities.ContainerCreateOptions) (*specs.LinuxMemory, er if m := c.Memory; len(m) > 0 { ml, err := units.RAMInBytes(m) if err != nil { - return nil, errors.Wrapf(err, "invalid value for memory") + return nil, fmt.Errorf("invalid value for memory: %w", err) } LimitToSwap(memory, c.MemorySwap, ml) hasLimits = true @@ -151,7 +151,7 @@ func getMemoryLimits(c *entities.ContainerCreateOptions) (*specs.LinuxMemory, er if m := c.MemoryReservation; len(m) > 0 { mr, err := units.RAMInBytes(m) if err != nil { - return nil, errors.Wrapf(err, "invalid value for memory") + return nil, fmt.Errorf("invalid value for memory: %w", err) } memory.Reservation = &mr hasLimits = true @@ -164,7 +164,7 @@ func getMemoryLimits(c *entities.ContainerCreateOptions) (*specs.LinuxMemory, er ms, err = units.RAMInBytes(m) memory.Swap = &ms if err != nil { - return nil, errors.Wrapf(err, "invalid value for memory") + return nil, fmt.Errorf("invalid value for memory: %w", err) } hasLimits = true } @@ -248,7 +248,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions if len(c.HealthCmd) > 0 { if c.NoHealthCheck { - return errors.New("Cannot specify both --no-healthcheck and --health-cmd") + return errors.New("cannot specify both --no-healthcheck and --health-cmd") } s.HealthConfig, err = makeHealthCheckFromCli(c.HealthCmd, c.HealthInterval, c.HealthRetries, c.HealthTimeout, c.HealthStartPeriod) if err != nil { @@ -318,7 +318,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions if len(c.PodIDFile) > 0 { if len(s.Pod) > 0 { - return errors.New("Cannot specify both --pod and --pod-id-file") + return errors.New("cannot specify both --pod and --pod-id-file") } podID, err := ReadPodIDFile(c.PodIDFile) if err != nil { @@ -357,7 +357,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions // any case. osEnv, err := envLib.ParseSlice(os.Environ()) if err != nil { - return errors.Wrap(err, "error parsing host environment variables") + return fmt.Errorf("error parsing host environment variables: %w", err) } if !s.EnvHost { @@ -390,7 +390,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions // LABEL VARIABLES labels, err := parse.GetAllLabels(c.LabelFile, c.Label) if err != nil { - return errors.Wrapf(err, "unable to process labels") + return fmt.Errorf("unable to process labels: %w", err) } if systemdUnit, exists := osEnv[systemdDefine.EnvVariable]; exists { @@ -414,7 +414,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions for _, annotation := range c.Annotation { splitAnnotation := strings.SplitN(annotation, "=", 2) if len(splitAnnotation) < 2 { - return errors.Errorf("Annotations must be formatted KEY=VALUE") + return errors.New("annotations must be formatted KEY=VALUE") } annotations[splitAnnotation[0]] = splitAnnotation[1] } @@ -427,7 +427,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions for _, opt := range c.StorageOpts { split := strings.SplitN(opt, "=", 2) if len(split) != 2 { - return errors.Errorf("storage-opt must be formatted KEY=VALUE") + return errors.New("storage-opt must be formatted KEY=VALUE") } opts[split[0]] = split[1] } @@ -459,7 +459,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions if c.ShmSize != "" { var m opts.MemBytes if err := m.Set(c.ShmSize); err != nil { - return errors.Wrapf(err, "unable to translate --shm-size") + return fmt.Errorf("unable to translate --shm-size: %w", err) } val := m.Value() s.ShmSize = &val @@ -531,7 +531,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions for _, unified := range c.CgroupConf { splitUnified := strings.SplitN(unified, "=", 2) if len(splitUnified) < 2 { - return errors.Errorf("--cgroup-conf must be formatted KEY=VALUE") + return errors.New("--cgroup-conf must be formatted KEY=VALUE") } unifieds[splitUnified[0]] = splitUnified[1] } @@ -608,7 +608,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions for _, ctl := range c.Sysctl { splitCtl := strings.SplitN(ctl, "=", 2) if len(splitCtl) < 2 { - return errors.Errorf("invalid sysctl value %q", ctl) + return fmt.Errorf("invalid sysctl value %q", ctl) } sysmap[splitCtl[0]] = splitCtl[1] } @@ -731,7 +731,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions } ul, err := units.ParseUlimit(u) if err != nil { - return errors.Wrapf(err, "ulimit option %q requires name=SOFT:HARD, failed to be parsed", u) + return fmt.Errorf("ulimit option %q requires name=SOFT:HARD, failed to be parsed: %w", u, err) } rl := specs.POSIXRlimit{ Type: ul.Name, @@ -745,7 +745,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions for _, o := range c.LogOptions { split := strings.SplitN(o, "=", 2) if len(split) < 2 { - return errors.Errorf("invalid log option %q", o) + return fmt.Errorf("invalid log option %q", o) } switch strings.ToLower(split[0]) { case "driver": @@ -782,19 +782,19 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions // No retries specified case 2: if strings.ToLower(splitRestart[0]) != "on-failure" { - return errors.Errorf("restart policy retries can only be specified with on-failure restart policy") + return errors.New("restart policy retries can only be specified with on-failure restart policy") } retries, err := strconv.Atoi(splitRestart[1]) if err != nil { - return errors.Wrapf(err, "error parsing restart policy retry count") + return fmt.Errorf("error parsing restart policy retry count: %w", err) } if retries < 0 { - return errors.Errorf("must specify restart policy retry count as a number greater than 0") + return errors.New("must specify restart policy retry count as a number greater than 0") } var retriesUint = uint(retries) s.RestartRetries = &retriesUint default: - return errors.Errorf("invalid restart policy: may specify retries at most once") + return errors.New("invalid restart policy: may specify retries at most once") } s.RestartPolicy = splitRestart[0] } @@ -869,7 +869,7 @@ func makeHealthCheckFromCli(inCmd, interval string, retries uint, timeout, start } // Every healthcheck requires a command if len(cmdArr) == 0 { - return nil, errors.New("Must define a healthcheck command for all healthchecks") + return nil, errors.New("must define a healthcheck command for all healthchecks") } var concat string @@ -902,7 +902,7 @@ func makeHealthCheckFromCli(inCmd, interval string, retries uint, timeout, start } intervalDuration, err := time.ParseDuration(interval) if err != nil { - return nil, errors.Wrapf(err, "invalid healthcheck-interval") + return nil, fmt.Errorf("invalid healthcheck-interval: %w", err) } hc.Interval = intervalDuration @@ -913,7 +913,7 @@ func makeHealthCheckFromCli(inCmd, interval string, retries uint, timeout, start hc.Retries = int(retries) timeoutDuration, err := time.ParseDuration(timeout) if err != nil { - return nil, errors.Wrapf(err, "invalid healthcheck-timeout") + return nil, fmt.Errorf("invalid healthcheck-timeout: %w", err) } if timeoutDuration < time.Duration(1) { return nil, errors.New("healthcheck-timeout must be at least 1 second") @@ -922,7 +922,7 @@ func makeHealthCheckFromCli(inCmd, interval string, retries uint, timeout, start startPeriodDuration, err := time.ParseDuration(startPeriod) if err != nil { - return nil, errors.Wrapf(err, "invalid healthcheck-start-period") + return nil, fmt.Errorf("invalid healthcheck-start-period: %w", err) } if startPeriodDuration < time.Duration(0) { return nil, errors.New("healthcheck-start-period must be 0 seconds or greater") @@ -1035,17 +1035,17 @@ func parseSecrets(secrets []string) ([]specgen.Secret, map[string]string, error) for _, val := range split { kv := strings.SplitN(val, "=", 2) if len(kv) < 2 { - return nil, nil, errors.Wrapf(secretParseError, "option %s must be in form option=value", val) + return nil, nil, fmt.Errorf("option %s must be in form option=value: %w", val, secretParseError) } switch kv[0] { case "source": source = kv[1] case "type": if secretType != "" { - return nil, nil, errors.Wrap(secretParseError, "cannot set more than one secret type") + return nil, nil, fmt.Errorf("cannot set more than one secret type: %w", secretParseError) } if kv[1] != "mount" && kv[1] != "env" { - return nil, nil, errors.Wrapf(secretParseError, "type %s is invalid", kv[1]) + return nil, nil, fmt.Errorf("type %s is invalid: %w", kv[1], secretParseError) } secretType = kv[1] case "target": @@ -1054,26 +1054,26 @@ func parseSecrets(secrets []string) ([]specgen.Secret, map[string]string, error) mountOnly = true mode64, err := strconv.ParseUint(kv[1], 8, 32) if err != nil { - return nil, nil, errors.Wrapf(secretParseError, "mode %s invalid", kv[1]) + return nil, nil, fmt.Errorf("mode %s invalid: %w", kv[1], secretParseError) } mode = uint32(mode64) case "uid", "UID": mountOnly = true uid64, err := strconv.ParseUint(kv[1], 10, 32) if err != nil { - return nil, nil, errors.Wrapf(secretParseError, "UID %s invalid", kv[1]) + return nil, nil, fmt.Errorf("UID %s invalid: %w", kv[1], secretParseError) } uid = uint32(uid64) case "gid", "GID": mountOnly = true gid64, err := strconv.ParseUint(kv[1], 10, 32) if err != nil { - return nil, nil, errors.Wrapf(secretParseError, "GID %s invalid", kv[1]) + return nil, nil, fmt.Errorf("GID %s invalid: %w", kv[1], secretParseError) } gid = uint32(gid64) default: - return nil, nil, errors.Wrapf(secretParseError, "option %s invalid", val) + return nil, nil, fmt.Errorf("option %s invalid: %w", val, secretParseError) } } @@ -1081,7 +1081,7 @@ func parseSecrets(secrets []string) ([]specgen.Secret, map[string]string, error) secretType = "mount" } if source == "" { - return nil, nil, errors.Wrapf(secretParseError, "no source found %s", val) + return nil, nil, fmt.Errorf("no source found %s: %w", val, secretParseError) } if secretType == "mount" { mountSecret := specgen.Secret{ @@ -1095,7 +1095,7 @@ func parseSecrets(secrets []string) ([]specgen.Secret, map[string]string, error) } if secretType == "env" { if mountOnly { - return nil, nil, errors.Wrap(secretParseError, "UID, GID, Mode options cannot be set with secret type env") + return nil, nil, fmt.Errorf("UID, GID, Mode options cannot be set with secret type env: %w", secretParseError) } if target == "" { target = source diff --git a/pkg/specgenutil/util.go b/pkg/specgenutil/util.go index fa2e90457..66d148672 100644 --- a/pkg/specgenutil/util.go +++ b/pkg/specgenutil/util.go @@ -1,6 +1,8 @@ package specgenutil import ( + "errors" + "fmt" "io/ioutil" "net" "os" @@ -10,7 +12,6 @@ import ( "github.com/containers/common/libnetwork/types" "github.com/containers/common/pkg/config" storageTypes "github.com/containers/storage/types" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -19,7 +20,7 @@ import ( func ReadPodIDFile(path string) (string, error) { content, err := ioutil.ReadFile(path) if err != nil { - return "", errors.Wrap(err, "error reading pod ID file") + return "", fmt.Errorf("error reading pod ID file: %w", err) } return strings.Split(string(content), "\n")[0], nil } @@ -50,7 +51,7 @@ func CreateExpose(expose []string) (map[uint16]string, error) { proto := "tcp" splitProto := strings.Split(e, "/") if len(splitProto) > 2 { - return nil, errors.Errorf("invalid expose format - protocol can only be specified once") + return nil, errors.New("invalid expose format - protocol can only be specified once") } else if len(splitProto) == 2 { proto = splitProto[1] } @@ -96,7 +97,7 @@ func CreatePortBindings(ports []string) ([]types.PortMapping, error) { case 2: proto = &(splitProto[1]) default: - return nil, errors.Errorf("invalid port format - protocol can only be specified once") + return nil, errors.New("invalid port format - protocol can only be specified once") } remainder := splitProto[0] @@ -111,23 +112,23 @@ func CreatePortBindings(ports []string) ([]types.PortMapping, error) { // We potentially have an IPv6 address haveV6 = true if !strings.HasPrefix(splitV6[0], "[") { - return nil, errors.Errorf("invalid port format - IPv6 addresses must be enclosed by []") + return nil, errors.New("invalid port format - IPv6 addresses must be enclosed by []") } if !strings.HasPrefix(splitV6[1], ":") { - return nil, errors.Errorf("invalid port format - IPv6 address must be followed by a colon (':')") + return nil, errors.New("invalid port format - IPv6 address must be followed by a colon (':')") } ipNoPrefix := strings.TrimPrefix(splitV6[0], "[") hostIP = &ipNoPrefix remainder = strings.TrimPrefix(splitV6[1], ":") default: - return nil, errors.Errorf("invalid port format - at most one IPv6 address can be specified in a --publish") + return nil, errors.New("invalid port format - at most one IPv6 address can be specified in a --publish") } splitPort := strings.Split(remainder, ":") switch len(splitPort) { case 1: if haveV6 { - return nil, errors.Errorf("invalid port format - must provide host and destination port if specifying an IP") + return nil, errors.New("invalid port format - must provide host and destination port if specifying an IP") } ctrPort = splitPort[0] case 2: @@ -135,13 +136,13 @@ func CreatePortBindings(ports []string) ([]types.PortMapping, error) { ctrPort = splitPort[1] case 3: if haveV6 { - return nil, errors.Errorf("invalid port format - when v6 address specified, must be [ipv6]:hostPort:ctrPort") + return nil, errors.New("invalid port format - when v6 address specified, must be [ipv6]:hostPort:ctrPort") } hostIP = &(splitPort[0]) hostPort = &(splitPort[1]) ctrPort = splitPort[2] default: - return nil, errors.Errorf("invalid port format - format is [[hostIP:]hostPort:]containerPort") + return nil, errors.New("invalid port format - format is [[hostIP:]hostPort:]containerPort") } newPort, err := parseSplitPort(hostIP, hostPort, ctrPort, proto) @@ -160,30 +161,30 @@ func CreatePortBindings(ports []string) ([]types.PortMapping, error) { func parseSplitPort(hostIP, hostPort *string, ctrPort string, protocol *string) (types.PortMapping, error) { newPort := types.PortMapping{} if ctrPort == "" { - return newPort, errors.Errorf("must provide a non-empty container port to publish") + return newPort, errors.New("must provide a non-empty container port to publish") } ctrStart, ctrLen, err := parseAndValidateRange(ctrPort) if err != nil { - return newPort, errors.Wrapf(err, "error parsing container port") + return newPort, fmt.Errorf("error parsing container port: %w", err) } newPort.ContainerPort = ctrStart newPort.Range = ctrLen if protocol != nil { if *protocol == "" { - return newPort, errors.Errorf("must provide a non-empty protocol to publish") + return newPort, errors.New("must provide a non-empty protocol to publish") } newPort.Protocol = *protocol } if hostIP != nil { if *hostIP == "" { - return newPort, errors.Errorf("must provide a non-empty container host IP to publish") + return newPort, errors.New("must provide a non-empty container host IP to publish") } else if *hostIP != "0.0.0.0" { // If hostIP is 0.0.0.0, leave it unset - CNI treats // 0.0.0.0 and empty differently, Docker does not. testIP := net.ParseIP(*hostIP) if testIP == nil { - return newPort, errors.Errorf("cannot parse %q as an IP address", *hostIP) + return newPort, fmt.Errorf("cannot parse %q as an IP address", *hostIP) } newPort.HostIP = testIP.String() } @@ -196,10 +197,10 @@ func parseSplitPort(hostIP, hostPort *string, ctrPort string, protocol *string) } else { hostStart, hostLen, err := parseAndValidateRange(*hostPort) if err != nil { - return newPort, errors.Wrapf(err, "error parsing host port") + return newPort, fmt.Errorf("error parsing host port: %w", err) } if hostLen != ctrLen { - return newPort, errors.Errorf("host and container port ranges have different lengths: %d vs %d", hostLen, ctrLen) + return newPort, fmt.Errorf("host and container port ranges have different lengths: %d vs %d", hostLen, ctrLen) } newPort.HostPort = hostStart } @@ -216,11 +217,11 @@ func parseSplitPort(hostIP, hostPort *string, ctrPort string, protocol *string) func parseAndValidateRange(portRange string) (uint16, uint16, error) { splitRange := strings.Split(portRange, "-") if len(splitRange) > 2 { - return 0, 0, errors.Errorf("invalid port format - port ranges are formatted as startPort-stopPort") + return 0, 0, errors.New("invalid port format - port ranges are formatted as startPort-stopPort") } if splitRange[0] == "" { - return 0, 0, errors.Errorf("port numbers cannot be negative") + return 0, 0, errors.New("port numbers cannot be negative") } startPort, err := parseAndValidatePort(splitRange[0]) @@ -231,14 +232,14 @@ func parseAndValidateRange(portRange string) (uint16, uint16, error) { var rangeLen uint16 = 1 if len(splitRange) == 2 { if splitRange[1] == "" { - return 0, 0, errors.Errorf("must provide ending number for port range") + return 0, 0, errors.New("must provide ending number for port range") } endPort, err := parseAndValidatePort(splitRange[1]) if err != nil { return 0, 0, err } if endPort <= startPort { - return 0, 0, errors.Errorf("the end port of a range must be higher than the start port - %d is not higher than %d", endPort, startPort) + return 0, 0, fmt.Errorf("the end port of a range must be higher than the start port - %d is not higher than %d", endPort, startPort) } // Our range is the total number of ports // involved, so we need to add 1 (8080:8081 is @@ -253,10 +254,10 @@ func parseAndValidateRange(portRange string) (uint16, uint16, error) { func parseAndValidatePort(port string) (uint16, error) { num, err := strconv.Atoi(port) if err != nil { - return 0, errors.Wrapf(err, "invalid port number") + return 0, fmt.Errorf("invalid port number: %w", err) } if num < 1 || num > 65535 { - return 0, errors.Errorf("port numbers must be between 1 and 65535 (inclusive), got %d", num) + return 0, fmt.Errorf("port numbers must be between 1 and 65535 (inclusive), got %d", num) } return uint16(num), nil } diff --git a/pkg/specgenutil/volumes.go b/pkg/specgenutil/volumes.go index 016166a20..e9fffdca9 100644 --- a/pkg/specgenutil/volumes.go +++ b/pkg/specgenutil/volumes.go @@ -2,6 +2,7 @@ package specgenutil import ( "encoding/csv" + "errors" "fmt" "path" "strings" @@ -11,14 +12,13 @@ import ( "github.com/containers/podman/v4/pkg/specgen" "github.com/containers/podman/v4/pkg/util" spec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" ) var ( - errDuplicateDest = errors.Errorf("duplicate mount destination") - optionArgError = errors.Errorf("must provide an argument for option") - noDestError = errors.Errorf("must set volume destination") - errInvalidSyntax = errors.Errorf("incorrect mount format: should be --mount type=<bind|tmpfs|volume>,[src=<host-dir|volume-name>,]target=<ctr-dir>[,options]") + errDuplicateDest = errors.New("duplicate mount destination") + errOptionArg = errors.New("must provide an argument for option") + errNoDest = errors.New("must set volume destination") + errInvalidSyntax = errors.New("incorrect mount format: should be --mount type=<bind|tmpfs|volume>,[src=<host-dir|volume-name>,]target=<ctr-dir>[,options]") ) // Parse all volume-related options in the create config into a set of mounts @@ -50,20 +50,20 @@ func parseVolumes(volumeFlag, mountFlag, tmpfsFlag []string, addReadOnlyTmpfs bo // Start with --volume. for dest, mount := range volumeMounts { if _, ok := unifiedMounts[dest]; ok { - return nil, nil, nil, nil, errors.Wrapf(errDuplicateDest, dest) + return nil, nil, nil, nil, fmt.Errorf("%v: %w", dest, errDuplicateDest) } unifiedMounts[dest] = mount } for dest, volume := range volumeVolumes { if _, ok := unifiedVolumes[dest]; ok { - return nil, nil, nil, nil, errors.Wrapf(errDuplicateDest, dest) + return nil, nil, nil, nil, fmt.Errorf("%v: %w", dest, errDuplicateDest) } unifiedVolumes[dest] = volume } // Now --tmpfs for dest, tmpfs := range tmpfsMounts { if _, ok := unifiedMounts[dest]; ok { - return nil, nil, nil, nil, errors.Wrapf(errDuplicateDest, dest) + return nil, nil, nil, nil, fmt.Errorf("%v: %w", dest, errDuplicateDest) } unifiedMounts[dest] = tmpfs } @@ -93,7 +93,7 @@ func parseVolumes(volumeFlag, mountFlag, tmpfsFlag []string, addReadOnlyTmpfs bo allMounts := make(map[string]bool) testAndSet := func(dest string) error { if _, ok := allMounts[dest]; ok { - return errors.Wrapf(errDuplicateDest, "conflict at mount destination %v", dest) + return fmt.Errorf("conflict at mount destination %v: %w", dest, errDuplicateDest) } allMounts[dest] = true return nil @@ -125,7 +125,7 @@ func parseVolumes(volumeFlag, mountFlag, tmpfsFlag []string, addReadOnlyTmpfs bo if mount.Type == define.TypeBind { absSrc, err := specgen.ConvertWinMountPath(mount.Source) if err != nil { - return nil, nil, nil, nil, errors.Wrapf(err, "error getting absolute path of %s", mount.Source) + return nil, nil, nil, nil, fmt.Errorf("error getting absolute path of %s: %w", mount.Source, err) } mount.Source = absSrc } @@ -199,7 +199,7 @@ func Mounts(mountFlag []string) (map[string]spec.Mount, map[string]*specgen.Name return nil, nil, nil, err } if _, ok := finalMounts[mount.Destination]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, mount.Destination) + return nil, nil, nil, fmt.Errorf("%v: %w", mount.Destination, errDuplicateDest) } finalMounts[mount.Destination] = mount case define.TypeTmpfs: @@ -208,7 +208,7 @@ func Mounts(mountFlag []string) (map[string]spec.Mount, map[string]*specgen.Name return nil, nil, nil, err } if _, ok := finalMounts[mount.Destination]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, mount.Destination) + return nil, nil, nil, fmt.Errorf("%v: %w", mount.Destination, errDuplicateDest) } finalMounts[mount.Destination] = mount case define.TypeDevpts: @@ -217,7 +217,7 @@ func Mounts(mountFlag []string) (map[string]spec.Mount, map[string]*specgen.Name return nil, nil, nil, err } if _, ok := finalMounts[mount.Destination]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, mount.Destination) + return nil, nil, nil, fmt.Errorf("%v: %w", mount.Destination, errDuplicateDest) } finalMounts[mount.Destination] = mount case "image": @@ -226,7 +226,7 @@ func Mounts(mountFlag []string) (map[string]spec.Mount, map[string]*specgen.Name return nil, nil, nil, err } if _, ok := finalImageVolumes[volume.Destination]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, volume.Destination) + return nil, nil, nil, fmt.Errorf("%v: %w", volume.Destination, errDuplicateDest) } finalImageVolumes[volume.Destination] = volume case "volume": @@ -235,11 +235,11 @@ func Mounts(mountFlag []string) (map[string]spec.Mount, map[string]*specgen.Name return nil, nil, nil, err } if _, ok := finalNamedVolumes[volume.Dest]; ok { - return nil, nil, nil, errors.Wrapf(errDuplicateDest, volume.Dest) + return nil, nil, nil, fmt.Errorf("%v: %w", volume.Dest, errDuplicateDest) } finalNamedVolumes[volume.Dest] = volume default: - return nil, nil, nil, errors.Errorf("invalid filesystem type %q", mountType) + return nil, nil, nil, fmt.Errorf("invalid filesystem type %q", mountType) } } @@ -261,7 +261,7 @@ func getBindMount(args []string) (spec.Mount, error) { newMount.Options = append(newMount.Options, "bind") case "readonly", "ro", "rw": if setRORW { - return newMount, errors.Wrapf(optionArgError, "cannot pass 'readonly', 'ro', or 'rw' options more than once") + return newMount, fmt.Errorf("cannot pass 'readonly', 'ro', or 'rw' options more than once: %w", errOptionArg) } setRORW = true // Can be formatted as one of: @@ -288,26 +288,26 @@ func getBindMount(args []string) (spec.Mount, error) { newMount.Options = append(newMount.Options, "ro") } default: - return newMount, errors.Wrapf(optionArgError, "'readonly', 'ro', or 'rw' must be set to true or false, instead received %q", kv[1]) + return newMount, fmt.Errorf("'readonly', 'ro', or 'rw' must be set to true or false, instead received %q: %w", kv[1], errOptionArg) } default: - return newMount, errors.Wrapf(optionArgError, "badly formatted option %q", val) + return newMount, fmt.Errorf("badly formatted option %q: %w", val, errOptionArg) } case "nosuid", "suid": if setSuid { - return newMount, errors.Wrapf(optionArgError, "cannot pass 'nosuid' and 'suid' options more than once") + return newMount, fmt.Errorf("cannot pass 'nosuid' and 'suid' options more than once: %w", errOptionArg) } setSuid = true newMount.Options = append(newMount.Options, kv[0]) case "nodev", "dev": if setDev { - return newMount, errors.Wrapf(optionArgError, "cannot pass 'nodev' and 'dev' options more than once") + return newMount, fmt.Errorf("cannot pass 'nodev' and 'dev' options more than once: %w", errOptionArg) } setDev = true newMount.Options = append(newMount.Options, kv[0]) case "noexec", "exec": if setExec { - return newMount, errors.Wrapf(optionArgError, "cannot pass 'noexec' and 'exec' options more than once") + return newMount, fmt.Errorf("cannot pass 'noexec' and 'exec' options more than once: %w", errOptionArg) } setExec = true newMount.Options = append(newMount.Options, kv[0]) @@ -315,21 +315,21 @@ func getBindMount(args []string) (spec.Mount, error) { newMount.Options = append(newMount.Options, kv[0]) case "bind-propagation": if len(kv) == 1 { - return newMount, errors.Wrapf(optionArgError, kv[0]) + return newMount, fmt.Errorf("%v: %w", kv[0], errOptionArg) } newMount.Options = append(newMount.Options, kv[1]) case "src", "source": if len(kv) == 1 { - return newMount, errors.Wrapf(optionArgError, kv[0]) + return newMount, fmt.Errorf("%v: %w", kv[0], errOptionArg) } if len(kv[1]) == 0 { - return newMount, errors.Wrapf(optionArgError, "host directory cannot be empty") + return newMount, fmt.Errorf("host directory cannot be empty: %w", errOptionArg) } newMount.Source = kv[1] setSource = true case "target", "dst", "destination": if len(kv) == 1 { - return newMount, errors.Wrapf(optionArgError, kv[0]) + return newMount, fmt.Errorf("%v: %w", kv[0], errOptionArg) } if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil { return newMount, err @@ -338,11 +338,11 @@ func getBindMount(args []string) (spec.Mount, error) { setDest = true case "relabel": if setRelabel { - return newMount, errors.Wrapf(optionArgError, "cannot pass 'relabel' option more than once") + return newMount, fmt.Errorf("cannot pass 'relabel' option more than once: %w", errOptionArg) } setRelabel = true if len(kv) != 2 { - return newMount, errors.Wrapf(util.ErrBadMntOption, "%s mount option must be 'private' or 'shared'", kv[0]) + return newMount, fmt.Errorf("%s mount option must be 'private' or 'shared': %w", kv[0], util.ErrBadMntOption) } switch kv[1] { case "private": @@ -350,11 +350,11 @@ func getBindMount(args []string) (spec.Mount, error) { case "shared": newMount.Options = append(newMount.Options, "z") default: - return newMount, errors.Wrapf(util.ErrBadMntOption, "%s mount option must be 'private' or 'shared'", kv[0]) + return newMount, fmt.Errorf("%s mount option must be 'private' or 'shared': %w", kv[0], util.ErrBadMntOption) } case "U", "chown": if setOwnership { - return newMount, errors.Wrapf(optionArgError, "cannot pass 'U' or 'chown' option more than once") + return newMount, fmt.Errorf("cannot pass 'U' or 'chown' option more than once: %w", errOptionArg) } ok, err := validChownFlag(val) if err != nil { @@ -375,12 +375,12 @@ func getBindMount(args []string) (spec.Mount, error) { // Since Docker ignores this option so shall we. continue default: - return newMount, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) + return newMount, fmt.Errorf("%s: %w", kv[0], util.ErrBadMntOption) } } if !setDest { - return newMount, noDestError + return newMount, errNoDest } if !setSource { @@ -409,49 +409,49 @@ func getTmpfsMount(args []string) (spec.Mount, error) { switch kv[0] { case "tmpcopyup", "notmpcopyup": if setTmpcopyup { - return newMount, errors.Wrapf(optionArgError, "cannot pass 'tmpcopyup' and 'notmpcopyup' options more than once") + return newMount, fmt.Errorf("cannot pass 'tmpcopyup' and 'notmpcopyup' options more than once: %w", errOptionArg) } setTmpcopyup = true newMount.Options = append(newMount.Options, kv[0]) case "ro", "rw": if setRORW { - return newMount, errors.Wrapf(optionArgError, "cannot pass 'ro' and 'rw' options more than once") + return newMount, fmt.Errorf("cannot pass 'ro' and 'rw' options more than once: %w", errOptionArg) } setRORW = true newMount.Options = append(newMount.Options, kv[0]) case "nosuid", "suid": if setSuid { - return newMount, errors.Wrapf(optionArgError, "cannot pass 'nosuid' and 'suid' options more than once") + return newMount, fmt.Errorf("cannot pass 'nosuid' and 'suid' options more than once: %w", errOptionArg) } setSuid = true newMount.Options = append(newMount.Options, kv[0]) case "nodev", "dev": if setDev { - return newMount, errors.Wrapf(optionArgError, "cannot pass 'nodev' and 'dev' options more than once") + return newMount, fmt.Errorf("cannot pass 'nodev' and 'dev' options more than once: %w", errOptionArg) } setDev = true newMount.Options = append(newMount.Options, kv[0]) case "noexec", "exec": if setExec { - return newMount, errors.Wrapf(optionArgError, "cannot pass 'noexec' and 'exec' options more than once") + return newMount, fmt.Errorf("cannot pass 'noexec' and 'exec' options more than once: %w", errOptionArg) } setExec = true newMount.Options = append(newMount.Options, kv[0]) case "tmpfs-mode": if len(kv) == 1 { - return newMount, errors.Wrapf(optionArgError, kv[0]) + return newMount, fmt.Errorf("%v: %w", kv[0], errOptionArg) } newMount.Options = append(newMount.Options, fmt.Sprintf("mode=%s", kv[1])) case "tmpfs-size": if len(kv) == 1 { - return newMount, errors.Wrapf(optionArgError, kv[0]) + return newMount, fmt.Errorf("%v: %w", kv[0], errOptionArg) } newMount.Options = append(newMount.Options, fmt.Sprintf("size=%s", kv[1])) case "src", "source": - return newMount, errors.Errorf("source is not supported with tmpfs mounts") + return newMount, fmt.Errorf("source is not supported with tmpfs mounts") case "target", "dst", "destination": if len(kv) == 1 { - return newMount, errors.Wrapf(optionArgError, kv[0]) + return newMount, fmt.Errorf("%v: %w", kv[0], errOptionArg) } if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil { return newMount, err @@ -460,7 +460,7 @@ func getTmpfsMount(args []string) (spec.Mount, error) { setDest = true case "U", "chown": if setOwnership { - return newMount, errors.Wrapf(optionArgError, "cannot pass 'U' or 'chown' option more than once") + return newMount, fmt.Errorf("cannot pass 'U' or 'chown' option more than once: %w", errOptionArg) } ok, err := validChownFlag(val) if err != nil { @@ -475,12 +475,12 @@ func getTmpfsMount(args []string) (spec.Mount, error) { // Since Docker ignores this option so shall we. continue default: - return newMount, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) + return newMount, fmt.Errorf("%s: %w", kv[0], util.ErrBadMntOption) } } if !setDest { - return newMount, noDestError + return newMount, errNoDest } return newMount, nil @@ -502,7 +502,7 @@ func getDevptsMount(args []string) (spec.Mount, error) { newMount.Options = append(newMount.Options, val) case "target", "dst", "destination": if len(kv) == 1 { - return newMount, errors.Wrapf(optionArgError, kv[0]) + return newMount, fmt.Errorf("%v: %w", kv[0], errOptionArg) } if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil { return newMount, err @@ -510,12 +510,12 @@ func getDevptsMount(args []string) (spec.Mount, error) { newMount.Destination = unixPathClean(kv[1]) setDest = true default: - return newMount, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) + return newMount, fmt.Errorf("%s: %w", kv[0], util.ErrBadMntOption) } } if !setDest { - return newMount, noDestError + return newMount, errNoDest } return newMount, nil @@ -536,38 +536,38 @@ func getNamedVolume(args []string) (*specgen.NamedVolume, error) { newVolume.Options = append(newVolume.Options, val) case "ro", "rw": if setRORW { - return nil, errors.Wrapf(optionArgError, "cannot pass 'ro' and 'rw' options more than once") + return nil, fmt.Errorf("cannot pass 'ro' and 'rw' options more than once: %w", errOptionArg) } setRORW = true newVolume.Options = append(newVolume.Options, kv[0]) case "nosuid", "suid": if setSuid { - return nil, errors.Wrapf(optionArgError, "cannot pass 'nosuid' and 'suid' options more than once") + return nil, fmt.Errorf("cannot pass 'nosuid' and 'suid' options more than once: %w", errOptionArg) } setSuid = true newVolume.Options = append(newVolume.Options, kv[0]) case "nodev", "dev": if setDev { - return nil, errors.Wrapf(optionArgError, "cannot pass 'nodev' and 'dev' options more than once") + return nil, fmt.Errorf("cannot pass 'nodev' and 'dev' options more than once: %w", errOptionArg) } setDev = true newVolume.Options = append(newVolume.Options, kv[0]) case "noexec", "exec": if setExec { - return nil, errors.Wrapf(optionArgError, "cannot pass 'noexec' and 'exec' options more than once") + return nil, fmt.Errorf("cannot pass 'noexec' and 'exec' options more than once: %w", errOptionArg) } setExec = true newVolume.Options = append(newVolume.Options, kv[0]) case "volume-label": - return nil, errors.Errorf("the --volume-label option is not presently implemented") + return nil, fmt.Errorf("the --volume-label option is not presently implemented") case "src", "source": if len(kv) == 1 { - return nil, errors.Wrapf(optionArgError, kv[0]) + return nil, fmt.Errorf("%v: %w", kv[0], errOptionArg) } newVolume.Name = kv[1] case "target", "dst", "destination": if len(kv) == 1 { - return nil, errors.Wrapf(optionArgError, kv[0]) + return nil, fmt.Errorf("%v: %w", kv[0], errOptionArg) } if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil { return nil, err @@ -576,7 +576,7 @@ func getNamedVolume(args []string) (*specgen.NamedVolume, error) { setDest = true case "U", "chown": if setOwnership { - return newVolume, errors.Wrapf(optionArgError, "cannot pass 'U' or 'chown' option more than once") + return newVolume, fmt.Errorf("cannot pass 'U' or 'chown' option more than once: %w", errOptionArg) } ok, err := validChownFlag(val) if err != nil { @@ -591,12 +591,12 @@ func getNamedVolume(args []string) (*specgen.NamedVolume, error) { // Since Docker ignores this option so shall we. continue default: - return nil, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) + return nil, fmt.Errorf("%s: %w", kv[0], util.ErrBadMntOption) } } if !setDest { - return nil, noDestError + return nil, errNoDest } return newVolume, nil @@ -614,12 +614,12 @@ func getImageVolume(args []string) (*specgen.ImageVolume, error) { switch kv[0] { case "src", "source": if len(kv) == 1 { - return nil, errors.Wrapf(optionArgError, kv[0]) + return nil, fmt.Errorf("%v: %w", kv[0], errOptionArg) } newVolume.Source = kv[1] case "target", "dst", "destination": if len(kv) == 1 { - return nil, errors.Wrapf(optionArgError, kv[0]) + return nil, fmt.Errorf("%v: %w", kv[0], errOptionArg) } if err := parse.ValidateVolumeCtrDir(kv[1]); err != nil { return nil, err @@ -632,19 +632,19 @@ func getImageVolume(args []string) (*specgen.ImageVolume, error) { case "false": // Nothing to do. RO is default. default: - return nil, errors.Wrapf(util.ErrBadMntOption, "invalid rw value %q", kv[1]) + return nil, fmt.Errorf("invalid rw value %q: %w", kv[1], util.ErrBadMntOption) } case "consistency": // Often used on MACs and mistakenly on Linux platforms. // Since Docker ignores this option so shall we. continue default: - return nil, errors.Wrapf(util.ErrBadMntOption, "%s", kv[0]) + return nil, fmt.Errorf("%s: %w", kv[0], util.ErrBadMntOption) } } if len(newVolume.Source)*len(newVolume.Destination) == 0 { - return nil, errors.Errorf("must set source and destination for image volume") + return nil, errors.New("must set source and destination for image volume") } return newVolume, nil @@ -666,7 +666,7 @@ func getTmpfsMounts(tmpfsFlag []string) (map[string]spec.Mount, error) { } if _, ok := m[destPath]; ok { - return nil, errors.Wrapf(errDuplicateDest, destPath) + return nil, fmt.Errorf("%v: %w", destPath, errDuplicateDest) } mount := spec.Mount{ @@ -692,10 +692,10 @@ func validChownFlag(flag string) (bool, error) { case "false": return false, nil default: - return false, errors.Wrapf(optionArgError, "'U' or 'chown' must be set to true or false, instead received %q", kv[1]) + return false, fmt.Errorf("'U' or 'chown' must be set to true or false, instead received %q: %w", kv[1], errOptionArg) } default: - return false, errors.Wrapf(optionArgError, "badly formatted option %q", flag) + return false, fmt.Errorf("badly formatted option %q: %w", flag, errOptionArg) } return true, nil diff --git a/pkg/systemd/generate/common.go b/pkg/systemd/generate/common.go index e53d37897..60b0c4b52 100644 --- a/pkg/systemd/generate/common.go +++ b/pkg/systemd/generate/common.go @@ -1,11 +1,11 @@ package generate import ( + "fmt" "strconv" "strings" "github.com/containers/podman/v4/pkg/systemd/define" - "github.com/pkg/errors" ) // minTimeoutStopSec is the minimal stop timeout for generated systemd units. @@ -20,7 +20,7 @@ func validateRestartPolicy(restart string) error { return nil } } - return errors.Errorf("%s is not a valid restart policy", restart) + return fmt.Errorf("%s is not a valid restart policy", restart) } const headerTemplate = `# {{{{.ServiceName}}}}{{{{- if (eq .IdentifySpecifier true) }}}}@{{{{- end}}}}.service diff --git a/pkg/systemd/generate/containers.go b/pkg/systemd/generate/containers.go index e953a1f1f..6596ef73b 100644 --- a/pkg/systemd/generate/containers.go +++ b/pkg/systemd/generate/containers.go @@ -2,6 +2,7 @@ package generate import ( "bytes" + "errors" "fmt" "os" "sort" @@ -14,7 +15,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/systemd/define" "github.com/containers/podman/v4/version" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/pflag" ) @@ -186,14 +186,14 @@ func generateContainerInfo(ctr *libpod.Container, options entities.GenerateSyste config := ctr.Config() conmonPidFile := config.ConmonPidFile if conmonPidFile == "" { - return nil, errors.Errorf("conmon PID file path is empty, try to recreate the container with --conmon-pidfile flag") + return nil, errors.New("conmon PID file path is empty, try to recreate the container with --conmon-pidfile flag") } createCommand := []string{} if config.CreateCommand != nil { createCommand = config.CreateCommand } else if options.New { - return nil, errors.Errorf("cannot use --new on container %q: no create command found: only works on containers created directly with podman but not via REST API", ctr.ID()) + return nil, fmt.Errorf("cannot use --new on container %q: no create command found: only works on containers created directly with podman but not via REST API", ctr.ID()) } nameOrID, serviceName := containerServiceName(ctr, options) @@ -204,7 +204,7 @@ func generateContainerInfo(ctr *libpod.Container, options entities.GenerateSyste } else { runRoot = ctr.Runtime().RunRoot() if runRoot == "" { - return nil, errors.Errorf("could not look up container's runroot: got empty string") + return nil, errors.New("could not look up container's runroot: got empty string") } } @@ -350,7 +350,7 @@ func executeContainerTemplate(info *containerInfo, options entities.GenerateSyst } } if index == 0 { - return "", errors.Errorf("container's create command is too short or invalid: %v", info.CreateCommand) + return "", fmt.Errorf("container's create command is too short or invalid: %v", info.CreateCommand) } // We're hard-coding the first five arguments and append the // CreateCommand with a stripped command and subcommand. @@ -520,7 +520,7 @@ func executeContainerTemplate(info *containerInfo, options entities.GenerateSyst // template execution. templ, err := template.New("container_template").Delims("{{{{", "}}}}").Parse(containerTemplate) if err != nil { - return "", errors.Wrap(err, "error parsing systemd service template") + return "", fmt.Errorf("error parsing systemd service template: %w", err) } var buf bytes.Buffer @@ -531,7 +531,7 @@ func executeContainerTemplate(info *containerInfo, options entities.GenerateSyst // Now parse the generated template (i.e., buf) and execute it. templ, err = template.New("container_template").Delims("{{{{", "}}}}").Parse(buf.String()) if err != nil { - return "", errors.Wrap(err, "error parsing systemd service template") + return "", fmt.Errorf("error parsing systemd service template: %w", err) } buf = bytes.Buffer{} diff --git a/pkg/systemd/generate/pods.go b/pkg/systemd/generate/pods.go index 4043fbfcb..8640418a7 100644 --- a/pkg/systemd/generate/pods.go +++ b/pkg/systemd/generate/pods.go @@ -2,6 +2,7 @@ package generate import ( "bytes" + "errors" "fmt" "os" "sort" @@ -13,7 +14,6 @@ import ( "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/systemd/define" "github.com/containers/podman/v4/version" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/pflag" ) @@ -141,7 +141,7 @@ func PodUnits(pod *libpod.Pod, options entities.GenerateSystemdOptions) (map[str // Error out if the pod has no infra container, which we require to be the // main service. if !pod.HasInfraContainer() { - return nil, errors.Errorf("generating systemd unit files: Pod %q has no infra container", pod.Name()) + return nil, fmt.Errorf("generating systemd unit files: Pod %q has no infra container", pod.Name()) } podInfo, err := generatePodInfo(pod, options) @@ -160,7 +160,7 @@ func PodUnits(pod *libpod.Pod, options entities.GenerateSystemdOptions) (map[str return nil, err } if len(containers) == 0 { - return nil, errors.Errorf("generating systemd unit files: Pod %q has no containers", pod.Name()) + return nil, fmt.Errorf("generating systemd unit files: Pod %q has no containers", pod.Name()) } graph, err := libpod.BuildContainerGraph(containers) if err != nil { @@ -217,7 +217,7 @@ func generatePodInfo(pod *libpod.Pod, options entities.GenerateSystemdOptions) ( // containerInfo acts as the main service of the pod. infraCtr, err := pod.InfraContainer() if err != nil { - return nil, errors.Wrap(err, "could not find infra container") + return nil, fmt.Errorf("could not find infra container: %w", err) } stopTimeout := infraCtr.StopTimeout() @@ -228,12 +228,12 @@ func generatePodInfo(pod *libpod.Pod, options entities.GenerateSystemdOptions) ( config := infraCtr.Config() conmonPidFile := config.ConmonPidFile if conmonPidFile == "" { - return nil, errors.Errorf("conmon PID file path is empty, try to recreate the container with --conmon-pidfile flag") + return nil, errors.New("conmon PID file path is empty, try to recreate the container with --conmon-pidfile flag") } createCommand := pod.CreateCommand() if options.New && len(createCommand) == 0 { - return nil, errors.Errorf("cannot use --new on pod %q: no create command found", pod.ID()) + return nil, fmt.Errorf("cannot use --new on pod %q: no create command found", pod.ID()) } nameOrID := pod.ID() @@ -312,7 +312,7 @@ func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions) var podRootArgs, podCreateArgs []string switch len(info.CreateCommand) { case 0, 1, 2: - return "", errors.Errorf("pod does not appear to be created via `podman pod create`: %v", info.CreateCommand) + return "", fmt.Errorf("pod does not appear to be created via `podman pod create`: %v", info.CreateCommand) default: // Make sure that pod was created with `pod create` and // not something else, such as `run --pod new`. @@ -323,7 +323,7 @@ func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions) } } if podCreateIndex == 0 { - return "", errors.Errorf("pod does not appear to be created via `podman pod create`: %v", info.CreateCommand) + return "", fmt.Errorf("pod does not appear to be created via `podman pod create`: %v", info.CreateCommand) } podRootArgs = info.CreateCommand[1 : podCreateIndex-1] info.RootFlags = strings.Join(escapeSystemdArguments(podRootArgs), " ") @@ -402,7 +402,7 @@ func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions) // template execution. templ, err := template.New("pod_template").Delims("{{{{", "}}}}").Parse(podTemplate) if err != nil { - return "", errors.Wrap(err, "error parsing systemd service template") + return "", fmt.Errorf("error parsing systemd service template: %w", err) } var buf bytes.Buffer @@ -413,7 +413,7 @@ func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions) // Now parse the generated template (i.e., buf) and execute it. templ, err = template.New("pod_template").Delims("{{{{", "}}}}").Parse(buf.String()) if err != nil { - return "", errors.Wrap(err, "error parsing systemd service template") + return "", fmt.Errorf("error parsing systemd service template: %w", err) } buf = bytes.Buffer{} diff --git a/pkg/trust/trust.go b/pkg/trust/trust.go index 1d0cc61ba..663a1b5e2 100644 --- a/pkg/trust/trust.go +++ b/pkg/trust/trust.go @@ -5,6 +5,7 @@ import ( "bytes" "encoding/base64" "encoding/json" + "fmt" "io/ioutil" "os" "os/exec" @@ -14,7 +15,6 @@ import ( "github.com/containers/image/v5/types" "github.com/docker/docker/pkg/homedir" "github.com/ghodss/yaml" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -126,11 +126,11 @@ func LoadAndMergeConfig(dirPath string) (*RegistryConfiguration, error) { var config RegistryConfiguration err = yaml.Unmarshal(configBytes, &config) if err != nil { - return nil, errors.Wrapf(err, "error parsing %s", configPath) + return nil, fmt.Errorf("error parsing %s: %w", configPath, err) } if config.DefaultDocker != nil { if mergedConfig.DefaultDocker != nil { - return nil, errors.Errorf(`Error parsing signature storage configuration: "default-docker" defined both in "%s" and "%s"`, + return nil, fmt.Errorf(`error parsing signature storage configuration: "default-docker" defined both in "%s" and "%s"`, dockerDefaultMergedFrom, configPath) } mergedConfig.DefaultDocker = config.DefaultDocker @@ -138,7 +138,7 @@ func LoadAndMergeConfig(dirPath string) (*RegistryConfiguration, error) { } for nsName, nsConfig := range config.Docker { // includes config.Docker == nil if _, ok := mergedConfig.Docker[nsName]; ok { - return nil, errors.Errorf(`Error parsing signature storage configuration: "docker" namespace "%s" defined both in "%s" and "%s"`, + return nil, fmt.Errorf(`error parsing signature storage configuration: "docker" namespace "%s" defined both in "%s" and "%s"`, nsName, nsMergedFrom[nsName], configPath) } mergedConfig.Docker[nsName] = nsConfig @@ -234,10 +234,10 @@ func GetPolicy(policyPath string) (PolicyContent, error) { var policyContentStruct PolicyContent policyContent, err := ioutil.ReadFile(policyPath) if err != nil { - return policyContentStruct, errors.Wrap(err, "unable to read policy file") + return policyContentStruct, fmt.Errorf("unable to read policy file: %w", err) } if err := json.Unmarshal(policyContent, &policyContentStruct); err != nil { - return policyContentStruct, errors.Wrapf(err, "could not parse trust policies from %s", policyPath) + return policyContentStruct, fmt.Errorf("could not parse trust policies from %s: %w", policyPath, err) } return policyContentStruct, nil } diff --git a/pkg/util/filters.go b/pkg/util/filters.go index 05ba4f82c..08148806f 100644 --- a/pkg/util/filters.go +++ b/pkg/util/filters.go @@ -2,6 +2,7 @@ package util import ( "encoding/json" + "errors" "fmt" "net/http" "path/filepath" @@ -9,14 +10,13 @@ import ( "time" "github.com/containers/podman/v4/pkg/timetype" - "github.com/pkg/errors" ) // ComputeUntilTimestamp extracts until timestamp from filters func ComputeUntilTimestamp(filterValues []string) (time.Time, error) { invalid := time.Time{} if len(filterValues) != 1 { - return invalid, errors.Errorf("specify exactly one timestamp for until") + return invalid, errors.New("specify exactly one timestamp for until") } ts, err := timetype.GetTimestamp(filterValues[0], time.Now()) if err != nil { diff --git a/pkg/util/mountOpts.go b/pkg/util/mountOpts.go index d1dd75a82..49fd5b467 100644 --- a/pkg/util/mountOpts.go +++ b/pkg/util/mountOpts.go @@ -1,16 +1,16 @@ package util import ( + "errors" + "fmt" "strings" - - "github.com/pkg/errors" ) var ( // ErrBadMntOption indicates that an invalid mount option was passed. - ErrBadMntOption = errors.Errorf("invalid mount option") + ErrBadMntOption = errors.New("invalid mount option") // ErrDupeMntOption indicates that a duplicate mount option was passed. - ErrDupeMntOption = errors.Errorf("duplicate mount option passed") + ErrDupeMntOption = errors.New("duplicate mount option passed") ) type defaultMountOptions struct { @@ -47,7 +47,7 @@ func ProcessOptions(options []string, isTmpfs bool, sourcePath string) ([]string if strings.HasPrefix(splitOpt[0], "idmap") { if foundIdmap { - return nil, errors.Wrapf(ErrDupeMntOption, "the 'idmap' option can only be set once") + return nil, fmt.Errorf("the 'idmap' option can only be set once: %w", ErrDupeMntOption) } foundIdmap = true newOptions = append(newOptions, opt) @@ -57,7 +57,7 @@ func ProcessOptions(options []string, isTmpfs bool, sourcePath string) ([]string switch splitOpt[0] { case "copy", "nocopy": if foundCopy { - return nil, errors.Wrapf(ErrDupeMntOption, "only one of 'nocopy' and 'copy' can be used") + return nil, fmt.Errorf("only one of 'nocopy' and 'copy' can be used: %w", ErrDupeMntOption) } foundCopy = true case "O": @@ -67,51 +67,51 @@ func ProcessOptions(options []string, isTmpfs bool, sourcePath string) ([]string newOptions = append(newOptions, opt) case "exec", "noexec": if foundExec { - return nil, errors.Wrapf(ErrDupeMntOption, "only one of 'noexec' and 'exec' can be used") + return nil, fmt.Errorf("only one of 'noexec' and 'exec' can be used: %w", ErrDupeMntOption) } foundExec = true case "suid", "nosuid": if foundSuid { - return nil, errors.Wrapf(ErrDupeMntOption, "only one of 'nosuid' and 'suid' can be used") + return nil, fmt.Errorf("only one of 'nosuid' and 'suid' can be used: %w", ErrDupeMntOption) } foundSuid = true case "nodev", "dev": if foundDev { - return nil, errors.Wrapf(ErrDupeMntOption, "only one of 'nodev' and 'dev' can be used") + return nil, fmt.Errorf("only one of 'nodev' and 'dev' can be used: %w", ErrDupeMntOption) } foundDev = true case "rw", "ro": if foundWrite { - return nil, errors.Wrapf(ErrDupeMntOption, "only one of 'rw' and 'ro' can be used") + return nil, fmt.Errorf("only one of 'rw' and 'ro' can be used: %w", ErrDupeMntOption) } foundWrite = true case "private", "rprivate", "slave", "rslave", "shared", "rshared", "unbindable", "runbindable": if foundProp { - return nil, errors.Wrapf(ErrDupeMntOption, "only one root propagation mode can be used") + return nil, fmt.Errorf("only one root propagation mode can be used: %w", ErrDupeMntOption) } foundProp = true case "size": if !isTmpfs { - return nil, errors.Wrapf(ErrBadMntOption, "the 'size' option is only allowed with tmpfs mounts") + return nil, fmt.Errorf("the 'size' option is only allowed with tmpfs mounts: %w", ErrBadMntOption) } if foundSize { - return nil, errors.Wrapf(ErrDupeMntOption, "only one tmpfs size can be specified") + return nil, fmt.Errorf("only one tmpfs size can be specified: %w", ErrDupeMntOption) } foundSize = true case "mode": if !isTmpfs { - return nil, errors.Wrapf(ErrBadMntOption, "the 'mode' option is only allowed with tmpfs mounts") + return nil, fmt.Errorf("the 'mode' option is only allowed with tmpfs mounts: %w", ErrBadMntOption) } if foundMode { - return nil, errors.Wrapf(ErrDupeMntOption, "only one tmpfs mode can be specified") + return nil, fmt.Errorf("only one tmpfs mode can be specified: %w", ErrDupeMntOption) } foundMode = true case "tmpcopyup": if !isTmpfs { - return nil, errors.Wrapf(ErrBadMntOption, "the 'tmpcopyup' option is only allowed with tmpfs mounts") + return nil, fmt.Errorf("the 'tmpcopyup' option is only allowed with tmpfs mounts: %w", ErrBadMntOption) } if foundCopyUp { - return nil, errors.Wrapf(ErrDupeMntOption, "the 'tmpcopyup' or 'notmpcopyup' option can only be set once") + return nil, fmt.Errorf("the 'tmpcopyup' or 'notmpcopyup' option can only be set once: %w", ErrDupeMntOption) } foundCopyUp = true case "consistency": @@ -120,37 +120,37 @@ func ProcessOptions(options []string, isTmpfs bool, sourcePath string) ([]string continue case "notmpcopyup": if !isTmpfs { - return nil, errors.Wrapf(ErrBadMntOption, "the 'notmpcopyup' option is only allowed with tmpfs mounts") + return nil, fmt.Errorf("the 'notmpcopyup' option is only allowed with tmpfs mounts: %w", ErrBadMntOption) } if foundCopyUp { - return nil, errors.Wrapf(ErrDupeMntOption, "the 'tmpcopyup' or 'notmpcopyup' option can only be set once") + return nil, fmt.Errorf("the 'tmpcopyup' or 'notmpcopyup' option can only be set once: %w", ErrDupeMntOption) } foundCopyUp = true // do not propagate notmpcopyup to the OCI runtime continue case "bind", "rbind": if isTmpfs { - return nil, errors.Wrapf(ErrBadMntOption, "the 'bind' and 'rbind' options are not allowed with tmpfs mounts") + return nil, fmt.Errorf("the 'bind' and 'rbind' options are not allowed with tmpfs mounts: %w", ErrBadMntOption) } if foundBind { - return nil, errors.Wrapf(ErrDupeMntOption, "only one of 'rbind' and 'bind' can be used") + return nil, fmt.Errorf("only one of 'rbind' and 'bind' can be used: %w", ErrDupeMntOption) } foundBind = true case "z", "Z": if isTmpfs { - return nil, errors.Wrapf(ErrBadMntOption, "the 'z' and 'Z' options are not allowed with tmpfs mounts") + return nil, fmt.Errorf("the 'z' and 'Z' options are not allowed with tmpfs mounts: %w", ErrBadMntOption) } if foundZ { - return nil, errors.Wrapf(ErrDupeMntOption, "only one of 'z' and 'Z' can be used") + return nil, fmt.Errorf("only one of 'z' and 'Z' can be used: %w", ErrDupeMntOption) } foundZ = true case "U": if foundU { - return nil, errors.Wrapf(ErrDupeMntOption, "the 'U' option can only be set once") + return nil, fmt.Errorf("the 'U' option can only be set once: %w", ErrDupeMntOption) } foundU = true default: - return nil, errors.Wrapf(ErrBadMntOption, "unknown mount option %q", opt) + return nil, fmt.Errorf("unknown mount option %q: %w", opt, ErrBadMntOption) } newOptions = append(newOptions, opt) } @@ -187,11 +187,11 @@ func ProcessOptions(options []string, isTmpfs bool, sourcePath string) ([]string func ParseDriverOpts(option string) (string, string, error) { token := strings.SplitN(option, "=", 2) if len(token) != 2 { - return "", "", errors.Wrapf(ErrBadMntOption, "cannot parse driver opts") + return "", "", fmt.Errorf("cannot parse driver opts: %w", ErrBadMntOption) } opt := strings.SplitN(token[1], "=", 2) if len(opt) != 2 { - return "", "", errors.Wrapf(ErrBadMntOption, "cannot parse driver opts") + return "", "", fmt.Errorf("cannot parse driver opts: %w", ErrBadMntOption) } return opt[0], opt[1], nil } diff --git a/pkg/util/utils.go b/pkg/util/utils.go index ad5db9a1a..33c11d611 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -2,6 +2,7 @@ package util import ( "encoding/json" + "errors" "fmt" "io/fs" "math" @@ -27,7 +28,6 @@ import ( stypes "github.com/containers/storage/types" v1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/term" ) @@ -68,7 +68,7 @@ func ParseRegistryCreds(creds string) (*types.DockerAuthConfig, error) { fmt.Print("Password: ") termPassword, err := term.ReadPassword(0) if err != nil { - return nil, errors.Wrapf(err, "could not read password from terminal") + return nil, fmt.Errorf("could not read password from terminal: %w", err) } password = string(termPassword) } @@ -129,7 +129,7 @@ func GetImageConfig(changes []string) (ImageConfig, error) { if len(split) != 2 { split = strings.SplitN(change, "=", 2) if len(split) != 2 { - return ImageConfig{}, errors.Errorf("invalid change %q - must be formatted as KEY VALUE", change) + return ImageConfig{}, fmt.Errorf("invalid change %q - must be formatted as KEY VALUE", change) } } @@ -139,7 +139,7 @@ func GetImageConfig(changes []string) (ImageConfig, error) { case "USER": // Assume literal contents are the user. if value == "" { - return ImageConfig{}, errors.Errorf("invalid change %q - must provide a value to USER", change) + return ImageConfig{}, fmt.Errorf("invalid change %q - must provide a value to USER", change) } config.User = value case "EXPOSE": @@ -148,14 +148,14 @@ func GetImageConfig(changes []string) (ImageConfig, error) { // Protocol must be "tcp" or "udp" splitPort := strings.Split(value, "/") if len(splitPort) > 2 { - return ImageConfig{}, errors.Errorf("invalid change %q - EXPOSE port must be formatted as PORT[/PROTO]", change) + return ImageConfig{}, fmt.Errorf("invalid change %q - EXPOSE port must be formatted as PORT[/PROTO]", change) } portNum, err := strconv.Atoi(splitPort[0]) if err != nil { - return ImageConfig{}, errors.Wrapf(err, "invalid change %q - EXPOSE port must be an integer", change) + return ImageConfig{}, fmt.Errorf("invalid change %q - EXPOSE port must be an integer: %w", change, err) } if portNum > 65535 || portNum <= 0 { - return ImageConfig{}, errors.Errorf("invalid change %q - EXPOSE port must be a valid port number", change) + return ImageConfig{}, fmt.Errorf("invalid change %q - EXPOSE port must be a valid port number", change) } proto := "tcp" if len(splitPort) > 1 { @@ -164,7 +164,7 @@ func GetImageConfig(changes []string) (ImageConfig, error) { case "tcp", "udp": proto = testProto default: - return ImageConfig{}, errors.Errorf("invalid change %q - EXPOSE protocol must be TCP or UDP", change) + return ImageConfig{}, fmt.Errorf("invalid change %q - EXPOSE protocol must be TCP or UDP", change) } } if config.ExposedPorts == nil { @@ -188,7 +188,7 @@ func GetImageConfig(changes []string) (ImageConfig, error) { key = splitEnv[0] // We do need a key if key == "" { - return ImageConfig{}, errors.Errorf("invalid change %q - ENV must have at least one argument", change) + return ImageConfig{}, fmt.Errorf("invalid change %q - ENV must have at least one argument", change) } // Perfectly valid to not have a value if len(splitEnv) == 2 { @@ -250,11 +250,11 @@ func GetImageConfig(changes []string) (ImageConfig, error) { testUnmarshal = strings.Split(value, " ") } if len(testUnmarshal) == 0 { - return ImageConfig{}, errors.Errorf("invalid change %q - must provide at least one argument to VOLUME", change) + return ImageConfig{}, fmt.Errorf("invalid change %q - must provide at least one argument to VOLUME", change) } for _, vol := range testUnmarshal { if vol == "" { - return ImageConfig{}, errors.Errorf("invalid change %q - VOLUME paths must not be empty", change) + return ImageConfig{}, fmt.Errorf("invalid change %q - VOLUME paths must not be empty", change) } if config.Volumes == nil { config.Volumes = make(map[string]struct{}) @@ -268,7 +268,7 @@ func GetImageConfig(changes []string) (ImageConfig, error) { // WORKDIR c results in /A/b/c // Just need to check it's not empty... if value == "" { - return ImageConfig{}, errors.Errorf("invalid change %q - must provide a non-empty WORKDIR", change) + return ImageConfig{}, fmt.Errorf("invalid change %q - must provide a non-empty WORKDIR", change) } config.WorkingDir = filepath.Join(config.WorkingDir, value) case "LABEL": @@ -285,7 +285,7 @@ func GetImageConfig(changes []string) (ImageConfig, error) { splitLabel := strings.SplitN(value, "=", 2) // Unlike ENV, LABEL must have a value if len(splitLabel) != 2 { - return ImageConfig{}, errors.Errorf("invalid change %q - LABEL must be formatted key=value", change) + return ImageConfig{}, fmt.Errorf("invalid change %q - LABEL must be formatted key=value", change) } key = splitLabel[0] val = splitLabel[1] @@ -298,7 +298,7 @@ func GetImageConfig(changes []string) (ImageConfig, error) { } // Check key after we strip quotations if key == "" { - return ImageConfig{}, errors.Errorf("invalid change %q - LABEL must have a non-empty key", change) + return ImageConfig{}, fmt.Errorf("invalid change %q - LABEL must have a non-empty key", change) } if config.Labels == nil { config.Labels = make(map[string]string) @@ -308,17 +308,17 @@ func GetImageConfig(changes []string) (ImageConfig, error) { // Check the provided signal for validity. killSignal, err := ParseSignal(value) if err != nil { - return ImageConfig{}, errors.Wrapf(err, "invalid change %q - KILLSIGNAL must be given a valid signal", change) + return ImageConfig{}, fmt.Errorf("invalid change %q - KILLSIGNAL must be given a valid signal: %w", change, err) } config.StopSignal = fmt.Sprintf("%d", killSignal) case "ONBUILD": // Onbuild always appends. if value == "" { - return ImageConfig{}, errors.Errorf("invalid change %q - ONBUILD must be given an argument", change) + return ImageConfig{}, fmt.Errorf("invalid change %q - ONBUILD must be given an argument", change) } config.OnBuild = append(config.OnBuild, value) default: - return ImageConfig{}, errors.Errorf("invalid change %q - invalid instruction %s", change, outerKey) + return ImageConfig{}, fmt.Errorf("invalid change %q - invalid instruction %s", change, outerKey) } } @@ -336,7 +336,7 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) { } // 64 is SIGRTMAX; wish we could get this from a standard Go library if sig < 1 || sig > 64 { - return -1, errors.Errorf("valid signals are 1 through 64") + return -1, errors.New("valid signals are 1 through 64") } return sig, nil } @@ -362,10 +362,10 @@ func GetKeepIDMapping() (*stypes.IDMappingOptions, int, int, error) { uids, gids, err := rootless.GetConfiguredMappings() if err != nil { - return nil, -1, -1, errors.Wrapf(err, "cannot read mappings") + return nil, -1, -1, fmt.Errorf("cannot read mappings: %w", err) } if len(uids) == 0 || len(gids) == 0 { - return nil, -1, -1, errors.Wrapf(err, "keep-id requires additional UIDs or GIDs defined in /etc/subuid and /etc/subgid to function correctly") + return nil, -1, -1, fmt.Errorf("keep-id requires additional UIDs or GIDs defined in /etc/subuid and /etc/subgid to function correctly: %w", err) } maxUID, maxGID := 0, 0 for _, u := range uids { @@ -403,10 +403,10 @@ func GetNoMapMapping() (*stypes.IDMappingOptions, int, int, error) { } uids, gids, err := rootless.GetConfiguredMappings() if err != nil { - return nil, -1, -1, errors.Wrapf(err, "cannot read mappings") + return nil, -1, -1, fmt.Errorf("cannot read mappings: %w", err) } if len(uids) == 0 || len(gids) == 0 { - return nil, -1, -1, errors.Wrapf(err, "nomap requires additional UIDs or GIDs defined in /etc/subuid and /etc/subgid to function correctly") + return nil, -1, -1, fmt.Errorf("nomap requires additional UIDs or GIDs defined in /etc/subuid and /etc/subgid to function correctly: %w", err) } options.UIDMap, options.GIDMap = nil, nil uid, gid := 0, 0 @@ -566,7 +566,7 @@ func ParseInputTime(inputTime string, since bool) (time.Time, error) { // input might be a duration duration, err := time.ParseDuration(inputTime) if err != nil { - return time.Time{}, errors.Errorf("unable to interpret time value") + return time.Time{}, errors.New("unable to interpret time value") } if since { return time.Now().Add(-duration), nil @@ -607,7 +607,7 @@ func HomeDir() (string, error) { if home == "" { usr, err := user.LookupId(fmt.Sprintf("%d", rootless.GetRootlessUID())) if err != nil { - return "", errors.Wrapf(err, "unable to resolve HOME directory") + return "", fmt.Errorf("unable to resolve HOME directory: %w", err) } home = usr.HomeDir } @@ -645,12 +645,12 @@ func ValidateSysctls(strSlice []string) (map[string]string, error) { foundMatch := false arr := strings.Split(val, "=") if len(arr) < 2 { - return nil, errors.Errorf("%s is invalid, sysctl values must be in the form of KEY=VALUE", val) + return nil, fmt.Errorf("%s is invalid, sysctl values must be in the form of KEY=VALUE", val) } trimmed := fmt.Sprintf("%s=%s", strings.TrimSpace(arr[0]), strings.TrimSpace(arr[1])) if trimmed != val { - return nil, errors.Errorf("'%s' is invalid, extra spaces found", val) + return nil, fmt.Errorf("'%s' is invalid, extra spaces found", val) } if validSysctlMap[arr[0]] { @@ -666,7 +666,7 @@ func ValidateSysctls(strSlice []string) (map[string]string, error) { } } if !foundMatch { - return nil, errors.Errorf("sysctl '%s' is not allowed", arr[0]) + return nil, fmt.Errorf("sysctl '%s' is not allowed", arr[0]) } } return sysctl, nil @@ -680,9 +680,9 @@ func CreateCidFile(cidfile string, id string) error { cidFile, err := OpenExclusiveFile(cidfile) if err != nil { if os.IsExist(err) { - return errors.Errorf("container id file exists. Ensure another container is not using it or delete %s", cidfile) + return fmt.Errorf("container id file exists. Ensure another container is not using it or delete %s", cidfile) } - return errors.Errorf("opening cidfile %s", cidfile) + return fmt.Errorf("opening cidfile %s", cidfile) } if _, err = cidFile.WriteString(id); err != nil { logrus.Error(err) diff --git a/pkg/util/utils_darwin.go b/pkg/util/utils_darwin.go index 66ae85e9c..3a2e587df 100644 --- a/pkg/util/utils_darwin.go +++ b/pkg/util/utils_darwin.go @@ -4,7 +4,7 @@ package util import ( - "github.com/pkg/errors" + "errors" ) func GetContainerPidInformationDescriptors() ([]string, error) { diff --git a/pkg/util/utils_linux.go b/pkg/util/utils_linux.go index bc522361f..e2d9e3e89 100644 --- a/pkg/util/utils_linux.go +++ b/pkg/util/utils_linux.go @@ -1,6 +1,7 @@ package util import ( + "errors" "fmt" "io/fs" "io/ioutil" @@ -14,7 +15,6 @@ import ( "github.com/containers/psgo" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -53,7 +53,7 @@ func FindDeviceNodes() (map[string]string, error) { // We are a device node. Get major/minor. sysstat, ok := info.Sys().(*syscall.Stat_t) if !ok { - return errors.Errorf("Could not convert stat output for use") + return errors.New("could not convert stat output for use") } // We must typeconvert sysstat.Rdev from uint64->int to avoid constant overflow rdev := int(sysstat.Rdev) diff --git a/pkg/util/utils_supported.go b/pkg/util/utils_supported.go index 50e4b1b7b..b3d690158 100644 --- a/pkg/util/utils_supported.go +++ b/pkg/util/utils_supported.go @@ -7,13 +7,13 @@ package util // should work to take darwin from this import ( + "errors" "fmt" "os" "path/filepath" "syscall" "github.com/containers/podman/v4/pkg/rootless" - "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -51,12 +51,12 @@ func GetRuntimeDir() (string, error) { if runtimeDir == "" { home := os.Getenv("HOME") if home == "" { - rootlessRuntimeDirError = fmt.Errorf("neither XDG_RUNTIME_DIR nor HOME was set non-empty") + rootlessRuntimeDirError = errors.New("neither XDG_RUNTIME_DIR nor HOME was set non-empty") return } resolvedHome, err := filepath.EvalSymlinks(home) if err != nil { - rootlessRuntimeDirError = errors.Wrapf(err, "cannot resolve %s", home) + rootlessRuntimeDirError = fmt.Errorf("cannot resolve %s: %w", home, err) return } runtimeDir = filepath.Join(resolvedHome, "rundir") @@ -80,7 +80,7 @@ func GetRootlessConfigHomeDir() (string, error) { home := os.Getenv("HOME") resolvedHome, err := filepath.EvalSymlinks(home) if err != nil { - rootlessConfigHomeDirError = errors.Wrapf(err, "cannot resolve %s", home) + rootlessConfigHomeDirError = fmt.Errorf("cannot resolve %s: %w", home, err) return } tmpDir := filepath.Join(resolvedHome, ".config") @@ -115,7 +115,7 @@ func GetRootlessPauseProcessPidPath() (string, error) { // files. func GetRootlessPauseProcessPidPathGivenDir(libpodTmpDir string) (string, error) { if libpodTmpDir == "" { - return "", errors.Errorf("must provide non-empty temporary directory") + return "", errors.New("must provide non-empty temporary directory") } return filepath.Join(libpodTmpDir, "pause.pid"), nil } diff --git a/pkg/util/utils_unsupported.go b/pkg/util/utils_unsupported.go index 896346493..3a0f8646b 100644 --- a/pkg/util/utils_unsupported.go +++ b/pkg/util/utils_unsupported.go @@ -3,11 +3,9 @@ package util -import ( - "github.com/pkg/errors" -) +import "errors" // FindDeviceNodes is not implemented anywhere except Linux. func FindDeviceNodes() (map[string]string, error) { - return nil, errors.Errorf("not supported on non-Linux OSes") + return nil, errors.New("not supported on non-Linux OSes") } diff --git a/pkg/util/utils_windows.go b/pkg/util/utils_windows.go index b91680f7a..703e5472a 100644 --- a/pkg/util/utils_windows.go +++ b/pkg/util/utils_windows.go @@ -4,35 +4,36 @@ package util import ( + "errors" + "fmt" "path/filepath" "github.com/containers/storage/pkg/homedir" - "github.com/pkg/errors" ) var errNotImplemented = errors.New("not yet implemented") // IsCgroup2UnifiedMode returns whether we are running in cgroup 2 unified mode. func IsCgroup2UnifiedMode() (bool, error) { - return false, errors.Wrap(errNotImplemented, "IsCgroup2Unified") + return false, fmt.Errorf("IsCgroup2Unified: %w", errNotImplemented) } // GetContainerPidInformationDescriptors returns a string slice of all supported // format descriptors of GetContainerPidInformation. func GetContainerPidInformationDescriptors() ([]string, error) { - return nil, errors.Wrap(errNotImplemented, "GetContainerPidInformationDescriptors") + return nil, fmt.Errorf("GetContainerPidInformationDescriptors: %w", errNotImplemented) } // GetRootlessPauseProcessPidPath returns the path to the file that holds the pid for // the pause process func GetRootlessPauseProcessPidPath() (string, error) { - return "", errors.Wrap(errNotImplemented, "GetRootlessPauseProcessPidPath") + return "", fmt.Errorf("GetRootlessPauseProcessPidPath: %w", errNotImplemented) } // GetRootlessPauseProcessPidPath returns the path to the file that holds the pid for // the pause process func GetRootlessPauseProcessPidPathGivenDir(unused string) (string, error) { - return "", errors.Wrap(errNotImplemented, "GetRootlessPauseProcessPidPath") + return "", fmt.Errorf("GetRootlessPauseProcessPidPath: %w", errNotImplemented) } // GetRuntimeDir returns the runtime directory |