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-11-21 10:01:51 +00:00
"github.com/kyverno/kyverno/pkg/engine/apicall"
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"
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 ,
configuration config . Configuration ,
metricsConfig metrics . MetricsConfigManager ,
eventGenerator event . Interface ,
2023-04-13 11:29:40 +00:00
jp jmespath . Interface ,
2023-06-13 12:21:40 +00:00
backgroundScanInterval time . Duration ,
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" ) ,
2023-06-13 12:21:40 +00:00
backgroundScanInterval ,
2023-01-20 15:53:27 +00:00
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-11-21 10:01:51 +00:00
genWorkers int
maxQueuedEvents int
omitEvents string
maxAPICallResponseLength int64
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-11-21 10:01:51 +00:00
flagset . Int64Var ( & maxAPICallResponseLength , "maxAPICallResponseLength" , 2 * 1000 * 1000 , "Maximum allowed response size from API Calls. A value of 0 bypasses checks (not recommended)." )
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-06-27 05:44:15 +00:00
internal . WithDeferredLoading ( ) ,
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 ( ) ,
2024-01-03 01:12:05 +00:00
internal . WithEventsClient ( ) ,
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 ( )
2023-06-13 12:21:40 +00:00
var err error
bgscanInterval := time . Hour
val := os . Getenv ( "BACKGROUND_SCAN_INTERVAL" )
if val != "" {
if bgscanInterval , err = time . ParseDuration ( val ) ; err != nil {
setup . Logger . Error ( err , "failed to set the background scan interval" )
os . Exit ( 1 )
}
}
setup . Logger . V ( 2 ) . Info ( "setting the background scan interval" , "value" , bgscanInterval . String ( ) )
2023-01-20 15:53:27 +00:00
// 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 )
2024-01-30 22:08:15 +00:00
omitEventsValues := strings . Split ( omitEvents , "," )
2023-05-10 11:48:41 +00:00
if omitEvents == "" {
2024-01-30 22:08:15 +00:00
omitEventsValues = [ ] string { }
2023-05-10 11:48:41 +00:00
}
2024-01-30 22:08:15 +00:00
var wg sync . WaitGroup
2023-01-20 15:53:27 +00:00
eventGenerator := event . NewEventGenerator (
2024-01-03 01:12:05 +00:00
setup . EventsClient ,
2023-01-20 15:53:27 +00:00
logging . WithName ( "EventGenerator" ) ,
2024-01-30 22:08:15 +00:00
omitEventsValues ... ,
)
eventController := internal . NewController (
event . ControllerName ,
eventGenerator ,
event . Workers ,
2023-01-20 15:53:27 +00:00
)
// this controller only subscribe to events, nothing is returned...
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-08-06 19:54:52 +00:00
setup . ImageVerifyCacheClient ,
2023-04-11 12:05:20 +00:00
setup . KubeClient ,
2023-04-14 09:00:52 +00:00
setup . KyvernoClient ,
2023-06-16 13:37:08 +00:00
setup . RegistrySecretLister ,
2023-11-21 10:01:51 +00:00
apicall . NewAPICallConfiguration ( maxAPICallResponseLength ) ,
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 )
}
// 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 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-06-13 12:21:40 +00:00
bgscanInterval ,
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 )
}
2024-01-30 22:08:15 +00:00
// start non leader controllers
eventController . Run ( signalCtx , setup . Logger , & wg )
2023-01-20 15:53:27 +00:00
// start leader election
2023-04-03 15:17:44 +00:00
le . Run ( signalCtx )
2024-01-30 22:08:15 +00:00
// wait for everything to shut down and exit
2023-04-03 15:17:44 +00:00
wg . Wait ( )
2023-01-20 15:53:27 +00:00
}