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 <jakubmguzik@gmail.com>
This commit is contained in:
Jakub Guzik
2021-03-20 22:56:01 +01:00
parent ebc9871c93
commit 907b34c46f
4 changed files with 58 additions and 31 deletions

View File

@ -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 {

View File

@ -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)

View File

@ -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.

View File

@ -280,6 +280,32 @@ t GET containers/json 200 \
podman stop bar
#compat api list containers sanity checks
t GET containers/json?filters='garb1age}' 500 \
.cause="invalid character 'g' looking for beginning of value"
t GET containers/json?filters='{"label":["testl' 500 \
.cause="unexpected end of JSON input"
#libpod api list containers sanity checks
t GET libpod/containers/json?filters='garb1age}' 500 \
.cause="invalid character 'g' looking for beginning of value"
t GET libpod/containers/json?filters='{"label":["testl' 500 \
.cause="unexpected end of JSON input"
# Prune containers - bad filter input
t POST containers/prune?filters='garb1age}' 500 \
.cause="invalid character 'g' looking for beginning of value"
t POST libpod/containers/prune?filters='garb1age}' 500 \
.cause="invalid character 'g' looking for beginning of value"
## Prune containers with illformed label
t POST containers/prune?filters='{"label":["tes' 500 \
.cause="unexpected end of JSON input"
t POST libpod/containers/prune?filters='{"label":["tes' 500 \
.cause="unexpected end of JSON input"
t GET libpod/containers/json?filters='{"label":["testlabel"]}' 200 length=0
# Test CPU limit (NanoCPUs)
t POST containers/create Image=$IMAGE HostConfig='{"NanoCpus":500000}' 201 \
.Id~[0-9a-f]\\{64\\}