@@ -19,14 +19,14 @@ import (
1919 "context"
2020 "errors"
2121 "fmt"
22+ "reflect"
2223 "strings"
2324 "sync"
2425
2526 "github.com/go-logr/logr"
2627 v1beta1 "github.com/open-policy-agent/frameworks/constraint/pkg/apis/templates/v1beta1"
2728 constraintclient "github.com/open-policy-agent/frameworks/constraint/pkg/client"
2829 "github.com/open-policy-agent/frameworks/constraint/pkg/client/drivers/k8scel/transform"
29- "github.com/open-policy-agent/frameworks/constraint/pkg/core/constraints"
3030 constraintstatusv1beta1 "github.com/open-policy-agent/gatekeeper/v3/apis/status/v1beta1"
3131 "github.com/open-policy-agent/gatekeeper/v3/pkg/controller/config/process"
3232 "github.com/open-policy-agent/gatekeeper/v3/pkg/controller/constraintstatus"
@@ -36,7 +36,7 @@ import (
3636 "github.com/open-policy-agent/gatekeeper/v3/pkg/readiness"
3737 "github.com/open-policy-agent/gatekeeper/v3/pkg/util"
3838 "github.com/open-policy-agent/gatekeeper/v3/pkg/watch"
39- admissionregistrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1 "
39+ admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1 "
4040 corev1 "k8s.io/api/core/v1"
4141 apierrors "k8s.io/apimachinery/pkg/api/errors"
4242 "k8s.io/apimachinery/pkg/api/meta"
@@ -59,6 +59,8 @@ import (
5959
6060var log = logf .Log .WithName ("controller" ).WithValues (logging .Process , "constraint_controller" )
6161
62+ var vapMux sync.RWMutex
63+
6264var VapAPIEnabled * bool
6365
6466var VapEnforcement VapFlagType
@@ -85,6 +87,15 @@ func (v *VapFlagType) Set(value string) error {
8587 return fmt .Errorf ("invalid value %s. Allowed values are %s, %s, %s" , value , VapFlagNone , VapFlagGatekeeperDefault , VapFlagVapDefault )
8688}
8789
90+ // setting defaults when not set; required for unit test
91+ func (v * VapFlagType ) SetDefaultIfEmpty () {
92+ if * v == "" {
93+ * v = VapFlagType (VapFlagGatekeeperDefault )
94+ VapAPIEnabled = new (bool )
95+ * VapAPIEnabled = true
96+ }
97+ }
98+
8899type Adder struct {
89100 CFClient * constraintclient.Client
90101 ConstraintsCache * ConstraintsCache
@@ -145,9 +156,8 @@ type ConstraintsCache struct {
145156}
146157
147158type tags struct {
148- enforcementAction util.EnforcementAction
149- status metrics.Status
150- generateVapBinding bool
159+ enforcementAction util.EnforcementAction
160+ status metrics.Status
151161}
152162
153163// newReconciler returns a new reconcile.Reconciler.
@@ -230,8 +240,7 @@ type ReconcileConstraint struct {
230240 // that would otherwise trigger a watch. The bool returns whether
231241 // the function was executed, which can be used to determine
232242 // whether the reconciler should infer the object has been deleted
233- ifWatching func (schema.GroupVersionKind , func () error ) (bool , error )
234- generateVapBinding bool
243+ ifWatching func (schema.GroupVersionKind , func () error ) (bool , error )
235244}
236245
237246// +kubebuilder:rbac:groups=constraints.gatekeeper.sh,resources=*,verbs=get;list;watch;create;update;patch;delete
@@ -263,6 +272,7 @@ func (r *ReconcileConstraint) Reconcile(ctx context.Context, request reconcile.R
263272 return reconcile.Result {}, nil
264273 }
265274
275+ generateVapBinding := false
266276 deleted := false
267277 instance := & unstructured.Unstructured {}
268278 instance .SetGroupVersionKind (gvk )
@@ -294,7 +304,7 @@ func (r *ReconcileConstraint) Reconcile(ctx context.Context, request reconcile.R
294304 }
295305 // unless constraint vap label is false, default to parent
296306 if useVap == "no" {
297- r . generateVapBinding = false
307+ generateVapBinding = false
298308 } else {
299309 log .Info ("constraint resource use-vap label is not no; will default to parent constraint template label" )
300310 parentCTUseVap , err := r .getCTVapLabel (ctx , instance .GetKind ())
@@ -303,8 +313,8 @@ func (r *ReconcileConstraint) Reconcile(ctx context.Context, request reconcile.R
303313 return reconcile.Result {}, err
304314 }
305315 log .Info ("constraint resource" , "parentCTUseVap" , parentCTUseVap )
306- r . generateVapBinding = ShouldGenerateVap (parentCTUseVap )
307- log .Info ("constraint resource" , "generateVapBinding" , r . generateVapBinding )
316+ generateVapBinding = ShouldGenerateVap (parentCTUseVap )
317+ log .Info ("constraint resource" , "generateVapBinding" , generateVapBinding )
308318 }
309319 constraintKey := strings .Join ([]string {instance .GetKind (), instance .GetName ()}, "/" )
310320 enforcementAction , err := util .GetEnforcementAction (instance .Object )
@@ -329,23 +339,20 @@ func (r *ReconcileConstraint) Reconcile(ctx context.Context, request reconcile.R
329339 status .Status .ConstraintUID = instance .GetUID ()
330340 status .Status .ObservedGeneration = instance .GetGeneration ()
331341 status .Status .Errors = nil
332- cachedTags := r .constraintsCache .getTagsByConstraintKey (constraintKey )
333- cachedGenerateVapBinding := cachedTags .generateVapBinding
334- log .Info ("constraint" , "cachedGenerateVapBinding" , cachedGenerateVapBinding )
335342
336- if c , err := r .cfClient .GetConstraint (instance ); err != nil || ! constraints . SemanticEqual (instance , c ) || r . generateVapBinding != cachedGenerateVapBinding {
343+ if c , err := r .cfClient .GetConstraint (instance ); err != nil || ! reflect . DeepEqual (instance , c ) {
337344 // generate vapbinding resources
338- if r . generateVapBinding && IsVapAPIEnabled () {
339- currentVapBinding := & admissionregistrationv1alpha1 .ValidatingAdmissionPolicyBinding {}
345+ if generateVapBinding && IsVapAPIEnabled () {
346+ currentVapBinding := & admissionregistrationv1beta1 .ValidatingAdmissionPolicyBinding {}
340347 vapBindingName := fmt .Sprintf ("gatekeeper-%s" , instance .GetName ())
341348 log .Info ("check if vapbinding exists" , "vapBindingName" , vapBindingName )
342349 if err := r .reader .Get (ctx , types.NamespacedName {Name : vapBindingName }, currentVapBinding ); err != nil {
343- if ! apierrors .IsNotFound (err ) {
350+ if ! apierrors .IsNotFound (err ) && ! strings . Contains ( err . Error (), "failed to get API group resources" ) {
344351 return reconcile.Result {}, err
345352 }
346353 currentVapBinding = nil
347354 }
348- newVapBinding := & admissionregistrationv1alpha1 .ValidatingAdmissionPolicyBinding {}
355+ newVapBinding := & admissionregistrationv1beta1 .ValidatingAdmissionPolicyBinding {}
349356 transformedVapBinding , err := transform .ConstraintToBinding (instance )
350357 if err != nil {
351358 status .Status .Errors = append (status .Status .Errors , constraintstatusv1beta1.Error {Message : err .Error ()})
@@ -375,18 +382,7 @@ func (r *ReconcileConstraint) Reconcile(ctx context.Context, request reconcile.R
375382 return reconcile.Result {}, err
376383 }
377384 } else {
378- uc , err := runtime .DefaultUnstructuredConverter .ToUnstructured (currentVapBinding )
379- if err != nil {
380- log .Error (err , "error converting to unstructured" )
381- return reconcile.Result {}, err
382- }
383- un , err := runtime .DefaultUnstructuredConverter .ToUnstructured (newVapBinding )
384- if err != nil {
385- log .Error (err , "error converting to unstructured" )
386- return reconcile.Result {}, err
387- }
388-
389- if ! constraints .SemanticEqual (& unstructured.Unstructured {Object : un }, & unstructured.Unstructured {Object : uc }) {
385+ if ! reflect .DeepEqual (currentVapBinding , newVapBinding ) {
390386 log .Info ("updating vapbinding" )
391387 if err := r .writer .Update (ctx , newVapBinding ); err != nil {
392388 status .Status .Errors = append (status .Status .Errors , constraintstatusv1beta1.Error {Message : err .Error ()})
@@ -400,12 +396,12 @@ func (r *ReconcileConstraint) Reconcile(ctx context.Context, request reconcile.R
400396 }
401397 // do not generate vapbinding resources
402398 // remove if exists
403- if ! r . generateVapBinding && r . generateVapBinding != cachedGenerateVapBinding && IsVapAPIEnabled () {
404- currentVapBinding := & admissionregistrationv1alpha1 .ValidatingAdmissionPolicyBinding {}
399+ if ! generateVapBinding && IsVapAPIEnabled () {
400+ currentVapBinding := & admissionregistrationv1beta1 .ValidatingAdmissionPolicyBinding {}
405401 vapBindingName := fmt .Sprintf ("gatekeeper-%s" , instance .GetName ())
406402 log .Info ("check if vapbinding exists" , "vapBindingName" , vapBindingName )
407403 if err := r .reader .Get (ctx , types.NamespacedName {Name : vapBindingName }, currentVapBinding ); err != nil {
408- if ! apierrors .IsNotFound (err ) {
404+ if ! apierrors .IsNotFound (err ) && ! strings . Contains ( err . Error (), "failed to get API group resources" ) {
409405 return reconcile.Result {}, err
410406 }
411407 currentVapBinding = nil
@@ -423,9 +419,8 @@ func (r *ReconcileConstraint) Reconcile(ctx context.Context, request reconcile.R
423419 }
424420 if err := r .cacheConstraint (ctx , instance ); err != nil {
425421 r .constraintsCache .addConstraintKey (constraintKey , tags {
426- enforcementAction : enforcementAction ,
427- status : metrics .ErrorStatus ,
428- generateVapBinding : r .generateVapBinding ,
422+ enforcementAction : enforcementAction ,
423+ status : metrics .ErrorStatus ,
429424 })
430425 status .Status .Errors = append (status .Status .Errors , constraintstatusv1beta1.Error {Message : err .Error ()})
431426 if err2 := r .writer .Update (ctx , status ); err2 != nil {
@@ -444,9 +439,8 @@ func (r *ReconcileConstraint) Reconcile(ctx context.Context, request reconcile.R
444439
445440 // adding constraint to cache and sending metrics
446441 r .constraintsCache .addConstraintKey (constraintKey , tags {
447- enforcementAction : enforcementAction ,
448- status : metrics .ActiveStatus ,
449- generateVapBinding : r .generateVapBinding ,
442+ enforcementAction : enforcementAction ,
443+ status : metrics .ActiveStatus ,
450444 })
451445 reportMetrics = true
452446 } else {
@@ -586,9 +580,8 @@ func (c *ConstraintsCache) addConstraintKey(constraintKey string, t tags) {
586580 defer c .mux .Unlock ()
587581
588582 c .cache [constraintKey ] = tags {
589- enforcementAction : t .enforcementAction ,
590- status : t .status ,
591- generateVapBinding : t .generateVapBinding ,
583+ enforcementAction : t .enforcementAction ,
584+ status : t .status ,
592585 }
593586}
594587
@@ -599,13 +592,6 @@ func (c *ConstraintsCache) deleteConstraintKey(constraintKey string) {
599592 delete (c .cache , constraintKey )
600593}
601594
602- func (c * ConstraintsCache ) getTagsByConstraintKey (constraintKey string ) tags {
603- c .mux .Lock ()
604- defer c .mux .Unlock ()
605-
606- return c .cache [constraintKey ]
607- }
608-
609595func (c * ConstraintsCache ) reportTotalConstraints (ctx context.Context , reporter StatsReporter ) {
610596 c .mux .RLock ()
611597 defer c .mux .RUnlock ()
@@ -640,6 +626,9 @@ func ShouldGenerateVap(useVapLabel string) bool {
640626}
641627
642628func IsVapAPIEnabled () bool {
629+ vapMux .Lock ()
630+ defer vapMux .Unlock ()
631+
643632 if VapAPIEnabled != nil {
644633 return * VapAPIEnabled
645634 }
0 commit comments