summaryrefslogtreecommitdiff
path: root/pkg/util
diff options
context:
space:
mode:
authorJakub Guzik <jakubmguzik@gmail.com>2021-03-19 00:09:18 +0100
committerJakub Guzik <jakubmguzik@gmail.com>2021-03-19 00:09:29 +0100
commitaa2d6e6e6c7434058c4b1a46d4354391ed4d96d0 (patch)
treed52ba042d287135d4ca14f4619413316c9fea7e4 /pkg/util
parent5d9b07096b49877608250c7d51e0ee35b9d502c7 (diff)
downloadpodman-aa2d6e6e6c7434058c4b1a46d4354391ed4d96d0.tar.gz
podman-aa2d6e6e6c7434058c4b1a46d4354391ed4d96d0.tar.bz2
podman-aa2d6e6e6c7434058c4b1a46d4354391ed4d96d0.zip
Fix volumes and networks list/prune filters in http api
This is the continuation work started in #9711. It turns out that list/prune commands for volumes in libpod/compat api have very dangerous error handling when broken filter input is supplied. Problem also affects network list/prune in libpod. This commit unifies filter handling across libpod/compat api and adds sanity apiv2 testcases. Signed-off-by: Jakub Guzik <jakubmguzik@gmail.com>
Diffstat (limited to 'pkg/util')
-rw-r--r--pkg/util/filters.go70
1 files changed, 70 insertions, 0 deletions
diff --git a/pkg/util/filters.go b/pkg/util/filters.go
index bf16f89e3..51b2c5331 100644
--- a/pkg/util/filters.go
+++ b/pkg/util/filters.go
@@ -1,6 +1,10 @@
package util
import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "strings"
"time"
"github.com/containers/podman/v3/pkg/timetype"
@@ -23,3 +27,69 @@ func ComputeUntilTimestamp(filter string, filterValues []string) (time.Time, err
}
return time.Unix(seconds, nanoseconds), nil
}
+
+// filtersFromRequests extracts the "filters" parameter from the specified
+// http.Request. The parameter can either be a `map[string][]string` as done
+// in new versions of Docker and libpod, or a `map[string]map[string]bool` as
+// done in older versions of Docker. We have to do a bit of Yoga to support
+// both - just as Docker does as well.
+//
+// Please refer to https://github.com/containers/podman/issues/6899 for some
+// background.
+func FiltersFromRequest(r *http.Request) ([]string, error) {
+ var (
+ compatFilters map[string]map[string]bool
+ filters map[string][]string
+ libpodFilters []string
+ raw []byte
+ )
+
+ if _, found := r.URL.Query()["filters"]; found {
+ raw = []byte(r.Form.Get("filters"))
+ } else if _, found := r.URL.Query()["Filters"]; found {
+ raw = []byte(r.Form.Get("Filters"))
+ } else {
+ return []string{}, nil
+ }
+
+ // Backwards compat with older versions of Docker.
+ if err := json.Unmarshal(raw, &compatFilters); err == nil {
+ for filterKey, filterMap := range compatFilters {
+ for filterValue, toAdd := range filterMap {
+ if toAdd {
+ libpodFilters = append(libpodFilters, fmt.Sprintf("%s=%s", filterKey, filterValue))
+ }
+ }
+ }
+ return libpodFilters, nil
+ }
+
+ if err := json.Unmarshal(raw, &filters); err != nil {
+ return nil, err
+ }
+
+ for filterKey, filterSlice := range filters {
+ for _, filterValue := range filterSlice {
+ libpodFilters = append(libpodFilters, fmt.Sprintf("%s=%s", filterKey, filterValue))
+ }
+ }
+
+ return libpodFilters, nil
+}
+
+// PrepareFilters prepares a *map[string][]string of filters to be later searched
+// in lipod and compat API to get desired filters
+func PrepareFilters(r *http.Request) (*map[string][]string, error) {
+ filtersList, err := FiltersFromRequest(r)
+ if err != nil {
+ return nil, err
+ }
+ filterMap := map[string][]string{}
+ for _, filter := range filtersList {
+ split := strings.SplitN(filter, "=", 2)
+ if len(split) > 1 {
+ filterMap[split[0]] = append(filterMap[split[0]], split[1])
+ }
+ }
+ return &filterMap, nil
+}