Repository: pravega/zookeeper-operator
Pull request #401 (2021-10-14 09:39:18)

[Issue-400] add disableFinalizer flag


### Change log description

add DisableFinalizer config and skip adding zkFinalziers when set it to true.

### Purpose of the change

Issue-400

### What the code does

skip adding zkFinalziers when DisableFinalizer set to true.

### How to verify it

Set disableFinalizer to true in values and deploy zookeeper operator, the deployed zookeeper  clusters should have the finalizers as empty.And when delete operator before deleting zookeeper  clusters, zk cluster deletion will not be blocked.



Patch:
diff --git a/charts/zookeeper-operator/README.md b/charts/zookeeper-operator/README.md
index 273456f..0de315d 100644
--- a/charts/zookeeper-operator/README.md
+++ b/charts/zookeeper-operator/README.md
@@ -56,3 +56,5 @@ The following table lists the configurable parameters of the zookeeper-operator
 | `additionalEnv` | Additional Environment Variables | `[]` |
 | `additionalSidecars` | Additional Sidecars Configuration | `[]` |
 | `additionalVolumes` | Additional volumes required for sidecars | `[]` |
+| `disableFinalizer` | Disable finalizer for zookeeper clusters, PVCs clean-up will be skipped.| `false` |
+
diff --git a/charts/zookeeper-operator/templates/operator.yaml b/charts/zookeeper-operator/templates/operator.yaml
index 346cfa9..4e6f257 100644
--- a/charts/zookeeper-operator/templates/operator.yaml
+++ b/charts/zookeeper-operator/templates/operator.yaml
@@ -34,6 +34,10 @@ spec:
           name: metrics
         command:
         - zookeeper-operator
+        {{- if .Values.disableFinalizer }}
+        args:
+        - -disableFinalizer
+        {{- end }}
         env:
         - name: WATCH_NAMESPACE
           value: "{{ .Values.watchNamespace }}"
diff --git a/charts/zookeeper-operator/values.yaml b/charts/zookeeper-operator/values.yaml
index 9df0e1d..3f11ab6 100644
--- a/charts/zookeeper-operator/values.yaml
+++ b/charts/zookeeper-operator/values.yaml
@@ -73,3 +73,5 @@ additionalVolumes: {}
 #   emptyDir: {}
 # - name: volume2
 #   emptyDir: {}
+
+disableFinalizer: false
diff --git a/cmd/manager/main.go b/cmd/manager/main.go
index 217b6d8..8970370 100644
--- a/cmd/manager/main.go
+++ b/cmd/manager/main.go
@@ -24,6 +24,7 @@ import (
 	sdkVersion "github.com/operator-framework/operator-sdk/version"
 	"github.com/pravega/zookeeper-operator/pkg/apis"
 	"github.com/pravega/zookeeper-operator/pkg/controller"
+	zkConfig "github.com/pravega/zookeeper-operator/pkg/controller/config"
 	"github.com/pravega/zookeeper-operator/pkg/utils"
 	"github.com/pravega/zookeeper-operator/pkg/version"
 	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
@@ -42,6 +43,8 @@ var (
 
 func init() {
 	flag.BoolVar(&versionFlag, "version", false, "Show version and quit")
+	flag.BoolVar(&zkConfig.DisableFinalizer, "disableFinalizer", false,
+		"Disable finalizers for zookeeperclusters. Use this flag with awareness of the consequences")
 }
 
 func printVersion() {
diff --git a/pkg/controller/config/config.go b/pkg/controller/config/config.go
new file mode 100644
index 0000000..1453ebc
--- /dev/null
+++ b/pkg/controller/config/config.go
@@ -0,0 +1,17 @@
+/**
+ * Copyright (c) 2018 Dell Inc., or its subsidiaries. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+package config
+
+// DisableFinalizer disables the finalizers for zookeeper clusters and
+// skips the pvc deletion phase when zookeeper cluster get deleted.
+// This is useful when operator deletion may happen before zookeeper clusters deletion.
+// NOTE: enabling this flag with caution! It causes pvc of zk undeleted.
+var DisableFinalizer bool
diff --git a/pkg/controller/zookeepercluster/zookeepercluster_controller.go b/pkg/controller/zookeepercluster/zookeepercluster_controller.go
index b2c9b2e..0d684e5 100644
--- a/pkg/controller/zookeepercluster/zookeepercluster_controller.go
+++ b/pkg/controller/zookeepercluster/zookeepercluster_controller.go
@@ -17,11 +17,11 @@ import (
 	"time"
 
 	"github.com/operator-framework/operator-sdk/pkg/predicate"
-	"k8s.io/client-go/kubernetes/scheme"
-	"sigs.k8s.io/controller-runtime/pkg/client/fake"
-
+	"github.com/pravega/zookeeper-operator/pkg/controller/config"
 	"github.com/pravega/zookeeper-operator/pkg/utils"
 	"github.com/pravega/zookeeper-operator/pkg/yamlexporter"
+	"k8s.io/client-go/kubernetes/scheme"
+	"sigs.k8s.io/controller-runtime/pkg/client/fake"
 
 	"github.com/go-logr/logr"
 	zookeeperv1beta1 "github.com/pravega/zookeeper-operator/pkg/apis/zookeeper/v1beta1"
@@ -733,7 +733,7 @@ func (r *ReconcileZookeeperCluster) reconcileFinalizers(instance *zookeeperv1bet
 		return nil
 	}
 	if instance.DeletionTimestamp.IsZero() {
-		if !utils.ContainsString(instance.ObjectMeta.Finalizers, utils.ZkFinalizer) {
+		if !utils.ContainsString(instance.ObjectMeta.Finalizers, utils.ZkFinalizer) && !config.DisableFinalizer {
 			instance.ObjectMeta.Finalizers = append(instance.ObjectMeta.Finalizers, utils.ZkFinalizer)
 			if err = r.client.Update(context.TODO(), instance); err != nil {
 				return err


Test patch:
diff --git a/pkg/controller/zookeepercluster/zookeepercluster_controller_test.go b/pkg/controller/zookeepercluster/zookeepercluster_controller_test.go
index 0a2af85..048be79 100644
--- a/pkg/controller/zookeepercluster/zookeepercluster_controller_test.go
+++ b/pkg/controller/zookeepercluster/zookeepercluster_controller_test.go
@@ -17,6 +17,7 @@ import (
 	"time"
 
 	"github.com/pravega/zookeeper-operator/pkg/apis/zookeeper/v1beta1"
+	"github.com/pravega/zookeeper-operator/pkg/controller/config"
 	"github.com/pravega/zookeeper-operator/pkg/zk"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
@@ -609,6 +610,32 @@ var _ = Describe("ZookeeperCluster Controller", func() {
 			})
 		})
 
+		Context("reconcileFinalizers", func() {
+			var (
+				cl  client.Client
+				err error
+			)
+			BeforeEach(func() {
+				z.WithDefaults()
+				z.Spec.Persistence = nil
+				cl = fake.NewFakeClient(z)
+			})
+			It("should have 1 finalizer, should not raise an error", func() {
+				config.DisableFinalizer = false
+				r = &ReconcileZookeeperCluster{client: cl, scheme: s, zkClient: mockZkClient}
+				err = r.reconcileFinalizers(z)
+				Expect(z.ObjectMeta.Finalizers).To(HaveLen(1))
+				Ω(err).To(BeNil())
+			})
+			It("should have 0 finalizer, should not raise an error", func() {
+				config.DisableFinalizer = true
+				r = &ReconcileZookeeperCluster{client: cl, scheme: s, zkClient: mockZkClient}
+				err = r.reconcileFinalizers(z)
+				Expect(z.ObjectMeta.Finalizers).To(HaveLen(0))
+				Ω(err).To(BeNil())
+			})
+		})
+
 		Context("Checking resource version", func() {
 			var (
 				sts *appsv1.StatefulSet