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

feat(filter): add dateOlderThanNow #80

Merged
merged 4 commits into from
Oct 16, 2024
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
4 changes: 4 additions & 0 deletions pkg/docs/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import (
func GeneratePropertiesMap(data interface{}) map[string]string {
properties := map[string]string{}

if data == nil {
return properties
}

v := reflect.ValueOf(data)
if v.Kind() == reflect.Ptr {
v = v.Elem()
Expand Down
16 changes: 16 additions & 0 deletions pkg/docs/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ func TestGenerateProperties(t *testing.T) {
skipped string //nolint:unused
}

type TestResource4 struct {
name string //nolint:unused
ignore string //nolint:unused
example string //nolint:unused
}

cases := []struct {
name string
in interface{}
Expand Down Expand Up @@ -70,6 +76,16 @@ func TestGenerateProperties(t *testing.T) {
"Delta": "A property rename",
},
},
{
name: "TestResource4",
in: TestResource4{},
want: map[string]string{},
},
{
name: "nil",
in: nil,
want: map[string]string{},
},
}

for _, c := range cases {
Expand Down
60 changes: 55 additions & 5 deletions pkg/filter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ different `group` are combined with an `OR` operation.

There is also the concept of a `global` filter that is applied to all resources.

## Global

You can define a global filter that will be applied to all resources. This is useful for defining a set of filters that
should be applied to all resources.

It has a special key called `__global__`.

This only works when you are defining it as a resource type as part of the `Filters` `map[string][]Filter` type.

## Types

There are multiple filter types that can be used to filter the resources. These types are used to match against the
Expand All @@ -19,14 +28,55 @@ property.
- regex
- contains
- dateOlderThan
- dateOlderThanNow
- suffix
- prefix
- In
- NotIn

## Global
### empty / exact

You can define a global filter that will be applied to all resources. This is useful for defining a set of filters that
should be applied to all resources.
These are identical, if you leave your type empty, it will choose exact. Exact will only match if values are identical.

It has a special key called `__global__`.
### glob

A glob allows for matching values using asterisk for a wild card, you may have more than one asterisk.

### regex

A regex allows for matching values with any valid regular expression.

### contains

A contains type allows for matching a value if it has the value contained within the property value.

### dateOlderThan

This allows you to filter a property's value based on whether it is older

### dateOlderThanNow

This allows you to filter a properties value based on whether it is older than the current time in UTC with an addition
or subtraction of a duration value.

For example if the property is `CreatedDate` and the value is `2024-04-14T12:00:00Z` and the current time is
`2024-04-14T18:00:00Z` then you can set a negative duration like `-12h`. In this case it would not match, as the
`CreatedDate` would be **after** the adjusted time.

If you adjusted it `-4h` then it **would** match as the `CreatedDate` would be **before** the adjusted time.

### suffix

This allows you to match a value if the value being filtered on is the suffix of the property value.

### prefix

This allows you to match a value if the value being filtered on is the prefix of the property value.

### In

This allows you to match a value if it is in a list of values.

### NotIn

This only works when you are defining it as a resource type as part of the `Filters` `map[string][]Filter` type.
This allows you to match a value if it is not in a list of values.
40 changes: 29 additions & 11 deletions pkg/filter/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,17 @@ import (
type Type string

const (
Empty Type = ""
Exact Type = "exact"
Glob Type = "glob"
Regex Type = "regex"
Contains Type = "contains"
DateOlderThan Type = "dateOlderThan"
Suffix Type = "suffix"
Prefix Type = "prefix"
NotIn Type = "NotIn"
In Type = "In"
Empty Type = ""
Exact Type = "exact"
Glob Type = "glob"
Regex Type = "regex"
Contains Type = "contains"
DateOlderThan Type = "dateOlderThan"
DateOlderThanNow Type = "dateOlderThanNow"
Suffix Type = "suffix"
Prefix Type = "prefix"
NotIn Type = "NotIn"
In Type = "In"

Global = "__global__"
)
Expand Down Expand Up @@ -106,7 +107,7 @@ func (f *Filter) Validate() error {
}

// Match checks if the filter matches the given value
func (f *Filter) Match(o string) (bool, error) {
func (f *Filter) Match(o string) (bool, error) { //nolint:gocyclo
switch f.Type {
case Empty, Exact:
return f.Value == o, nil
Expand Down Expand Up @@ -140,6 +141,23 @@ func (f *Filter) Match(o string) (bool, error) {

return fieldTimeWithOffset.After(time.Now()), nil

case DateOlderThanNow:
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
}

adjustedTime := time.Now().UTC().Add(duration)

return adjustedTime.After(fieldTime), nil

case Prefix:
return strings.HasPrefix(o, f.Value), nil

Expand Down
21 changes: 21 additions & 0 deletions pkg/filter/filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,27 @@ func TestFilter_UnmarshalFilter(t *testing.T) {
},
error: true,
},
{
name: "dateOlderThanNow",
yaml: `{"type":"dateOlderThanNow","value":"0"}`,
match: []string{
past.Format(time.RFC3339),
},
mismatch: []string{
future.Format(time.RFC3339),
},
},
{
name: "dateOlderThanNow2",
yaml: `{"type": "dateOlderThanNow", "value": "-36h"}`, // -36 hours
match: []string{
past.Add(-13 * time.Hour).Format(time.RFC3339),
},
mismatch: []string{
past.Format(time.RFC3339), // -24 hours
future.Format(time.RFC3339), // +24 hours
},
},
{
yaml: `{"type":"prefix","value":"someprefix-"}`,
match: []string{"someprefix-1234", "someprefix-someprefix", "someprefix-asdafd"},
Expand Down