From 21fd92e3e429b3207bf6f9109d2b62b886affbdd Mon Sep 17 00:00:00 2001 From: Vishal Choudhary Date: Wed, 9 Oct 2024 16:13:59 +0530 Subject: [PATCH] feat: add --backgroundReports flag to disable mutateexisting and generate reporting (#11361) Signed-off-by: Vishal Choudhary --- charts/kyverno/README.md | 1 + charts/kyverno/templates/_helpers.tpl | 5 ++- .../background-controller/deployment.yaml | 1 + charts/kyverno/values.yaml | 3 ++ cmd/background-controller/main.go | 5 +++ config/install-latest-testing.yaml | 1 + pkg/background/generate/controller.go | 37 ++++++++++-------- pkg/background/mutate/mutate.go | 35 +++++++++-------- pkg/background/update_request_controller.go | 39 ++++++++++--------- 9 files changed, 75 insertions(+), 52 deletions(-) diff --git a/charts/kyverno/README.md b/charts/kyverno/README.md index 526d733fd3..59cc7c4444 100644 --- a/charts/kyverno/README.md +++ b/charts/kyverno/README.md @@ -327,6 +327,7 @@ The chart values are organised per component. | features.aggregateReports.enabled | bool | `true` | Enables the feature | | features.policyReports.enabled | bool | `true` | Enables the feature | | features.validatingAdmissionPolicyReports.enabled | bool | `false` | Enables the feature | +| features.backgroundReports.enabled | bool | `true` | Enables the feature | | features.autoUpdateWebhooks.enabled | bool | `true` | Enables the feature | | features.backgroundScan.enabled | bool | `true` | Enables the feature | | features.backgroundScan.backgroundScanWorkers | int | `2` | Number of background scan workers | diff --git a/charts/kyverno/templates/_helpers.tpl b/charts/kyverno/templates/_helpers.tpl index 8461348dd9..76c8fc22b9 100644 --- a/charts/kyverno/templates/_helpers.tpl +++ b/charts/kyverno/templates/_helpers.tpl @@ -25,6 +25,9 @@ {{- with .validatingAdmissionPolicyReports -}} {{- $flags = append $flags (print "--validatingAdmissionPolicyReports=" .enabled) -}} {{- end -}} +{{- with .backgroundReports -}} + {{- $flags = append $flags (print "--backgroundReports=" .enabled) -}} +{{- end -}} {{- with .autoUpdateWebhooks -}} {{- $flags = append $flags (print "--autoUpdateWebhooks=" .enabled) -}} {{- end -}} @@ -97,4 +100,4 @@ {{- with $flags -}} {{- toYaml . -}} {{- end -}} -{{- end -}} \ No newline at end of file +{{- end -}} diff --git a/charts/kyverno/templates/background-controller/deployment.yaml b/charts/kyverno/templates/background-controller/deployment.yaml index a532d3f846..8a4355b7b6 100644 --- a/charts/kyverno/templates/background-controller/deployment.yaml +++ b/charts/kyverno/templates/background-controller/deployment.yaml @@ -119,6 +119,7 @@ spec: - --imagePullSecrets={{- join "," (concat (keys .Values.imagePullSecrets) .Values.existingImagePullSecrets) }} {{- end }} {{- include "kyverno.features.flags" (pick (mergeOverwrite .Values.features .Values.backgroundController.featuresOverride) + "backgroundReports" "configMapCaching" "deferredLoading" "globalContext" diff --git a/charts/kyverno/values.yaml b/charts/kyverno/values.yaml index 106585a1e6..545e517e03 100644 --- a/charts/kyverno/values.yaml +++ b/charts/kyverno/values.yaml @@ -636,6 +636,9 @@ features: validatingAdmissionPolicyReports: # -- Enables the feature enabled: false + backgroundReports: + # -- Enables the feature + enabled: true autoUpdateWebhooks: # -- Enables the feature enabled: true diff --git a/cmd/background-controller/main.go b/cmd/background-controller/main.go index 6e27e16e83..e1ed7c5b17 100644 --- a/cmd/background-controller/main.go +++ b/cmd/background-controller/main.go @@ -55,6 +55,7 @@ func createrLeaderControllers( jp jmespath.Interface, backgroundScanInterval time.Duration, urGenerator generator.UpdateRequestGenerator, + backgroundReports bool, reportsBreaker breaker.Breaker, ) ([]internal.Controller, error) { policyCtrl, err := policy.NewPolicyController( @@ -87,6 +88,7 @@ func createrLeaderControllers( eventGenerator, configuration, jp, + backgroundReports, reportsBreaker, ) return []internal.Controller{ @@ -101,6 +103,7 @@ func main() { maxQueuedEvents int omitEvents string maxAPICallResponseLength int64 + backgroundReports bool maxBackgroundReports int ) flagset := flag.NewFlagSet("updaterequest-controller", flag.ExitOnError) @@ -108,6 +111,7 @@ func main() { flagset.IntVar(&maxQueuedEvents, "maxQueuedEvents", 1000, "Maximum events to be queued.") flagset.StringVar(&omitEvents, "omitEvents", "", "Set this flag to a comma sperated list of PolicyViolation, PolicyApplied, PolicyError, PolicySkipped to disable events, e.g. --omitEvents=PolicyApplied,PolicyViolation") flagset.Int64Var(&maxAPICallResponseLength, "maxAPICallResponseLength", 2*1000*1000, "Maximum allowed response size from API Calls. A value of 0 bypasses checks (not recommended).") + flagset.BoolVar(&backgroundReports, "backgroundReports", true, "Enables or disables reports for mutate existing and generate rules.") flagset.IntVar(&maxBackgroundReports, "maxBackgroundReports", 10000, "Maximum number of background reports before we stop creating new ones") // config appConfig := internal.NewConfiguration( @@ -247,6 +251,7 @@ func main() { setup.Jp, bgscanInterval, urGenerator, + backgroundReports, reportsBreaker, ) if err != nil { diff --git a/config/install-latest-testing.yaml b/config/install-latest-testing.yaml index 6a94ef434e..008bf56185 100644 --- a/config/install-latest-testing.yaml +++ b/config/install-latest-testing.yaml @@ -50881,6 +50881,7 @@ spec: - --disableMetrics=false - --otelConfig=prometheus - --metricsPort=8000 + - --backgroundReports=true - --enableConfigMapCaching=true - --enableDeferredLoading=true - --maxAPICallResponseLength=2000000 diff --git a/pkg/background/generate/controller.go b/pkg/background/generate/controller.go index b767130e40..0012674344 100644 --- a/pkg/background/generate/controller.go +++ b/pkg/background/generate/controller.go @@ -58,7 +58,8 @@ type GenerateController struct { log logr.Logger jp jmespath.Interface - reportsBreaker breaker.Breaker + backgroundReports bool + reportsBreaker breaker.Breaker } // NewGenerateController returns an instance of the Generate-Request Controller @@ -75,22 +76,24 @@ func NewGenerateController( eventGen event.Interface, log logr.Logger, jp jmespath.Interface, + backgroundReports bool, reportsBreaker breaker.Breaker, ) *GenerateController { c := GenerateController{ - client: client, - kyvernoClient: kyvernoClient, - statusControl: statusControl, - engine: engine, - policyLister: policyLister, - npolicyLister: npolicyLister, - urLister: urLister, - nsLister: nsLister, - configuration: dynamicConfig, - eventGen: eventGen, - log: log, - jp: jp, - reportsBreaker: reportsBreaker, + client: client, + kyvernoClient: kyvernoClient, + statusControl: statusControl, + engine: engine, + policyLister: policyLister, + npolicyLister: npolicyLister, + urLister: urLister, + nsLister: nsLister, + configuration: dynamicConfig, + eventGen: eventGen, + log: log, + jp: jp, + backgroundReports: backgroundReports, + reportsBreaker: reportsBreaker, } return &c } @@ -233,7 +236,7 @@ func (c *GenerateController) applyGenerate(trigger unstructured.Unstructured, ur logger.V(4).Info(doesNotApply) return nil, errors.New(doesNotApply) } - if c.needsReports(trigger) { + if c.needsReports(trigger, c.backgroundReports) { if err := c.createReports(context.TODO(), policyContext.NewResource(), engineResponse); err != nil { c.log.Error(err, "failed to create report") } @@ -370,8 +373,8 @@ func (c *GenerateController) GetUnstrResource(genResourceSpec kyvernov1.Resource return resource, nil } -func (c *GenerateController) needsReports(trigger unstructured.Unstructured) bool { - createReport := true +func (c *GenerateController) needsReports(trigger unstructured.Unstructured, backgroundReports bool) bool { + createReport := backgroundReports // check if the resource supports reporting if !reportutils.IsGvkSupported(trigger.GroupVersionKind()) { createReport = false diff --git a/pkg/background/mutate/mutate.go b/pkg/background/mutate/mutate.go index fd7c9b2099..a6ec5d864f 100644 --- a/pkg/background/mutate/mutate.go +++ b/pkg/background/mutate/mutate.go @@ -47,7 +47,8 @@ type mutateExistingController struct { log logr.Logger jp jmespath.Interface - reportsBreaker breaker.Breaker + backgroundReports bool + reportsBreaker breaker.Breaker } // NewMutateExistingController returns an instance of the MutateExistingController @@ -63,21 +64,23 @@ func NewMutateExistingController( eventGen event.Interface, log logr.Logger, jp jmespath.Interface, + backgroundReports bool, reportsBreaker breaker.Breaker, ) *mutateExistingController { c := mutateExistingController{ - client: client, - kyvernoClient: kyvernoClient, - statusControl: statusControl, - engine: engine, - policyLister: policyLister, - npolicyLister: npolicyLister, - nsLister: nsLister, - configuration: dynamicConfig, - eventGen: eventGen, - log: log, - jp: jp, - reportsBreaker: reportsBreaker, + client: client, + kyvernoClient: kyvernoClient, + statusControl: statusControl, + engine: engine, + policyLister: policyLister, + npolicyLister: npolicyLister, + nsLister: nsLister, + configuration: dynamicConfig, + eventGen: eventGen, + log: log, + jp: jp, + backgroundReports: backgroundReports, + reportsBreaker: reportsBreaker, } return &c } @@ -164,7 +167,7 @@ func (c *mutateExistingController) ProcessUR(ur *kyvernov2.UpdateRequest) error } er := c.engine.Mutate(context.TODO(), policyContext) - if c.needsReports(trigger) { + if c.needsReports(trigger, c.backgroundReports) { if err := c.createReports(context.TODO(), policyContext.NewResource(), er); err != nil { c.log.Error(err, "failed to create report") } @@ -255,8 +258,8 @@ func (c *mutateExistingController) report(err error, policy kyvernov1.PolicyInte c.eventGen.Add(events...) } -func (c *mutateExistingController) needsReports(trigger *unstructured.Unstructured) bool { - createReport := true +func (c *mutateExistingController) needsReports(trigger *unstructured.Unstructured, backgroundReports bool) bool { + createReport := backgroundReports if trigger == nil { return createReport } diff --git a/pkg/background/update_request_controller.go b/pkg/background/update_request_controller.go index 8c4d2880f9..d4d10f87bc 100644 --- a/pkg/background/update_request_controller.go +++ b/pkg/background/update_request_controller.go @@ -58,10 +58,11 @@ type controller struct { // queue queue workqueue.TypedRateLimitingInterface[any] - eventGen event.Interface - configuration config.Configuration - jp jmespath.Interface - reportsBreaker breaker.Breaker + eventGen event.Interface + configuration config.Configuration + jp jmespath.Interface + backgroundReports bool + reportsBreaker breaker.Breaker } // NewController returns an instance of the Generate-Request Controller @@ -76,22 +77,24 @@ func NewController( eventGen event.Interface, configuration config.Configuration, jp jmespath.Interface, + backgroundReports bool, reportsBreaker breaker.Breaker, ) Controller { urLister := urInformer.Lister().UpdateRequests(config.KyvernoNamespace()) c := controller{ - client: client, - kyvernoClient: kyvernoClient, - engine: engine, - cpolLister: cpolInformer.Lister(), - polLister: polInformer.Lister(), - urLister: urLister, - nsLister: namespaceInformer.Lister(), - queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultTypedControllerRateLimiter[any](), "background"), - eventGen: eventGen, - configuration: configuration, - jp: jp, - reportsBreaker: reportsBreaker, + client: client, + kyvernoClient: kyvernoClient, + engine: engine, + cpolLister: cpolInformer.Lister(), + polLister: polInformer.Lister(), + urLister: urLister, + nsLister: namespaceInformer.Lister(), + queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultTypedControllerRateLimiter[any](), "background"), + eventGen: eventGen, + configuration: configuration, + jp: jp, + backgroundReports: backgroundReports, + reportsBreaker: reportsBreaker, } _, _ = urInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: c.addUR, @@ -224,10 +227,10 @@ func (c *controller) processUR(ur *kyvernov2.UpdateRequest) error { statusControl := common.NewStatusControl(c.kyvernoClient, c.urLister) switch ur.Spec.GetRequestType() { case kyvernov2.Mutate: - ctrl := mutate.NewMutateExistingController(c.client, c.kyvernoClient, statusControl, c.engine, c.cpolLister, c.polLister, c.nsLister, c.configuration, c.eventGen, logger, c.jp, c.reportsBreaker) + ctrl := mutate.NewMutateExistingController(c.client, c.kyvernoClient, statusControl, c.engine, c.cpolLister, c.polLister, c.nsLister, c.configuration, c.eventGen, logger, c.jp, c.backgroundReports, c.reportsBreaker) return ctrl.ProcessUR(ur) case kyvernov2.Generate: - ctrl := generate.NewGenerateController(c.client, c.kyvernoClient, statusControl, c.engine, c.cpolLister, c.polLister, c.urLister, c.nsLister, c.configuration, c.eventGen, logger, c.jp, c.reportsBreaker) + ctrl := generate.NewGenerateController(c.client, c.kyvernoClient, statusControl, c.engine, c.cpolLister, c.polLister, c.urLister, c.nsLister, c.configuration, c.eventGen, logger, c.jp, c.backgroundReports, c.reportsBreaker) return ctrl.ProcessUR(ur) } return nil