2019-05-10 00:05:21 -07:00
package event
import (
2022-10-03 11:19:01 +02:00
"context"
2023-03-17 11:48:48 +01:00
"sync"
2020-12-23 17:48:00 -08:00
2020-07-20 08:00:02 -07:00
"github.com/go-logr/logr"
2023-12-22 11:47:22 +01:00
"github.com/kyverno/kyverno/pkg/client/clientset/versioned/scheme"
2022-08-31 14:03:47 +08:00
"github.com/kyverno/kyverno/pkg/clients/dclient"
2022-05-17 16:14:31 +02:00
corev1 "k8s.io/api/core/v1"
2019-05-10 00:05:21 -07:00
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
2023-12-22 11:47:22 +01:00
"k8s.io/apimachinery/pkg/util/sets"
2023-07-26 17:06:51 +03:00
"k8s.io/client-go/tools/events"
2023-12-22 11:47:22 +01:00
"k8s.io/klog/v2"
2019-05-10 00:05:21 -07:00
)
2023-01-26 22:19:02 +01:00
const (
2023-12-22 11:47:22 +01:00
Workers = 3
CleanupWorkers = 3
2023-01-26 22:19:02 +01:00
eventWorkQueueName = "kyverno-events"
workQueueRetryLimit = 3
)
// generator generate events
type generator struct {
2023-12-22 11:47:22 +01:00
// broadcaster
broadcaster events . EventBroadcaster
2022-04-25 20:20:40 +08:00
2023-12-22 11:47:22 +01:00
// recorders
recorders map [ Source ] events . EventRecorder
2022-07-21 00:52:15 +08:00
2023-12-22 11:47:22 +01:00
// config
omitEvents sets . Set [ string ]
logger logr . Logger
}
2023-05-10 17:18:41 +05:30
2023-12-22 11:47:22 +01:00
// Interface to generate event
type Interface interface {
Add ( infoList ... Info )
2019-05-10 00:05:21 -07:00
}
2023-01-26 22:19:02 +01:00
// Controller interface to generate event
type Controller interface {
Interface
2023-03-17 11:48:48 +01:00
Run ( context . Context , int , * sync . WaitGroup )
2023-01-26 22:19:02 +01:00
}
2022-08-24 15:08:24 +02:00
// NewEventGenerator to generate a new event controller
2023-12-22 11:47:22 +01:00
func NewEventGenerator ( client dclient . Interface , logger logr . Logger , omitEvents ... string ) Controller {
return & generator {
broadcaster : events . NewBroadcaster ( & events . EventSinkImpl {
Interface : client . GetEventsInterface ( ) ,
} ) ,
omitEvents : sets . New ( omitEvents ... ) ,
logger : logger ,
2019-12-26 11:50:41 -08:00
}
2023-07-18 13:01:09 +03:00
}
2022-05-17 08:19:03 +02:00
// Add queues an event for generation
2023-01-26 22:19:02 +01:00
func ( gen * generator ) Add ( infos ... Info ) {
2023-12-22 11:47:22 +01:00
logger := gen . logger
2023-01-07 15:14:51 -08:00
logger . V ( 3 ) . Info ( "generating events" , "count" , len ( infos ) )
2019-06-27 11:43:07 -07:00
for _ , info := range infos {
2023-12-22 11:47:22 +01:00
// don't create event for resources with generateName as the name is not generated yet
if info . Regarding . Name == "" {
logger . V ( 3 ) . Info ( "skipping event creation for resource without a name" , "kind" , info . Regarding . Kind , "name" , info . Regarding . Name , "namespace" , info . Regarding . Namespace )
2019-09-04 15:30:09 -07:00
continue
}
2023-12-22 11:47:22 +01:00
if gen . omitEvents . Has ( string ( info . Reason ) ) {
logger . V ( 6 ) . Info ( "omitting event" , "kind" , info . Regarding . Kind , "name" , info . Regarding . Name , "namespace" , info . Regarding . Namespace , "reason" , info . Reason )
continue
2023-05-10 17:18:41 +05:30
}
2023-12-22 11:47:22 +01:00
gen . emitEvent ( info )
logger . V ( 6 ) . Info ( "creating event" , "kind" , info . Regarding . Kind , "name" , info . Regarding . Name , "namespace" , info . Regarding . Namespace , "reason" , info . Reason )
2019-06-26 18:04:50 -07:00
}
2019-05-10 00:05:21 -07:00
}
2019-08-09 13:41:56 -07:00
// Run begins generator
2023-03-17 11:48:48 +01:00
func ( gen * generator ) Run ( ctx context . Context , workers int , waitGroup * sync . WaitGroup ) {
2023-12-22 11:47:22 +01:00
logger := gen . logger
2020-03-17 11:05:20 -07:00
logger . Info ( "start" )
2023-12-22 11:47:22 +01:00
defer logger . Info ( "terminated" )
2023-03-17 11:48:48 +01:00
defer utilruntime . HandleCrash ( )
2023-12-22 11:47:22 +01:00
defer gen . stopRecorders ( )
defer logger . Info ( "shutting down..." )
if err := gen . startRecorders ( ctx ) ; err != nil {
logger . Error ( err , "failed to start recorders" )
return
2019-05-10 00:05:21 -07:00
}
2022-10-03 11:19:01 +02:00
<- ctx . Done ( )
2019-05-15 07:30:22 -07:00
}
2019-07-19 16:17:10 -07:00
2023-12-22 11:47:22 +01:00
func ( gen * generator ) startRecorders ( ctx context . Context ) error {
if err := gen . broadcaster . StartRecordingToSinkWithContext ( ctx ) ; err != nil {
return err
2019-05-10 00:05:21 -07:00
}
2023-12-22 11:47:22 +01:00
logger := klog . Background ( ) . V ( int ( 0 ) )
// TODO: logger watcher should be stopped
if _ , err := gen . broadcaster . StartLogging ( logger ) ; err != nil {
return err
2019-07-19 16:17:10 -07:00
}
2023-12-22 11:47:22 +01:00
gen . recorders = map [ Source ] events . EventRecorder {
PolicyController : gen . broadcaster . NewRecorder ( scheme . Scheme , string ( PolicyController ) ) ,
AdmissionController : gen . broadcaster . NewRecorder ( scheme . Scheme , string ( AdmissionController ) ) ,
GeneratePolicyController : gen . broadcaster . NewRecorder ( scheme . Scheme , string ( GeneratePolicyController ) ) ,
MutateExistingController : gen . broadcaster . NewRecorder ( scheme . Scheme , string ( MutateExistingController ) ) ,
CleanupController : gen . broadcaster . NewRecorder ( scheme . Scheme , string ( CleanupController ) ) ,
2020-11-03 16:07:02 -08:00
}
2023-12-22 11:47:22 +01:00
return nil
2019-07-19 16:17:10 -07:00
}
2023-12-22 11:47:22 +01:00
func ( gen * generator ) stopRecorders ( ) {
gen . broadcaster . Shutdown ( )
2019-05-10 00:05:21 -07:00
}
2023-12-22 11:47:22 +01:00
func ( gen * generator ) emitEvent ( key Info ) {
logger := gen . logger
2022-05-17 16:14:31 +02:00
eventType := corev1 . EventTypeWarning
2023-01-26 22:19:02 +01:00
if key . Reason == PolicyApplied || key . Reason == PolicySkipped {
2022-05-17 16:14:31 +02:00
eventType = corev1 . EventTypeNormal
2021-06-30 00:43:11 +03:00
}
2023-12-22 11:47:22 +01:00
if recorder := gen . recorders [ key . Source ] ; recorder != nil {
logger . V ( 3 ) . Info ( "creating the event" , "source" , key . Source , "type" , eventType , "resource" , key . Resource ( ) )
recorder . Eventf ( & key . Regarding , key . Related , eventType , string ( key . Reason ) , string ( key . Action ) , key . Message )
} else {
2020-03-17 11:05:20 -07:00
logger . Info ( "info.source not defined for the request" )
2019-05-10 00:05:21 -07:00
}
}