Skip to content

Commit 9ce3325

Browse files
committed
first working version
1 parent 17914ec commit 9ce3325

File tree

11 files changed

+366
-26
lines changed

11 files changed

+366
-26
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
.idea
1+
.idea
2+
config.yaml

config.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
sinceNow: true
2+
filters:
3+
- objectKind: Job
4+
eventReason: BackoffLimitExceeded

example.yaml.ref

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
apiVersion: v1
2+
items:
3+
- apiVersion: v1
4+
count: 1
5+
eventTime: null
6+
firstTimestamp: "2019-10-14T07:11:45Z"
7+
involvedObject:
8+
apiVersion: batch/v1
9+
kind: Job
10+
name: test
11+
namespace: default
12+
resourceVersion: "101294040"
13+
uid: dfe0b858-ee51-11e9-ae04-0a92e6d821d8
14+
kind: Event
15+
lastTimestamp: "2019-10-14T07:11:45Z"
16+
message: Job has reached the specified backoff limit
17+
metadata:
18+
creationTimestamp: "2019-10-14T07:11:45Z"
19+
name: test.15cd71ec765990ca
20+
namespace: default
21+
resourceVersion: "101294059"
22+
selfLink: /api/v1/namespaces/default/events/test.15cd71ec765990ca
23+
uid: e17d1c66-ee51-11e9-9a81-12fd51bfaa24
24+
reason: BackoffLimitExceeded
25+
reportingComponent: ""
26+
reportingInstance: ""
27+
source:
28+
component: job-controller
29+
type: Warning

example/main.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"flag"
6+
"fmt"
7+
v1 "k8s.io/api/core/v1"
8+
_ "k8s.io/client-go/plugin/pkg/client/auth"
9+
"k8seventwatcher"
10+
"log"
11+
"os"
12+
)
13+
14+
func main() {
15+
kubeConfigPath := flag.String("kubeconfig", "", "path of k8s k8sConfig file to use")
16+
configPath := flag.String("config", "config.yaml", "path of k8sConfig file to use")
17+
18+
flag.Parse()
19+
20+
watcher, err := k8seventwatcher.NewK8sEventWatcher(
21+
*configPath,
22+
kubeConfigPath,
23+
os.Stdout,
24+
)
25+
if err != nil {
26+
log.Fatal(err)
27+
}
28+
29+
if err := watcher.Start(func(event *v1.Event) {
30+
log.Printf("got event: %+v\n", event)
31+
}); err != nil {
32+
log.Fatal(err)
33+
}
34+
35+
fmt.Println("Press 'Enter' to exit...")
36+
bufio.NewReader(os.Stdin).ReadBytes('\n')
37+
38+
watcher.Stop()
39+
}

go.mod

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
module k8s-event-watcher
1+
module k8seventwatcher
22

33
go 1.13
44

55
require (
6+
gopkg.in/yaml.v2 v2.2.4
67
k8s.io/api v0.0.0-20190620084959-7cf5895f2711
8+
k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719
79
k8s.io/client-go v0.0.0-20190620085101-78d2af792bab
810
)

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
7474
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
7575
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
7676
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
77+
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
78+
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
7779
k8s.io/api v0.0.0-20190620084959-7cf5895f2711 h1:BblVYz/wE5WtBsD/Gvu54KyBUTJMflolzc5I2DTvh50=
7880
k8s.io/api v0.0.0-20190620084959-7cf5895f2711/go.mod h1:TBhBqb1AWbBQbW3XRusr7n7E4v2+5ZY8r8sAMnyFC5A=
7981
k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719 h1:uV4S5IB5g4Nvi+TBVNf3e9L4wrirlwYJ6w88jUQxTUw=

internal/config.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package internal
2+
3+
import (
4+
"errors"
5+
"gopkg.in/yaml.v2"
6+
v1 "k8s.io/api/core/v1"
7+
"log"
8+
)
9+
10+
type Config struct {
11+
Filters []*EventFilter `yaml:"filters"`
12+
13+
// If true, accepts only events generated since the app has been launched
14+
SinceNow bool `yaml:"sinceNow"`
15+
}
16+
17+
func (c *Config) Validate() error {
18+
if len(c.Filters) == 0 {
19+
return errors.New("zero filters provided")
20+
}
21+
22+
for _, filter := range c.Filters {
23+
if err := filter.Validate(); err != nil {
24+
return err
25+
}
26+
}
27+
28+
return nil
29+
}
30+
31+
func (c *Config) MatchesEvent(event *v1.Event) bool {
32+
for _, filter := range c.Filters {
33+
if filter.Matches(event) {
34+
return true
35+
}
36+
}
37+
38+
return false
39+
}
40+
41+
func (c *Config) Dump() string {
42+
data, err := yaml.Marshal(c)
43+
if err != nil {
44+
log.Fatalf("failed to dump Config: %+v", c)
45+
}
46+
47+
return string(data)
48+
}

internal/filter.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package internal
2+
3+
import (
4+
"errors"
5+
v1 "k8s.io/api/core/v1"
6+
)
7+
8+
type EventFilter struct {
9+
ObjectNamespace *Regexp `yaml:"objectNamespace,omitempty"`
10+
ObjectKind *Regexp `yaml:"objectKind,omitempty"`
11+
ObjectName *Regexp `yaml:"objectName,omitempty"`
12+
EventType *Regexp `yaml:"eventType,omitempty"`
13+
EventReason *Regexp `yaml:"eventReason,omitempty"`
14+
}
15+
16+
func (f *EventFilter) Validate() error {
17+
// At least one filter must exist
18+
if f.ObjectNamespace != nil {
19+
return nil
20+
}
21+
if f.ObjectKind != nil {
22+
return nil
23+
}
24+
if f.ObjectName != nil {
25+
return nil
26+
}
27+
if f.EventType != nil {
28+
return nil
29+
}
30+
if f.EventReason != nil {
31+
return nil
32+
}
33+
return errors.New("no filter attributes provided")
34+
}
35+
36+
func (f *EventFilter) Matches(event *v1.Event) bool {
37+
if f.ObjectNamespace != nil {
38+
if !f.ObjectNamespace.MatchString(event.InvolvedObject.Namespace) {
39+
return false
40+
}
41+
}
42+
if f.ObjectKind != nil {
43+
if !f.ObjectKind.MatchString(event.InvolvedObject.Kind) {
44+
return false
45+
}
46+
}
47+
if f.ObjectName != nil {
48+
if !f.ObjectName.MatchString(event.InvolvedObject.Name) {
49+
return false
50+
}
51+
}
52+
if f.EventType != nil {
53+
if !f.EventType.MatchString(event.Type) {
54+
return false
55+
}
56+
}
57+
if f.EventReason != nil {
58+
if !f.EventReason.MatchString(event.Reason) {
59+
return false
60+
}
61+
}
62+
63+
return true
64+
}

internal/regex.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package internal
2+
3+
import "regexp"
4+
5+
type Regexp struct {
6+
*regexp.Regexp
7+
}
8+
9+
func (r *Regexp) UnmarshalYAML(unmarshal func(interface{}) error) error {
10+
regexString := ""
11+
err := unmarshal(&regexString)
12+
if err != nil {
13+
return err
14+
}
15+
16+
(*r).Regexp, err = regexp.Compile(regexString)
17+
if err != nil {
18+
return err
19+
}
20+
21+
return nil
22+
}
23+
24+
func (r *Regexp) MarshalYAML() (interface{}, error) {
25+
return r.Regexp.String(), nil
26+
}

log.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package k8seventwatcher
2+
3+
import "fmt"
4+
5+
func (w *K8sEventWatcher) logEntryDebug(format string, args ...interface{}) {
6+
if ! w.Debug {
7+
return
8+
}
9+
if w.logger != nil {
10+
w.logger.Printf("[K8EW] (DEBUG): "+format+"\n", args...)
11+
}
12+
}
13+
14+
func (w *K8sEventWatcher) logEntryInfo(format string, args ...interface{}) {
15+
if w.logger != nil {
16+
w.logger.Printf("[K8EW] (INFO): "+format+"\n", args...)
17+
}
18+
}
19+
20+
func (w *K8sEventWatcher) logEntryError(format string, args ...interface{}) {
21+
if w.logger != nil {
22+
w.logger.Printf("[K8EW] (ERROR): "+format+"\n", args...)
23+
}
24+
}
25+
26+
func errorf(format string, args ...interface{}) error {
27+
return fmt.Errorf("[K8EW]: "+format+"\n", args)
28+
}

0 commit comments

Comments
 (0)