Skip to content

Commit

Permalink
refactor matchResource & add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
adityathebe committed Sep 1, 2023
1 parent 391dccb commit 0f9aa67
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 15 deletions.
27 changes: 27 additions & 0 deletions events/hey_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package events

import (
"fmt"
"testing"

"github.com/flanksource/commons/logger"
)

func TestLabe(t *testing.T) {
out := []int{1, 2, 3, 4, 5}
in := []int{6, 7, 8, 9, 10}

OUTER:
for _, o := range out {
logger.Infof("In %d", o)

for _, i := range in {
if o*i == 14 {
fmt.Println("Continuing to outer")
continue OUTER
}
}

logger.Infof("Completed %d", o)
}
}
23 changes: 9 additions & 14 deletions events/playbook.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,39 +144,34 @@ func logToJobHistory(ctx *api.Context, playbookID, err string) {
// matchResource returns true if any one of the matchFilter is true
// for the given labels and cel env.
func matchResource(labels map[string]string, celEnv map[string]any, matchFilters []v1.PlaybookEventDetail) (bool, error) {
outer:
for _, mf := range matchFilters {
var (
filterPassed = true
allLabelsMatched = true
)

if mf.Filter != "" {
filterPassed = false
res, err := gomplate.RunTemplate(celEnv, gomplate.Template{Expression: mf.Filter})
if err != nil {
return false, err
}

filterPassed, _ = strconv.ParseBool(res)
if ok, err := strconv.ParseBool(res); err != nil {
return false, api.Errorf(api.EINVALID, "expression didn't evaluate to a boolean value. got %s", res)
} else if !ok {
continue outer
}
}

for k, v := range mf.Labels {
qVal, ok := labels[k]
if !ok {
allLabelsMatched = false
break
continue outer
}

configuredLabels := strings.Split(v, ",")
if !collections.MatchItems(qVal, configuredLabels...) {
allLabelsMatched = false
break
continue outer
}
}

if filterPassed && allLabelsMatched {
return true, nil
}
return true, nil
}

return false, nil
Expand Down
212 changes: 212 additions & 0 deletions events/playbook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package events

import (
"encoding/json"
"testing"

"github.com/flanksource/duty/fixtures/dummy"
"github.com/flanksource/duty/models"
Expand Down Expand Up @@ -94,3 +95,214 @@ var _ = ginkgo.Describe("Should save playbook run on the correct event", ginkgo.
Expect(playbook.Status).To(Equal(models.PlaybookRunStatusScheduled))
})
})

func Test_matchResource(t *testing.T) {
type args struct {
labels map[string]string
eventResource EventResource
matchFilters []v1.PlaybookEventDetail
}
tests := []struct {
name string
args args
want bool
wantErr bool
}{
{
name: "With Filter | Without Labels | Match",
args: args{
labels: map[string]string{
"telemetry": "enabled",
},
eventResource: EventResource{
Component: &models.Component{
Type: "Entity",
},
},
matchFilters: []v1.PlaybookEventDetail{{Filter: "component.type == 'Entity'"}},
},
want: true,
wantErr: false,
},
{
name: "With Filter | Without Labels | No match",
args: args{
eventResource: EventResource{
Component: &models.Component{
Type: "Database",
},
},
matchFilters: []v1.PlaybookEventDetail{{Filter: "component.type == 'Entity'"}},
},
want: false,
wantErr: false,
},
{
name: "Without Filter | With Labels | Match",
args: args{
labels: map[string]string{
"telemetry": "enabled",
},
eventResource: EventResource{},
matchFilters: []v1.PlaybookEventDetail{
{
Labels: map[string]string{
"telemetry": "enabled",
},
},
},
},
want: true,
wantErr: false,
},
{
name: "Without Filter | With Labels | No match",
args: args{
labels: map[string]string{
"telemetry": "enabled",
},
eventResource: EventResource{},
matchFilters: []v1.PlaybookEventDetail{
{
Labels: map[string]string{
"telemetry": "enabled",
"env": "production",
},
},
},
},
want: false,
wantErr: false,
},
{
name: "With Filter | With Labels | match",
args: args{
labels: map[string]string{
"telemetry": "enabled",
},
eventResource: EventResource{
Check: &models.Check{
Type: "http",
},
},
matchFilters: []v1.PlaybookEventDetail{
{
Labels: map[string]string{
"telemetry": "enabled",
},
Filter: "check.type == 'http'",
},
},
},
want: true,
wantErr: false,
},
{
name: "With Filter | With Labels | no match",
args: args{
labels: map[string]string{
"telemetry": "enabled",
},
eventResource: EventResource{
Check: &models.Check{
Type: "http",
},
},
matchFilters: []v1.PlaybookEventDetail{
{
Labels: map[string]string{
"telemetry": "enabled",
},
Filter: "check.type == 'exec'",
},
},
},
want: false,
wantErr: false,
},
{
name: "With Filter | With Labels | one of the filters match",
args: args{
labels: map[string]string{
"telemetry": "enabled",
},
eventResource: EventResource{
Check: &models.Check{
Type: "http",
},
CheckSummary: &models.CheckSummary{
Uptime: types.Uptime{
Failed: 12,
},
},
},
matchFilters: []v1.PlaybookEventDetail{
{
Labels: map[string]string{
"telemetry": "enabled",
"env": "production",
},
},
{Filter: "check.type == 'http' && check_summary.uptime.failed > 15"},
{Filter: "check.type == 'http' && check_summary.uptime.failed > 10"},
},
},
want: true,
wantErr: false,
},
{
name: "Invalid filter expression",
args: args{
eventResource: EventResource{
Check: &models.Check{
Type: "http",
},
CheckSummary: &models.CheckSummary{
Uptime: types.Uptime{
Failed: 12,
},
},
},
matchFilters: []v1.PlaybookEventDetail{
{Filter: "summary.uptime.failed > 15"},
},
},
want: false,
wantErr: true,
},
{
name: "Expression not returning boolean",
args: args{
eventResource: EventResource{
Check: &models.Check{
Type: "http",
},
CheckSummary: &models.CheckSummary{
Uptime: types.Uptime{
Failed: 12,
},
},
},
matchFilters: []v1.PlaybookEventDetail{
{Filter: "check.type"},
},
},
want: false,
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := matchResource(tt.args.labels, tt.args.eventResource.AsMap(), tt.args.matchFilters)
if (err != nil) != tt.wantErr {
t.Errorf("matchResource() error = %v, wantErr %v", err, tt.wantErr)
return
}

if got != tt.want {
t.Errorf("matchResource() = %v, want %v", got, tt.want)
}
})
}
}
2 changes: 1 addition & 1 deletion fixtures/playbooks/stop-crashloop-pods.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ spec:
- event: failed
labels:
alertname: KubePodCrashLoopingcontainer
description: Stop Pods that's on CrashLoop
description: Stop Pods that are on CrashLoop
actions:
- name: 'Stop pod'
exec:
Expand Down

0 comments on commit 0f9aa67

Please sign in to comment.