Skip to content

Commit 5c16504

Browse files
authored
Merge pull request #14 from pubg/feature/slack-webhook
feature: Send logs to Slack using a Slack webhook #13
2 parents a9ab1b3 + dcd7f6e commit 5c16504

File tree

13 files changed

+388
-75
lines changed

13 files changed

+388
-75
lines changed

controller/controller.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"time"
77

88
"github.com/pubg/kube-image-deployer/interfaces"
9-
"k8s.io/klog/v2"
109

1110
pkgRuntime "k8s.io/apimachinery/pkg/runtime"
1211
"k8s.io/apimachinery/pkg/util/runtime"
@@ -24,6 +23,7 @@ type Controller struct {
2423
informer cache.Controller
2524
imageNotifier interfaces.IImageNotifier
2625
applyStrategicMergePatch ApplyStrategicMergePatch
26+
logger interfaces.ILogger
2727

2828
syncedImages map[Image]bool
2929
syncedImagesMutex sync.RWMutex
@@ -45,6 +45,7 @@ type ControllerOpt struct {
4545
ImageNotifier interfaces.IImageNotifier
4646
ApplyStrategicMergePatch ApplyStrategicMergePatch
4747
ControllerWatchKey string
48+
Logger interfaces.ILogger
4849
}
4950

5051
// NewController creates a new Controller.
@@ -58,6 +59,7 @@ func NewController(opt ControllerOpt) *Controller {
5859
imageNotifier: opt.ImageNotifier,
5960
applyStrategicMergePatch: opt.ApplyStrategicMergePatch,
6061
watchKey: opt.ControllerWatchKey,
62+
logger: opt.Logger,
6163
syncedImages: make(map[Image]bool),
6264
syncedImagesMutex: sync.RWMutex{},
6365
imageUpdateNotifyList: make([]imageUpdateNotify, 0),
@@ -95,7 +97,7 @@ func (c *Controller) handleErr(err error, key interface{}) {
9597

9698
// This controller retries 5 times if something goes wrong. After that, it stops trying.
9799
if c.queue.NumRequeues(key) < 5 {
98-
klog.V(2).Infof("[%s] Error syncing %v: %v", c.resource, key, err)
100+
c.logger.Infof("[%s] Error syncing %v: %v", c.resource, key, err)
99101

100102
// Re-enqueue the key rate limited. Based on the rate limiter on the
101103
// queue and the re-enqueue history, the key will be processed later again.
@@ -106,7 +108,7 @@ func (c *Controller) handleErr(err error, key interface{}) {
106108
c.queue.Forget(key)
107109
// Report to an external entity that, even after several retries, we could not successfully process this key
108110
runtime.HandleError(err)
109-
klog.V(2).Infof("[%s] Dropping out of the queue: key:%q, err:%v", c.resource, key, err)
111+
c.logger.Infof("[%s] Dropping out of the queue: key:%q, err:%v", c.resource, key, err)
110112
}
111113

112114
// Run begins watching and syncing.
@@ -115,7 +117,7 @@ func (c *Controller) Run(workers int, stopCh chan struct{}) {
115117

116118
// Let the workers stop when we are done
117119
defer c.queue.ShutDown()
118-
klog.V(2).Infof("[%s] Starting controller", c.resource)
120+
c.logger.Infof("[%s] Starting controller", c.resource)
119121

120122
go c.informer.Run(stopCh)
121123

@@ -132,7 +134,7 @@ func (c *Controller) Run(workers int, stopCh chan struct{}) {
132134
go wait.Until(c.patchUpdateNotifyList, time.Second, stopCh)
133135

134136
<-stopCh
135-
klog.V(2).Infof("[%s] Stopping controller", c.resource)
137+
c.logger.Infof("[%s] Stopping controller", c.resource)
136138
}
137139

138140
func (c *Controller) GetReresourceName() string {

controller/onUpdateImageHash.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66

77
"github.com/pubg/kube-image-deployer/util"
88
v1 "k8s.io/api/core/v1"
9-
"k8s.io/klog/v2"
109
)
1110

1211
type patch struct {
@@ -44,7 +43,7 @@ func (c *Controller) getPatchMapByUpdates(updates []imageUpdateNotify) map[strin
4443
patchMap := make(map[string][]patch)
4544

4645
for _, update := range updates {
47-
klog.V(2).Infof("[%s] OnUpdateImageString %s, %s, %s", c.resource, update.url, update.tag, update.imageString)
46+
c.logger.Infof("[%s] OnUpdateImageString %s, %s, %s", c.resource, update.url, update.tag, update.imageString)
4847

4948
c.syncedImagesMutex.RLock()
5049
defer c.syncedImagesMutex.RUnlock()
@@ -90,7 +89,7 @@ func (c *Controller) applyPatchList(key string, patchList []patch) error {
9089
}
9190

9291
for _, patch := range patchList {
93-
klog.V(2).Infof("[%s] OnUpdateImageString patch %+v", c.resource, patch)
92+
c.logger.Infof("[%s] OnUpdateImageString patch %+v", c.resource, patch)
9493

9594
if !exists { // 삭제된 리소스인 경우 무시
9695
return fmt.Errorf("[%s] OnUpdateImageString patch not exists key=%s", c.resource, key)
@@ -124,7 +123,7 @@ func (c *Controller) applyPatchList(key string, patchList []patch) error {
124123
}
125124

126125
if len(Containers) == 0 && len(InitContainers) == 0 { // 변경된 이미지가 없는 경우 무시
127-
klog.V(2).Infof("[%s] OnUpdateImageString patch containers not changed %+v", c.resource, patchList)
126+
c.logger.Infof("[%s] OnUpdateImageString patch containers not changed %+v", c.resource, patchList)
128127
return nil
129128
}
130129

@@ -140,7 +139,7 @@ func (c *Controller) applyPatchList(key string, patchList []patch) error {
140139
return fmt.Errorf("[%s] OnUpdateImageString patch apply error namespace=%s, name=%s, patchString=%s, err=%s", c.resource, namespace, name, patchString, err)
141140
}
142141

143-
klog.Warningf("[%s] OnUpdateImageString patch apply success namespace=%s, name=%s, patchString=%s", c.resource, namespace, name, patchString)
142+
c.logger.Warningf("[%s] OnUpdateImageString patch apply success namespace=%s, name=%s, patchString=%s", c.resource, namespace, name, patchString)
144143
return nil
145144

146145
}
@@ -176,7 +175,7 @@ func (c *Controller) patchUpdateNotifyList() {
176175

177176
for key, patchList := range patchMap {
178177
if err := c.applyPatchList(key, patchList); err != nil {
179-
klog.Error(err)
178+
c.logger.Errorf(err.Error()) // just logging
180179
}
181180
}
182181

controller/sync.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"strings"
55

66
"github.com/pubg/kube-image-deployer/util"
7-
"k8s.io/klog"
87
)
98

109
type Image struct {
@@ -18,7 +17,7 @@ func (c *Controller) syncKey(key string) error {
1817

1918
obj, exists, err := c.indexer.GetByKey(key)
2019
if err != nil {
21-
klog.Errorf("[%s] Fetching object with key %s from store failed with %v", c.resource, key, err)
20+
c.logger.Errorf("[%s] Fetching object with key %s from store failed with %v", c.resource, key, err)
2221
return err
2322
}
2423

@@ -50,7 +49,12 @@ func (c *Controller) syncKey(key string) error {
5049
func (c *Controller) getImagesFromCurrentWorkload(obj interface{}, key string) (images map[Image]bool) {
5150

5251
images = make(map[Image]bool)
53-
annotations := util.GetAnnotations(obj)
52+
annotations, err := util.GetAnnotations(obj)
53+
54+
if err != nil {
55+
c.logger.Errorf("[%s] GetAnnotations error : %v", c.resource, err)
56+
return
57+
}
5458

5559
for annotationKey, annotationValue := range annotations {
5660

@@ -79,7 +83,7 @@ func (c *Controller) getImagesFromCurrentWorkload(obj interface{}, key string) (
7983
}
8084

8185
if len(images) == 0 {
82-
klog.Warningf("[%s] getImagesFromCurrentWorkload undefined or invalid annotation key=%s\n", c.resource, key)
86+
c.logger.Warningf("[%s] getImagesFromCurrentWorkload undefined or invalid annotation key=%s\n", c.resource, key)
8387
}
8488

8589
return
@@ -112,7 +116,7 @@ func (c *Controller) registImage(image Image) {
112116
c.syncedImagesMutex.Unlock()
113117
return
114118
} else {
115-
klog.V(2).Infof("[%s] registImage image=%+v\n", c.resource, image)
119+
c.logger.Infof("[%s] registImage image=%+v\n", c.resource, image)
116120
c.syncedImages[image] = true
117121
c.syncedImagesMutex.Unlock()
118122
}
@@ -127,7 +131,7 @@ func (c *Controller) unregistImage(image Image) {
127131
return
128132
}
129133

130-
klog.V(2).Infof("[%s] unregistImage image=%+v\n", c.resource, image)
134+
c.logger.Infof("[%s] unregistImage image=%+v\n", c.resource, image)
131135

132136
c.syncedImagesMutex.Lock()
133137
delete(c.syncedImages, image)

imageNotifier/imageNotifier.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import (
55
"time"
66

77
"github.com/pubg/kube-image-deployer/interfaces"
8+
l "github.com/pubg/kube-image-deployer/logger"
89
"k8s.io/apimachinery/pkg/util/wait"
9-
"k8s.io/klog/v2"
1010
)
1111

1212
type ImageNotifierId struct {
@@ -22,19 +22,26 @@ type ImageNotifier struct {
2222
stopCh chan struct{}
2323

2424
remoteRegistry interfaces.IRemoteRegistry
25+
logger interfaces.ILogger
2526
}
2627

2728
func NewImageNotifier(stopCh chan struct{}, remoteRegistry interfaces.IRemoteRegistry, imageCheckIntervalSec uint) *ImageNotifier {
28-
imageNotifier := &ImageNotifier{
29+
r := &ImageNotifier{
2930
list: make(map[ImageNotifierId]*ImageUpdateNotify),
3031
mutex: sync.RWMutex{},
3132
stopCh: stopCh,
3233
remoteRegistry: remoteRegistry,
34+
logger: l.NewLogger(),
3335
}
3436

35-
go wait.Until(imageNotifier.checkAllImageNotifyList, time.Second*time.Duration(imageCheckIntervalSec), stopCh)
37+
go wait.Until(r.checkAllImageNotifyList, time.Second*time.Duration(imageCheckIntervalSec), stopCh)
3638

37-
return imageNotifier
39+
return r
40+
}
41+
42+
func (r *ImageNotifier) WithLogger(logger interfaces.ILogger) *ImageNotifier {
43+
r.logger = logger
44+
return r
3845
}
3946

4047
// RegistImage regist to imageNotifier
@@ -53,7 +60,7 @@ func (r *ImageNotifier) RegistImage(controller interfaces.IController, url, tag,
5360
}
5461

5562
// 신규
56-
klog.Infof("[%s] RegistImage %s:%s\n", controller.GetReresourceName(), url, tag)
63+
r.logger.Infof("[%s] RegistImage %s:%s\n", controller.GetReresourceName(), url, tag)
5764

5865
imageUpdateNotify := NewImageUpdateNotify(url, tag, "", controller)
5966

@@ -71,23 +78,23 @@ func (r *ImageNotifier) UnregistImage(controller interfaces.IController, url, ta
7178
existsImageUpdateNotify, ok := r.list[notifyId]
7279

7380
if !ok { // ??
74-
klog.Errorf("[%s] UnregistImage existsImageUpdateNotify notfound url=%s, tag=%s", controller.GetReresourceName(), url, tag)
81+
r.logger.Errorf("[%s] UnregistImage existsImageUpdateNotify notfound url=%s, tag=%s", controller.GetReresourceName(), url, tag)
7582
return
7683
}
7784

7885
referenceCount := existsImageUpdateNotify.subReferenceCount()
7986

8087
if referenceCount <= 0 { // 이미지를 참조하는 대상이 더이상 없으면 삭제
8188
delete(r.list, notifyId)
82-
klog.Infof("[%s] UnregistImage %s:%s\n", controller.GetReresourceName(), url, tag)
89+
r.logger.Infof("[%s] UnregistImage %s:%s\n", controller.GetReresourceName(), url, tag)
8390
}
8491

8592
}
8693

8794
func (r *ImageNotifier) checkImageUpdate(image checkImage) {
8895
imageString, err := r.remoteRegistry.GetImageString(image.url, image.tag, "")
8996
if err != nil {
90-
klog.Errorf("[%s] checkImageUpdate %s:%s err=%s\n", image.controller.GetReresourceName(), image.url, image.tag, err)
97+
r.logger.Errorf("[%s] checkImageUpdate %s:%s err=%s\n", image.controller.GetReresourceName(), image.url, image.tag, err)
9198
return
9299
}
93100

interfaces/interfaces.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,9 @@ type IImageNotifier interface {
1414
type IRemoteRegistry interface {
1515
GetImageString(url, tag, platformString string) (string, error)
1616
}
17+
18+
type ILogger interface {
19+
Infof(format string, args ...interface{})
20+
Errorf(format string, args ...interface{})
21+
Warningf(format string, args ...interface{})
22+
}

logger/logger.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package logger
2+
3+
import (
4+
"fmt"
5+
6+
"k8s.io/klog"
7+
)
8+
9+
type Logger struct {
10+
slack *Slack
11+
depth int
12+
}
13+
14+
func NewLogger() *Logger {
15+
return &Logger{
16+
depth: 1,
17+
slack: nil, // default=disabled
18+
}
19+
}
20+
21+
func (l *Logger) SetDepth(depth int) *Logger {
22+
l.depth = depth
23+
return l
24+
}
25+
26+
func (l *Logger) WithSlack(stopCh chan struct{}, webhookUrl, msgPrefix string) *Logger {
27+
l.slack = NewSlack(stopCh, webhookUrl, msgPrefix)
28+
return l
29+
}
30+
31+
func (l *Logger) Infof(format string, args ...interface{}) {
32+
if !klog.V(2) {
33+
return
34+
}
35+
msg := fmt.Sprintf(format, args...)
36+
klog.InfoDepth(l.depth, msg)
37+
if l.slack != nil {
38+
l.slack.InfoDepth(l.depth+1, msg)
39+
}
40+
}
41+
42+
func (l *Logger) Errorf(format string, args ...interface{}) {
43+
msg := fmt.Sprintf(format, args...)
44+
klog.ErrorDepth(l.depth, msg)
45+
if l.slack != nil {
46+
l.slack.ErrorDepth(l.depth+1, msg)
47+
}
48+
}
49+
50+
func (l *Logger) Warningf(format string, args ...interface{}) {
51+
msg := fmt.Sprintf(format, args...)
52+
klog.WarningDepth(l.depth, msg)
53+
if l.slack != nil {
54+
l.slack.WarningDepth(l.depth+1, msg)
55+
}
56+
}

0 commit comments

Comments
 (0)