2019-05-10 00:05:21 -07:00
|
|
|
package event
|
|
|
|
|
|
|
|
import (
|
|
|
|
"time"
|
|
|
|
|
2019-05-30 12:28:56 -07:00
|
|
|
"github.com/golang/glog"
|
2019-05-21 11:00:09 -07:00
|
|
|
"github.com/nirmata/kyverno/pkg/client/clientset/versioned/scheme"
|
|
|
|
policyscheme "github.com/nirmata/kyverno/pkg/client/clientset/versioned/scheme"
|
|
|
|
v1alpha1 "github.com/nirmata/kyverno/pkg/client/listers/policy/v1alpha1"
|
2019-05-29 14:12:09 -07:00
|
|
|
client "github.com/nirmata/kyverno/pkg/dclient"
|
2019-05-21 11:00:09 -07:00
|
|
|
"github.com/nirmata/kyverno/pkg/sharedinformer"
|
2019-05-10 00:05:21 -07:00
|
|
|
v1 "k8s.io/api/core/v1"
|
|
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
|
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
|
|
|
"k8s.io/apimachinery/pkg/util/wait"
|
|
|
|
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
|
|
|
"k8s.io/client-go/tools/record"
|
|
|
|
"k8s.io/client-go/util/workqueue"
|
|
|
|
)
|
|
|
|
|
2019-05-10 10:38:38 -07:00
|
|
|
type controller struct {
|
2019-05-15 07:30:22 -07:00
|
|
|
client *client.Client
|
2019-05-15 12:29:09 -07:00
|
|
|
policyLister v1alpha1.PolicyLister
|
2019-05-10 00:05:21 -07:00
|
|
|
queue workqueue.RateLimitingInterface
|
|
|
|
recorder record.EventRecorder
|
|
|
|
}
|
|
|
|
|
2019-05-10 10:38:38 -07:00
|
|
|
//Generator to generate event
|
|
|
|
type Generator interface {
|
2019-06-27 11:43:07 -07:00
|
|
|
Add(infoList ...*Info)
|
2019-05-10 00:05:21 -07:00
|
|
|
}
|
2019-05-10 10:38:38 -07:00
|
|
|
|
|
|
|
//Controller api
|
|
|
|
type Controller interface {
|
|
|
|
Generator
|
2019-05-14 18:02:11 +03:00
|
|
|
Run(stopCh <-chan struct{})
|
2019-05-15 07:30:22 -07:00
|
|
|
Stop()
|
2019-05-10 00:05:21 -07:00
|
|
|
}
|
|
|
|
|
2019-05-10 10:38:38 -07:00
|
|
|
//NewEventController to generate a new event controller
|
2019-05-15 07:30:22 -07:00
|
|
|
func NewEventController(client *client.Client,
|
2019-05-30 12:28:56 -07:00
|
|
|
shareInformer sharedinformer.PolicyInformer) Controller {
|
2019-05-14 18:02:11 +03:00
|
|
|
|
2019-07-17 17:53:13 -07:00
|
|
|
return &controller{
|
2019-05-15 07:30:22 -07:00
|
|
|
client: client,
|
2019-05-15 12:29:09 -07:00
|
|
|
policyLister: shareInformer.GetLister(),
|
2019-05-10 00:05:21 -07:00
|
|
|
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), eventWorkQueueName),
|
2019-05-15 07:30:22 -07:00
|
|
|
recorder: initRecorder(client),
|
2019-05-10 00:05:21 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-15 07:30:22 -07:00
|
|
|
func initRecorder(client *client.Client) record.EventRecorder {
|
2019-05-10 00:05:21 -07:00
|
|
|
// Initliaze Event Broadcaster
|
2019-05-21 09:27:04 -07:00
|
|
|
err := policyscheme.AddToScheme(scheme.Scheme)
|
|
|
|
if err != nil {
|
2019-06-20 11:20:09 -07:00
|
|
|
glog.Error(err)
|
2019-05-21 09:27:04 -07:00
|
|
|
return nil
|
|
|
|
}
|
2019-05-10 00:05:21 -07:00
|
|
|
eventBroadcaster := record.NewBroadcaster()
|
2019-05-30 12:28:56 -07:00
|
|
|
eventBroadcaster.StartLogging(glog.Infof)
|
2019-05-15 07:30:22 -07:00
|
|
|
eventInterface, err := client.GetEventsInterface()
|
|
|
|
if err != nil {
|
2019-06-20 11:20:09 -07:00
|
|
|
glog.Error(err) // TODO: add more specific error
|
2019-05-15 07:30:22 -07:00
|
|
|
return nil
|
|
|
|
}
|
2019-05-10 00:05:21 -07:00
|
|
|
eventBroadcaster.StartRecordingToSink(
|
|
|
|
&typedcorev1.EventSinkImpl{
|
2019-05-15 07:30:22 -07:00
|
|
|
Interface: eventInterface})
|
2019-05-10 00:05:21 -07:00
|
|
|
recorder := eventBroadcaster.NewRecorder(
|
|
|
|
scheme.Scheme,
|
|
|
|
v1.EventSource{Component: eventSource})
|
|
|
|
return recorder
|
|
|
|
}
|
|
|
|
|
2019-06-27 11:43:07 -07:00
|
|
|
func (c *controller) Add(infos ...*Info) {
|
|
|
|
for _, info := range infos {
|
2019-06-26 18:04:50 -07:00
|
|
|
c.queue.Add(*info)
|
|
|
|
}
|
2019-05-10 00:05:21 -07:00
|
|
|
}
|
|
|
|
|
2019-05-14 18:02:11 +03:00
|
|
|
func (c *controller) Run(stopCh <-chan struct{}) {
|
2019-05-10 00:05:21 -07:00
|
|
|
defer utilruntime.HandleCrash()
|
|
|
|
|
|
|
|
for i := 0; i < eventWorkerThreadCount; i++ {
|
2019-05-10 10:38:38 -07:00
|
|
|
go wait.Until(c.runWorker, time.Second, stopCh)
|
2019-05-10 00:05:21 -07:00
|
|
|
}
|
2019-05-30 12:28:56 -07:00
|
|
|
glog.Info("Started eventbuilder controller workers")
|
2019-05-10 00:05:21 -07:00
|
|
|
}
|
|
|
|
|
2019-05-15 07:30:22 -07:00
|
|
|
func (c *controller) Stop() {
|
2019-06-20 16:50:54 -07:00
|
|
|
defer c.queue.ShutDown()
|
2019-05-30 12:28:56 -07:00
|
|
|
glog.Info("Shutting down eventbuilder controller workers")
|
2019-05-15 07:30:22 -07:00
|
|
|
}
|
2019-07-19 16:17:10 -07:00
|
|
|
|
2019-05-10 10:38:38 -07:00
|
|
|
func (c *controller) runWorker() {
|
|
|
|
for c.processNextWorkItem() {
|
2019-05-10 00:05:21 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-19 16:17:10 -07:00
|
|
|
func (c *controller) handleErr(err error, key interface{}) {
|
|
|
|
if err == nil {
|
|
|
|
c.queue.Forget(key)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
// This controller retries if something goes wrong. After that, it stops trying.
|
2019-07-19 16:18:36 -07:00
|
|
|
if c.queue.NumRequeues(key) < workQueueRetryLimit {
|
2019-07-19 16:17:10 -07:00
|
|
|
glog.Warningf("Error syncing events %v: %v", key, err)
|
|
|
|
// Re-enqueue the key rate limited. Based on the rate limiter on the
|
|
|
|
// queue and the re-enqueue history, the key will be processed later again.
|
|
|
|
c.queue.AddRateLimited(key)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
c.queue.Forget(key)
|
|
|
|
glog.Error(err)
|
|
|
|
glog.Warningf("Dropping the key out of the queue: %v", err)
|
|
|
|
}
|
|
|
|
|
2019-05-10 10:38:38 -07:00
|
|
|
func (c *controller) processNextWorkItem() bool {
|
|
|
|
obj, shutdown := c.queue.Get()
|
2019-05-10 00:05:21 -07:00
|
|
|
if shutdown {
|
|
|
|
return false
|
|
|
|
}
|
2019-07-19 16:17:10 -07:00
|
|
|
|
2019-05-10 00:05:21 -07:00
|
|
|
err := func(obj interface{}) error {
|
2019-05-10 10:38:38 -07:00
|
|
|
defer c.queue.Done(obj)
|
2019-05-10 12:36:55 -07:00
|
|
|
var key Info
|
2019-05-10 00:05:21 -07:00
|
|
|
var ok bool
|
2019-07-19 16:17:10 -07:00
|
|
|
|
2019-05-10 12:36:55 -07:00
|
|
|
if key, ok = obj.(Info); !ok {
|
2019-05-10 10:38:38 -07:00
|
|
|
c.queue.Forget(obj)
|
2019-05-30 12:28:56 -07:00
|
|
|
glog.Warningf("Expecting type info by got %v\n", obj)
|
2019-05-10 00:05:21 -07:00
|
|
|
return nil
|
|
|
|
}
|
2019-07-19 16:17:10 -07:00
|
|
|
err := c.syncHandler(key)
|
|
|
|
c.handleErr(err, obj)
|
2019-05-10 00:05:21 -07:00
|
|
|
return nil
|
|
|
|
}(obj)
|
|
|
|
if err != nil {
|
2019-07-19 16:17:10 -07:00
|
|
|
glog.Error(err)
|
|
|
|
return true
|
2019-05-10 00:05:21 -07:00
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2019-07-19 16:17:10 -07:00
|
|
|
func (c *controller) syncHandler(key Info) error {
|
2019-06-26 12:41:42 -07:00
|
|
|
var robj runtime.Object
|
2019-05-10 00:05:21 -07:00
|
|
|
var err error
|
2019-05-15 07:30:22 -07:00
|
|
|
|
2019-05-10 00:05:21 -07:00
|
|
|
switch key.Kind {
|
|
|
|
case "Policy":
|
2019-05-15 07:30:22 -07:00
|
|
|
//TODO: policy is clustered resource so wont need namespace
|
2019-06-26 15:31:18 -07:00
|
|
|
robj, err = c.policyLister.Get(key.Name)
|
2019-05-10 00:05:21 -07:00
|
|
|
if err != nil {
|
2019-07-08 16:53:34 -07:00
|
|
|
glog.Errorf("Error creating event: unable to get policy %s, will retry ", key.Name)
|
2019-05-10 00:05:21 -07:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
default:
|
2019-07-08 15:34:21 -07:00
|
|
|
robj, err = c.client.GetResource(key.Kind, key.Namespace, key.Name)
|
2019-05-10 00:05:21 -07:00
|
|
|
if err != nil {
|
2019-07-08 18:03:21 -07:00
|
|
|
glog.Errorf("Error creating event: unable to get resource %s, %s, will retry ", key.Kind, key.Namespace+"/"+key.Name)
|
2019-05-10 00:05:21 -07:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2019-07-08 16:53:34 -07:00
|
|
|
|
2019-06-26 12:41:42 -07:00
|
|
|
if key.Reason == PolicyApplied.String() {
|
|
|
|
c.recorder.Event(robj, v1.EventTypeNormal, key.Reason, key.Message)
|
|
|
|
} else {
|
|
|
|
c.recorder.Event(robj, v1.EventTypeWarning, key.Reason, key.Message)
|
|
|
|
}
|
2019-05-10 00:05:21 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-05-10 12:36:55 -07:00
|
|
|
//NewEvent returns a new event
|
2019-06-26 18:16:06 -07:00
|
|
|
func NewEvent(rkind string, rnamespace string, rname string, reason Reason, message MsgKey, args ...interface{}) *Info {
|
2019-06-26 15:31:18 -07:00
|
|
|
msgText, err := getEventMsg(message, args...)
|
2019-05-10 00:05:21 -07:00
|
|
|
if err != nil {
|
2019-06-20 11:20:09 -07:00
|
|
|
glog.Error(err)
|
2019-05-10 00:05:21 -07:00
|
|
|
}
|
2019-06-26 18:04:50 -07:00
|
|
|
return &Info{
|
2019-06-26 12:41:42 -07:00
|
|
|
Kind: rkind,
|
|
|
|
Name: rname,
|
|
|
|
Namespace: rnamespace,
|
|
|
|
Reason: reason.String(),
|
|
|
|
Message: msgText,
|
2019-05-10 00:05:21 -07:00
|
|
|
}
|
|
|
|
}
|