2023-01-20 15:53:27 +00:00
package main
import (
"context"
"errors"
"flag"
"os"
2023-05-10 11:48:41 +00:00
"strings"
2023-01-20 15:53:27 +00:00
"sync"
"time"
"github.com/kyverno/kyverno/cmd/internal"
"github.com/kyverno/kyverno/pkg/background"
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions"
"github.com/kyverno/kyverno/pkg/clients/dclient"
"github.com/kyverno/kyverno/pkg/config"
policymetricscontroller "github.com/kyverno/kyverno/pkg/controllers/metrics/policy"
2023-01-31 07:46:38 +00:00
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
2023-04-13 11:29:40 +00:00
"github.com/kyverno/kyverno/pkg/engine/jmespath"
2023-01-20 15:53:27 +00:00
"github.com/kyverno/kyverno/pkg/event"
"github.com/kyverno/kyverno/pkg/leaderelection"
"github.com/kyverno/kyverno/pkg/logging"
"github.com/kyverno/kyverno/pkg/metrics"
"github.com/kyverno/kyverno/pkg/policy"
"github.com/kyverno/kyverno/pkg/registryclient"
kubeinformers "k8s.io/client-go/informers"
kyamlopenapi "sigs.k8s.io/kustomize/kyaml/openapi"
)
const (
resyncPeriod = 15 * time . Minute
)
func createrLeaderControllers (
2023-02-03 05:01:11 +00:00
eng engineapi . Engine ,
2023-02-07 13:44:51 +00:00
genWorkers int ,
2023-01-20 15:53:27 +00:00
kubeInformer kubeinformers . SharedInformerFactory ,
kyvernoInformer kyvernoinformer . SharedInformerFactory ,
kyvernoClient versioned . Interface ,
dynamicClient dclient . Interface ,
rclient registryclient . Client ,
configuration config . Configuration ,
metricsConfig metrics . MetricsConfigManager ,
eventGenerator event . Interface ,
2023-04-13 11:29:40 +00:00
jp jmespath . Interface ,
2023-01-20 15:53:27 +00:00
) ( [ ] internal . Controller , error ) {
policyCtrl , err := policy . NewPolicyController (
kyvernoClient ,
dynamicClient ,
2023-02-03 05:01:11 +00:00
eng ,
2023-01-20 15:53:27 +00:00
kyvernoInformer . Kyverno ( ) . V1 ( ) . ClusterPolicies ( ) ,
kyvernoInformer . Kyverno ( ) . V1 ( ) . Policies ( ) ,
kyvernoInformer . Kyverno ( ) . V1beta1 ( ) . UpdateRequests ( ) ,
configuration ,
eventGenerator ,
kubeInformer . Core ( ) . V1 ( ) . Namespaces ( ) ,
logging . WithName ( "PolicyController" ) ,
time . Hour ,
metricsConfig ,
2023-04-13 11:29:40 +00:00
jp ,
2023-01-20 15:53:27 +00:00
)
if err != nil {
return nil , err
}
2023-02-07 13:44:51 +00:00
backgroundController := background . NewController (
kyvernoClient ,
dynamicClient ,
eng ,
kyvernoInformer . Kyverno ( ) . V1 ( ) . ClusterPolicies ( ) ,
kyvernoInformer . Kyverno ( ) . V1 ( ) . Policies ( ) ,
kyvernoInformer . Kyverno ( ) . V1beta1 ( ) . UpdateRequests ( ) ,
kubeInformer . Core ( ) . V1 ( ) . Namespaces ( ) ,
eventGenerator ,
configuration ,
2023-04-13 11:29:40 +00:00
jp ,
2023-02-07 13:44:51 +00:00
)
2023-01-20 15:53:27 +00:00
return [ ] internal . Controller {
internal . NewController ( "policy-controller" , policyCtrl , 2 ) ,
2023-02-07 13:44:51 +00:00
internal . NewController ( "background-controller" , backgroundController , genWorkers ) ,
2023-01-20 15:53:27 +00:00
} , err
}
func main ( ) {
var (
2023-04-11 17:44:49 +00:00
genWorkers int
maxQueuedEvents int
2023-05-10 11:48:41 +00:00
omitEvents string
2023-01-20 15:53:27 +00:00
)
flagset := flag . NewFlagSet ( "updaterequest-controller" , flag . ExitOnError )
2023-02-07 13:44:51 +00:00
flagset . IntVar ( & genWorkers , "genWorkers" , 10 , "Workers for the background controller." )
2023-01-20 15:53:27 +00:00
flagset . IntVar ( & maxQueuedEvents , "maxQueuedEvents" , 1000 , "Maximum events to be queued." )
2023-05-10 11:48:41 +00:00
flagset . StringVar ( & omitEvents , "omit-events" , "" , "Set this flag to a comma sperated list of PolicyViolation, PolicyApplied, PolicyError, PolicySkipped to disable events, e.g. --omit-events=PolicyApplied,PolicyViolation" )
2023-01-20 15:53:27 +00:00
// config
appConfig := internal . NewConfiguration (
internal . WithProfiling ( ) ,
internal . WithMetrics ( ) ,
internal . WithTracing ( ) ,
internal . WithKubeconfig ( ) ,
2023-04-11 07:12:05 +00:00
internal . WithPolicyExceptions ( ) ,
internal . WithConfigMapCaching ( ) ,
2023-04-11 13:32:17 +00:00
internal . WithRegistryClient ( ) ,
2023-04-11 17:44:49 +00:00
internal . WithLeaderElection ( ) ,
2023-04-14 09:00:52 +00:00
internal . WithKyvernoClient ( ) ,
internal . WithDynamicClient ( ) ,
internal . WithKyvernoDynamicClient ( ) ,
2023-01-20 15:53:27 +00:00
internal . WithFlagSets ( flagset ) ,
)
// parse flags
internal . ParseFlags ( appConfig )
2023-04-11 13:32:17 +00:00
// setup
signalCtx , setup , sdown := internal . Setup ( appConfig , "kyverno-background-controller" , false )
2023-01-20 15:53:27 +00:00
defer sdown ( )
// THIS IS AN UGLY FIX
// ELSE KYAML IS NOT THREAD SAFE
kyamlopenapi . Schema ( )
// informer factories
2023-04-14 09:00:52 +00:00
kyvernoInformer := kyvernoinformer . NewSharedInformerFactory ( setup . KyvernoClient , resyncPeriod )
2023-05-10 11:48:41 +00:00
emitEventsValues := strings . Split ( omitEvents , "," )
if omitEvents == "" {
emitEventsValues = [ ] string { }
}
2023-01-20 15:53:27 +00:00
eventGenerator := event . NewEventGenerator (
2023-04-14 09:00:52 +00:00
setup . KyvernoDynamicClient ,
2023-01-20 15:53:27 +00:00
kyvernoInformer . Kyverno ( ) . V1 ( ) . ClusterPolicies ( ) ,
kyvernoInformer . Kyverno ( ) . V1 ( ) . Policies ( ) ,
maxQueuedEvents ,
2023-05-10 11:48:41 +00:00
emitEventsValues ,
2023-01-20 15:53:27 +00:00
logging . WithName ( "EventGenerator" ) ,
)
// this controller only subscribe to events, nothing is returned...
2023-03-17 10:48:48 +00:00
var wg sync . WaitGroup
2023-01-20 15:53:27 +00:00
policymetricscontroller . NewController (
2023-04-11 12:05:20 +00:00
setup . MetricsManager ,
2023-01-20 15:53:27 +00:00
kyvernoInformer . Kyverno ( ) . V1 ( ) . ClusterPolicies ( ) ,
kyvernoInformer . Kyverno ( ) . V1 ( ) . Policies ( ) ,
2023-03-17 10:48:48 +00:00
& wg ,
2023-01-20 15:53:27 +00:00
)
2023-04-11 07:12:05 +00:00
engine := internal . NewEngine (
signalCtx ,
2023-04-11 12:05:20 +00:00
setup . Logger ,
setup . Configuration ,
setup . MetricsConfiguration ,
2023-04-13 11:29:40 +00:00
setup . Jp ,
2023-04-14 09:00:52 +00:00
setup . KyvernoDynamicClient ,
2023-04-11 13:32:17 +00:00
setup . RegistryClient ,
2023-04-11 12:05:20 +00:00
setup . KubeClient ,
2023-04-14 09:00:52 +00:00
setup . KyvernoClient ,
2023-02-03 05:01:11 +00:00
)
2023-01-20 15:53:27 +00:00
// start informers and wait for cache sync
2023-04-11 13:32:17 +00:00
if ! internal . StartInformersAndWaitForCacheSync ( signalCtx , setup . Logger , kyvernoInformer ) {
2023-04-11 12:05:20 +00:00
setup . Logger . Error ( errors . New ( "failed to wait for cache sync" ) , "failed to wait for cache sync" )
2023-01-20 15:53:27 +00:00
os . Exit ( 1 )
}
// start event generator
2023-03-17 10:48:48 +00:00
go eventGenerator . Run ( signalCtx , 3 , & wg )
2023-01-20 15:53:27 +00:00
// setup leader election
le , err := leaderelection . New (
2023-04-11 12:05:20 +00:00
setup . Logger . WithName ( "leader-election" ) ,
2023-02-07 13:44:51 +00:00
"kyverno-background-controller" ,
2023-01-20 15:53:27 +00:00
config . KyvernoNamespace ( ) ,
2023-04-11 17:44:49 +00:00
setup . LeaderElectionClient ,
2023-01-20 15:53:27 +00:00
config . KyvernoPodName ( ) ,
2023-04-11 17:44:49 +00:00
internal . LeaderElectionRetryPeriod ( ) ,
2023-01-20 15:53:27 +00:00
func ( ctx context . Context ) {
2023-04-11 12:05:20 +00:00
logger := setup . Logger . WithName ( "leader" )
2023-01-20 15:53:27 +00:00
// create leader factories
2023-04-11 12:05:20 +00:00
kubeInformer := kubeinformers . NewSharedInformerFactory ( setup . KubeClient , resyncPeriod )
2023-04-14 09:00:52 +00:00
kyvernoInformer := kyvernoinformer . NewSharedInformerFactory ( setup . KyvernoClient , resyncPeriod )
2023-01-20 15:53:27 +00:00
// create leader controllers
leaderControllers , err := createrLeaderControllers (
2023-02-03 05:01:11 +00:00
engine ,
2023-02-07 13:44:51 +00:00
genWorkers ,
2023-01-20 15:53:27 +00:00
kubeInformer ,
kyvernoInformer ,
2023-04-14 09:00:52 +00:00
setup . KyvernoClient ,
setup . KyvernoDynamicClient ,
2023-04-11 13:32:17 +00:00
setup . RegistryClient ,
2023-04-11 12:05:20 +00:00
setup . Configuration ,
setup . MetricsManager ,
2023-01-20 15:53:27 +00:00
eventGenerator ,
2023-04-13 11:29:40 +00:00
setup . Jp ,
2023-01-20 15:53:27 +00:00
)
if err != nil {
logger . Error ( err , "failed to create leader controllers" )
os . Exit ( 1 )
}
// start informers and wait for cache sync
2023-02-09 15:53:27 +00:00
if ! internal . StartInformersAndWaitForCacheSync ( signalCtx , logger , kyvernoInformer , kubeInformer ) {
2023-01-20 15:53:27 +00:00
logger . Error ( errors . New ( "failed to wait for cache sync" ) , "failed to wait for cache sync" )
os . Exit ( 1 )
}
// start leader controllers
var wg sync . WaitGroup
for _ , controller := range leaderControllers {
controller . Run ( signalCtx , logger . WithName ( "controllers" ) , & wg )
}
// wait all controllers shut down
wg . Wait ( )
} ,
nil ,
)
if err != nil {
2023-04-11 12:05:20 +00:00
setup . Logger . Error ( err , "failed to initialize leader election" )
2023-01-20 15:53:27 +00:00
os . Exit ( 1 )
}
// start leader election
2023-04-03 15:17:44 +00:00
le . Run ( signalCtx )
wg . Wait ( )
2023-01-20 15:53:27 +00:00
}