1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
package config
import (
"fmt"
"regexp"
"strconv"
"strings"
"time"
"github.com/mb0/glob"
)
type FilterType string
const (
FilterTypeEmpty FilterType = ""
FilterTypeExact = "exact"
FilterTypeGlob = "glob"
FilterTypeRegex = "regex"
FilterTypeContains = "contains"
FilterTypeDateOlderThan = "dateOlderThan"
)
type Filters map[string][]Filter
func (f Filters) Merge(f2 Filters) {
for resourceType, filter := range f2 {
f[resourceType] = append(f[resourceType], filter...)
}
}
type Filter struct {
Property string
Type FilterType
Value string
Invert string
}
func (f Filter) Match(o string) (bool, error) {
switch f.Type {
case FilterTypeEmpty:
fallthrough
case FilterTypeExact:
return f.Value == o, nil
case FilterTypeContains:
return strings.Contains(o, f.Value), nil
case FilterTypeGlob:
return glob.Match(f.Value, o)
case FilterTypeRegex:
re, err := regexp.Compile(f.Value)
if err != nil {
return false, err
}
return re.MatchString(o), nil
case FilterTypeDateOlderThan:
if o == "" {
return false, nil
}
duration, err := time.ParseDuration(f.Value)
if err != nil {
return false, err
}
fieldTime, err := parseDate(o)
if err != nil {
return false, err
}
fieldTimeWithOffset := fieldTime.Add(duration)
return fieldTimeWithOffset.After(time.Now()), nil
default:
return false, fmt.Errorf("unknown type %s", f.Type)
}
}
func parseDate(input string) (time.Time, error) {
if i, err := strconv.ParseInt(input, 10, 64); err == nil {
t := time.Unix(i, 0)
return t, nil
}
formats := []string{"2006-01-02",
"2006/01/02",
"2006-01-02T15:04:05Z",
time.RFC3339Nano, // Format of t.MarshalText() and t.MarshalJSON()
time.RFC3339,
}
for _, f := range formats {
t, err := time.Parse(f, input)
if err == nil {
return t, nil
}
}
return time.Now(), fmt.Errorf("unable to parse time %s", input)
}
func (f *Filter) UnmarshalYAML(unmarshal func(interface{}) error) error {
var value string
if unmarshal(&value) == nil {
f.Type = FilterTypeExact
f.Value = value
return nil
}
m := map[string]string{}
err := unmarshal(m)
if err != nil {
return err
}
f.Type = FilterType(m["type"])
f.Value = m["value"]
f.Property = m["property"]
f.Invert = m["invert"]
return nil
}
func NewExactFilter(value string) Filter {
return Filter{
Type: FilterTypeExact,
Value: value,
}
}
|