From 907b34c46fe474911d4321795f029583e8daeeec Mon Sep 17 00:00:00 2001 From: Jakub Guzik Date: Sat, 20 Mar 2021 22:56:01 +0100 Subject: Fix containers list/prune http api filter behaviour The problem described in #9711 and followed by #9758 affects containers as well. When user provides wrong filter input, error message should occur, not fallback to full list/prune command. This change fixes the issue. Additionally, there are error message fixes for docker http api compat. Signed-off-by: Jakub Guzik --- pkg/api/handlers/compat/containers.go | 22 ++++++++++++---------- pkg/api/handlers/compat/containers_prune.go | 17 +++++++---------- pkg/api/handlers/libpod/containers.go | 24 +++++++++++++----------- 3 files changed, 32 insertions(+), 31 deletions(-) (limited to 'pkg/api/handlers') diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index d3277b815..e7146a5d8 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -19,6 +19,7 @@ import ( "github.com/containers/podman/v3/pkg/domain/infra/abi" "github.com/containers/podman/v3/pkg/ps" "github.com/containers/podman/v3/pkg/signal" + "github.com/containers/podman/v3/pkg/util" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/go-connections/nat" @@ -92,23 +93,24 @@ func ListContainers(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) decoder := r.Context().Value("decoder").(*schema.Decoder) query := struct { - All bool `schema:"all"` - Limit int `schema:"limit"` - Size bool `schema:"size"` - Filters map[string][]string `schema:"filters"` + All bool `schema:"all"` + Limit int `schema:"limit"` + Size bool `schema:"size"` }{ // override any golang type defaults } - if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + filterMap, err := util.PrepareFilters(r) + + if dErr := decoder.Decode(&query, r.URL.Query()); dErr != nil || err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) return } - filterFuncs := make([]libpod.ContainerFilter, 0, len(query.Filters)) + filterFuncs := make([]libpod.ContainerFilter, 0, len(*filterMap)) all := query.All || query.Limit > 0 - if len(query.Filters) > 0 { - for k, v := range query.Filters { + if len((*filterMap)) > 0 { + for k, v := range *filterMap { generatedFunc, err := filters.GenerateContainerFilterFuncs(k, v, runtime) if err != nil { utils.InternalServerError(w, err) @@ -120,7 +122,7 @@ func ListContainers(w http.ResponseWriter, r *http.Request) { // Docker thinks that if status is given as an input, then we should override // the all setting and always deal with all containers. - if len(query.Filters["status"]) > 0 { + if len((*filterMap)["status"]) > 0 { all = true } if !all { diff --git a/pkg/api/handlers/compat/containers_prune.go b/pkg/api/handlers/compat/containers_prune.go index dc4d53af6..e37929d27 100644 --- a/pkg/api/handlers/compat/containers_prune.go +++ b/pkg/api/handlers/compat/containers_prune.go @@ -9,23 +9,20 @@ import ( "github.com/containers/podman/v3/pkg/api/handlers/utils" "github.com/containers/podman/v3/pkg/domain/entities/reports" "github.com/containers/podman/v3/pkg/domain/filters" - "github.com/gorilla/schema" + "github.com/containers/podman/v3/pkg/util" "github.com/pkg/errors" ) func PruneContainers(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) - decoder := r.Context().Value("decoder").(*schema.Decoder) - - query := struct { - Filters map[string][]string `schema:"filters"` - }{} - if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + filtersMap, err := util.PrepareFilters(r) + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) return } - filterFuncs := make([]libpod.ContainerFilter, 0, len(query.Filters)) - for k, v := range query.Filters { + + filterFuncs := make([]libpod.ContainerFilter, 0, len(*filtersMap)) + for k, v := range *filtersMap { generatedFunc, err := filters.GenerateContainerFilterFuncs(k, v, runtime) if err != nil { utils.InternalServerError(w, err) diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go index 01b9ec101..77269db8b 100644 --- a/pkg/api/handlers/libpod/containers.go +++ b/pkg/api/handlers/libpod/containers.go @@ -11,6 +11,7 @@ import ( "github.com/containers/podman/v3/pkg/api/handlers/utils" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/domain/infra/abi" + "github.com/containers/podman/v3/pkg/util" "github.com/gorilla/schema" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -59,20 +60,21 @@ func ContainerExists(w http.ResponseWriter, r *http.Request) { func ListContainers(w http.ResponseWriter, r *http.Request) { decoder := r.Context().Value("decoder").(*schema.Decoder) query := struct { - All bool `schema:"all"` - External bool `schema:"external"` - Filters map[string][]string `schema:"filters"` - Last int `schema:"last"` // alias for limit - Limit int `schema:"limit"` - Namespace bool `schema:"namespace"` - Size bool `schema:"size"` - Sync bool `schema:"sync"` + All bool `schema:"all"` + External bool `schema:"external"` + Last int `schema:"last"` // alias for limit + Limit int `schema:"limit"` + Namespace bool `schema:"namespace"` + Size bool `schema:"size"` + Sync bool `schema:"sync"` }{ // override any golang type defaults } - if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + filterMap, err := util.PrepareFilters(r) + + if dErr := decoder.Decode(&query, r.URL.Query()); dErr != nil || err != nil { + utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) return } @@ -94,7 +96,7 @@ func ListContainers(w http.ResponseWriter, r *http.Request) { opts := entities.ContainerListOptions{ All: query.All, External: query.External, - Filters: query.Filters, + Filters: *filterMap, Last: limit, Namespace: query.Namespace, // Always return Pod, should not be part of the API. -- cgit v1.2.3-54-g00ecf