Skip to content

Commit

Permalink
change to watching gatekeeper
Browse files Browse the repository at this point in the history
Signed-off-by: Yi Rae Kim <[email protected]>
  • Loading branch information
yiraeChristineKim committed Nov 6, 2023
1 parent de74236 commit 0585b39
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 64 deletions.
52 changes: 4 additions & 48 deletions controllers/constraintstatus_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"sync"
"time"

operatorv1alpha1 "github.com/gatekeeper/gatekeeper-operator/api/v1alpha1"
"github.com/go-logr/logr"
constraintV1 "github.com/open-policy-agent/frameworks/constraint/pkg/apis/templates/v1beta1"
"github.com/open-policy-agent/gatekeeper/v3/apis/config/v1alpha1"
Expand Down Expand Up @@ -91,10 +90,6 @@ func (r *ConstraintStatusReconciler) Reconcile(ctx context.Context,
log := r.Log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
log.Info("Reconciling ConstraintPodStatus and Config")

// check Automatic set in gatekeeper resource
if !r.getAutomaticSet(ctx) {
return reconcile.Result{RequeueAfter: time.Minute * 3}, nil
}
// Get config or create if not exist
config := &v1alpha1.Config{}
err := r.Get(ctx, types.NamespacedName{
Expand Down Expand Up @@ -156,19 +151,19 @@ func (r *ConstraintStatusReconciler) Reconcile(ctx context.Context,
constraint, err := r.DynamicClient.Resource(constraintGVR).Get(ctx, constraintName, metav1.GetOptions{})
if err != nil {
if apierrors.IsNotFound(err) {
r.Log.Info("The Constraint is deleted in the config resouce", constraint.GetName())
r.Log.Info("The Constraint is deleted in the config resouce", "constraintName:", constraint.GetName())

return reconcile.Result{}, nil
return reconcile.Result{}, nil //nolint:nilerr
}

return reconcile.Result{}, err
}

constraintMatchKinds, _, err := unstructured.NestedSlice(constraint.Object, "spec", "match", "kinds")
if err != nil {
r.Log.V(1).Info("There is no provided kinds in contsraint", constraint.GetName())
r.Log.V(1).Info("There is no provided kinds in contsraint", "constraintName:", constraint.GetName())

return reconcile.Result{}, nil
return reconcile.Result{}, nil //nolint:nilerr
}
// remove
constraintSyncOnlyEntries, err := r.getSyncOnlys(constraintMatchKinds)
Expand Down Expand Up @@ -293,45 +288,6 @@ func (r *ConstraintStatusReconciler) refreshDiscoveryInfo() error {
return nil
}

// Check audit.automatic set in gatekeeper resource.
// audit.automatic is false or not set then skip adding constraintpodstatus controller
func (r *ConstraintStatusReconciler) getAutomaticSet(ctx context.Context) bool {
gatekeeper := &operatorv1alpha1.Gatekeeper{}

if err := r.Get(ctx, types.NamespacedName{
Namespace: "",
Name: "gatekeeper",
}, gatekeeper); err != nil {
if apierrors.IsNotFound(err) {
r.Log.V(1).Info("Gatekeeper resource is not found")

return false
}

r.Log.Error(err, "Getting gatekeeper resource has error")

return false
}

audit := gatekeeper.Spec.Audit
if audit == nil {
return false
}

auditFromCache := audit.AuditFromCache
if auditFromCache == nil {
return false
}

if *auditFromCache != operatorv1alpha1.AuditFromCacheAutomatic {
r.Log.V(1).Info("AuditFromCache is not set")

return false
}

return true
}

func (r *ConstraintStatusReconciler) getUniqSyncOnly() []v1alpha1.SyncOnlyEntry {
syncOnlySet := map[v1alpha1.SyncOnlyEntry]bool{}
// Add to table for unique filtering
Expand Down
75 changes: 59 additions & 16 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"fmt"
"os"
"sync"
"time"

// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them.
Expand Down Expand Up @@ -265,33 +266,72 @@ func (c *ConstraintStatusInstaller) setIsInstalled(isInstalled bool) {
}

// Check constraintpodstatuses.status.gatekeeper.sh crd status has "NamesAccepted" condition.
func (c *ConstraintStatusInstaller) isApiAvailable(result watch.Event) bool {
crd, ok := runtime.DefaultUnstructuredConverter.ToUnstructured(result.Object)
func (c *ConstraintStatusInstaller) isApiAvailable(
mainCtx context.Context, result watch.Event, dynamicClient *dynamic.DynamicClient,
) bool {
gatekeeper, ok := runtime.DefaultUnstructuredConverter.ToUnstructured(result.Object)
if ok != nil {
return false
}

conditions, _, err := unstructured.NestedSlice(crd, "status", "conditions")
audit, _, err := unstructured.NestedMap(gatekeeper, "spec", "audit")
if err != nil {
return false
}

auditFromCache := audit["auditFromCache"]
if auditFromCache != string(operatorv1alpha1.AuditFromCacheAutomatic) {
setupLog.V(1).Info("auditFromCache is not Automatic. ConstraintStatus controller cannot be created")
return false
}

// Start checking constraintpodstatuses.status.gatekeeper.sh crd exist and available
constraintCrdGVR := schema.GroupVersionResource{
Group: "apiextensions.k8s.io",
Version: "v1",
Resource: "customresourcedefinitions",
}

crdUnstructured, err := dynamicClient.Resource(constraintCrdGVR).Get(mainCtx, "constraintpodstatuses.status.gatekeeper.sh",
metav1.GetOptions{})
if err != nil {
setupLog.V(1).Info("Parsing Constraintpodstatuses crd has error (crd), Wait for crd status update")
time.Sleep(time.Second)
return c.isApiAvailable(mainCtx, result, dynamicClient)
}

conditions, _, err := unstructured.NestedSlice(crdUnstructured.Object, "status", "conditions")
if err != nil {
setupLog.V(1).Info("Parsing Constraintpodstatuses crd has error (Condition), Wait for crd status update")
time.Sleep(time.Second)
return c.isApiAvailable(mainCtx, result, dynamicClient)
}

for _, condition := range conditions {
conditionObj, ok := condition.(map[string]interface{})
if !ok {
continue
}

conditionStatus := conditionObj["status"].(string)
conditionType := conditionObj["type"].(string)
conditionStatus, ok := conditionObj["status"].(string)
if !ok {
continue
}

conditionType, ok := conditionObj["type"].(string)
if !ok {
continue
}

if conditionType == string(v1.NamesAccepted) && conditionStatus == "True" {
return true
}
}

setupLog.V(1).Info("Constraintpodstatuses crd is not ready, Wait for crd status update")

return false
time.Sleep(time.Second)
return c.isApiAvailable(mainCtx, result, dynamicClient)
}

// Watch the constraintpodstatuses resource in this function. When adding or Modified events comes,
Expand All @@ -317,14 +357,15 @@ func (c *ConstraintStatusInstaller) watchGatekeeperInstall(mainCtx context.Conte
watcher, _ = c.newWatcher(mainCtx, dynamicClient)
continue
}

switch result.Type { //nolint:exhaustive
case watch.Modified, watch.Added:
if c.getIsInstalled() {
continue
}

// Check constraintpodstatuses crd available
if !c.isApiAvailable(result) {
if !c.isApiAvailable(mainCtx, result, dynamicClient) {
break
}

Expand All @@ -342,6 +383,7 @@ func (c *ConstraintStatusInstaller) watchGatekeeperInstall(mainCtx context.Conte
setupLog.Error(err, "unable to start ConstraintStatus manager")
}
}()

case watch.Deleted:
c.setIsInstalled(false)
ctxCancel()
Expand All @@ -355,19 +397,20 @@ func (c *ConstraintStatusInstaller) watchGatekeeperInstall(mainCtx context.Conte
}
}

func (c *ConstraintStatusInstaller) newWatcher(mainCtx context.Context, dynamicClient *dynamic.DynamicClient) (*toolsWatch.RetryWatcher, error) {
fieldSelector := "metadata.name=constraintpodstatuses.status.gatekeeper.sh"
func (c *ConstraintStatusInstaller) newWatcher(mainCtx context.Context,
dynamicClient *dynamic.DynamicClient,
) (*toolsWatch.RetryWatcher, error) {
timeout := int64(30)
crdGVR := schema.GroupVersionResource{
Group: "apiextensions.k8s.io",
Version: "v1",
Resource: "customresourcedefinitions",
gatekeeperGVR := schema.GroupVersionResource{
Group: "operator.gatekeeper.sh",
Version: "v1alpha1",
Resource: "gatekeepers",
}

watchFunc := func(options metav1.ListOptions) (watch.Interface, error) {
return dynamicClient.Resource(crdGVR).Watch(mainCtx,
metav1.ListOptions{FieldSelector: fieldSelector, TimeoutSeconds: &timeout})
return dynamicClient.Resource(gatekeeperGVR).Watch(mainCtx,
metav1.ListOptions{TimeoutSeconds: &timeout})
}

return toolsWatch.NewRetryWatcher(crdGVR.Version, &cache.ListWatch{WatchFunc: watchFunc})
return toolsWatch.NewRetryWatcher(gatekeeperGVR.Version, &cache.ListWatch{WatchFunc: watchFunc})
}

0 comments on commit 0585b39

Please sign in to comment.