mirror of
https://github.com/containers/podman
synced 2024-10-20 09:13:46 +00:00
bd09b7aa79
Automated for .go files via gomove [1]: `gomove github.com/containers/podman/v3 github.com/containers/podman/v4` Remaining files via vgrep [2]: `vgrep github.com/containers/podman/v3` [1] https://github.com/KSubedi/gomove [2] https://github.com/vrothberg/vgrep Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
129 lines
3.6 KiB
Go
129 lines
3.6 KiB
Go
package util
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/containers/podman/v4/pkg/timetype"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// ComputeUntilTimestamp extracts until timestamp from filters
|
|
func ComputeUntilTimestamp(filterValues []string) (time.Time, error) {
|
|
invalid := time.Time{}
|
|
if len(filterValues) != 1 {
|
|
return invalid, errors.Errorf("specify exactly one timestamp for until")
|
|
}
|
|
ts, err := timetype.GetTimestamp(filterValues[0], time.Now())
|
|
if err != nil {
|
|
return invalid, err
|
|
}
|
|
seconds, nanoseconds, err := timetype.ParseTimestamps(ts, 0)
|
|
if err != nil {
|
|
return invalid, 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
|
|
}
|
|
|
|
func matchPattern(pattern string, value string) bool {
|
|
if strings.Contains(pattern, "*") {
|
|
filter := fmt.Sprintf("*%s*", pattern)
|
|
filter = strings.ReplaceAll(filter, string(filepath.Separator), "|")
|
|
newName := strings.ReplaceAll(value, string(filepath.Separator), "|")
|
|
match, _ := filepath.Match(filter, newName)
|
|
return match
|
|
}
|
|
return false
|
|
}
|
|
|
|
// MatchLabelFilters matches labels and returns true if they are valid
|
|
func MatchLabelFilters(filterValues []string, labels map[string]string) bool {
|
|
outer:
|
|
for _, filterValue := range filterValues {
|
|
filterArray := strings.SplitN(filterValue, "=", 2)
|
|
filterKey := filterArray[0]
|
|
if len(filterArray) > 1 {
|
|
filterValue = filterArray[1]
|
|
} else {
|
|
filterValue = ""
|
|
}
|
|
for labelKey, labelValue := range labels {
|
|
if ((labelKey == filterKey) || matchPattern(filterKey, labelKey)) && (filterValue == "" || labelValue == filterValue) {
|
|
continue outer
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
return true
|
|
}
|