/
filter.go
130 lines (108 loc) · 2.54 KB
/
filter.go
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
130
package config
import (
"fmt"
"regexp"
"strconv"
"strings"
"time"
"github.com/mb0/glob"
)
type FilterType string
const (
FilterTypeEmpty FilterType = ""
FilterTypeExact FilterType = "exact"
FilterTypeGlob FilterType = "glob"
FilterTypeRegex FilterType = "regex"
FilterTypeContains FilterType = "contains"
FilterTypeDateOlderThan FilterType = "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",
"2006-01-02 15:04:05.000 -0700 MST", // Date format used by AWS for CreateTime on ASGs
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,
}
}