summaryrefslogtreecommitdiff
path: root/pkg/api
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/api')
-rw-r--r--pkg/api/handlers/compat/containers.go42
-rw-r--r--pkg/api/handlers/libpod/images.go47
-rw-r--r--pkg/api/handlers/libpod/pods.go67
-rw-r--r--pkg/api/handlers/libpod/volumes.go14
-rw-r--r--pkg/api/handlers/swagger/responses.go7
-rw-r--r--pkg/api/handlers/utils/errors.go26
-rw-r--r--pkg/api/server/register_images.go38
7 files changed, 161 insertions, 80 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index 616f0a138..38fe0196a 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -2,6 +2,7 @@ package compat
import (
"encoding/json"
+ "errors"
"fmt"
"net/http"
"sort"
@@ -27,7 +28,6 @@ import (
"github.com/docker/go-connections/nat"
"github.com/docker/go-units"
"github.com/gorilla/schema"
- "github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -46,7 +46,7 @@ func RemoveContainer(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
}
@@ -73,7 +73,7 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) {
name := utils.GetName(r)
reports, err := containerEngine.ContainerRm(r.Context(), []string{name}, options)
if err != nil {
- if errors.Cause(err) == define.ErrNoSuchCtr {
+ if errors.Is(err, define.ErrNoSuchCtr) {
utils.ContainerNotFound(w, name, err)
return
}
@@ -83,7 +83,7 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) {
}
if len(reports) > 0 && reports[0].Err != nil {
err = reports[0].Err
- if errors.Cause(err) == define.ErrNoSuchCtr {
+ if errors.Is(err, define.ErrNoSuchCtr) {
utils.ContainerNotFound(w, name, err)
return
}
@@ -110,12 +110,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
}
@@ -164,7 +164,7 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
for _, ctnr := range containers {
api, err := LibpodToContainer(ctnr, query.Size)
if err != nil {
- if errors.Cause(err) == define.ErrNoSuchCtr {
+ if errors.Is(err, define.ErrNoSuchCtr) {
// container was removed between the initial fetch of the list and conversion
logrus.Debugf("Container %s removed between initial fetch and conversion, ignoring in output", ctnr.ID())
continue
@@ -187,7 +187,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
}
@@ -215,7 +215,7 @@ func KillContainer(w http.ResponseWriter, r *http.Request) {
Signal: "KILL",
}
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
}
@@ -228,12 +228,12 @@ func KillContainer(w http.ResponseWriter, r *http.Request) {
}
report, err := containerEngine.ContainerKill(r.Context(), []string{name}, options)
if err != nil {
- if errors.Cause(err) == define.ErrCtrStateInvalid ||
- errors.Cause(err) == define.ErrCtrStopped {
+ if errors.Is(err, define.ErrCtrStateInvalid) ||
+ errors.Is(err, define.ErrCtrStopped) {
utils.Error(w, http.StatusConflict, err)
return
}
- if errors.Cause(err) == define.ErrNoSuchCtr {
+ if errors.Is(err, define.ErrNoSuchCtr) {
utils.ContainerNotFound(w, name, err)
return
}
@@ -289,8 +289,10 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error
return nil, err
}
stateStr := state.String()
- if stateStr == "configured" {
- stateStr = "created"
+
+ // Some docker states are not the same as ours. This makes sure the state string stays true to the Docker API
+ if state == define.ContainerStateCreated {
+ stateStr = define.ContainerStateConfigured.String()
}
switch state {
@@ -420,9 +422,9 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON,
state.Running = true
}
- // docker calls the configured state "created"
- if state.Status == define.ContainerStateConfigured.String() {
- state.Status = define.ContainerStateCreated.String()
+ // Dockers created state is our configured state
+ if state.Status == define.ContainerStateCreated.String() {
+ state.Status = define.ContainerStateConfigured.String()
}
if l.HasHealthCheck() && state.Status != "created" {
@@ -510,7 +512,7 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON,
for ep := range inspect.HostConfig.PortBindings {
splitp := strings.SplitN(ep, "/", 2)
if len(splitp) != 2 {
- return nil, errors.Errorf("PORT/PROTOCOL Format required for %q", ep)
+ return nil, fmt.Errorf("PORT/PROTOCOL Format required for %q", ep)
}
exposedPort, err := nat.NewPort(splitp[1], splitp[0])
if err != nil {
@@ -614,7 +616,7 @@ func RenameContainer(w http.ResponseWriter, r *http.Request) {
Name string `schema:"name"`
}{}
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
}
@@ -625,7 +627,7 @@ func RenameContainer(w http.ResponseWriter, r *http.Request) {
}
if _, err := runtime.RenameContainer(r.Context(), ctr, query.Name); err != nil {
- if errors.Cause(err) == define.ErrPodExists || errors.Cause(err) == define.ErrCtrExists {
+ if errors.Is(err, define.ErrPodExists) || errors.Is(err, define.ErrCtrExists) {
utils.Error(w, http.StatusConflict, err)
return
}
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index a8a50ae58..b71217efa 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -21,7 +21,9 @@ 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"
@@ -613,10 +615,11 @@ 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 {
@@ -624,7 +627,7 @@ func ImagesBatchRemove(w http.ResponseWriter, r *http.Request) {
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,7 +640,8 @@ 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,
}
@@ -647,7 +651,7 @@ func ImagesRemove(w http.ResponseWriter, r *http.Request) {
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 +674,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, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ 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, errors.Wrapf(define.ErrInvalidArg, "cannot use the user transfer function on the remote client"))
+ return
+ }
+
+ utils.WriteResponse(w, http.StatusOK, &reports.ScpReport{Id: rep.Names[0]})
+}
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
}
diff --git a/pkg/api/handlers/swagger/responses.go b/pkg/api/handlers/swagger/responses.go
index 55fc1a77f..93a508b39 100644
--- a/pkg/api/handlers/swagger/responses.go
+++ b/pkg/api/handlers/swagger/responses.go
@@ -41,6 +41,13 @@ type imagesLoadResponseLibpod struct {
Body entities.ImageLoadReport
}
+// Image Scp
+// swagger:response
+type imagesScpResponseLibpod struct {
+ // in:body
+ Body reports.ScpReport
+}
+
// Image Import
// swagger:response
type imagesImportResponseLibpod struct {
diff --git a/pkg/api/handlers/utils/errors.go b/pkg/api/handlers/utils/errors.go
index bf60b2c84..ab1b6f227 100644
--- a/pkg/api/handlers/utils/errors.go
+++ b/pkg/api/handlers/utils/errors.go
@@ -1,17 +1,18 @@
package utils
import (
+ "errors"
+ "fmt"
"net/http"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/errorhandling"
"github.com/containers/storage"
- "github.com/pkg/errors"
log "github.com/sirupsen/logrus"
)
var (
- ErrLinkNotSupport = errors.New("Link is not supported")
+ ErrLinkNotSupport = errors.New("link is not supported")
)
// TODO: document the exported functions in this file and make them more
@@ -25,7 +26,7 @@ func Error(w http.ResponseWriter, code int, err error) {
// Log detailed message of what happened to machine running podman service
log.Infof("Request Failed(%s): %s", http.StatusText(code), err.Error())
em := errorhandling.ErrorModel{
- Because: (errors.Cause(err)).Error(),
+ Because: errorhandling.Cause(err).Error(),
Message: err.Error(),
ResponseCode: code,
}
@@ -33,51 +34,50 @@ func Error(w http.ResponseWriter, code int, err error) {
}
func VolumeNotFound(w http.ResponseWriter, name string, err error) {
- if errors.Cause(err) != define.ErrNoSuchVolume {
+ if !errors.Is(err, define.ErrNoSuchVolume) {
InternalServerError(w, err)
}
Error(w, http.StatusNotFound, err)
}
func ContainerNotFound(w http.ResponseWriter, name string, err error) {
- switch errors.Cause(err) {
- case define.ErrNoSuchCtr, define.ErrCtrExists:
+ if errors.Is(err, define.ErrNoSuchCtr) || errors.Is(err, define.ErrCtrExists) {
Error(w, http.StatusNotFound, err)
- default:
+ } else {
InternalServerError(w, err)
}
}
func ImageNotFound(w http.ResponseWriter, name string, err error) {
- if errors.Cause(err) != storage.ErrImageUnknown {
+ if !errors.Is(err, storage.ErrImageUnknown) {
InternalServerError(w, err)
}
Error(w, http.StatusNotFound, err)
}
func NetworkNotFound(w http.ResponseWriter, name string, err error) {
- if errors.Cause(err) != define.ErrNoSuchNetwork {
+ if !errors.Is(err, define.ErrNoSuchNetwork) {
InternalServerError(w, err)
}
Error(w, http.StatusNotFound, err)
}
func PodNotFound(w http.ResponseWriter, name string, err error) {
- if errors.Cause(err) != define.ErrNoSuchPod {
+ if !errors.Is(err, define.ErrNoSuchPod) {
InternalServerError(w, err)
}
Error(w, http.StatusNotFound, err)
}
func SessionNotFound(w http.ResponseWriter, name string, err error) {
- if errors.Cause(err) != define.ErrNoSuchExecSession {
+ if !errors.Is(err, define.ErrNoSuchExecSession) {
InternalServerError(w, err)
}
Error(w, http.StatusNotFound, err)
}
func SecretNotFound(w http.ResponseWriter, nameOrID string, err error) {
- if errors.Cause(err).Error() != "no such secret" {
+ if errorhandling.Cause(err).Error() != "no such secret" {
InternalServerError(w, err)
}
Error(w, http.StatusNotFound, err)
@@ -92,7 +92,7 @@ func InternalServerError(w http.ResponseWriter, err error) {
}
func BadRequest(w http.ResponseWriter, key string, value string, err error) {
- e := errors.Wrapf(err, "failed to parse query parameter '%s': %q", key, value)
+ e := fmt.Errorf("failed to parse query parameter '%s': %q: %w", key, value, err)
Error(w, http.StatusBadRequest, e)
}
diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go
index 1617a5dd7..a2f46cb35 100644
--- a/pkg/api/server/register_images.go
+++ b/pkg/api/server/register_images.go
@@ -948,6 +948,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// name: ignore
// description: Ignore if a specified image does not exist and do not throw an error.
// type: boolean
+ // - in: query
+ // name: lookupManifest
+ // description: Resolves to manifest list instead of image.
+ // type: boolean
// produces:
// - application/json
// responses:
@@ -1615,5 +1619,39 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// 500:
// $ref: "#/responses/internalError"
r.Handle(VersionedPath("/libpod/build"), s.APIHandler(compat.BuildImage)).Methods(http.MethodPost)
+
+ // swagger:operation POST /libpod/images/scp/{name} libpod ImageScpLibpod
+ // ---
+ // tags:
+ // - images
+ // summary: Copy an image from one host to another
+ // description: Copy an image from one host to another
+ // parameters:
+ // - in: path
+ // name: name
+ // required: true
+ // description: source connection/image
+ // type: string
+ // - in: query
+ // name: destination
+ // required: false
+ // description: dest connection/image
+ // type: string
+ // - in: query
+ // name: quiet
+ // required: false
+ // description: quiet output
+ // type: boolean
+ // default: false
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // $ref: "#/responses/imagesScpResponseLibpod"
+ // 400:
+ // $ref: "#/responses/badParamError"
+ // 500:
+ // $ref: '#/responses/internalError'
+ r.Handle(VersionedPath("/libpod/images/scp/{name:.*}"), s.APIHandler(libpod.ImageScp)).Methods(http.MethodPost)
return nil
}