Skip to content

Commit

Permalink
update events configured to watch custom fields
Browse files Browse the repository at this point in the history
  • Loading branch information
Surbhidongaonkar committed Dec 7, 2019
1 parent d8f10a6 commit 2df9857
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 42 deletions.
16 changes: 15 additions & 1 deletion config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,12 @@ resources:
- create
- update
- delete
- update
- error
updateSetting:
includeDiff: true
fields:
- spec
- status
- name: statefulset
namespaces:
include:
Expand All @@ -43,6 +47,11 @@ resources:
- update
- delete
- error
updateSetting:
includeDiff: true
fields:
- spec
- status
- name: ingress
namespaces:
include:
Expand Down Expand Up @@ -134,6 +143,11 @@ resources:
- update
- delete
- error
updateSetting:
includeDiff: true
fields:
- spec
- status
- name: role
namespaces:
include:
Expand Down
20 changes: 20 additions & 0 deletions deploy-all-in-one.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ data:
- update
- delete
- error
updateSetting:
includeDiff: true
fields:
- spec
- status
- name: statefulset
namespaces:
include:
Expand All @@ -52,6 +57,11 @@ data:
- update
- delete
- error
updateSetting:
includeDiff: true
fields:
- spec
- status
- name: ingress
namespaces:
include:
Expand Down Expand Up @@ -123,6 +133,11 @@ data:
- update
- delete
- error
updateSetting:
includeDiff: true
fields:
- spec
- status
- name: job
namespaces:
include:
Expand All @@ -134,6 +149,11 @@ data:
- update
- delete
- error
updateSetting:
includeDiff: true
fields:
- spec
- status
- name: role
namespaces:
include:
Expand Down
15 changes: 15 additions & 0 deletions helm/botkube/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ config:
- update
- delete
- error
updateSetting:
includeDiff: true
fields:
- spec
- status
- name: statefulset
namespaces:
include:
Expand All @@ -72,6 +77,11 @@ config:
- update
- delete
- error
updateSetting:
includeDiff: true
fields:
- spec
- status
- name: ingress
namespaces:
include:
Expand Down Expand Up @@ -153,6 +163,11 @@ config:
- update
- delete
- error
updateSetting:
includeDiff: true
fields:
- spec
- status
- name: role
namespaces:
include:
Expand Down
16 changes: 13 additions & 3 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ var Notify = true
// NotifType to change notification type
type NotifType string

// FieldType to specify the resource fields for which to get notification
type FieldType string

// Config structure of configuration yaml file
type Config struct {
Resources []Resource
Expand All @@ -53,9 +56,16 @@ type Config struct {

// Resource contains resources to watch
type Resource struct {
Name string
Namespaces Namespaces
Events []EventType
Name string
Namespaces Namespaces
Events []EventType
UpdateSetting UpdateSetting `yaml:"updateSetting"`
}

//UpdateSetting struct defines updateEvent fields specification
type UpdateSetting struct {
Fields []FieldType
IncludeDiff bool `yaml:"includeDiff"`
}

// Namespaces contains namespaces to include and ignore
Expand Down
17 changes: 10 additions & 7 deletions pkg/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,13 +163,16 @@ func sendEvent(obj, oldObj interface{}, c *config.Config, notifiers []notify.Not

// check for siginificant Update Events in objects
if eventType == config.UpdateEvent {
updateMsg := utils.Diff(oldObj, obj)
if len(updateMsg) > 0 {
event.Messages = append(event.Messages, updateMsg)
} else {
// skipping least significant update
log.Logger.Debug("skipping least significant Update event")
event.Skip = true
updatesetting, exists := utils.AllowedUpdateEventsMap[utils.KindNS{Resource: kind, Namespace: "all"}]
if exists {
updateMsg := utils.Diff(oldObj, obj, updatesetting)
if len(updateMsg) > 0 {
event.Messages = append(event.Messages, updateMsg)
} else {
// skipping least significant update
log.Logger.Debug("skipping least significant Update event")
event.Skip = true
}
}
}

Expand Down
54 changes: 30 additions & 24 deletions pkg/utils/cmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,53 @@ package utils

import (
"fmt"
"strings"
"strings"

"github.com/google/go-cmp/cmp"
"github.com/infracloudio/botkube/pkg/config"
)

// SpecDiffReporter is a simple custom reporter that only records differences
// detected in Object Spec during comparison.
type SpecDiffReporter struct {
path cmp.Path
diffs []string
// DiffReporter is a simple custom reporter that records differences
// detected in Object during comparison.
type DiffReporter struct {
field string
path cmp.Path
diffs []string
}

// PushStep custom implements Reporter interface
func (r *SpecDiffReporter) PushStep(ps cmp.PathStep) {
r.path = append(r.path, ps)
func (r *DiffReporter) PushStep(ps cmp.PathStep) {
r.path = append(r.path, ps)
}

// Report custom implements Reporter interface
func (r *SpecDiffReporter) Report(rs cmp.Result) {
func (r *DiffReporter) Report(rs cmp.Result) {
if !rs.Equal() {
vx, vy := r.path.Last().Values()
path := fmt.Sprintf("%#v", r.path)
if ok := strings.Contains(path, ".Spec."); ok {
r.diffs = append(r.diffs, fmt.Sprintf("%#v:\n\t-: %+v\n\t+: %+v\n", r.path, vx, vy))
}
}
vx, vy := r.path.Last().Values()
path := fmt.Sprintf("%#v", r.path)
if ok := strings.Contains(path, "."+strings.Title(r.field)); ok {
r.diffs = append(r.diffs, fmt.Sprintf("%#v:\n\t-: %+v\n\t+: %+v\n", r.path, vx, vy))
}
}
}

// PopStep custom implements Reporter interface
func (r *SpecDiffReporter) PopStep() {
r.path = r.path[:len(r.path)-1]
func (r *DiffReporter) PopStep() {
r.path = r.path[:len(r.path)-1]
}

// String custom implements Reporter interface
func (r *SpecDiffReporter) String() string {
return strings.Join(r.diffs, "\n")
func (r *DiffReporter) String() string {
return strings.Join(r.diffs, "\n")
}

// Diff provides differences between two objects spec
func Diff(x, y interface{}) string {
var r SpecDiffReporter
cmp.Equal(x, y, cmp.Reporter(&r))
return r.String()
func Diff(x, y interface{}, updatesetting config.UpdateSetting) string {
msg := ""
for _, val := range updatesetting.Fields {
var r DiffReporter
r.field = string(val)
cmp.Equal(x, y, cmp.Reporter(&r))
msg = msg + r.String()
}
return msg
}
82 changes: 77 additions & 5 deletions pkg/utils/cmp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ package utils
import (
"fmt"
"testing"

"github.com/infracloudio/botkube/pkg/config"
)

// Object mocks kubernetes objects
type Object struct {
Spec Spec
Other Other
Spec Spec
Status Status
Data Data
Rules Rules
Other Other
}

// Other mocks fileds like MetaData, Status etc in kubernetes objects
Expand All @@ -21,6 +26,21 @@ type Spec struct {
Port int
}

// Status mocks ObjectStatus field in kubernetes object
type Status struct {
Replicas int
}

// Data mocks ObjectData field in kubernetes object like configmap
type Data struct {
Properties string
}

// Rules mocks ObjectRules field in kubernetes object
type Rules struct {
Verbs string
}

// ExpectedDiff struct to generate expected diff
type ExpectedDiff struct {
Path string
Expand All @@ -32,11 +52,13 @@ func TestDiff(t *testing.T) {
tests := map[string]struct {
old Object
new Object
update config.UpdateSetting
expected ExpectedDiff
}{
`Spec Diff`: {
old: Object{Spec: Spec{Port: 81}, Other: Other{Foo: "bar"}},
new: Object{Spec: Spec{Port: 83}, Other: Other{Foo: "bar"}},
old: Object{Spec: Spec{Port: 81}, Other: Other{Foo: "bar"}},
new: Object{Spec: Spec{Port: 83}, Other: Other{Foo: "bar"}},
update: config.UpdateSetting{Fields: []config.FieldType{"Spec"}, IncludeDiff: true},
expected: ExpectedDiff{
Path: "{utils.Object}.Spec.Port",
X: "81",
Expand All @@ -46,13 +68,63 @@ func TestDiff(t *testing.T) {
`Non Spec Diff`: {
old: Object{Spec: Spec{Port: 81}, Other: Other{Foo: "bar"}},
new: Object{Spec: Spec{Port: 81}, Other: Other{Foo: "boo"}},
update: config.UpdateSetting{Fields: []config.FieldType{"metadata"}, IncludeDiff: true},
expected: ExpectedDiff{},
},
`Status Diff`: {
old: Object{Status: Status{Replicas: 1}, Other: Other{Foo: "bar"}},
new: Object{Status: Status{Replicas: 2}, Other: Other{Foo: "bar"}},
update: config.UpdateSetting{Fields: []config.FieldType{"Status"}, IncludeDiff: true},
expected: ExpectedDiff{
Path: "{utils.Object}.Status.Replicas",
X: "1",
Y: "2",
},
},
`Non Status Diff`: {
old: Object{Status: Status{Replicas: 1}, Other: Other{Foo: "bar"}},
new: Object{Status: Status{Replicas: 1}, Other: Other{Foo: "boo"}},
update: config.UpdateSetting{Fields: []config.FieldType{"metadata"}, IncludeDiff: true},
expected: ExpectedDiff{},
},
`Data Diff`: {
old: Object{Data: Data{Properties: "Color: blue"}, Other: Other{Foo: "bar"}},
new: Object{Data: Data{Properties: "Color: red"}, Other: Other{Foo: "bar"}},
update: config.UpdateSetting{Fields: []config.FieldType{"Data"}, IncludeDiff: true},
expected: ExpectedDiff{
Path: "{utils.Object}.Data.Properties",
X: "Color: blue",
Y: "Color: red",
},
},
`Non Data Diff`: {
old: Object{Data: Data{Properties: "Color: blue"}, Other: Other{Foo: "bar"}},
new: Object{Data: Data{Properties: "Color: blue"}, Other: Other{Foo: "boo"}},
update: config.UpdateSetting{Fields: []config.FieldType{"metadata"}, IncludeDiff: true},
expected: ExpectedDiff{},
},
`Rules Diff`: {
old: Object{Rules: Rules{Verbs: "list"}, Other: Other{Foo: "bar"}},
new: Object{Rules: Rules{Verbs: "watch"}, Other: Other{Foo: "bar"}},
update: config.UpdateSetting{Fields: []config.FieldType{"Rules"}, IncludeDiff: true},
expected: ExpectedDiff{
Path: "{utils.Object}.Rules.Verbs",
X: "list",
Y: "watch",
},
},
`Non Rules Diff`: {
old: Object{Rules: Rules{Verbs: "list"}, Other: Other{Foo: "bar"}},
new: Object{Rules: Rules{Verbs: "list"}, Other: Other{Foo: "boo"}},
update: config.UpdateSetting{Fields: []config.FieldType{"metadata"}, IncludeDiff: true},
expected: ExpectedDiff{},

},
}
for name, test := range tests {
name, test := name, test
t.Run(name, func(t *testing.T) {
if actual := Diff(test.old, test.new); actual != test.expected.MockDiff() {
if actual := Diff(test.old, test.new, test.update); actual != test.expected.MockDiff() {
t.Errorf("expected: %+v != actual: %+v\n", test.expected.MockDiff(), actual)
}
})
Expand Down
Loading

0 comments on commit 2df9857

Please sign in to comment.