summaryrefslogtreecommitdiff
path: root/pkg/api/handlers/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/api/handlers/libpod')
-rw-r--r--pkg/api/handlers/libpod/containers.go28
-rw-r--r--pkg/api/handlers/libpod/containers_stats.go2
-rw-r--r--pkg/api/handlers/libpod/images.go133
-rw-r--r--pkg/api/handlers/libpod/networks.go18
-rw-r--r--pkg/api/handlers/libpod/pods.go67
-rw-r--r--pkg/api/handlers/libpod/volumes.go14
6 files changed, 146 insertions, 116 deletions
diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go
index 6b5bee403..5d85d4009 100644
--- a/pkg/api/handlers/libpod/containers.go
+++ b/pkg/api/handlers/libpod/containers.go
@@ -1,6 +1,7 @@
package libpod
import (
+ "errors"
"fmt"
"io/ioutil"
"net/http"
@@ -16,7 +17,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"
"github.com/sirupsen/logrus"
)
@@ -35,7 +35,7 @@ func ContainerExists(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
}
@@ -45,7 +45,7 @@ func ContainerExists(w http.ResponseWriter, r *http.Request) {
report, err := containerEngine.ContainerExists(r.Context(), name, options)
if err != nil {
- if errors.Cause(err) == define.ErrNoSuchCtr {
+ if errors.Is(err, define.ErrNoSuchCtr) {
utils.ContainerNotFound(w, name, err)
return
}
@@ -75,12 +75,12 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
filterMap, err := util.PrepareFilters(r)
if err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to decode filter parameters for %s", r.URL.String()))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to decode filter parameters for %s: %w", r.URL.String(), err))
return
}
if err := decoder.Decode(&query, r.URL.Query()); 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
}
@@ -115,10 +115,6 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
- if len(pss) == 0 {
- utils.WriteResponse(w, http.StatusOK, "[]")
- return
- }
utils.WriteResponse(w, http.StatusOK, pss)
}
@@ -131,7 +127,7 @@ func GetContainer(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
}
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
@@ -225,7 +221,7 @@ func Checkpoint(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
}
@@ -311,7 +307,7 @@ func Restore(w http.ResponseWriter, r *http.Request) {
// override any golang type defaults
}
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
}
@@ -348,11 +344,11 @@ func Restore(w http.ResponseWriter, r *http.Request) {
ir := abi.ImageEngine{Libpod: runtime}
report, err := ir.Exists(r.Context(), name)
if err != nil {
- utils.Error(w, http.StatusNotFound, errors.Wrapf(err, "failed to find container or checkpoint image %s", name))
+ utils.Error(w, http.StatusNotFound, fmt.Errorf("failed to find container or checkpoint image %s: %w", name, err))
return
}
if !report.Value {
- utils.Error(w, http.StatusNotFound, errors.Errorf("failed to find container or checkpoint image %s", name))
+ utils.Error(w, http.StatusNotFound, fmt.Errorf("failed to find container or checkpoint image %s", name))
return
}
}
@@ -384,7 +380,7 @@ func InitContainer(w http.ResponseWriter, r *http.Request) {
return
}
err = ctr.Init(r.Context(), ctr.PodID() != "")
- if errors.Cause(err) == define.ErrCtrStateInvalid {
+ if errors.Is(err, define.ErrCtrStateInvalid) {
utils.Error(w, http.StatusNotModified, err)
return
}
@@ -404,7 +400,7 @@ func ShouldRestart(w http.ResponseWriter, r *http.Request) {
name := utils.GetName(r)
report, err := containerEngine.ShouldRestart(r.Context(), name)
if err != nil {
- if errors.Cause(err) == define.ErrNoSuchCtr {
+ if errors.Is(err, define.ErrNoSuchCtr) {
utils.ContainerNotFound(w, name, err)
return
}
diff --git a/pkg/api/handlers/libpod/containers_stats.go b/pkg/api/handlers/libpod/containers_stats.go
index d34254fd7..46d722a3d 100644
--- a/pkg/api/handlers/libpod/containers_stats.go
+++ b/pkg/api/handlers/libpod/containers_stats.go
@@ -66,7 +66,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
flusher.Flush()
}
- // Setup JSON encoder for streaming.
+ // Set up JSON encoder for streaming.
coder := json.NewEncoder(w)
coder.SetEscapeHTML(true)
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index a8a50ae58..ed1c65f8e 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -2,6 +2,7 @@ package libpod
import (
"context"
+ "errors"
"fmt"
"io"
"io/ioutil"
@@ -21,13 +22,14 @@ import (
api "github.com/containers/podman/v4/pkg/api/types"
"github.com/containers/podman/v4/pkg/auth"
"github.com/containers/podman/v4/pkg/domain/entities"
+ "github.com/containers/podman/v4/pkg/domain/entities/reports"
"github.com/containers/podman/v4/pkg/domain/infra/abi"
+ domainUtils "github.com/containers/podman/v4/pkg/domain/utils"
"github.com/containers/podman/v4/pkg/errorhandling"
"github.com/containers/podman/v4/pkg/util"
utils2 "github.com/containers/podman/v4/utils"
"github.com/containers/storage"
"github.com/gorilla/schema"
- "github.com/pkg/errors"
)
// Commit
@@ -48,11 +50,11 @@ func ImageExists(w http.ResponseWriter, r *http.Request) {
ir := abi.ImageEngine{Libpod: runtime}
report, err := ir.Exists(r.Context(), name)
if err != nil {
- utils.Error(w, http.StatusNotFound, errors.Wrapf(err, "failed to find image %s", name))
+ utils.Error(w, http.StatusNotFound, fmt.Errorf("failed to find image %s: %w", name, err))
return
}
if !report.Value {
- utils.Error(w, http.StatusNotFound, errors.Errorf("failed to find image %s", name))
+ utils.Error(w, http.StatusNotFound, fmt.Errorf("failed to find image %s", name))
return
}
utils.WriteResponse(w, http.StatusNoContent, "")
@@ -68,18 +70,18 @@ func ImageTree(w http.ResponseWriter, r *http.Request) {
WhatRequires: false,
}
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
}
ir := abi.ImageEngine{Libpod: runtime}
options := entities.ImageTreeOptions{WhatRequires: query.WhatRequires}
report, err := ir.Tree(r.Context(), name, options)
if err != nil {
- if errors.Cause(err) == storage.ErrImageUnknown {
- utils.Error(w, http.StatusNotFound, errors.Wrapf(err, "failed to find image %s", name))
+ if errors.Is(err, storage.ErrImageUnknown) {
+ utils.Error(w, http.StatusNotFound, fmt.Errorf("failed to find image %s: %w", name, err))
return
}
- utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed to generate image tree for %s", name))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to generate image tree for %s: %w", name, err))
return
}
utils.WriteResponse(w, http.StatusOK, report)
@@ -89,13 +91,13 @@ func GetImage(w http.ResponseWriter, r *http.Request) {
name := utils.GetName(r)
newImage, err := utils.GetImage(r, name)
if err != nil {
- utils.Error(w, http.StatusNotFound, errors.Wrapf(err, "failed to find image %s", name))
+ utils.Error(w, http.StatusNotFound, fmt.Errorf("failed to find image %s: %w", name, err))
return
}
options := &libimage.InspectOptions{WithParent: true, WithSize: true}
inspect, err := newImage.Inspect(r.Context(), options)
if err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "failed in inspect image %s", inspect.ID))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed in inspect image %s: %w", inspect.ID, err))
return
}
utils.WriteResponse(w, http.StatusOK, inspect)
@@ -115,15 +117,13 @@ 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 decode filter parameters for %s", r.URL.String()))
+ fmt.Errorf("failed to decode filter parameters for %s: %w", r.URL.String(), err))
return
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, http.StatusInternalServerError,
- 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
}
@@ -172,7 +172,7 @@ func ExportImage(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
}
name := utils.GetName(r)
@@ -186,23 +186,23 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
case define.OCIArchive, define.V2s2Archive:
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
}
output = 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
}
case define.OCIManifestDir, define.V2s2ManifestDir:
tmpdir, err := ioutil.TempDir("", "save")
if err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tempdir"))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to create tempdir: %w", err))
return
}
output = tmpdir
default:
- utils.Error(w, http.StatusInternalServerError, errors.Errorf("unknown format %q", query.Format))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unknown format %q", query.Format))
return
}
@@ -231,7 +231,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
}
rdr, err := os.Open(output)
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()
@@ -252,20 +252,20 @@ func ExportImages(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
}
// References are mandatory!
if len(query.References) == 0 {
- utils.Error(w, http.StatusBadRequest, errors.New("No references"))
+ utils.Error(w, http.StatusBadRequest, errors.New("no references"))
return
}
// Format is mandatory! Currently, we only support multi-image docker
// archives.
if len(query.References) > 1 && query.Format != define.V2s2Archive {
- utils.Error(w, http.StatusInternalServerError, errors.Errorf("multi-image archives must use format of %s", define.V2s2Archive))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("multi-image archives must use format of %s", define.V2s2Archive))
return
}
@@ -283,23 +283,23 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
case define.V2s2Archive, define.OCIArchive:
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
}
output = 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
}
case define.OCIManifestDir, define.V2s2ManifestDir:
tmpdir, err := ioutil.TempDir("", "save")
if err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to create tmpdir"))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to create tmpdir: %w", err))
return
}
output = tmpdir
default:
- utils.Error(w, http.StatusInternalServerError, errors.Errorf("unsupported format %q", query.Format))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unsupported format %q", query.Format))
return
}
defer os.RemoveAll(output)
@@ -321,7 +321,7 @@ func ExportImages(w http.ResponseWriter, r *http.Request) {
rdr, err := os.Open(output)
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()
@@ -333,7 +333,7 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) {
tmpfile, err := ioutil.TempFile("", "libpod-images-load.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())
@@ -342,7 +342,7 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) {
tmpfile.Close()
if err != nil && err != io.EOF {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file"))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to write archive to temporary file: %w", err))
return
}
@@ -351,7 +351,7 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) {
loadOptions := entities.ImageLoadOptions{Input: tmpfile.Name()}
loadReport, err := imageEngine.Load(r.Context(), loadOptions)
if err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to load image"))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to load image: %w", err))
return
}
utils.WriteResponse(w, http.StatusOK, loadReport)
@@ -373,7 +373,7 @@ func ImagesImport(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
}
@@ -382,14 +382,14 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) {
if len(query.URL) == 0 {
tmpfile, err := ioutil.TempFile("", "libpod-images-import.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())
defer tmpfile.Close()
if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file"))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to write archive to temporary file: %w", err))
return
}
@@ -409,7 +409,7 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) {
}
report, err := imageEngine.Import(r.Context(), importOptions)
if err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "unable to import tarball"))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("unable to import tarball: %w", err))
return
}
@@ -431,7 +431,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
// This is where you can override the golang default value for one of fields
}
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
}
@@ -477,7 +477,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
imageEngine := abi.ImageEngine{Libpod: runtime}
if err := imageEngine.Push(context.Background(), source, destination, options); 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
}
@@ -507,12 +507,12 @@ func CommitContainer(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
}
rtc, err := runtime.GetConfig()
if err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to get runtime config"))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to get runtime config: %w", err))
return
}
sc := runtime.SystemContext()
@@ -530,7 +530,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
case "docker":
mimeType = manifest.DockerV2Schema2MediaType
default:
- utils.InternalServerError(w, errors.Errorf("unrecognized image format %q", query.Format))
+ utils.InternalServerError(w, fmt.Errorf("unrecognized image format %q", query.Format))
return
}
options.CommitOptions = buildah.CommitOptions{
@@ -559,7 +559,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
}
commitImage, err := ctr.Commit(r.Context(), destImage, options)
if err != nil && !strings.Contains(err.Error(), "is not running") {
- utils.Error(w, http.StatusInternalServerError, errors.Wrapf(err, "CommitFailure"))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("CommitFailure: %w", err))
return
}
utils.WriteResponse(w, http.StatusOK, entities.IDResponse{ID: commitImage.ID()})
@@ -598,8 +598,8 @@ func UntagImage(w http.ResponseWriter, r *http.Request) {
name := utils.GetName(r)
if err := imageEngine.Untag(r.Context(), name, tags, opts); err != nil {
- if errors.Cause(err) == storage.ErrImageUnknown {
- utils.ImageNotFound(w, name, errors.Wrapf(err, "failed to find image %s", name))
+ if errors.Is(err, storage.ErrImageUnknown) {
+ utils.ImageNotFound(w, name, fmt.Errorf("failed to find image %s: %w", name, err))
} else {
utils.Error(w, http.StatusInternalServerError, err)
}
@@ -613,18 +613,19 @@ func ImagesBatchRemove(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
- All bool `schema:"all"`
- Force bool `schema:"force"`
- Ignore bool `schema:"ignore"`
- Images []string `schema:"images"`
+ All bool `schema:"all"`
+ Force bool `schema:"force"`
+ Ignore bool `schema:"ignore"`
+ LookupManifest bool `schema:"lookupManifest"`
+ Images []string `schema:"images"`
}{}
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
}
- opts := entities.ImageRemoveOptions{All: query.All, Force: query.Force, Ignore: query.Ignore}
+ opts := entities.ImageRemoveOptions{All: query.All, Force: query.Force, Ignore: query.Ignore, LookupManifest: query.LookupManifest}
imageEngine := abi.ImageEngine{Libpod: runtime}
rmReport, rmErrors := imageEngine.Remove(r.Context(), query.Images, opts)
strErrs := errorhandling.ErrorsToStrings(rmErrors)
@@ -637,17 +638,18 @@ func ImagesRemove(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
- Force bool `schema:"force"`
+ Force bool `schema:"force"`
+ LookupManifest bool `schema:"lookupManifest"`
}{
Force: false,
}
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
}
- opts := entities.ImageRemoveOptions{Force: query.Force}
+ opts := entities.ImageRemoveOptions{Force: query.Force, LookupManifest: query.LookupManifest}
imageEngine := abi.ImageEngine{Libpod: runtime}
rmReport, rmErrors := imageEngine.Remove(r.Context(), []string{utils.GetName(r)}, opts)
@@ -670,3 +672,32 @@ func ImagesRemove(w http.ResponseWriter, r *http.Request) {
utils.Error(w, http.StatusInternalServerError, errorhandling.JoinErrors(rmErrors))
}
}
+
+func ImageScp(w http.ResponseWriter, r *http.Request) {
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ query := struct {
+ Destination string `schema:"destination"`
+ Quiet bool `schema:"quiet"`
+ }{
+ // This is where you can override the golang default value for one of fields
+ }
+ 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))
+ return
+ }
+
+ sourceArg := utils.GetName(r)
+
+ rep, source, dest, _, err := domainUtils.ExecuteTransfer(sourceArg, query.Destination, []string{}, query.Quiet)
+ if err != nil {
+ utils.Error(w, http.StatusInternalServerError, err)
+ return
+ }
+
+ if source != nil || dest != nil {
+ utils.Error(w, http.StatusBadRequest, fmt.Errorf("cannot use the user transfer function on the remote client: %w", define.ErrInvalidArg))
+ return
+ }
+
+ utils.WriteResponse(w, http.StatusOK, &reports.ScpReport{Id: rep.Names[0]})
+}
diff --git a/pkg/api/handlers/libpod/networks.go b/pkg/api/handlers/libpod/networks.go
index 16f499d4c..7169a6d44 100644
--- a/pkg/api/handlers/libpod/networks.go
+++ b/pkg/api/handlers/libpod/networks.go
@@ -2,8 +2,11 @@ package libpod
import (
"encoding/json"
+ "fmt"
"net/http"
+ "errors"
+
"github.com/containers/common/libnetwork/types"
"github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define"
@@ -13,7 +16,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 CreateNetwork(w http.ResponseWriter, r *http.Request) {
@@ -25,7 +27,7 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
network := types.Network{}
if err := json.NewDecoder(r.Body).Decode(&network); err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to decode request JSON payload"))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to decode request JSON payload: %w", err))
return
}
@@ -52,7 +54,7 @@ func ListNetworks(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()))
+ fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err))
return
}
@@ -83,7 +85,7 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, http.StatusInternalServerError,
- 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
}
name := utils.GetName(r)
@@ -99,7 +101,7 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
}
if reports[0].Err != nil {
// If the network cannot be found, we return a 404.
- if errors.Cause(reports[0].Err) == define.ErrNoSuchNetwork {
+ if errors.Is(reports[0].Err, define.ErrNoSuchNetwork) {
utils.Error(w, http.StatusNotFound, reports[0].Err)
return
}
@@ -142,18 +144,18 @@ func Connect(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
var netConnect entities.NetworkConnectOptions
if err := json.NewDecoder(r.Body).Decode(&netConnect); err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to decode request JSON payload"))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to decode request JSON payload: %w", err))
return
}
name := utils.GetName(r)
err := runtime.ConnectContainerToNetwork(netConnect.Container, name, netConnect.PerNetworkOptions)
if err != nil {
- if errors.Cause(err) == define.ErrNoSuchCtr {
+ if errors.Is(err, define.ErrNoSuchCtr) {
utils.ContainerNotFound(w, netConnect.Container, err)
return
}
- if errors.Cause(err) == define.ErrNoSuchNetwork {
+ if errors.Is(err, define.ErrNoSuchNetwork) {
utils.Error(w, http.StatusNotFound, err)
return
}
diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go
index 5b92358fa..92fd94390 100644
--- a/pkg/api/handlers/libpod/pods.go
+++ b/pkg/api/handlers/libpod/pods.go
@@ -2,6 +2,7 @@ package libpod
import (
"encoding/json"
+ "errors"
"fmt"
"net/http"
"strings"
@@ -19,7 +20,6 @@ import (
"github.com/containers/podman/v4/pkg/specgenutil"
"github.com/containers/podman/v4/pkg/util"
"github.com/gorilla/schema"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -33,11 +33,11 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
)
psg := specgen.PodSpecGenerator{InfraContainerSpec: &specgen.SpecGenerator{}}
if err := json.NewDecoder(r.Body).Decode(&psg); err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, failedToDecodeSpecgen))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("%v: %w", failedToDecodeSpecgen, err))
return
}
if err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, failedToDecodeSpecgen))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("%v: %w", failedToDecodeSpecgen, err))
return
}
if !psg.NoInfra {
@@ -51,17 +51,17 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
}
err = specgenutil.FillOutSpecGen(psg.InfraContainerSpec, &infraOptions, []string{}) // necessary for default values in many cases (userns, idmappings)
if err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "error filling out specgen"))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("error filling out specgen: %w", err))
return
}
out, err := json.Marshal(psg) // marshal our spec so the matching options can be unmarshaled into infra
if err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, failedToDecodeSpecgen))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("%v: %w", failedToDecodeSpecgen, err))
return
}
err = json.Unmarshal(out, psg.InfraContainerSpec) // unmarhal matching options
if err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, failedToDecodeSpecgen))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("%v: %w", failedToDecodeSpecgen, err))
return
}
// a few extra that do not have the same json tags
@@ -75,10 +75,10 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
pod, err := generate.MakePod(&podSpecComplete, runtime)
if err != nil {
httpCode := http.StatusInternalServerError
- if errors.Cause(err) == define.ErrPodExists {
+ if errors.Is(err, define.ErrPodExists) {
httpCode = http.StatusConflict
}
- utils.Error(w, httpCode, errors.Wrap(err, "failed to make pod"))
+ utils.Error(w, httpCode, fmt.Errorf("failed to make pod: %w", err))
return
}
utils.WriteResponse(w, http.StatusCreated, entities.IDResponse{ID: pod.ID()})
@@ -89,7 +89,7 @@ func Pods(w http.ResponseWriter, r *http.Request) {
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()))
+ utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err))
return
}
@@ -139,7 +139,7 @@ func PodStop(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
}
name := utils.GetName(r)
@@ -164,7 +164,7 @@ func PodStop(w http.ResponseWriter, r *http.Request) {
} else {
responses, stopError = pod.Stop(r.Context(), false)
}
- if stopError != nil && errors.Cause(stopError) != define.ErrPodPartialFail {
+ if stopError != nil && !errors.Is(stopError, define.ErrPodPartialFail) {
utils.Error(w, http.StatusInternalServerError, err)
return
}
@@ -178,7 +178,7 @@ func PodStop(w http.ResponseWriter, r *http.Request) {
report := entities.PodStopReport{Id: pod.ID()}
for id, err := range responses {
- report.Errs = append(report.Errs, errors.Wrapf(err, "error stopping container %s", id))
+ report.Errs = append(report.Errs, fmt.Errorf("error stopping container %s: %w", id, err))
}
code := http.StatusOK
@@ -207,14 +207,14 @@ func PodStart(w http.ResponseWriter, r *http.Request) {
}
responses, err := pod.Start(r.Context())
- if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
+ if err != nil && !errors.Is(err, define.ErrPodPartialFail) {
utils.Error(w, http.StatusConflict, err)
return
}
report := entities.PodStartReport{Id: pod.ID()}
for id, err := range responses {
- report.Errs = append(report.Errs, errors.Wrapf(err, "error starting container "+id))
+ report.Errs = append(report.Errs, fmt.Errorf("%v: %w", "error starting container "+id, err))
}
code := http.StatusOK
@@ -237,7 +237,7 @@ func PodDelete(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
}
name := utils.GetName(r)
@@ -263,14 +263,14 @@ func PodRestart(w http.ResponseWriter, r *http.Request) {
return
}
responses, err := pod.Restart(r.Context())
- if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
+ if err != nil && !errors.Is(err, define.ErrPodPartialFail) {
utils.Error(w, http.StatusInternalServerError, err)
return
}
report := entities.PodRestartReport{Id: pod.ID()}
for id, err := range responses {
- report.Errs = append(report.Errs, errors.Wrapf(err, "error restarting container %s", id))
+ report.Errs = append(report.Errs, fmt.Errorf("error restarting container %s: %w", id, err))
}
code := http.StatusOK
@@ -314,14 +314,14 @@ func PodPause(w http.ResponseWriter, r *http.Request) {
return
}
responses, err := pod.Pause(r.Context())
- if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
+ if err != nil && !errors.Is(err, define.ErrPodPartialFail) {
utils.Error(w, http.StatusInternalServerError, err)
return
}
report := entities.PodPauseReport{Id: pod.ID()}
for id, v := range responses {
- report.Errs = append(report.Errs, errors.Wrapf(v, "error pausing container %s", id))
+ report.Errs = append(report.Errs, fmt.Errorf("error pausing container %s: %w", id, v))
}
code := http.StatusOK
@@ -340,14 +340,14 @@ func PodUnpause(w http.ResponseWriter, r *http.Request) {
return
}
responses, err := pod.Unpause(r.Context())
- if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
+ if err != nil && !errors.Is(err, define.ErrPodPartialFail) {
utils.Error(w, http.StatusInternalServerError, err)
return
}
report := entities.PodUnpauseReport{Id: pod.ID()}
for id, v := range responses {
- report.Errs = append(report.Errs, errors.Wrapf(v, "error unpausing container %s", id))
+ report.Errs = append(report.Errs, fmt.Errorf("error unpausing container %s: %w", id, v))
}
code := http.StatusOK
@@ -374,7 +374,7 @@ func PodTop(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
}
@@ -456,7 +456,7 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
// override any golang type defaults
}
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 _, found := r.URL.Query()["signal"]; found {
@@ -465,7 +465,7 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
sig, err := util.ParseSignal(signal)
if err != nil {
- utils.InternalServerError(w, errors.Wrapf(err, "unable to parse signal value"))
+ utils.InternalServerError(w, fmt.Errorf("unable to parse signal value: %w", err))
return
}
name := utils.GetName(r)
@@ -488,12 +488,12 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
}
}
if !hasRunning {
- utils.Error(w, http.StatusConflict, errors.Errorf("cannot kill a pod with no running containers: %s", pod.ID()))
+ utils.Error(w, http.StatusConflict, fmt.Errorf("cannot kill a pod with no running containers: %s", pod.ID()))
return
}
responses, err := pod.Kill(r.Context(), uint(sig))
- if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
+ if err != nil && !errors.Is(err, define.ErrPodPartialFail) {
utils.Error(w, http.StatusInternalServerError, err)
return
}
@@ -534,7 +534,7 @@ func PodStats(w http.ResponseWriter, r *http.Request) {
// default would go here
}
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
}
@@ -549,13 +549,12 @@ func PodStats(w http.ResponseWriter, r *http.Request) {
reports, err := containerEngine.PodStats(r.Context(), query.NamesOrIDs, options)
// Error checks as documented in swagger.
- switch errors.Cause(err) {
- case define.ErrNoSuchPod:
- utils.Error(w, http.StatusNotFound, err)
- return
- case nil:
- // Nothing to do.
- default:
+ if err != nil {
+ if errors.Is(err, define.ErrNoSuchPod) {
+ utils.Error(w, http.StatusNotFound, err)
+ return
+ }
+
utils.InternalServerError(w, err)
return
}
diff --git a/pkg/api/handlers/libpod/volumes.go b/pkg/api/handlers/libpod/volumes.go
index e792dea35..5eac76f5b 100644
--- a/pkg/api/handlers/libpod/volumes.go
+++ b/pkg/api/handlers/libpod/volumes.go
@@ -2,9 +2,12 @@ package libpod
import (
"encoding/json"
+ "fmt"
"net/http"
"net/url"
+ "errors"
+
"github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/api/handlers/utils"
@@ -16,7 +19,6 @@ import (
"github.com/containers/podman/v4/pkg/domain/infra/abi/parse"
"github.com/containers/podman/v4/pkg/util"
"github.com/gorilla/schema"
- "github.com/pkg/errors"
)
func CreateVolume(w http.ResponseWriter, r *http.Request) {
@@ -30,14 +32,14 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, http.StatusInternalServerError,
- 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
}
input := entities.VolumeCreateOptions{}
// decode params from body
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
- utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ utils.Error(w, http.StatusInternalServerError, fmt.Errorf("Decode(): %w", err))
return
}
@@ -108,7 +110,7 @@ func ListVolumes(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()))
+ fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err))
return
}
@@ -181,7 +183,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, http.StatusInternalServerError,
- 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
}
name := utils.GetName(r)
@@ -191,7 +193,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
return
}
if err := runtime.RemoveVolume(r.Context(), vol, query.Force, query.Timeout); err != nil {
- if errors.Cause(err) == define.ErrVolumeBeingUsed {
+ if errors.Is(err, define.ErrVolumeBeingUsed) {
utils.Error(w, http.StatusConflict, err)
return
}