Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix containers list/prune http api filter behaviour #9773

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions pkg/api/handlers/compat/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand All @@ -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 {
Expand Down
17 changes: 7 additions & 10 deletions pkg/api/handlers/compat/containers_prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
24 changes: 13 additions & 11 deletions pkg/api/handlers/libpod/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
}
Expand All @@ -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.
Expand Down
26 changes: 26 additions & 0 deletions test/apiv2/20-containers.at
Original file line number Diff line number Diff line change
Expand Up @@ -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\\}
Expand Down