diff --git a/CHANGELOG.md b/CHANGELOG.md
index 95ae1d5d86ad8d12f98b4244e07ab89b8812c2f8..9655b4502ed2d72d89f0bb17eb9c10c4b7224805 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,18 @@
+### v0.6.0
+##### June 11, 2021
+
+#### :tada: Features
+
+- Breaked the CRDs into Redis standalone cluster setup
+- Optimized code configuration for creating Redis cluster
+- Removed string secret type and secret type password is only supported
+- Structured and optimized golang based codebase
+- Removed divisive terminlogies
+
+#### :beetle: Bug Fixes
+
+- Removed the monitor label to resolve service endpoint issue
+
 ### v0.5.0
 ##### May 1, 2021
 
diff --git a/Makefile b/Makefile
index bfe922976ea4756345129d8d1e82b1c852375332..78038b98082729cb9e1f3dc34245092a1aaf90c0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 # Current Operator version
-VERSION ?= 0.5.0
+VERSION ?= 0.6.0
 # Default bundle image tag
 BUNDLE_IMG ?= controller-bundle:$(VERSION)
 # Options for 'bundle-build'
@@ -12,7 +12,7 @@ endif
 BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL)
 
 # Image URL to use all building/pushing image targets
-IMG ?= quay.io/opstree/redis-operator:v0.5.0
+IMG ?= quay.io/opstree/redis-operator:v0.6.0
 # Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
 CRD_OPTIONS ?= "crd:trivialVersions=true,preserveUnknownFields=false"
 
diff --git a/PROJECT b/PROJECT
index f3e74c9ffe0167745a408f76c00c69f3aebfe54f..7a9f7907a750d6cdbcdad4ff236b411c42bb7b5c 100644
--- a/PROJECT
+++ b/PROJECT
@@ -1,5 +1,9 @@
 domain: redis.opstreelabs.in
-layout: go.kubebuilder.io/v3
+layout:
+- go.kubebuilder.io/v3
+plugins:
+  manifests.sdk.operatorframework.io/v2: {}
+  scorecard.sdk.operatorframework.io/v2: {}
 projectName: redis-operator
 repo: redis-operator
 resources:
@@ -11,7 +15,13 @@ resources:
   kind: Redis
   path: redis-operator/api/v1beta1
   version: v1beta1
+- api:
+    crdVersion: v1
+    namespaced: true
+  controller: true
+  domain: redis.opstreelabs.in
+  group: redis
+  kind: RedisCluster
+  path: redis-operator/api/v1beta1
+  version: v1beta1
 version: "3"
-plugins:
-  manifests.sdk.operatorframework.io/v2: {}
-  scorecard.sdk.operatorframework.io/v2: {}
diff --git a/README.md b/README.md
index 8cccfc7ab145653ab92ae9dcfb842860087cb787..3e10b9f28800e27d20feb1b71033031a0a7eff72 100644
--- a/README.md
+++ b/README.md
@@ -23,14 +23,14 @@
   </a>
 </p>
 
-A Golang based redis operator that will make/oversee Redis standalone/cluster mode setup on top of the Kubernetes. It can create a redis cluster setup with best practices on Cloud as well as the Bare metal environment. Also, it provides an in-built monitoring capability using redis-exporter.
+A Golang based redis operator that will make/oversee Redis standalone and cluster mode setup on top of the Kubernetes. It can create a redis cluster setup with best practices on Cloud as well as the Bare metal environment. Also, it provides an in-built monitoring capability using redis-exporter.
 
 For documentation, please refer to https://ot-container-kit.github.io/redis-operator/
 
 ## Architecture
 
 <div align="center">
-    <img src="./static/redis-operator.png">
+    <img src="./static/redis-operator-architecture.png">
 </div>
 
 ### Purpose
@@ -41,7 +41,8 @@ The purpose of creating this operator was to provide an easy and production grad
 
 Here the features which are supported by this operator:-
 
-- Redis cluster/standalone mode setup
+- Redis cluster and standalone mode setup
+- Redis cluster failover and recovery
 - Inbuilt monitoring with prometheus exporter
 - Dynamic storage provisioning with pvc template
 - Resources restrictions with k8s requests and limits
@@ -88,15 +89,14 @@ Creating redis cluster or standalone setup.
 
 ```shell
 # Create redis cluster setup
-$ helm upgrade redis-cluster ot-helm/redis-setup \
-  --set setupMode="cluster" --set cluster.size=3 \
-  --install --namespace redis-operator
+$ helm upgrade redis-cluster ot-helm/redis-cluster \
+  --set redisCluster.clusterSize=3 --install \ 
+  --namespace redis-operator
 ```
 
 ```shell
 # Create redis standalone setup
-$ helm upgrade redis ot-helm/redis-setup \
-  --set setupMode="standalone" \
+$ helm upgrade redis ot-helm/redis \
   --install --namespace redis-operator
 ```
 
diff --git a/api/v1beta1/common_types.go b/api/v1beta1/common_types.go
new file mode 100644
index 0000000000000000000000000000000000000000..cacab97ebac313e4239ecfa86d6d4990eea88d96
--- /dev/null
+++ b/api/v1beta1/common_types.go
@@ -0,0 +1,49 @@
+/*
+Copyright 2020 Opstree Solutions.
+
+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
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1beta1
+
+import (
+	corev1 "k8s.io/api/core/v1"
+)
+
+// KubernetesConfig will be the JSON struct for Basic Redis Config
+type KubernetesConfig struct {
+	Image                  string                       `json:"image"`
+	ImagePullPolicy        corev1.PullPolicy            `json:"imagePullPolicy,omitempty"`
+	Resources              *corev1.ResourceRequirements `json:"resources,omitempty"`
+	ExistingPasswordSecret *ExistingPasswordSecret      `json:"redisSecret,omitempty"`
+	ServiceType            string                       `json:"serviceType"`
+}
+
+// ExistingPasswordSecret is the struct to access the existing secret
+type ExistingPasswordSecret struct {
+	Name *string `json:"name,omitempty"`
+	Key  *string `json:"key,omitempty"`
+}
+
+// Storage is the inteface to add pvc and pv support in redis
+type Storage struct {
+	VolumeClaimTemplate corev1.PersistentVolumeClaim `json:"volumeClaimTemplate,omitempty"`
+}
+
+// RedisExporter interface will have the information for redis exporter related stuff
+type RedisExporter struct {
+	Enabled         bool                         `json:"enabled,omitempty"`
+	Image           string                       `json:"image"`
+	Resources       *corev1.ResourceRequirements `json:"resources,omitempty"`
+	ImagePullPolicy corev1.PullPolicy            `json:"imagePullPolicy,omitempty"`
+}
diff --git a/api/v1beta1/redis_types.go b/api/v1beta1/redis_types.go
index f76c83f1792394582b4e50d5e405a58d0cee0573..0009f65df2fd8024c4614e78d5b78ffaeb05f862 100644
--- a/api/v1beta1/redis_types.go
+++ b/api/v1beta1/redis_types.go
@@ -26,84 +26,21 @@ import (
 
 // RedisSpec defines the desired state of Redis
 type RedisSpec struct {
-	Mode              string                     `json:"mode"`
-	Size              *int32                     `json:"size,omitempty"`
-	GlobalConfig      GlobalConfig               `json:"global"`
-	Service           Service                    `json:"service"`
-	Master            RedisMaster                `json:"master,omitempty"`
-	Slave             RedisSlave                 `json:"slave,omitempty"`
-	RedisExporter     *RedisExporter             `json:"redisExporter,omitempty"`
-	RedisConfig       map[string]string          `json:"redisConfig"`
-	Resources         *Resources                 `json:"resources,omitempty"`
-	Storage           *Storage                   `json:"storage,omitempty"`
-	NodeSelector      map[string]string          `json:"nodeSelector,omitempty"`
-	SecurityContext   *corev1.PodSecurityContext `json:"securityContext,omitempty"`
-	PriorityClassName string                     `json:"priorityClassName,omitempty"`
-	Affinity          *corev1.Affinity           `json:"affinity,omitempty"`
-	Tolerations       *[]corev1.Toleration       `json:"tolerations,omitempty"`
+	KubernetesConfig  KubernetesConfig             `json:"kubernetesConfig"`
+	RedisExporter     *RedisExporter               `json:"redisExporter,omitempty"`
+	RedisConfig       map[string]string            `json:"redisConfig"`
+	Resources         *corev1.ResourceRequirements `json:"resources,omitempty"`
+	Storage           *Storage                     `json:"storage,omitempty"`
+	NodeSelector      map[string]string            `json:"nodeSelector,omitempty"`
+	SecurityContext   *corev1.PodSecurityContext   `json:"securityContext,omitempty"`
+	PriorityClassName string                       `json:"priorityClassName,omitempty"`
+	Affinity          *corev1.Affinity             `json:"affinity,omitempty"`
+	Tolerations       *[]corev1.Toleration         `json:"tolerations,omitempty"`
 }
 
 // RedisStatus defines the observed state of Redis
 type RedisStatus struct {
-	Cluster RedisSpec `json:"cluster,omitempty"`
-}
-
-// Storage is the inteface to add pvc and pv support in redis
-type Storage struct {
-	VolumeClaimTemplate corev1.PersistentVolumeClaim `json:"volumeClaimTemplate,omitempty"`
-}
-
-// RedisMaster interface will have the redis master configuration
-type RedisMaster struct {
-	Resources   Resources         `json:"resources,omitempty"`
-	RedisConfig map[string]string `json:"redisConfig,omitempty"`
-	Service     Service           `json:"service,omitempty"`
-}
-
-// RedisExporter interface will have the information for redis exporter related stuff
-type RedisExporter struct {
-	Enabled         bool              `json:"enabled,omitempty"`
-	Image           string            `json:"image"`
-	Resources       *Resources        `json:"resources,omitempty"`
-	ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
-}
-
-// GlobalConfig will be the JSON struct for Basic Redis Config
-type GlobalConfig struct {
-	Image                  string                  `json:"image"`
-	ImagePullPolicy        corev1.PullPolicy       `json:"imagePullPolicy,omitempty"`
-	Password               *string                 `json:"password,omitempty"`
-	Resources              *Resources              `json:"resources,omitempty"`
-	ExistingPasswordSecret *ExistingPasswordSecret `json:"existingPasswordSecret,omitempty"`
-}
-
-type ExistingPasswordSecret struct {
-	Name *string `json:"name,omitempty"`
-	Key  *string `json:"key,omitempty"`
-}
-
-// RedisSlave interface will have the redis slave configuration
-type RedisSlave struct {
-	Resources   Resources         `json:"resources,omitempty"`
-	RedisConfig map[string]string `json:"redisConfig,omitempty"`
-	Service     Service           `json:"service,omitempty"`
-}
-
-// ResourceDescription describes CPU and memory resources defined for a cluster.
-type ResourceDescription struct {
-	CPU    string `json:"cpu"`
-	Memory string `json:"memory"`
-}
-
-// Service is the struct for service definition
-type Service struct {
-	Type string `json:"type"`
-}
-
-// Resources describes requests and limits for the cluster resouces.
-type Resources struct {
-	ResourceRequests ResourceDescription `json:"requests,omitempty"`
-	ResourceLimits   ResourceDescription `json:"limits,omitempty"`
+	Redis RedisSpec `json:"redis,omitempty"`
 }
 
 // +kubebuilder:object:root=true
diff --git a/api/v1beta1/rediscluster_types.go b/api/v1beta1/rediscluster_types.go
new file mode 100644
index 0000000000000000000000000000000000000000..7f497e00db9f1bfa0c67fcbd62a81a56f384685e
--- /dev/null
+++ b/api/v1beta1/rediscluster_types.go
@@ -0,0 +1,78 @@
+/*
+Copyright 2020 Opstree Solutions.
+
+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
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1beta1
+
+import (
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// RedisClusterSpec defines the desired state of RedisCluster
+type RedisClusterSpec struct {
+	Size              *int32                       `json:"clusterSize"`
+	KubernetesConfig  KubernetesConfig             `json:"kubernetesConfig"`
+	RedisLeader       RedisLeader                  `json:"redisLeader,omitempty"`
+	RedisFollower     RedisFollower                `json:"redisFollower,omitempty"`
+	RedisExporter     *RedisExporter               `json:"redisExporter,omitempty"`
+	Storage           *Storage                     `json:"storage,omitempty"`
+	NodeSelector      map[string]string            `json:"nodeSelector,omitempty"`
+	SecurityContext   *corev1.PodSecurityContext   `json:"securityContext,omitempty"`
+	PriorityClassName string                       `json:"priorityClassName,omitempty"`
+	Affinity          *corev1.Affinity             `json:"affinity,omitempty"`
+	Tolerations       *[]corev1.Toleration         `json:"tolerations,omitempty"`
+	Resources         *corev1.ResourceRequirements `json:"resources,omitempty"`
+}
+
+// RedisLeader interface will have the redis leader configuration
+type RedisLeader struct {
+	Service string `json:"serviceType,omitempty"`
+}
+
+// RedisFollower interface will have the redis follower configuration
+type RedisFollower struct {
+	Service string `json:"serviceType,omitempty"`
+}
+
+// RedisClusterStatus defines the observed state of RedisCluster
+type RedisClusterStatus struct {
+	RedisCluster RedisCluster `json:"redisCluster,omitempty"`
+}
+
+//+kubebuilder:object:root=true
+//+kubebuilder:subresource:status
+
+// RedisCluster is the Schema for the redisclusters API
+type RedisCluster struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	Spec   RedisClusterSpec `json:"spec,omitempty"`
+	Status RedisClusterSpec `json:"status,omitempty"`
+}
+
+//+kubebuilder:object:root=true
+
+// RedisClusterList contains a list of RedisCluster
+type RedisClusterList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []RedisCluster `json:"items"`
+}
+
+func init() {
+	SchemeBuilder.Register(&RedisCluster{}, &RedisClusterList{})
+}
diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go
index e99d29a3f7d7ba35cd99313daa94d1d25e799173..f90266d2dd50a404f5871e43baacf9926c6a82df 100644
--- a/api/v1beta1/zz_generated.deepcopy.go
+++ b/api/v1beta1/zz_generated.deepcopy.go
@@ -51,17 +51,12 @@ func (in *ExistingPasswordSecret) DeepCopy() *ExistingPasswordSecret {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *GlobalConfig) DeepCopyInto(out *GlobalConfig) {
+func (in *KubernetesConfig) DeepCopyInto(out *KubernetesConfig) {
 	*out = *in
-	if in.Password != nil {
-		in, out := &in.Password, &out.Password
-		*out = new(string)
-		**out = **in
-	}
 	if in.Resources != nil {
 		in, out := &in.Resources, &out.Resources
-		*out = new(Resources)
-		**out = **in
+		*out = new(v1.ResourceRequirements)
+		(*in).DeepCopyInto(*out)
 	}
 	if in.ExistingPasswordSecret != nil {
 		in, out := &in.ExistingPasswordSecret, &out.ExistingPasswordSecret
@@ -70,12 +65,12 @@ func (in *GlobalConfig) DeepCopyInto(out *GlobalConfig) {
 	}
 }
 
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GlobalConfig.
-func (in *GlobalConfig) DeepCopy() *GlobalConfig {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesConfig.
+func (in *KubernetesConfig) DeepCopy() *KubernetesConfig {
 	if in == nil {
 		return nil
 	}
-	out := new(GlobalConfig)
+	out := new(KubernetesConfig)
 	in.DeepCopyInto(out)
 	return out
 }
@@ -108,51 +103,58 @@ func (in *Redis) DeepCopyObject() runtime.Object {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *RedisExporter) DeepCopyInto(out *RedisExporter) {
+func (in *RedisCluster) DeepCopyInto(out *RedisCluster) {
 	*out = *in
-	if in.Resources != nil {
-		in, out := &in.Resources, &out.Resources
-		*out = new(Resources)
-		**out = **in
-	}
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	in.Status.DeepCopyInto(&out.Status)
 }
 
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisExporter.
-func (in *RedisExporter) DeepCopy() *RedisExporter {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisCluster.
+func (in *RedisCluster) DeepCopy() *RedisCluster {
 	if in == nil {
 		return nil
 	}
-	out := new(RedisExporter)
+	out := new(RedisCluster)
 	in.DeepCopyInto(out)
 	return out
 }
 
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *RedisCluster) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *RedisList) DeepCopyInto(out *RedisList) {
+func (in *RedisClusterList) DeepCopyInto(out *RedisClusterList) {
 	*out = *in
 	out.TypeMeta = in.TypeMeta
 	in.ListMeta.DeepCopyInto(&out.ListMeta)
 	if in.Items != nil {
 		in, out := &in.Items, &out.Items
-		*out = make([]Redis, len(*in))
+		*out = make([]RedisCluster, len(*in))
 		for i := range *in {
 			(*in)[i].DeepCopyInto(&(*out)[i])
 		}
 	}
 }
 
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisList.
-func (in *RedisList) DeepCopy() *RedisList {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisClusterList.
+func (in *RedisClusterList) DeepCopy() *RedisClusterList {
 	if in == nil {
 		return nil
 	}
-	out := new(RedisList)
+	out := new(RedisClusterList)
 	in.DeepCopyInto(out)
 	return out
 }
 
 // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
-func (in *RedisList) DeepCopyObject() runtime.Object {
+func (in *RedisClusterList) DeepCopyObject() runtime.Object {
 	if c := in.DeepCopy(); c != nil {
 		return c
 	}
@@ -160,65 +162,173 @@ func (in *RedisList) DeepCopyObject() runtime.Object {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *RedisMaster) DeepCopyInto(out *RedisMaster) {
+func (in *RedisClusterSpec) DeepCopyInto(out *RedisClusterSpec) {
 	*out = *in
-	out.Resources = in.Resources
-	if in.RedisConfig != nil {
-		in, out := &in.RedisConfig, &out.RedisConfig
+	if in.Size != nil {
+		in, out := &in.Size, &out.Size
+		*out = new(int32)
+		**out = **in
+	}
+	in.KubernetesConfig.DeepCopyInto(&out.KubernetesConfig)
+	out.RedisLeader = in.RedisLeader
+	out.RedisFollower = in.RedisFollower
+	if in.RedisExporter != nil {
+		in, out := &in.RedisExporter, &out.RedisExporter
+		*out = new(RedisExporter)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Storage != nil {
+		in, out := &in.Storage, &out.Storage
+		*out = new(Storage)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.NodeSelector != nil {
+		in, out := &in.NodeSelector, &out.NodeSelector
 		*out = make(map[string]string, len(*in))
 		for key, val := range *in {
 			(*out)[key] = val
 		}
 	}
-	out.Service = in.Service
+	if in.SecurityContext != nil {
+		in, out := &in.SecurityContext, &out.SecurityContext
+		*out = new(v1.PodSecurityContext)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Affinity != nil {
+		in, out := &in.Affinity, &out.Affinity
+		*out = new(v1.Affinity)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Tolerations != nil {
+		in, out := &in.Tolerations, &out.Tolerations
+		*out = new([]v1.Toleration)
+		if **in != nil {
+			in, out := *in, *out
+			*out = make([]v1.Toleration, len(*in))
+			for i := range *in {
+				(*in)[i].DeepCopyInto(&(*out)[i])
+			}
+		}
+	}
+	if in.Resources != nil {
+		in, out := &in.Resources, &out.Resources
+		*out = new(v1.ResourceRequirements)
+		(*in).DeepCopyInto(*out)
+	}
 }
 
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisMaster.
-func (in *RedisMaster) DeepCopy() *RedisMaster {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisClusterSpec.
+func (in *RedisClusterSpec) DeepCopy() *RedisClusterSpec {
 	if in == nil {
 		return nil
 	}
-	out := new(RedisMaster)
+	out := new(RedisClusterSpec)
 	in.DeepCopyInto(out)
 	return out
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *RedisSlave) DeepCopyInto(out *RedisSlave) {
+func (in *RedisClusterStatus) DeepCopyInto(out *RedisClusterStatus) {
 	*out = *in
-	out.Resources = in.Resources
-	if in.RedisConfig != nil {
-		in, out := &in.RedisConfig, &out.RedisConfig
-		*out = make(map[string]string, len(*in))
-		for key, val := range *in {
-			(*out)[key] = val
+	in.RedisCluster.DeepCopyInto(&out.RedisCluster)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisClusterStatus.
+func (in *RedisClusterStatus) DeepCopy() *RedisClusterStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(RedisClusterStatus)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RedisExporter) DeepCopyInto(out *RedisExporter) {
+	*out = *in
+	if in.Resources != nil {
+		in, out := &in.Resources, &out.Resources
+		*out = new(v1.ResourceRequirements)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisExporter.
+func (in *RedisExporter) DeepCopy() *RedisExporter {
+	if in == nil {
+		return nil
+	}
+	out := new(RedisExporter)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RedisFollower) DeepCopyInto(out *RedisFollower) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisFollower.
+func (in *RedisFollower) DeepCopy() *RedisFollower {
+	if in == nil {
+		return nil
+	}
+	out := new(RedisFollower)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RedisLeader) DeepCopyInto(out *RedisLeader) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisLeader.
+func (in *RedisLeader) DeepCopy() *RedisLeader {
+	if in == nil {
+		return nil
+	}
+	out := new(RedisLeader)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RedisList) DeepCopyInto(out *RedisList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]Redis, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
 		}
 	}
-	out.Service = in.Service
 }
 
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisSlave.
-func (in *RedisSlave) DeepCopy() *RedisSlave {
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisList.
+func (in *RedisList) DeepCopy() *RedisList {
 	if in == nil {
 		return nil
 	}
-	out := new(RedisSlave)
+	out := new(RedisList)
 	in.DeepCopyInto(out)
 	return out
 }
 
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *RedisList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *RedisSpec) DeepCopyInto(out *RedisSpec) {
 	*out = *in
-	if in.Size != nil {
-		in, out := &in.Size, &out.Size
-		*out = new(int32)
-		**out = **in
-	}
-	in.GlobalConfig.DeepCopyInto(&out.GlobalConfig)
-	out.Service = in.Service
-	in.Master.DeepCopyInto(&out.Master)
-	in.Slave.DeepCopyInto(&out.Slave)
+	in.KubernetesConfig.DeepCopyInto(&out.KubernetesConfig)
 	if in.RedisExporter != nil {
 		in, out := &in.RedisExporter, &out.RedisExporter
 		*out = new(RedisExporter)
@@ -233,8 +343,8 @@ func (in *RedisSpec) DeepCopyInto(out *RedisSpec) {
 	}
 	if in.Resources != nil {
 		in, out := &in.Resources, &out.Resources
-		*out = new(Resources)
-		**out = **in
+		*out = new(v1.ResourceRequirements)
+		(*in).DeepCopyInto(*out)
 	}
 	if in.Storage != nil {
 		in, out := &in.Storage, &out.Storage
@@ -284,7 +394,7 @@ func (in *RedisSpec) DeepCopy() *RedisSpec {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *RedisStatus) DeepCopyInto(out *RedisStatus) {
 	*out = *in
-	in.Cluster.DeepCopyInto(&out.Cluster)
+	in.Redis.DeepCopyInto(&out.Redis)
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RedisStatus.
@@ -297,53 +407,6 @@ func (in *RedisStatus) DeepCopy() *RedisStatus {
 	return out
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ResourceDescription) DeepCopyInto(out *ResourceDescription) {
-	*out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceDescription.
-func (in *ResourceDescription) DeepCopy() *ResourceDescription {
-	if in == nil {
-		return nil
-	}
-	out := new(ResourceDescription)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *Resources) DeepCopyInto(out *Resources) {
-	*out = *in
-	out.ResourceRequests = in.ResourceRequests
-	out.ResourceLimits = in.ResourceLimits
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources.
-func (in *Resources) DeepCopy() *Resources {
-	if in == nil {
-		return nil
-	}
-	out := new(Resources)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *Service) DeepCopyInto(out *Service) {
-	*out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Service.
-func (in *Service) DeepCopy() *Service {
-	if in == nil {
-		return nil
-	}
-	out := new(Service)
-	in.DeepCopyInto(out)
-	return out
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Storage) DeepCopyInto(out *Storage) {
 	*out = *in
diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml
index ecfcc5bb0e0f9621be03c817c4d419c15a3da2de..bb6be76cecf5d5092a1695134c5fb0f71179a21d 100644
--- a/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml
+++ b/config/crd/bases/redis.redis.opstreelabs.in_redis.yaml
@@ -627,104 +627,58 @@ spec:
                         type: array
                     type: object
                 type: object
-              global:
-                description: GlobalConfig will be the JSON struct for Basic Redis
+              kubernetesConfig:
+                description: KubernetesConfig will be the JSON struct for Basic Redis
                   Config
                 properties:
-                  existingPasswordSecret:
-                    properties:
-                      key:
-                        type: string
-                      name:
-                        type: string
-                    type: object
                   image:
                     type: string
                   imagePullPolicy:
                     description: PullPolicy describes a policy for if/when to pull
                       a container image
                     type: string
-                  password:
-                    type: string
-                  resources:
-                    description: Resources describes requests and limits for the cluster
-                      resouces.
+                  redisSecret:
+                    description: ExistingPasswordSecret is the struct to access the
+                      existing secret
                     properties:
-                      limits:
-                        description: ResourceDescription describes CPU and memory
-                          resources defined for a cluster.
-                        properties:
-                          cpu:
-                            type: string
-                          memory:
-                            type: string
-                        required:
-                        - cpu
-                        - memory
-                        type: object
-                      requests:
-                        description: ResourceDescription describes CPU and memory
-                          resources defined for a cluster.
-                        properties:
-                          cpu:
-                            type: string
-                          memory:
-                            type: string
-                        required:
-                        - cpu
-                        - memory
-                        type: object
-                    type: object
-                required:
-                - image
-                type: object
-              master:
-                description: RedisMaster interface will have the redis master configuration
-                properties:
-                  redisConfig:
-                    additionalProperties:
-                      type: string
+                      key:
+                        type: string
+                      name:
+                        type: string
                     type: object
                   resources:
-                    description: Resources describes requests and limits for the cluster
-                      resouces.
+                    description: ResourceRequirements describes the compute resource
+                      requirements.
                     properties:
                       limits:
-                        description: ResourceDescription describes CPU and memory
-                          resources defined for a cluster.
-                        properties:
-                          cpu:
-                            type: string
-                          memory:
-                            type: string
-                        required:
-                        - cpu
-                        - memory
+                        additionalProperties:
+                          anyOf:
+                          - type: integer
+                          - type: string
+                          pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                          x-kubernetes-int-or-string: true
+                        description: 'Limits describes the maximum amount of compute
+                          resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
                         type: object
                       requests:
-                        description: ResourceDescription describes CPU and memory
-                          resources defined for a cluster.
-                        properties:
-                          cpu:
-                            type: string
-                          memory:
-                            type: string
-                        required:
-                        - cpu
-                        - memory
+                        additionalProperties:
+                          anyOf:
+                          - type: integer
+                          - type: string
+                          pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                          x-kubernetes-int-or-string: true
+                        description: 'Requests describes the minimum amount of compute
+                          resources required. If Requests is omitted for a container,
+                          it defaults to Limits if that is explicitly specified, otherwise
+                          to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
                         type: object
                     type: object
-                  service:
-                    description: Service is the struct for service definition
-                    properties:
-                      type:
-                        type: string
-                    required:
-                    - type
-                    type: object
+                  serviceType:
+                    type: string
+                required:
+                - image
+                - serviceType
                 type: object
-              mode:
-                type: string
               nodeSelector:
                 additionalProperties:
                   type: string
@@ -748,64 +702,59 @@ spec:
                       a container image
                     type: string
                   resources:
-                    description: Resources describes requests and limits for the cluster
-                      resouces.
+                    description: ResourceRequirements describes the compute resource
+                      requirements.
                     properties:
                       limits:
-                        description: ResourceDescription describes CPU and memory
-                          resources defined for a cluster.
-                        properties:
-                          cpu:
-                            type: string
-                          memory:
-                            type: string
-                        required:
-                        - cpu
-                        - memory
+                        additionalProperties:
+                          anyOf:
+                          - type: integer
+                          - type: string
+                          pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                          x-kubernetes-int-or-string: true
+                        description: 'Limits describes the maximum amount of compute
+                          resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
                         type: object
                       requests:
-                        description: ResourceDescription describes CPU and memory
-                          resources defined for a cluster.
-                        properties:
-                          cpu:
-                            type: string
-                          memory:
-                            type: string
-                        required:
-                        - cpu
-                        - memory
+                        additionalProperties:
+                          anyOf:
+                          - type: integer
+                          - type: string
+                          pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                          x-kubernetes-int-or-string: true
+                        description: 'Requests describes the minimum amount of compute
+                          resources required. If Requests is omitted for a container,
+                          it defaults to Limits if that is explicitly specified, otherwise
+                          to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
                         type: object
                     type: object
                 required:
                 - image
                 type: object
               resources:
-                description: Resources describes requests and limits for the cluster
-                  resouces.
+                description: ResourceRequirements describes the compute resource requirements.
                 properties:
                   limits:
-                    description: ResourceDescription describes CPU and memory resources
-                      defined for a cluster.
-                    properties:
-                      cpu:
-                        type: string
-                      memory:
-                        type: string
-                    required:
-                    - cpu
-                    - memory
+                    additionalProperties:
+                      anyOf:
+                      - type: integer
+                      - type: string
+                      pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                      x-kubernetes-int-or-string: true
+                    description: 'Limits describes the maximum amount of compute resources
+                      allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
                     type: object
                   requests:
-                    description: ResourceDescription describes CPU and memory resources
-                      defined for a cluster.
-                    properties:
-                      cpu:
-                        type: string
-                      memory:
-                        type: string
-                    required:
-                    - cpu
-                    - memory
+                    additionalProperties:
+                      anyOf:
+                      - type: integer
+                      - type: string
+                      pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                      x-kubernetes-int-or-string: true
+                    description: 'Requests describes the minimum amount of compute
+                      resources required. If Requests is omitted for a container,
+                      it defaults to Limits if that is explicitly specified, otherwise
+                      to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
                     type: object
                 type: object
               securityContext:
@@ -954,63 +903,6 @@ spec:
                         type: string
                     type: object
                 type: object
-              service:
-                description: Service is the struct for service definition
-                properties:
-                  type:
-                    type: string
-                required:
-                - type
-                type: object
-              size:
-                format: int32
-                type: integer
-                minimum: 3
-              slave:
-                description: RedisSlave interface will have the redis slave configuration
-                properties:
-                  redisConfig:
-                    additionalProperties:
-                      type: string
-                    type: object
-                  resources:
-                    description: Resources describes requests and limits for the cluster
-                      resouces.
-                    properties:
-                      limits:
-                        description: ResourceDescription describes CPU and memory
-                          resources defined for a cluster.
-                        properties:
-                          cpu:
-                            type: string
-                          memory:
-                            type: string
-                        required:
-                        - cpu
-                        - memory
-                        type: object
-                      requests:
-                        description: ResourceDescription describes CPU and memory
-                          resources defined for a cluster.
-                        properties:
-                          cpu:
-                            type: string
-                          memory:
-                            type: string
-                        required:
-                        - cpu
-                        - memory
-                        type: object
-                    type: object
-                  service:
-                    description: Service is the struct for service definition
-                    properties:
-                      type:
-                        type: string
-                    required:
-                    - type
-                    type: object
-                type: object
               storage:
                 description: Storage is the inteface to add pvc and pv support in
                   redis
@@ -1270,15 +1162,13 @@ spec:
                   type: object
                 type: array
             required:
-            - global
-            - mode
+            - kubernetesConfig
             - redisConfig
-            - service
             type: object
           status:
             description: RedisStatus defines the observed state of Redis
             properties:
-              cluster:
+              redis:
                 description: RedisSpec defines the desired state of Redis
                 properties:
                   affinity:
@@ -1898,105 +1788,59 @@ spec:
                             type: array
                         type: object
                     type: object
-                  global:
-                    description: GlobalConfig will be the JSON struct for Basic Redis
-                      Config
+                  kubernetesConfig:
+                    description: KubernetesConfig will be the JSON struct for Basic
+                      Redis Config
                     properties:
-                      existingPasswordSecret:
-                        properties:
-                          key:
-                            type: string
-                          name:
-                            type: string
-                        type: object
                       image:
                         type: string
                       imagePullPolicy:
                         description: PullPolicy describes a policy for if/when to
                           pull a container image
                         type: string
-                      password:
-                        type: string
-                      resources:
-                        description: Resources describes requests and limits for the
-                          cluster resouces.
+                      redisSecret:
+                        description: ExistingPasswordSecret is the struct to access
+                          the existing secret
                         properties:
-                          limits:
-                            description: ResourceDescription describes CPU and memory
-                              resources defined for a cluster.
-                            properties:
-                              cpu:
-                                type: string
-                              memory:
-                                type: string
-                            required:
-                            - cpu
-                            - memory
-                            type: object
-                          requests:
-                            description: ResourceDescription describes CPU and memory
-                              resources defined for a cluster.
-                            properties:
-                              cpu:
-                                type: string
-                              memory:
-                                type: string
-                            required:
-                            - cpu
-                            - memory
-                            type: object
-                        type: object
-                    required:
-                    - image
-                    type: object
-                  master:
-                    description: RedisMaster interface will have the redis master
-                      configuration
-                    properties:
-                      redisConfig:
-                        additionalProperties:
-                          type: string
+                          key:
+                            type: string
+                          name:
+                            type: string
                         type: object
                       resources:
-                        description: Resources describes requests and limits for the
-                          cluster resouces.
+                        description: ResourceRequirements describes the compute resource
+                          requirements.
                         properties:
                           limits:
-                            description: ResourceDescription describes CPU and memory
-                              resources defined for a cluster.
-                            properties:
-                              cpu:
-                                type: string
-                              memory:
-                                type: string
-                            required:
-                            - cpu
-                            - memory
+                            additionalProperties:
+                              anyOf:
+                              - type: integer
+                              - type: string
+                              pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                              x-kubernetes-int-or-string: true
+                            description: 'Limits describes the maximum amount of compute
+                              resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
                             type: object
                           requests:
-                            description: ResourceDescription describes CPU and memory
-                              resources defined for a cluster.
-                            properties:
-                              cpu:
-                                type: string
-                              memory:
-                                type: string
-                            required:
-                            - cpu
-                            - memory
+                            additionalProperties:
+                              anyOf:
+                              - type: integer
+                              - type: string
+                              pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                              x-kubernetes-int-or-string: true
+                            description: 'Requests describes the minimum amount of
+                              compute resources required. If Requests is omitted for
+                              a container, it defaults to Limits if that is explicitly
+                              specified, otherwise to an implementation-defined value.
+                              More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
                             type: object
                         type: object
-                      service:
-                        description: Service is the struct for service definition
-                        properties:
-                          type:
-                            type: string
-                        required:
-                        - type
-                        type: object
+                      serviceType:
+                        type: string
+                    required:
+                    - image
+                    - serviceType
                     type: object
-                  mode:
-                    type: string
                   nodeSelector:
                     additionalProperties:
                       type: string
@@ -2020,64 +1864,61 @@ spec:
                           pull a container image
                         type: string
                       resources:
-                        description: Resources describes requests and limits for the
-                          cluster resouces.
+                        description: ResourceRequirements describes the compute resource
+                          requirements.
                         properties:
                           limits:
-                            description: ResourceDescription describes CPU and memory
-                              resources defined for a cluster.
-                            properties:
-                              cpu:
-                                type: string
-                              memory:
-                                type: string
-                            required:
-                            - cpu
-                            - memory
+                            additionalProperties:
+                              anyOf:
+                              - type: integer
+                              - type: string
+                              pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                              x-kubernetes-int-or-string: true
+                            description: 'Limits describes the maximum amount of compute
+                              resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
                             type: object
                           requests:
-                            description: ResourceDescription describes CPU and memory
-                              resources defined for a cluster.
-                            properties:
-                              cpu:
-                                type: string
-                              memory:
-                                type: string
-                            required:
-                            - cpu
-                            - memory
+                            additionalProperties:
+                              anyOf:
+                              - type: integer
+                              - type: string
+                              pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                              x-kubernetes-int-or-string: true
+                            description: 'Requests describes the minimum amount of
+                              compute resources required. If Requests is omitted for
+                              a container, it defaults to Limits if that is explicitly
+                              specified, otherwise to an implementation-defined value.
+                              More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
                             type: object
                         type: object
                     required:
                     - image
                     type: object
                   resources:
-                    description: Resources describes requests and limits for the cluster
-                      resouces.
+                    description: ResourceRequirements describes the compute resource
+                      requirements.
                     properties:
                       limits:
-                        description: ResourceDescription describes CPU and memory
-                          resources defined for a cluster.
-                        properties:
-                          cpu:
-                            type: string
-                          memory:
-                            type: string
-                        required:
-                        - cpu
-                        - memory
+                        additionalProperties:
+                          anyOf:
+                          - type: integer
+                          - type: string
+                          pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                          x-kubernetes-int-or-string: true
+                        description: 'Limits describes the maximum amount of compute
+                          resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
                         type: object
                       requests:
-                        description: ResourceDescription describes CPU and memory
-                          resources defined for a cluster.
-                        properties:
-                          cpu:
-                            type: string
-                          memory:
-                            type: string
-                        required:
-                        - cpu
-                        - memory
+                        additionalProperties:
+                          anyOf:
+                          - type: integer
+                          - type: string
+                          pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                          x-kubernetes-int-or-string: true
+                        description: 'Requests describes the minimum amount of compute
+                          resources required. If Requests is omitted for a container,
+                          it defaults to Limits if that is explicitly specified, otherwise
+                          to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
                         type: object
                     type: object
                   securityContext:
@@ -2230,62 +2071,6 @@ spec:
                             type: string
                         type: object
                     type: object
-                  service:
-                    description: Service is the struct for service definition
-                    properties:
-                      type:
-                        type: string
-                    required:
-                    - type
-                    type: object
-                  size:
-                    format: int32
-                    type: integer
-                  slave:
-                    description: RedisSlave interface will have the redis slave configuration
-                    properties:
-                      redisConfig:
-                        additionalProperties:
-                          type: string
-                        type: object
-                      resources:
-                        description: Resources describes requests and limits for the
-                          cluster resouces.
-                        properties:
-                          limits:
-                            description: ResourceDescription describes CPU and memory
-                              resources defined for a cluster.
-                            properties:
-                              cpu:
-                                type: string
-                              memory:
-                                type: string
-                            required:
-                            - cpu
-                            - memory
-                            type: object
-                          requests:
-                            description: ResourceDescription describes CPU and memory
-                              resources defined for a cluster.
-                            properties:
-                              cpu:
-                                type: string
-                              memory:
-                                type: string
-                            required:
-                            - cpu
-                            - memory
-                            type: object
-                        type: object
-                      service:
-                        description: Service is the struct for service definition
-                        properties:
-                          type:
-                            type: string
-                        required:
-                        - type
-                        type: object
-                    type: object
                   storage:
                     description: Storage is the inteface to add pvc and pv support
                       in redis
@@ -2556,26 +2341,11 @@ spec:
                       type: object
                     type: array
                 required:
-                - global
-                - mode
+                - kubernetesConfig
                 - redisConfig
-                - service
                 type: object
             type: object
         type: object
-    additionalPrinterColumns:
-    - jsonPath: .spec.size
-      description: Current master node count
-      name: Master
-      type: integer
-    - jsonPath: .spec.size
-      description: Current slave node count
-      name: Slave
-      type: integer
-    - jsonPath: .metadata.creationTimestamp
-      description: Last Deployment Time
-      name: Last Deployment Time
-      type: date
     served: true
     storage: true
     subresources:
diff --git a/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..da1645075ce7fac64c2686ae3799fe6d37d99dcb
--- /dev/null
+++ b/config/crd/bases/redis.redis.opstreelabs.in_redisclusters.yaml
@@ -0,0 +1,2347 @@
+
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    controller-gen.kubebuilder.io/version: v0.4.1
+  creationTimestamp: null
+  name: redisclusters.redis.redis.opstreelabs.in
+spec:
+  group: redis.redis.opstreelabs.in
+  names:
+    kind: RedisCluster
+    listKind: RedisClusterList
+    plural: redisclusters
+    singular: rediscluster
+  scope: Namespaced
+  versions:
+  - name: v1beta1
+    schema:
+      openAPIV3Schema:
+        description: RedisCluster is the Schema for the redisclusters API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: RedisClusterSpec defines the desired state of RedisCluster
+            properties:
+              affinity:
+                description: Affinity is a group of affinity scheduling rules.
+                properties:
+                  nodeAffinity:
+                    description: Describes node affinity scheduling rules for the
+                      pod.
+                    properties:
+                      preferredDuringSchedulingIgnoredDuringExecution:
+                        description: The scheduler will prefer to schedule pods to
+                          nodes that satisfy the affinity expressions specified by
+                          this field, but it may choose a node that violates one or
+                          more of the expressions. The node that is most preferred
+                          is the one with the greatest sum of weights, i.e. for each
+                          node that meets all of the scheduling requirements (resource
+                          request, requiredDuringScheduling affinity expressions,
+                          etc.), compute a sum by iterating through the elements of
+                          this field and adding "weight" to the sum if the node matches
+                          the corresponding matchExpressions; the node(s) with the
+                          highest sum are the most preferred.
+                        items:
+                          description: An empty preferred scheduling term matches
+                            all objects with implicit weight 0 (i.e. it's a no-op).
+                            A null preferred scheduling term matches no objects (i.e.
+                            is also a no-op).
+                          properties:
+                            preference:
+                              description: A node selector term, associated with the
+                                corresponding weight.
+                              properties:
+                                matchExpressions:
+                                  description: A list of node selector requirements
+                                    by node's labels.
+                                  items:
+                                    description: A node selector requirement is a
+                                      selector that contains values, a key, and an
+                                      operator that relates the key and values.
+                                    properties:
+                                      key:
+                                        description: The label key that the selector
+                                          applies to.
+                                        type: string
+                                      operator:
+                                        description: Represents a key's relationship
+                                          to a set of values. Valid operators are
+                                          In, NotIn, Exists, DoesNotExist. Gt, and
+                                          Lt.
+                                        type: string
+                                      values:
+                                        description: An array of string values. If
+                                          the operator is In or NotIn, the values
+                                          array must be non-empty. If the operator
+                                          is Exists or DoesNotExist, the values array
+                                          must be empty. If the operator is Gt or
+                                          Lt, the values array must have a single
+                                          element, which will be interpreted as an
+                                          integer. This array is replaced during a
+                                          strategic merge patch.
+                                        items:
+                                          type: string
+                                        type: array
+                                    required:
+                                    - key
+                                    - operator
+                                    type: object
+                                  type: array
+                                matchFields:
+                                  description: A list of node selector requirements
+                                    by node's fields.
+                                  items:
+                                    description: A node selector requirement is a
+                                      selector that contains values, a key, and an
+                                      operator that relates the key and values.
+                                    properties:
+                                      key:
+                                        description: The label key that the selector
+                                          applies to.
+                                        type: string
+                                      operator:
+                                        description: Represents a key's relationship
+                                          to a set of values. Valid operators are
+                                          In, NotIn, Exists, DoesNotExist. Gt, and
+                                          Lt.
+                                        type: string
+                                      values:
+                                        description: An array of string values. If
+                                          the operator is In or NotIn, the values
+                                          array must be non-empty. If the operator
+                                          is Exists or DoesNotExist, the values array
+                                          must be empty. If the operator is Gt or
+                                          Lt, the values array must have a single
+                                          element, which will be interpreted as an
+                                          integer. This array is replaced during a
+                                          strategic merge patch.
+                                        items:
+                                          type: string
+                                        type: array
+                                    required:
+                                    - key
+                                    - operator
+                                    type: object
+                                  type: array
+                              type: object
+                            weight:
+                              description: Weight associated with matching the corresponding
+                                nodeSelectorTerm, in the range 1-100.
+                              format: int32
+                              type: integer
+                          required:
+                          - preference
+                          - weight
+                          type: object
+                        type: array
+                      requiredDuringSchedulingIgnoredDuringExecution:
+                        description: If the affinity requirements specified by this
+                          field are not met at scheduling time, the pod will not be
+                          scheduled onto the node. If the affinity requirements specified
+                          by this field cease to be met at some point during pod execution
+                          (e.g. due to an update), the system may or may not try to
+                          eventually evict the pod from its node.
+                        properties:
+                          nodeSelectorTerms:
+                            description: Required. A list of node selector terms.
+                              The terms are ORed.
+                            items:
+                              description: A null or empty node selector term matches
+                                no objects. The requirements of them are ANDed. The
+                                TopologySelectorTerm type implements a subset of the
+                                NodeSelectorTerm.
+                              properties:
+                                matchExpressions:
+                                  description: A list of node selector requirements
+                                    by node's labels.
+                                  items:
+                                    description: A node selector requirement is a
+                                      selector that contains values, a key, and an
+                                      operator that relates the key and values.
+                                    properties:
+                                      key:
+                                        description: The label key that the selector
+                                          applies to.
+                                        type: string
+                                      operator:
+                                        description: Represents a key's relationship
+                                          to a set of values. Valid operators are
+                                          In, NotIn, Exists, DoesNotExist. Gt, and
+                                          Lt.
+                                        type: string
+                                      values:
+                                        description: An array of string values. If
+                                          the operator is In or NotIn, the values
+                                          array must be non-empty. If the operator
+                                          is Exists or DoesNotExist, the values array
+                                          must be empty. If the operator is Gt or
+                                          Lt, the values array must have a single
+                                          element, which will be interpreted as an
+                                          integer. This array is replaced during a
+                                          strategic merge patch.
+                                        items:
+                                          type: string
+                                        type: array
+                                    required:
+                                    - key
+                                    - operator
+                                    type: object
+                                  type: array
+                                matchFields:
+                                  description: A list of node selector requirements
+                                    by node's fields.
+                                  items:
+                                    description: A node selector requirement is a
+                                      selector that contains values, a key, and an
+                                      operator that relates the key and values.
+                                    properties:
+                                      key:
+                                        description: The label key that the selector
+                                          applies to.
+                                        type: string
+                                      operator:
+                                        description: Represents a key's relationship
+                                          to a set of values. Valid operators are
+                                          In, NotIn, Exists, DoesNotExist. Gt, and
+                                          Lt.
+                                        type: string
+                                      values:
+                                        description: An array of string values. If
+                                          the operator is In or NotIn, the values
+                                          array must be non-empty. If the operator
+                                          is Exists or DoesNotExist, the values array
+                                          must be empty. If the operator is Gt or
+                                          Lt, the values array must have a single
+                                          element, which will be interpreted as an
+                                          integer. This array is replaced during a
+                                          strategic merge patch.
+                                        items:
+                                          type: string
+                                        type: array
+                                    required:
+                                    - key
+                                    - operator
+                                    type: object
+                                  type: array
+                              type: object
+                            type: array
+                        required:
+                        - nodeSelectorTerms
+                        type: object
+                    type: object
+                  podAffinity:
+                    description: Describes pod affinity scheduling rules (e.g. co-locate
+                      this pod in the same node, zone, etc. as some other pod(s)).
+                    properties:
+                      preferredDuringSchedulingIgnoredDuringExecution:
+                        description: The scheduler will prefer to schedule pods to
+                          nodes that satisfy the affinity expressions specified by
+                          this field, but it may choose a node that violates one or
+                          more of the expressions. The node that is most preferred
+                          is the one with the greatest sum of weights, i.e. for each
+                          node that meets all of the scheduling requirements (resource
+                          request, requiredDuringScheduling affinity expressions,
+                          etc.), compute a sum by iterating through the elements of
+                          this field and adding "weight" to the sum if the node has
+                          pods which matches the corresponding podAffinityTerm; the
+                          node(s) with the highest sum are the most preferred.
+                        items:
+                          description: The weights of all of the matched WeightedPodAffinityTerm
+                            fields are added per-node to find the most preferred node(s)
+                          properties:
+                            podAffinityTerm:
+                              description: Required. A pod affinity term, associated
+                                with the corresponding weight.
+                              properties:
+                                labelSelector:
+                                  description: A label query over a set of resources,
+                                    in this case pods.
+                                  properties:
+                                    matchExpressions:
+                                      description: matchExpressions is a list of label
+                                        selector requirements. The requirements are
+                                        ANDed.
+                                      items:
+                                        description: A label selector requirement
+                                          is a selector that contains values, a key,
+                                          and an operator that relates the key and
+                                          values.
+                                        properties:
+                                          key:
+                                            description: key is the label key that
+                                              the selector applies to.
+                                            type: string
+                                          operator:
+                                            description: operator represents a key's
+                                              relationship to a set of values. Valid
+                                              operators are In, NotIn, Exists and
+                                              DoesNotExist.
+                                            type: string
+                                          values:
+                                            description: values is an array of string
+                                              values. If the operator is In or NotIn,
+                                              the values array must be non-empty.
+                                              If the operator is Exists or DoesNotExist,
+                                              the values array must be empty. This
+                                              array is replaced during a strategic
+                                              merge patch.
+                                            items:
+                                              type: string
+                                            type: array
+                                        required:
+                                        - key
+                                        - operator
+                                        type: object
+                                      type: array
+                                    matchLabels:
+                                      additionalProperties:
+                                        type: string
+                                      description: matchLabels is a map of {key,value}
+                                        pairs. A single {key,value} in the matchLabels
+                                        map is equivalent to an element of matchExpressions,
+                                        whose key field is "key", the operator is
+                                        "In", and the values array contains only "value".
+                                        The requirements are ANDed.
+                                      type: object
+                                  type: object
+                                namespaces:
+                                  description: namespaces specifies which namespaces
+                                    the labelSelector applies to (matches against);
+                                    null or empty list means "this pod's namespace"
+                                  items:
+                                    type: string
+                                  type: array
+                                topologyKey:
+                                  description: This pod should be co-located (affinity)
+                                    or not co-located (anti-affinity) with the pods
+                                    matching the labelSelector in the specified namespaces,
+                                    where co-located is defined as running on a node
+                                    whose value of the label with key topologyKey
+                                    matches that of any node on which any of the selected
+                                    pods is running. Empty topologyKey is not allowed.
+                                  type: string
+                              required:
+                              - topologyKey
+                              type: object
+                            weight:
+                              description: weight associated with matching the corresponding
+                                podAffinityTerm, in the range 1-100.
+                              format: int32
+                              type: integer
+                          required:
+                          - podAffinityTerm
+                          - weight
+                          type: object
+                        type: array
+                      requiredDuringSchedulingIgnoredDuringExecution:
+                        description: If the affinity requirements specified by this
+                          field are not met at scheduling time, the pod will not be
+                          scheduled onto the node. If the affinity requirements specified
+                          by this field cease to be met at some point during pod execution
+                          (e.g. due to a pod label update), the system may or may
+                          not try to eventually evict the pod from its node. When
+                          there are multiple elements, the lists of nodes corresponding
+                          to each podAffinityTerm are intersected, i.e. all terms
+                          must be satisfied.
+                        items:
+                          description: Defines a set of pods (namely those matching
+                            the labelSelector relative to the given namespace(s))
+                            that this pod should be co-located (affinity) or not co-located
+                            (anti-affinity) with, where co-located is defined as running
+                            on a node whose value of the label with key <topologyKey>
+                            matches that of any node on which a pod of the set of
+                            pods is running
+                          properties:
+                            labelSelector:
+                              description: A label query over a set of resources,
+                                in this case pods.
+                              properties:
+                                matchExpressions:
+                                  description: matchExpressions is a list of label
+                                    selector requirements. The requirements are ANDed.
+                                  items:
+                                    description: A label selector requirement is a
+                                      selector that contains values, a key, and an
+                                      operator that relates the key and values.
+                                    properties:
+                                      key:
+                                        description: key is the label key that the
+                                          selector applies to.
+                                        type: string
+                                      operator:
+                                        description: operator represents a key's relationship
+                                          to a set of values. Valid operators are
+                                          In, NotIn, Exists and DoesNotExist.
+                                        type: string
+                                      values:
+                                        description: values is an array of string
+                                          values. If the operator is In or NotIn,
+                                          the values array must be non-empty. If the
+                                          operator is Exists or DoesNotExist, the
+                                          values array must be empty. This array is
+                                          replaced during a strategic merge patch.
+                                        items:
+                                          type: string
+                                        type: array
+                                    required:
+                                    - key
+                                    - operator
+                                    type: object
+                                  type: array
+                                matchLabels:
+                                  additionalProperties:
+                                    type: string
+                                  description: matchLabels is a map of {key,value}
+                                    pairs. A single {key,value} in the matchLabels
+                                    map is equivalent to an element of matchExpressions,
+                                    whose key field is "key", the operator is "In",
+                                    and the values array contains only "value". The
+                                    requirements are ANDed.
+                                  type: object
+                              type: object
+                            namespaces:
+                              description: namespaces specifies which namespaces the
+                                labelSelector applies to (matches against); null or
+                                empty list means "this pod's namespace"
+                              items:
+                                type: string
+                              type: array
+                            topologyKey:
+                              description: This pod should be co-located (affinity)
+                                or not co-located (anti-affinity) with the pods matching
+                                the labelSelector in the specified namespaces, where
+                                co-located is defined as running on a node whose value
+                                of the label with key topologyKey matches that of
+                                any node on which any of the selected pods is running.
+                                Empty topologyKey is not allowed.
+                              type: string
+                          required:
+                          - topologyKey
+                          type: object
+                        type: array
+                    type: object
+                  podAntiAffinity:
+                    description: Describes pod anti-affinity scheduling rules (e.g.
+                      avoid putting this pod in the same node, zone, etc. as some
+                      other pod(s)).
+                    properties:
+                      preferredDuringSchedulingIgnoredDuringExecution:
+                        description: The scheduler will prefer to schedule pods to
+                          nodes that satisfy the anti-affinity expressions specified
+                          by this field, but it may choose a node that violates one
+                          or more of the expressions. The node that is most preferred
+                          is the one with the greatest sum of weights, i.e. for each
+                          node that meets all of the scheduling requirements (resource
+                          request, requiredDuringScheduling anti-affinity expressions,
+                          etc.), compute a sum by iterating through the elements of
+                          this field and adding "weight" to the sum if the node has
+                          pods which matches the corresponding podAffinityTerm; the
+                          node(s) with the highest sum are the most preferred.
+                        items:
+                          description: The weights of all of the matched WeightedPodAffinityTerm
+                            fields are added per-node to find the most preferred node(s)
+                          properties:
+                            podAffinityTerm:
+                              description: Required. A pod affinity term, associated
+                                with the corresponding weight.
+                              properties:
+                                labelSelector:
+                                  description: A label query over a set of resources,
+                                    in this case pods.
+                                  properties:
+                                    matchExpressions:
+                                      description: matchExpressions is a list of label
+                                        selector requirements. The requirements are
+                                        ANDed.
+                                      items:
+                                        description: A label selector requirement
+                                          is a selector that contains values, a key,
+                                          and an operator that relates the key and
+                                          values.
+                                        properties:
+                                          key:
+                                            description: key is the label key that
+                                              the selector applies to.
+                                            type: string
+                                          operator:
+                                            description: operator represents a key's
+                                              relationship to a set of values. Valid
+                                              operators are In, NotIn, Exists and
+                                              DoesNotExist.
+                                            type: string
+                                          values:
+                                            description: values is an array of string
+                                              values. If the operator is In or NotIn,
+                                              the values array must be non-empty.
+                                              If the operator is Exists or DoesNotExist,
+                                              the values array must be empty. This
+                                              array is replaced during a strategic
+                                              merge patch.
+                                            items:
+                                              type: string
+                                            type: array
+                                        required:
+                                        - key
+                                        - operator
+                                        type: object
+                                      type: array
+                                    matchLabels:
+                                      additionalProperties:
+                                        type: string
+                                      description: matchLabels is a map of {key,value}
+                                        pairs. A single {key,value} in the matchLabels
+                                        map is equivalent to an element of matchExpressions,
+                                        whose key field is "key", the operator is
+                                        "In", and the values array contains only "value".
+                                        The requirements are ANDed.
+                                      type: object
+                                  type: object
+                                namespaces:
+                                  description: namespaces specifies which namespaces
+                                    the labelSelector applies to (matches against);
+                                    null or empty list means "this pod's namespace"
+                                  items:
+                                    type: string
+                                  type: array
+                                topologyKey:
+                                  description: This pod should be co-located (affinity)
+                                    or not co-located (anti-affinity) with the pods
+                                    matching the labelSelector in the specified namespaces,
+                                    where co-located is defined as running on a node
+                                    whose value of the label with key topologyKey
+                                    matches that of any node on which any of the selected
+                                    pods is running. Empty topologyKey is not allowed.
+                                  type: string
+                              required:
+                              - topologyKey
+                              type: object
+                            weight:
+                              description: weight associated with matching the corresponding
+                                podAffinityTerm, in the range 1-100.
+                              format: int32
+                              type: integer
+                          required:
+                          - podAffinityTerm
+                          - weight
+                          type: object
+                        type: array
+                      requiredDuringSchedulingIgnoredDuringExecution:
+                        description: If the anti-affinity requirements specified by
+                          this field are not met at scheduling time, the pod will
+                          not be scheduled onto the node. If the anti-affinity requirements
+                          specified by this field cease to be met at some point during
+                          pod execution (e.g. due to a pod label update), the system
+                          may or may not try to eventually evict the pod from its
+                          node. When there are multiple elements, the lists of nodes
+                          corresponding to each podAffinityTerm are intersected, i.e.
+                          all terms must be satisfied.
+                        items:
+                          description: Defines a set of pods (namely those matching
+                            the labelSelector relative to the given namespace(s))
+                            that this pod should be co-located (affinity) or not co-located
+                            (anti-affinity) with, where co-located is defined as running
+                            on a node whose value of the label with key <topologyKey>
+                            matches that of any node on which a pod of the set of
+                            pods is running
+                          properties:
+                            labelSelector:
+                              description: A label query over a set of resources,
+                                in this case pods.
+                              properties:
+                                matchExpressions:
+                                  description: matchExpressions is a list of label
+                                    selector requirements. The requirements are ANDed.
+                                  items:
+                                    description: A label selector requirement is a
+                                      selector that contains values, a key, and an
+                                      operator that relates the key and values.
+                                    properties:
+                                      key:
+                                        description: key is the label key that the
+                                          selector applies to.
+                                        type: string
+                                      operator:
+                                        description: operator represents a key's relationship
+                                          to a set of values. Valid operators are
+                                          In, NotIn, Exists and DoesNotExist.
+                                        type: string
+                                      values:
+                                        description: values is an array of string
+                                          values. If the operator is In or NotIn,
+                                          the values array must be non-empty. If the
+                                          operator is Exists or DoesNotExist, the
+                                          values array must be empty. This array is
+                                          replaced during a strategic merge patch.
+                                        items:
+                                          type: string
+                                        type: array
+                                    required:
+                                    - key
+                                    - operator
+                                    type: object
+                                  type: array
+                                matchLabels:
+                                  additionalProperties:
+                                    type: string
+                                  description: matchLabels is a map of {key,value}
+                                    pairs. A single {key,value} in the matchLabels
+                                    map is equivalent to an element of matchExpressions,
+                                    whose key field is "key", the operator is "In",
+                                    and the values array contains only "value". The
+                                    requirements are ANDed.
+                                  type: object
+                              type: object
+                            namespaces:
+                              description: namespaces specifies which namespaces the
+                                labelSelector applies to (matches against); null or
+                                empty list means "this pod's namespace"
+                              items:
+                                type: string
+                              type: array
+                            topologyKey:
+                              description: This pod should be co-located (affinity)
+                                or not co-located (anti-affinity) with the pods matching
+                                the labelSelector in the specified namespaces, where
+                                co-located is defined as running on a node whose value
+                                of the label with key topologyKey matches that of
+                                any node on which any of the selected pods is running.
+                                Empty topologyKey is not allowed.
+                              type: string
+                          required:
+                          - topologyKey
+                          type: object
+                        type: array
+                    type: object
+                type: object
+              clusterSize:
+                format: int32
+                type: integer
+                minimum: 3
+              kubernetesConfig:
+                description: KubernetesConfig will be the JSON struct for Basic Redis
+                  Config
+                properties:
+                  image:
+                    type: string
+                  imagePullPolicy:
+                    description: PullPolicy describes a policy for if/when to pull
+                      a container image
+                    type: string
+                  redisSecret:
+                    description: ExistingPasswordSecret is the struct to access the
+                      existing secret
+                    properties:
+                      key:
+                        type: string
+                      name:
+                        type: string
+                    type: object
+                  resources:
+                    description: ResourceRequirements describes the compute resource
+                      requirements.
+                    properties:
+                      limits:
+                        additionalProperties:
+                          anyOf:
+                          - type: integer
+                          - type: string
+                          pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                          x-kubernetes-int-or-string: true
+                        description: 'Limits describes the maximum amount of compute
+                          resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                        type: object
+                      requests:
+                        additionalProperties:
+                          anyOf:
+                          - type: integer
+                          - type: string
+                          pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                          x-kubernetes-int-or-string: true
+                        description: 'Requests describes the minimum amount of compute
+                          resources required. If Requests is omitted for a container,
+                          it defaults to Limits if that is explicitly specified, otherwise
+                          to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                        type: object
+                    type: object
+                  serviceType:
+                    type: string
+                required:
+                - image
+                - serviceType
+                type: object
+              nodeSelector:
+                additionalProperties:
+                  type: string
+                type: object
+              priorityClassName:
+                type: string
+              redisExporter:
+                description: RedisExporter interface will have the information for
+                  redis exporter related stuff
+                properties:
+                  enabled:
+                    type: boolean
+                  image:
+                    type: string
+                  imagePullPolicy:
+                    description: PullPolicy describes a policy for if/when to pull
+                      a container image
+                    type: string
+                  resources:
+                    description: ResourceRequirements describes the compute resource
+                      requirements.
+                    properties:
+                      limits:
+                        additionalProperties:
+                          anyOf:
+                          - type: integer
+                          - type: string
+                          pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                          x-kubernetes-int-or-string: true
+                        description: 'Limits describes the maximum amount of compute
+                          resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                        type: object
+                      requests:
+                        additionalProperties:
+                          anyOf:
+                          - type: integer
+                          - type: string
+                          pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                          x-kubernetes-int-or-string: true
+                        description: 'Requests describes the minimum amount of compute
+                          resources required. If Requests is omitted for a container,
+                          it defaults to Limits if that is explicitly specified, otherwise
+                          to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                        type: object
+                    type: object
+                required:
+                - image
+                type: object
+              redisFollower:
+                description: RedisFollower interface will have the redis slave configuration
+                properties:
+                  serviceType:
+                    type: string
+                type: object
+              redisLeader:
+                description: RedisLeader interface will have the redis master configuration
+                properties:
+                  serviceType:
+                    type: string
+                type: object
+              resources:
+                description: ResourceRequirements describes the compute resource requirements.
+                properties:
+                  limits:
+                    additionalProperties:
+                      anyOf:
+                      - type: integer
+                      - type: string
+                      pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                      x-kubernetes-int-or-string: true
+                    description: 'Limits describes the maximum amount of compute resources
+                      allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                    type: object
+                  requests:
+                    additionalProperties:
+                      anyOf:
+                      - type: integer
+                      - type: string
+                      pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                      x-kubernetes-int-or-string: true
+                    description: 'Requests describes the minimum amount of compute
+                      resources required. If Requests is omitted for a container,
+                      it defaults to Limits if that is explicitly specified, otherwise
+                      to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                    type: object
+                type: object
+              securityContext:
+                description: PodSecurityContext holds pod-level security attributes
+                  and common container settings. Some fields are also present in container.securityContext.  Field
+                  values of container.securityContext take precedence over field values
+                  of PodSecurityContext.
+                properties:
+                  fsGroup:
+                    description: "A special supplemental group that applies to all
+                      containers in a pod. Some volume types allow the Kubelet to
+                      change the ownership of that volume to be owned by the pod:
+                      \n 1. The owning GID will be the FSGroup 2. The setgid bit is
+                      set (new files created in the volume will be owned by FSGroup)
+                      3. The permission bits are OR'd with rw-rw---- \n If unset,
+                      the Kubelet will not modify the ownership and permissions of
+                      any volume."
+                    format: int64
+                    type: integer
+                  fsGroupChangePolicy:
+                    description: 'fsGroupChangePolicy defines behavior of changing
+                      ownership and permission of the volume before being exposed
+                      inside Pod. This field will only apply to volume types which
+                      support fsGroup based ownership(and permissions). It will have
+                      no effect on ephemeral volume types such as: secret, configmaps
+                      and emptydir. Valid values are "OnRootMismatch" and "Always".
+                      If not specified defaults to "Always".'
+                    type: string
+                  runAsGroup:
+                    description: The GID to run the entrypoint of the container process.
+                      Uses runtime default if unset. May also be set in SecurityContext.  If
+                      set in both SecurityContext and PodSecurityContext, the value
+                      specified in SecurityContext takes precedence for that container.
+                    format: int64
+                    type: integer
+                  runAsNonRoot:
+                    description: Indicates that the container must run as a non-root
+                      user. If true, the Kubelet will validate the image at runtime
+                      to ensure that it does not run as UID 0 (root) and fail to start
+                      the container if it does. If unset or false, no such validation
+                      will be performed. May also be set in SecurityContext.  If set
+                      in both SecurityContext and PodSecurityContext, the value specified
+                      in SecurityContext takes precedence.
+                    type: boolean
+                  runAsUser:
+                    description: The UID to run the entrypoint of the container process.
+                      Defaults to user specified in image metadata if unspecified.
+                      May also be set in SecurityContext.  If set in both SecurityContext
+                      and PodSecurityContext, the value specified in SecurityContext
+                      takes precedence for that container.
+                    format: int64
+                    type: integer
+                  seLinuxOptions:
+                    description: The SELinux context to be applied to all containers.
+                      If unspecified, the container runtime will allocate a random
+                      SELinux context for each container.  May also be set in SecurityContext.  If
+                      set in both SecurityContext and PodSecurityContext, the value
+                      specified in SecurityContext takes precedence for that container.
+                    properties:
+                      level:
+                        description: Level is SELinux level label that applies to
+                          the container.
+                        type: string
+                      role:
+                        description: Role is a SELinux role label that applies to
+                          the container.
+                        type: string
+                      type:
+                        description: Type is a SELinux type label that applies to
+                          the container.
+                        type: string
+                      user:
+                        description: User is a SELinux user label that applies to
+                          the container.
+                        type: string
+                    type: object
+                  seccompProfile:
+                    description: The seccomp options to use by the containers in this
+                      pod.
+                    properties:
+                      localhostProfile:
+                        description: localhostProfile indicates a profile defined
+                          in a file on the node should be used. The profile must be
+                          preconfigured on the node to work. Must be a descending
+                          path, relative to the kubelet's configured seccomp profile
+                          location. Must only be set if type is "Localhost".
+                        type: string
+                      type:
+                        description: "type indicates which kind of seccomp profile
+                          will be applied. Valid options are: \n Localhost - a profile
+                          defined in a file on the node should be used. RuntimeDefault
+                          - the container runtime default profile should be used.
+                          Unconfined - no profile should be applied."
+                        type: string
+                    required:
+                    - type
+                    type: object
+                  supplementalGroups:
+                    description: A list of groups applied to the first process run
+                      in each container, in addition to the container's primary GID.  If
+                      unspecified, no groups will be added to any container.
+                    items:
+                      format: int64
+                      type: integer
+                    type: array
+                  sysctls:
+                    description: Sysctls hold a list of namespaced sysctls used for
+                      the pod. Pods with unsupported sysctls (by the container runtime)
+                      might fail to launch.
+                    items:
+                      description: Sysctl defines a kernel parameter to be set
+                      properties:
+                        name:
+                          description: Name of a property to set
+                          type: string
+                        value:
+                          description: Value of a property to set
+                          type: string
+                      required:
+                      - name
+                      - value
+                      type: object
+                    type: array
+                  windowsOptions:
+                    description: The Windows specific settings applied to all containers.
+                      If unspecified, the options within a container's SecurityContext
+                      will be used. If set in both SecurityContext and PodSecurityContext,
+                      the value specified in SecurityContext takes precedence.
+                    properties:
+                      gmsaCredentialSpec:
+                        description: GMSACredentialSpec is where the GMSA admission
+                          webhook (https://github.com/kubernetes-sigs/windows-gmsa)
+                          inlines the contents of the GMSA credential spec named by
+                          the GMSACredentialSpecName field.
+                        type: string
+                      gmsaCredentialSpecName:
+                        description: GMSACredentialSpecName is the name of the GMSA
+                          credential spec to use.
+                        type: string
+                      runAsUserName:
+                        description: The UserName in Windows to run the entrypoint
+                          of the container process. Defaults to the user specified
+                          in image metadata if unspecified. May also be set in PodSecurityContext.
+                          If set in both SecurityContext and PodSecurityContext, the
+                          value specified in SecurityContext takes precedence.
+                        type: string
+                    type: object
+                type: object
+              storage:
+                description: Storage is the inteface to add pvc and pv support in
+                  redis
+                properties:
+                  volumeClaimTemplate:
+                    description: PersistentVolumeClaim is a user's request for and
+                      claim to a persistent volume
+                    properties:
+                      apiVersion:
+                        description: 'APIVersion defines the versioned schema of this
+                          representation of an object. Servers should convert recognized
+                          schemas to the latest internal value, and may reject unrecognized
+                          values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+                        type: string
+                      kind:
+                        description: 'Kind is a string value representing the REST
+                          resource this object represents. Servers may infer this
+                          from the endpoint the client submits requests to. Cannot
+                          be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                        type: string
+                      metadata:
+                        description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata'
+                        type: object
+                      spec:
+                        description: 'Spec defines the desired characteristics of
+                          a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
+                        properties:
+                          accessModes:
+                            description: 'AccessModes contains the desired access
+                              modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
+                            items:
+                              type: string
+                            type: array
+                          dataSource:
+                            description: 'This field can be used to specify either:
+                              * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot
+                              - Beta) * An existing PVC (PersistentVolumeClaim) *
+                              An existing custom resource/object that implements data
+                              population (Alpha) In order to use VolumeSnapshot object
+                              types, the appropriate feature gate must be enabled
+                              (VolumeSnapshotDataSource or AnyVolumeDataSource) If
+                              the provisioner or an external controller can support
+                              the specified data source, it will create a new volume
+                              based on the contents of the specified data source.
+                              If the specified data source is not supported, the volume
+                              will not be created and the failure will be reported
+                              as an event. In the future, we plan to support more
+                              data source types and the behavior of the provisioner
+                              may change.'
+                            properties:
+                              apiGroup:
+                                description: APIGroup is the group for the resource
+                                  being referenced. If APIGroup is not specified,
+                                  the specified Kind must be in the core API group.
+                                  For any other third-party types, APIGroup is required.
+                                type: string
+                              kind:
+                                description: Kind is the type of resource being referenced
+                                type: string
+                              name:
+                                description: Name is the name of resource being referenced
+                                type: string
+                            required:
+                            - kind
+                            - name
+                            type: object
+                          resources:
+                            description: 'Resources represents the minimum resources
+                              the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources'
+                            properties:
+                              limits:
+                                additionalProperties:
+                                  anyOf:
+                                  - type: integer
+                                  - type: string
+                                  pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                  x-kubernetes-int-or-string: true
+                                description: 'Limits describes the maximum amount
+                                  of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                                type: object
+                              requests:
+                                additionalProperties:
+                                  anyOf:
+                                  - type: integer
+                                  - type: string
+                                  pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                  x-kubernetes-int-or-string: true
+                                description: 'Requests describes the minimum amount
+                                  of compute resources required. If Requests is omitted
+                                  for a container, it defaults to Limits if that is
+                                  explicitly specified, otherwise to an implementation-defined
+                                  value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                                type: object
+                            type: object
+                          selector:
+                            description: A label query over volumes to consider for
+                              binding.
+                            properties:
+                              matchExpressions:
+                                description: matchExpressions is a list of label selector
+                                  requirements. The requirements are ANDed.
+                                items:
+                                  description: A label selector requirement is a selector
+                                    that contains values, a key, and an operator that
+                                    relates the key and values.
+                                  properties:
+                                    key:
+                                      description: key is the label key that the selector
+                                        applies to.
+                                      type: string
+                                    operator:
+                                      description: operator represents a key's relationship
+                                        to a set of values. Valid operators are In,
+                                        NotIn, Exists and DoesNotExist.
+                                      type: string
+                                    values:
+                                      description: values is an array of string values.
+                                        If the operator is In or NotIn, the values
+                                        array must be non-empty. If the operator is
+                                        Exists or DoesNotExist, the values array must
+                                        be empty. This array is replaced during a
+                                        strategic merge patch.
+                                      items:
+                                        type: string
+                                      type: array
+                                  required:
+                                  - key
+                                  - operator
+                                  type: object
+                                type: array
+                              matchLabels:
+                                additionalProperties:
+                                  type: string
+                                description: matchLabels is a map of {key,value} pairs.
+                                  A single {key,value} in the matchLabels map is equivalent
+                                  to an element of matchExpressions, whose key field
+                                  is "key", the operator is "In", and the values array
+                                  contains only "value". The requirements are ANDed.
+                                type: object
+                            type: object
+                          storageClassName:
+                            description: 'Name of the StorageClass required by the
+                              claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1'
+                            type: string
+                          volumeMode:
+                            description: volumeMode defines what type of volume is
+                              required by the claim. Value of Filesystem is implied
+                              when not included in claim spec.
+                            type: string
+                          volumeName:
+                            description: VolumeName is the binding reference to the
+                              PersistentVolume backing this claim.
+                            type: string
+                        type: object
+                      status:
+                        description: 'Status represents the current information/status
+                          of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
+                        properties:
+                          accessModes:
+                            description: 'AccessModes contains the actual access modes
+                              the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
+                            items:
+                              type: string
+                            type: array
+                          capacity:
+                            additionalProperties:
+                              anyOf:
+                              - type: integer
+                              - type: string
+                              pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                              x-kubernetes-int-or-string: true
+                            description: Represents the actual resources of the underlying
+                              volume.
+                            type: object
+                          conditions:
+                            description: Current Condition of persistent volume claim.
+                              If underlying persistent volume is being resized then
+                              the Condition will be set to 'ResizeStarted'.
+                            items:
+                              description: PersistentVolumeClaimCondition contails
+                                details about state of pvc
+                              properties:
+                                lastProbeTime:
+                                  description: Last time we probed the condition.
+                                  format: date-time
+                                  type: string
+                                lastTransitionTime:
+                                  description: Last time the condition transitioned
+                                    from one status to another.
+                                  format: date-time
+                                  type: string
+                                message:
+                                  description: Human-readable message indicating details
+                                    about last transition.
+                                  type: string
+                                reason:
+                                  description: Unique, this should be a short, machine
+                                    understandable string that gives the reason for
+                                    condition's last transition. If it reports "ResizeStarted"
+                                    that means the underlying persistent volume is
+                                    being resized.
+                                  type: string
+                                status:
+                                  type: string
+                                type:
+                                  description: PersistentVolumeClaimConditionType
+                                    is a valid value of PersistentVolumeClaimCondition.Type
+                                  type: string
+                              required:
+                              - status
+                              - type
+                              type: object
+                            type: array
+                          phase:
+                            description: Phase represents the current phase of PersistentVolumeClaim.
+                            type: string
+                        type: object
+                    type: object
+                type: object
+              tolerations:
+                items:
+                  description: The pod this Toleration is attached to tolerates any
+                    taint that matches the triple <key,value,effect> using the matching
+                    operator <operator>.
+                  properties:
+                    effect:
+                      description: Effect indicates the taint effect to match. Empty
+                        means match all taint effects. When specified, allowed values
+                        are NoSchedule, PreferNoSchedule and NoExecute.
+                      type: string
+                    key:
+                      description: Key is the taint key that the toleration applies
+                        to. Empty means match all taint keys. If the key is empty,
+                        operator must be Exists; this combination means to match all
+                        values and all keys.
+                      type: string
+                    operator:
+                      description: Operator represents a key's relationship to the
+                        value. Valid operators are Exists and Equal. Defaults to Equal.
+                        Exists is equivalent to wildcard for value, so that a pod
+                        can tolerate all taints of a particular category.
+                      type: string
+                    tolerationSeconds:
+                      description: TolerationSeconds represents the period of time
+                        the toleration (which must be of effect NoExecute, otherwise
+                        this field is ignored) tolerates the taint. By default, it
+                        is not set, which means tolerate the taint forever (do not
+                        evict). Zero and negative values will be treated as 0 (evict
+                        immediately) by the system.
+                      format: int64
+                      type: integer
+                    value:
+                      description: Value is the taint value the toleration matches
+                        to. If the operator is Exists, the value should be empty,
+                        otherwise just a regular string.
+                      type: string
+                  type: object
+                type: array
+            required:
+            - clusterSize
+            - kubernetesConfig
+            type: object
+          status:
+            description: RedisClusterSpec defines the desired state of RedisCluster
+            properties:
+              affinity:
+                description: Affinity is a group of affinity scheduling rules.
+                properties:
+                  nodeAffinity:
+                    description: Describes node affinity scheduling rules for the
+                      pod.
+                    properties:
+                      preferredDuringSchedulingIgnoredDuringExecution:
+                        description: The scheduler will prefer to schedule pods to
+                          nodes that satisfy the affinity expressions specified by
+                          this field, but it may choose a node that violates one or
+                          more of the expressions. The node that is most preferred
+                          is the one with the greatest sum of weights, i.e. for each
+                          node that meets all of the scheduling requirements (resource
+                          request, requiredDuringScheduling affinity expressions,
+                          etc.), compute a sum by iterating through the elements of
+                          this field and adding "weight" to the sum if the node matches
+                          the corresponding matchExpressions; the node(s) with the
+                          highest sum are the most preferred.
+                        items:
+                          description: An empty preferred scheduling term matches
+                            all objects with implicit weight 0 (i.e. it's a no-op).
+                            A null preferred scheduling term matches no objects (i.e.
+                            is also a no-op).
+                          properties:
+                            preference:
+                              description: A node selector term, associated with the
+                                corresponding weight.
+                              properties:
+                                matchExpressions:
+                                  description: A list of node selector requirements
+                                    by node's labels.
+                                  items:
+                                    description: A node selector requirement is a
+                                      selector that contains values, a key, and an
+                                      operator that relates the key and values.
+                                    properties:
+                                      key:
+                                        description: The label key that the selector
+                                          applies to.
+                                        type: string
+                                      operator:
+                                        description: Represents a key's relationship
+                                          to a set of values. Valid operators are
+                                          In, NotIn, Exists, DoesNotExist. Gt, and
+                                          Lt.
+                                        type: string
+                                      values:
+                                        description: An array of string values. If
+                                          the operator is In or NotIn, the values
+                                          array must be non-empty. If the operator
+                                          is Exists or DoesNotExist, the values array
+                                          must be empty. If the operator is Gt or
+                                          Lt, the values array must have a single
+                                          element, which will be interpreted as an
+                                          integer. This array is replaced during a
+                                          strategic merge patch.
+                                        items:
+                                          type: string
+                                        type: array
+                                    required:
+                                    - key
+                                    - operator
+                                    type: object
+                                  type: array
+                                matchFields:
+                                  description: A list of node selector requirements
+                                    by node's fields.
+                                  items:
+                                    description: A node selector requirement is a
+                                      selector that contains values, a key, and an
+                                      operator that relates the key and values.
+                                    properties:
+                                      key:
+                                        description: The label key that the selector
+                                          applies to.
+                                        type: string
+                                      operator:
+                                        description: Represents a key's relationship
+                                          to a set of values. Valid operators are
+                                          In, NotIn, Exists, DoesNotExist. Gt, and
+                                          Lt.
+                                        type: string
+                                      values:
+                                        description: An array of string values. If
+                                          the operator is In or NotIn, the values
+                                          array must be non-empty. If the operator
+                                          is Exists or DoesNotExist, the values array
+                                          must be empty. If the operator is Gt or
+                                          Lt, the values array must have a single
+                                          element, which will be interpreted as an
+                                          integer. This array is replaced during a
+                                          strategic merge patch.
+                                        items:
+                                          type: string
+                                        type: array
+                                    required:
+                                    - key
+                                    - operator
+                                    type: object
+                                  type: array
+                              type: object
+                            weight:
+                              description: Weight associated with matching the corresponding
+                                nodeSelectorTerm, in the range 1-100.
+                              format: int32
+                              type: integer
+                          required:
+                          - preference
+                          - weight
+                          type: object
+                        type: array
+                      requiredDuringSchedulingIgnoredDuringExecution:
+                        description: If the affinity requirements specified by this
+                          field are not met at scheduling time, the pod will not be
+                          scheduled onto the node. If the affinity requirements specified
+                          by this field cease to be met at some point during pod execution
+                          (e.g. due to an update), the system may or may not try to
+                          eventually evict the pod from its node.
+                        properties:
+                          nodeSelectorTerms:
+                            description: Required. A list of node selector terms.
+                              The terms are ORed.
+                            items:
+                              description: A null or empty node selector term matches
+                                no objects. The requirements of them are ANDed. The
+                                TopologySelectorTerm type implements a subset of the
+                                NodeSelectorTerm.
+                              properties:
+                                matchExpressions:
+                                  description: A list of node selector requirements
+                                    by node's labels.
+                                  items:
+                                    description: A node selector requirement is a
+                                      selector that contains values, a key, and an
+                                      operator that relates the key and values.
+                                    properties:
+                                      key:
+                                        description: The label key that the selector
+                                          applies to.
+                                        type: string
+                                      operator:
+                                        description: Represents a key's relationship
+                                          to a set of values. Valid operators are
+                                          In, NotIn, Exists, DoesNotExist. Gt, and
+                                          Lt.
+                                        type: string
+                                      values:
+                                        description: An array of string values. If
+                                          the operator is In or NotIn, the values
+                                          array must be non-empty. If the operator
+                                          is Exists or DoesNotExist, the values array
+                                          must be empty. If the operator is Gt or
+                                          Lt, the values array must have a single
+                                          element, which will be interpreted as an
+                                          integer. This array is replaced during a
+                                          strategic merge patch.
+                                        items:
+                                          type: string
+                                        type: array
+                                    required:
+                                    - key
+                                    - operator
+                                    type: object
+                                  type: array
+                                matchFields:
+                                  description: A list of node selector requirements
+                                    by node's fields.
+                                  items:
+                                    description: A node selector requirement is a
+                                      selector that contains values, a key, and an
+                                      operator that relates the key and values.
+                                    properties:
+                                      key:
+                                        description: The label key that the selector
+                                          applies to.
+                                        type: string
+                                      operator:
+                                        description: Represents a key's relationship
+                                          to a set of values. Valid operators are
+                                          In, NotIn, Exists, DoesNotExist. Gt, and
+                                          Lt.
+                                        type: string
+                                      values:
+                                        description: An array of string values. If
+                                          the operator is In or NotIn, the values
+                                          array must be non-empty. If the operator
+                                          is Exists or DoesNotExist, the values array
+                                          must be empty. If the operator is Gt or
+                                          Lt, the values array must have a single
+                                          element, which will be interpreted as an
+                                          integer. This array is replaced during a
+                                          strategic merge patch.
+                                        items:
+                                          type: string
+                                        type: array
+                                    required:
+                                    - key
+                                    - operator
+                                    type: object
+                                  type: array
+                              type: object
+                            type: array
+                        required:
+                        - nodeSelectorTerms
+                        type: object
+                    type: object
+                  podAffinity:
+                    description: Describes pod affinity scheduling rules (e.g. co-locate
+                      this pod in the same node, zone, etc. as some other pod(s)).
+                    properties:
+                      preferredDuringSchedulingIgnoredDuringExecution:
+                        description: The scheduler will prefer to schedule pods to
+                          nodes that satisfy the affinity expressions specified by
+                          this field, but it may choose a node that violates one or
+                          more of the expressions. The node that is most preferred
+                          is the one with the greatest sum of weights, i.e. for each
+                          node that meets all of the scheduling requirements (resource
+                          request, requiredDuringScheduling affinity expressions,
+                          etc.), compute a sum by iterating through the elements of
+                          this field and adding "weight" to the sum if the node has
+                          pods which matches the corresponding podAffinityTerm; the
+                          node(s) with the highest sum are the most preferred.
+                        items:
+                          description: The weights of all of the matched WeightedPodAffinityTerm
+                            fields are added per-node to find the most preferred node(s)
+                          properties:
+                            podAffinityTerm:
+                              description: Required. A pod affinity term, associated
+                                with the corresponding weight.
+                              properties:
+                                labelSelector:
+                                  description: A label query over a set of resources,
+                                    in this case pods.
+                                  properties:
+                                    matchExpressions:
+                                      description: matchExpressions is a list of label
+                                        selector requirements. The requirements are
+                                        ANDed.
+                                      items:
+                                        description: A label selector requirement
+                                          is a selector that contains values, a key,
+                                          and an operator that relates the key and
+                                          values.
+                                        properties:
+                                          key:
+                                            description: key is the label key that
+                                              the selector applies to.
+                                            type: string
+                                          operator:
+                                            description: operator represents a key's
+                                              relationship to a set of values. Valid
+                                              operators are In, NotIn, Exists and
+                                              DoesNotExist.
+                                            type: string
+                                          values:
+                                            description: values is an array of string
+                                              values. If the operator is In or NotIn,
+                                              the values array must be non-empty.
+                                              If the operator is Exists or DoesNotExist,
+                                              the values array must be empty. This
+                                              array is replaced during a strategic
+                                              merge patch.
+                                            items:
+                                              type: string
+                                            type: array
+                                        required:
+                                        - key
+                                        - operator
+                                        type: object
+                                      type: array
+                                    matchLabels:
+                                      additionalProperties:
+                                        type: string
+                                      description: matchLabels is a map of {key,value}
+                                        pairs. A single {key,value} in the matchLabels
+                                        map is equivalent to an element of matchExpressions,
+                                        whose key field is "key", the operator is
+                                        "In", and the values array contains only "value".
+                                        The requirements are ANDed.
+                                      type: object
+                                  type: object
+                                namespaces:
+                                  description: namespaces specifies which namespaces
+                                    the labelSelector applies to (matches against);
+                                    null or empty list means "this pod's namespace"
+                                  items:
+                                    type: string
+                                  type: array
+                                topologyKey:
+                                  description: This pod should be co-located (affinity)
+                                    or not co-located (anti-affinity) with the pods
+                                    matching the labelSelector in the specified namespaces,
+                                    where co-located is defined as running on a node
+                                    whose value of the label with key topologyKey
+                                    matches that of any node on which any of the selected
+                                    pods is running. Empty topologyKey is not allowed.
+                                  type: string
+                              required:
+                              - topologyKey
+                              type: object
+                            weight:
+                              description: weight associated with matching the corresponding
+                                podAffinityTerm, in the range 1-100.
+                              format: int32
+                              type: integer
+                          required:
+                          - podAffinityTerm
+                          - weight
+                          type: object
+                        type: array
+                      requiredDuringSchedulingIgnoredDuringExecution:
+                        description: If the affinity requirements specified by this
+                          field are not met at scheduling time, the pod will not be
+                          scheduled onto the node. If the affinity requirements specified
+                          by this field cease to be met at some point during pod execution
+                          (e.g. due to a pod label update), the system may or may
+                          not try to eventually evict the pod from its node. When
+                          there are multiple elements, the lists of nodes corresponding
+                          to each podAffinityTerm are intersected, i.e. all terms
+                          must be satisfied.
+                        items:
+                          description: Defines a set of pods (namely those matching
+                            the labelSelector relative to the given namespace(s))
+                            that this pod should be co-located (affinity) or not co-located
+                            (anti-affinity) with, where co-located is defined as running
+                            on a node whose value of the label with key <topologyKey>
+                            matches that of any node on which a pod of the set of
+                            pods is running
+                          properties:
+                            labelSelector:
+                              description: A label query over a set of resources,
+                                in this case pods.
+                              properties:
+                                matchExpressions:
+                                  description: matchExpressions is a list of label
+                                    selector requirements. The requirements are ANDed.
+                                  items:
+                                    description: A label selector requirement is a
+                                      selector that contains values, a key, and an
+                                      operator that relates the key and values.
+                                    properties:
+                                      key:
+                                        description: key is the label key that the
+                                          selector applies to.
+                                        type: string
+                                      operator:
+                                        description: operator represents a key's relationship
+                                          to a set of values. Valid operators are
+                                          In, NotIn, Exists and DoesNotExist.
+                                        type: string
+                                      values:
+                                        description: values is an array of string
+                                          values. If the operator is In or NotIn,
+                                          the values array must be non-empty. If the
+                                          operator is Exists or DoesNotExist, the
+                                          values array must be empty. This array is
+                                          replaced during a strategic merge patch.
+                                        items:
+                                          type: string
+                                        type: array
+                                    required:
+                                    - key
+                                    - operator
+                                    type: object
+                                  type: array
+                                matchLabels:
+                                  additionalProperties:
+                                    type: string
+                                  description: matchLabels is a map of {key,value}
+                                    pairs. A single {key,value} in the matchLabels
+                                    map is equivalent to an element of matchExpressions,
+                                    whose key field is "key", the operator is "In",
+                                    and the values array contains only "value". The
+                                    requirements are ANDed.
+                                  type: object
+                              type: object
+                            namespaces:
+                              description: namespaces specifies which namespaces the
+                                labelSelector applies to (matches against); null or
+                                empty list means "this pod's namespace"
+                              items:
+                                type: string
+                              type: array
+                            topologyKey:
+                              description: This pod should be co-located (affinity)
+                                or not co-located (anti-affinity) with the pods matching
+                                the labelSelector in the specified namespaces, where
+                                co-located is defined as running on a node whose value
+                                of the label with key topologyKey matches that of
+                                any node on which any of the selected pods is running.
+                                Empty topologyKey is not allowed.
+                              type: string
+                          required:
+                          - topologyKey
+                          type: object
+                        type: array
+                    type: object
+                  podAntiAffinity:
+                    description: Describes pod anti-affinity scheduling rules (e.g.
+                      avoid putting this pod in the same node, zone, etc. as some
+                      other pod(s)).
+                    properties:
+                      preferredDuringSchedulingIgnoredDuringExecution:
+                        description: The scheduler will prefer to schedule pods to
+                          nodes that satisfy the anti-affinity expressions specified
+                          by this field, but it may choose a node that violates one
+                          or more of the expressions. The node that is most preferred
+                          is the one with the greatest sum of weights, i.e. for each
+                          node that meets all of the scheduling requirements (resource
+                          request, requiredDuringScheduling anti-affinity expressions,
+                          etc.), compute a sum by iterating through the elements of
+                          this field and adding "weight" to the sum if the node has
+                          pods which matches the corresponding podAffinityTerm; the
+                          node(s) with the highest sum are the most preferred.
+                        items:
+                          description: The weights of all of the matched WeightedPodAffinityTerm
+                            fields are added per-node to find the most preferred node(s)
+                          properties:
+                            podAffinityTerm:
+                              description: Required. A pod affinity term, associated
+                                with the corresponding weight.
+                              properties:
+                                labelSelector:
+                                  description: A label query over a set of resources,
+                                    in this case pods.
+                                  properties:
+                                    matchExpressions:
+                                      description: matchExpressions is a list of label
+                                        selector requirements. The requirements are
+                                        ANDed.
+                                      items:
+                                        description: A label selector requirement
+                                          is a selector that contains values, a key,
+                                          and an operator that relates the key and
+                                          values.
+                                        properties:
+                                          key:
+                                            description: key is the label key that
+                                              the selector applies to.
+                                            type: string
+                                          operator:
+                                            description: operator represents a key's
+                                              relationship to a set of values. Valid
+                                              operators are In, NotIn, Exists and
+                                              DoesNotExist.
+                                            type: string
+                                          values:
+                                            description: values is an array of string
+                                              values. If the operator is In or NotIn,
+                                              the values array must be non-empty.
+                                              If the operator is Exists or DoesNotExist,
+                                              the values array must be empty. This
+                                              array is replaced during a strategic
+                                              merge patch.
+                                            items:
+                                              type: string
+                                            type: array
+                                        required:
+                                        - key
+                                        - operator
+                                        type: object
+                                      type: array
+                                    matchLabels:
+                                      additionalProperties:
+                                        type: string
+                                      description: matchLabels is a map of {key,value}
+                                        pairs. A single {key,value} in the matchLabels
+                                        map is equivalent to an element of matchExpressions,
+                                        whose key field is "key", the operator is
+                                        "In", and the values array contains only "value".
+                                        The requirements are ANDed.
+                                      type: object
+                                  type: object
+                                namespaces:
+                                  description: namespaces specifies which namespaces
+                                    the labelSelector applies to (matches against);
+                                    null or empty list means "this pod's namespace"
+                                  items:
+                                    type: string
+                                  type: array
+                                topologyKey:
+                                  description: This pod should be co-located (affinity)
+                                    or not co-located (anti-affinity) with the pods
+                                    matching the labelSelector in the specified namespaces,
+                                    where co-located is defined as running on a node
+                                    whose value of the label with key topologyKey
+                                    matches that of any node on which any of the selected
+                                    pods is running. Empty topologyKey is not allowed.
+                                  type: string
+                              required:
+                              - topologyKey
+                              type: object
+                            weight:
+                              description: weight associated with matching the corresponding
+                                podAffinityTerm, in the range 1-100.
+                              format: int32
+                              type: integer
+                          required:
+                          - podAffinityTerm
+                          - weight
+                          type: object
+                        type: array
+                      requiredDuringSchedulingIgnoredDuringExecution:
+                        description: If the anti-affinity requirements specified by
+                          this field are not met at scheduling time, the pod will
+                          not be scheduled onto the node. If the anti-affinity requirements
+                          specified by this field cease to be met at some point during
+                          pod execution (e.g. due to a pod label update), the system
+                          may or may not try to eventually evict the pod from its
+                          node. When there are multiple elements, the lists of nodes
+                          corresponding to each podAffinityTerm are intersected, i.e.
+                          all terms must be satisfied.
+                        items:
+                          description: Defines a set of pods (namely those matching
+                            the labelSelector relative to the given namespace(s))
+                            that this pod should be co-located (affinity) or not co-located
+                            (anti-affinity) with, where co-located is defined as running
+                            on a node whose value of the label with key <topologyKey>
+                            matches that of any node on which a pod of the set of
+                            pods is running
+                          properties:
+                            labelSelector:
+                              description: A label query over a set of resources,
+                                in this case pods.
+                              properties:
+                                matchExpressions:
+                                  description: matchExpressions is a list of label
+                                    selector requirements. The requirements are ANDed.
+                                  items:
+                                    description: A label selector requirement is a
+                                      selector that contains values, a key, and an
+                                      operator that relates the key and values.
+                                    properties:
+                                      key:
+                                        description: key is the label key that the
+                                          selector applies to.
+                                        type: string
+                                      operator:
+                                        description: operator represents a key's relationship
+                                          to a set of values. Valid operators are
+                                          In, NotIn, Exists and DoesNotExist.
+                                        type: string
+                                      values:
+                                        description: values is an array of string
+                                          values. If the operator is In or NotIn,
+                                          the values array must be non-empty. If the
+                                          operator is Exists or DoesNotExist, the
+                                          values array must be empty. This array is
+                                          replaced during a strategic merge patch.
+                                        items:
+                                          type: string
+                                        type: array
+                                    required:
+                                    - key
+                                    - operator
+                                    type: object
+                                  type: array
+                                matchLabels:
+                                  additionalProperties:
+                                    type: string
+                                  description: matchLabels is a map of {key,value}
+                                    pairs. A single {key,value} in the matchLabels
+                                    map is equivalent to an element of matchExpressions,
+                                    whose key field is "key", the operator is "In",
+                                    and the values array contains only "value". The
+                                    requirements are ANDed.
+                                  type: object
+                              type: object
+                            namespaces:
+                              description: namespaces specifies which namespaces the
+                                labelSelector applies to (matches against); null or
+                                empty list means "this pod's namespace"
+                              items:
+                                type: string
+                              type: array
+                            topologyKey:
+                              description: This pod should be co-located (affinity)
+                                or not co-located (anti-affinity) with the pods matching
+                                the labelSelector in the specified namespaces, where
+                                co-located is defined as running on a node whose value
+                                of the label with key topologyKey matches that of
+                                any node on which any of the selected pods is running.
+                                Empty topologyKey is not allowed.
+                              type: string
+                          required:
+                          - topologyKey
+                          type: object
+                        type: array
+                    type: object
+                type: object
+              clusterSize:
+                format: int32
+                type: integer
+                minimum: 3
+              kubernetesConfig:
+                description: KubernetesConfig will be the JSON struct for Basic Redis
+                  Config
+                properties:
+                  image:
+                    type: string
+                  imagePullPolicy:
+                    description: PullPolicy describes a policy for if/when to pull
+                      a container image
+                    type: string
+                  redisSecret:
+                    description: ExistingPasswordSecret is the struct to access the
+                      existing secret
+                    properties:
+                      key:
+                        type: string
+                      name:
+                        type: string
+                    type: object
+                  resources:
+                    description: ResourceRequirements describes the compute resource
+                      requirements.
+                    properties:
+                      limits:
+                        additionalProperties:
+                          anyOf:
+                          - type: integer
+                          - type: string
+                          pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                          x-kubernetes-int-or-string: true
+                        description: 'Limits describes the maximum amount of compute
+                          resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                        type: object
+                      requests:
+                        additionalProperties:
+                          anyOf:
+                          - type: integer
+                          - type: string
+                          pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                          x-kubernetes-int-or-string: true
+                        description: 'Requests describes the minimum amount of compute
+                          resources required. If Requests is omitted for a container,
+                          it defaults to Limits if that is explicitly specified, otherwise
+                          to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                        type: object
+                    type: object
+                  serviceType:
+                    type: string
+                required:
+                - image
+                - serviceType
+                type: object
+              nodeSelector:
+                additionalProperties:
+                  type: string
+                type: object
+              priorityClassName:
+                type: string
+              redisExporter:
+                description: RedisExporter interface will have the information for
+                  redis exporter related stuff
+                properties:
+                  enabled:
+                    type: boolean
+                  image:
+                    type: string
+                  imagePullPolicy:
+                    description: PullPolicy describes a policy for if/when to pull
+                      a container image
+                    type: string
+                  resources:
+                    description: ResourceRequirements describes the compute resource
+                      requirements.
+                    properties:
+                      limits:
+                        additionalProperties:
+                          anyOf:
+                          - type: integer
+                          - type: string
+                          pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                          x-kubernetes-int-or-string: true
+                        description: 'Limits describes the maximum amount of compute
+                          resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                        type: object
+                      requests:
+                        additionalProperties:
+                          anyOf:
+                          - type: integer
+                          - type: string
+                          pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                          x-kubernetes-int-or-string: true
+                        description: 'Requests describes the minimum amount of compute
+                          resources required. If Requests is omitted for a container,
+                          it defaults to Limits if that is explicitly specified, otherwise
+                          to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                        type: object
+                    type: object
+                required:
+                - image
+                type: object
+              redisFollower:
+                description: RedisFollower interface will have the redis slave configuration
+                properties:
+                  serviceType:
+                    type: string
+                type: object
+              redisLeader:
+                description: RedisLeader interface will have the redis master configuration
+                properties:
+                  serviceType:
+                    type: string
+                type: object
+              resources:
+                description: ResourceRequirements describes the compute resource requirements.
+                properties:
+                  limits:
+                    additionalProperties:
+                      anyOf:
+                      - type: integer
+                      - type: string
+                      pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                      x-kubernetes-int-or-string: true
+                    description: 'Limits describes the maximum amount of compute resources
+                      allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                    type: object
+                  requests:
+                    additionalProperties:
+                      anyOf:
+                      - type: integer
+                      - type: string
+                      pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                      x-kubernetes-int-or-string: true
+                    description: 'Requests describes the minimum amount of compute
+                      resources required. If Requests is omitted for a container,
+                      it defaults to Limits if that is explicitly specified, otherwise
+                      to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                    type: object
+                type: object
+              securityContext:
+                description: PodSecurityContext holds pod-level security attributes
+                  and common container settings. Some fields are also present in container.securityContext.  Field
+                  values of container.securityContext take precedence over field values
+                  of PodSecurityContext.
+                properties:
+                  fsGroup:
+                    description: "A special supplemental group that applies to all
+                      containers in a pod. Some volume types allow the Kubelet to
+                      change the ownership of that volume to be owned by the pod:
+                      \n 1. The owning GID will be the FSGroup 2. The setgid bit is
+                      set (new files created in the volume will be owned by FSGroup)
+                      3. The permission bits are OR'd with rw-rw---- \n If unset,
+                      the Kubelet will not modify the ownership and permissions of
+                      any volume."
+                    format: int64
+                    type: integer
+                  fsGroupChangePolicy:
+                    description: 'fsGroupChangePolicy defines behavior of changing
+                      ownership and permission of the volume before being exposed
+                      inside Pod. This field will only apply to volume types which
+                      support fsGroup based ownership(and permissions). It will have
+                      no effect on ephemeral volume types such as: secret, configmaps
+                      and emptydir. Valid values are "OnRootMismatch" and "Always".
+                      If not specified defaults to "Always".'
+                    type: string
+                  runAsGroup:
+                    description: The GID to run the entrypoint of the container process.
+                      Uses runtime default if unset. May also be set in SecurityContext.  If
+                      set in both SecurityContext and PodSecurityContext, the value
+                      specified in SecurityContext takes precedence for that container.
+                    format: int64
+                    type: integer
+                  runAsNonRoot:
+                    description: Indicates that the container must run as a non-root
+                      user. If true, the Kubelet will validate the image at runtime
+                      to ensure that it does not run as UID 0 (root) and fail to start
+                      the container if it does. If unset or false, no such validation
+                      will be performed. May also be set in SecurityContext.  If set
+                      in both SecurityContext and PodSecurityContext, the value specified
+                      in SecurityContext takes precedence.
+                    type: boolean
+                  runAsUser:
+                    description: The UID to run the entrypoint of the container process.
+                      Defaults to user specified in image metadata if unspecified.
+                      May also be set in SecurityContext.  If set in both SecurityContext
+                      and PodSecurityContext, the value specified in SecurityContext
+                      takes precedence for that container.
+                    format: int64
+                    type: integer
+                  seLinuxOptions:
+                    description: The SELinux context to be applied to all containers.
+                      If unspecified, the container runtime will allocate a random
+                      SELinux context for each container.  May also be set in SecurityContext.  If
+                      set in both SecurityContext and PodSecurityContext, the value
+                      specified in SecurityContext takes precedence for that container.
+                    properties:
+                      level:
+                        description: Level is SELinux level label that applies to
+                          the container.
+                        type: string
+                      role:
+                        description: Role is a SELinux role label that applies to
+                          the container.
+                        type: string
+                      type:
+                        description: Type is a SELinux type label that applies to
+                          the container.
+                        type: string
+                      user:
+                        description: User is a SELinux user label that applies to
+                          the container.
+                        type: string
+                    type: object
+                  seccompProfile:
+                    description: The seccomp options to use by the containers in this
+                      pod.
+                    properties:
+                      localhostProfile:
+                        description: localhostProfile indicates a profile defined
+                          in a file on the node should be used. The profile must be
+                          preconfigured on the node to work. Must be a descending
+                          path, relative to the kubelet's configured seccomp profile
+                          location. Must only be set if type is "Localhost".
+                        type: string
+                      type:
+                        description: "type indicates which kind of seccomp profile
+                          will be applied. Valid options are: \n Localhost - a profile
+                          defined in a file on the node should be used. RuntimeDefault
+                          - the container runtime default profile should be used.
+                          Unconfined - no profile should be applied."
+                        type: string
+                    required:
+                    - type
+                    type: object
+                  supplementalGroups:
+                    description: A list of groups applied to the first process run
+                      in each container, in addition to the container's primary GID.  If
+                      unspecified, no groups will be added to any container.
+                    items:
+                      format: int64
+                      type: integer
+                    type: array
+                  sysctls:
+                    description: Sysctls hold a list of namespaced sysctls used for
+                      the pod. Pods with unsupported sysctls (by the container runtime)
+                      might fail to launch.
+                    items:
+                      description: Sysctl defines a kernel parameter to be set
+                      properties:
+                        name:
+                          description: Name of a property to set
+                          type: string
+                        value:
+                          description: Value of a property to set
+                          type: string
+                      required:
+                      - name
+                      - value
+                      type: object
+                    type: array
+                  windowsOptions:
+                    description: The Windows specific settings applied to all containers.
+                      If unspecified, the options within a container's SecurityContext
+                      will be used. If set in both SecurityContext and PodSecurityContext,
+                      the value specified in SecurityContext takes precedence.
+                    properties:
+                      gmsaCredentialSpec:
+                        description: GMSACredentialSpec is where the GMSA admission
+                          webhook (https://github.com/kubernetes-sigs/windows-gmsa)
+                          inlines the contents of the GMSA credential spec named by
+                          the GMSACredentialSpecName field.
+                        type: string
+                      gmsaCredentialSpecName:
+                        description: GMSACredentialSpecName is the name of the GMSA
+                          credential spec to use.
+                        type: string
+                      runAsUserName:
+                        description: The UserName in Windows to run the entrypoint
+                          of the container process. Defaults to the user specified
+                          in image metadata if unspecified. May also be set in PodSecurityContext.
+                          If set in both SecurityContext and PodSecurityContext, the
+                          value specified in SecurityContext takes precedence.
+                        type: string
+                    type: object
+                type: object
+              storage:
+                description: Storage is the inteface to add pvc and pv support in
+                  redis
+                properties:
+                  volumeClaimTemplate:
+                    description: PersistentVolumeClaim is a user's request for and
+                      claim to a persistent volume
+                    properties:
+                      apiVersion:
+                        description: 'APIVersion defines the versioned schema of this
+                          representation of an object. Servers should convert recognized
+                          schemas to the latest internal value, and may reject unrecognized
+                          values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+                        type: string
+                      kind:
+                        description: 'Kind is a string value representing the REST
+                          resource this object represents. Servers may infer this
+                          from the endpoint the client submits requests to. Cannot
+                          be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                        type: string
+                      metadata:
+                        description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata'
+                        type: object
+                      spec:
+                        description: 'Spec defines the desired characteristics of
+                          a volume requested by a pod author. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
+                        properties:
+                          accessModes:
+                            description: 'AccessModes contains the desired access
+                              modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
+                            items:
+                              type: string
+                            type: array
+                          dataSource:
+                            description: 'This field can be used to specify either:
+                              * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot
+                              - Beta) * An existing PVC (PersistentVolumeClaim) *
+                              An existing custom resource/object that implements data
+                              population (Alpha) In order to use VolumeSnapshot object
+                              types, the appropriate feature gate must be enabled
+                              (VolumeSnapshotDataSource or AnyVolumeDataSource) If
+                              the provisioner or an external controller can support
+                              the specified data source, it will create a new volume
+                              based on the contents of the specified data source.
+                              If the specified data source is not supported, the volume
+                              will not be created and the failure will be reported
+                              as an event. In the future, we plan to support more
+                              data source types and the behavior of the provisioner
+                              may change.'
+                            properties:
+                              apiGroup:
+                                description: APIGroup is the group for the resource
+                                  being referenced. If APIGroup is not specified,
+                                  the specified Kind must be in the core API group.
+                                  For any other third-party types, APIGroup is required.
+                                type: string
+                              kind:
+                                description: Kind is the type of resource being referenced
+                                type: string
+                              name:
+                                description: Name is the name of resource being referenced
+                                type: string
+                            required:
+                            - kind
+                            - name
+                            type: object
+                          resources:
+                            description: 'Resources represents the minimum resources
+                              the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources'
+                            properties:
+                              limits:
+                                additionalProperties:
+                                  anyOf:
+                                  - type: integer
+                                  - type: string
+                                  pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                  x-kubernetes-int-or-string: true
+                                description: 'Limits describes the maximum amount
+                                  of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                                type: object
+                              requests:
+                                additionalProperties:
+                                  anyOf:
+                                  - type: integer
+                                  - type: string
+                                  pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                                  x-kubernetes-int-or-string: true
+                                description: 'Requests describes the minimum amount
+                                  of compute resources required. If Requests is omitted
+                                  for a container, it defaults to Limits if that is
+                                  explicitly specified, otherwise to an implementation-defined
+                                  value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/'
+                                type: object
+                            type: object
+                          selector:
+                            description: A label query over volumes to consider for
+                              binding.
+                            properties:
+                              matchExpressions:
+                                description: matchExpressions is a list of label selector
+                                  requirements. The requirements are ANDed.
+                                items:
+                                  description: A label selector requirement is a selector
+                                    that contains values, a key, and an operator that
+                                    relates the key and values.
+                                  properties:
+                                    key:
+                                      description: key is the label key that the selector
+                                        applies to.
+                                      type: string
+                                    operator:
+                                      description: operator represents a key's relationship
+                                        to a set of values. Valid operators are In,
+                                        NotIn, Exists and DoesNotExist.
+                                      type: string
+                                    values:
+                                      description: values is an array of string values.
+                                        If the operator is In or NotIn, the values
+                                        array must be non-empty. If the operator is
+                                        Exists or DoesNotExist, the values array must
+                                        be empty. This array is replaced during a
+                                        strategic merge patch.
+                                      items:
+                                        type: string
+                                      type: array
+                                  required:
+                                  - key
+                                  - operator
+                                  type: object
+                                type: array
+                              matchLabels:
+                                additionalProperties:
+                                  type: string
+                                description: matchLabels is a map of {key,value} pairs.
+                                  A single {key,value} in the matchLabels map is equivalent
+                                  to an element of matchExpressions, whose key field
+                                  is "key", the operator is "In", and the values array
+                                  contains only "value". The requirements are ANDed.
+                                type: object
+                            type: object
+                          storageClassName:
+                            description: 'Name of the StorageClass required by the
+                              claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1'
+                            type: string
+                          volumeMode:
+                            description: volumeMode defines what type of volume is
+                              required by the claim. Value of Filesystem is implied
+                              when not included in claim spec.
+                            type: string
+                          volumeName:
+                            description: VolumeName is the binding reference to the
+                              PersistentVolume backing this claim.
+                            type: string
+                        type: object
+                      status:
+                        description: 'Status represents the current information/status
+                          of a persistent volume claim. Read-only. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims'
+                        properties:
+                          accessModes:
+                            description: 'AccessModes contains the actual access modes
+                              the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
+                            items:
+                              type: string
+                            type: array
+                          capacity:
+                            additionalProperties:
+                              anyOf:
+                              - type: integer
+                              - type: string
+                              pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                              x-kubernetes-int-or-string: true
+                            description: Represents the actual resources of the underlying
+                              volume.
+                            type: object
+                          conditions:
+                            description: Current Condition of persistent volume claim.
+                              If underlying persistent volume is being resized then
+                              the Condition will be set to 'ResizeStarted'.
+                            items:
+                              description: PersistentVolumeClaimCondition contails
+                                details about state of pvc
+                              properties:
+                                lastProbeTime:
+                                  description: Last time we probed the condition.
+                                  format: date-time
+                                  type: string
+                                lastTransitionTime:
+                                  description: Last time the condition transitioned
+                                    from one status to another.
+                                  format: date-time
+                                  type: string
+                                message:
+                                  description: Human-readable message indicating details
+                                    about last transition.
+                                  type: string
+                                reason:
+                                  description: Unique, this should be a short, machine
+                                    understandable string that gives the reason for
+                                    condition's last transition. If it reports "ResizeStarted"
+                                    that means the underlying persistent volume is
+                                    being resized.
+                                  type: string
+                                status:
+                                  type: string
+                                type:
+                                  description: PersistentVolumeClaimConditionType
+                                    is a valid value of PersistentVolumeClaimCondition.Type
+                                  type: string
+                              required:
+                              - status
+                              - type
+                              type: object
+                            type: array
+                          phase:
+                            description: Phase represents the current phase of PersistentVolumeClaim.
+                            type: string
+                        type: object
+                    type: object
+                type: object
+              tolerations:
+                items:
+                  description: The pod this Toleration is attached to tolerates any
+                    taint that matches the triple <key,value,effect> using the matching
+                    operator <operator>.
+                  properties:
+                    effect:
+                      description: Effect indicates the taint effect to match. Empty
+                        means match all taint effects. When specified, allowed values
+                        are NoSchedule, PreferNoSchedule and NoExecute.
+                      type: string
+                    key:
+                      description: Key is the taint key that the toleration applies
+                        to. Empty means match all taint keys. If the key is empty,
+                        operator must be Exists; this combination means to match all
+                        values and all keys.
+                      type: string
+                    operator:
+                      description: Operator represents a key's relationship to the
+                        value. Valid operators are Exists and Equal. Defaults to Equal.
+                        Exists is equivalent to wildcard for value, so that a pod
+                        can tolerate all taints of a particular category.
+                      type: string
+                    tolerationSeconds:
+                      description: TolerationSeconds represents the period of time
+                        the toleration (which must be of effect NoExecute, otherwise
+                        this field is ignored) tolerates the taint. By default, it
+                        is not set, which means tolerate the taint forever (do not
+                        evict). Zero and negative values will be treated as 0 (evict
+                        immediately) by the system.
+                      format: int64
+                      type: integer
+                    value:
+                      description: Value is the taint value the toleration matches
+                        to. If the operator is Exists, the value should be empty,
+                        otherwise just a regular string.
+                      type: string
+                  type: object
+                type: array
+            required:
+            - clusterSize
+            - kubernetesConfig
+            type: object
+        type: object
+    additionalPrinterColumns:
+    - jsonPath: .spec.clusterSize
+      description: Current master node count
+      name: Master
+      type: integer
+    - jsonPath: .spec.clusterSize
+      description: Current slave node count
+      name: Slave
+      type: integer
+    - jsonPath: .metadata.creationTimestamp
+      description: Last Deployment Time
+      name: Last Deployment Time
+      type: date
+    served: true
+    storage: true
+    subresources:
+      status: {}
+status:
+  acceptedNames:
+    kind: ""
+    plural: ""
+  conditions: []
+  storedVersions: []
diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml
index 10d6416e78df9d91c09d29823b1b4ef878cb13f5..6376c97423e683c9bce2b0d0de8de029eadaca19 100644
--- a/config/crd/kustomization.yaml
+++ b/config/crd/kustomization.yaml
@@ -3,17 +3,20 @@
 # It should be run by config/default
 resources:
 - bases/redis.redis.opstreelabs.in_redis.yaml
+- bases/redis.redis.opstreelabs.in_redisclusters.yaml
 # +kubebuilder:scaffold:crdkustomizeresource
 
 patchesStrategicMerge:
 # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
 # patches here are for enabling the conversion webhook for each CRD
 #- patches/webhook_in_redis.yaml
+#- patches/webhook_in_redisclusters.yaml
 # +kubebuilder:scaffold:crdkustomizewebhookpatch
 
 # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix.
 # patches here are for enabling the CA injection for each CRD
 #- patches/cainjection_in_redis.yaml
+#- patches/cainjection_in_redisclusters.yaml
 # +kubebuilder:scaffold:crdkustomizecainjectionpatch
 
 # the following config is for teaching kustomize how to do kustomization for CRDs.
diff --git a/config/crd/patches/cainjection_in_redisclusters.yaml b/config/crd/patches/cainjection_in_redisclusters.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..081973be5ab0f9a6906be9b9a134530078bbec11
--- /dev/null
+++ b/config/crd/patches/cainjection_in_redisclusters.yaml
@@ -0,0 +1,7 @@
+# The following patch adds a directive for certmanager to inject CA into the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
+  name: redisclusters.redis.redis.opstreelabs.in
diff --git a/config/crd/patches/webhook_in_redisclusters.yaml b/config/crd/patches/webhook_in_redisclusters.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0be675bd734b433207e252e6694b8efffd8d337f
--- /dev/null
+++ b/config/crd/patches/webhook_in_redisclusters.yaml
@@ -0,0 +1,14 @@
+# The following patch enables a conversion webhook for the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  name: redisclusters.redis.redis.opstreelabs.in
+spec:
+  conversion:
+    strategy: Webhook
+    webhook:
+      clientConfig:
+        service:
+          namespace: system
+          name: webhook-service
+          path: /convert
diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml
index 0000086911b6202bff21c1e1e849a337dee73732..5b95927503116934c2836421f90fc4a40c5c8565 100644
--- a/config/manager/manager.yaml
+++ b/config/manager/manager.yaml
@@ -1,3 +1,4 @@
+---
 apiVersion: v1
 kind: Namespace
 metadata:
@@ -29,7 +30,8 @@ spec:
         - /manager
         args:
         - --leader-elect
-        image: quay.io/opstree/redis-operator:v0.3.0
+        image: quay.io/opstree/redis-operator:v0.6.0
+        imagePullPolicy: Always
         name: manager
         securityContext:
           allowPrivilegeEscalation: false
@@ -48,10 +50,10 @@ spec:
         resources:
           limits:
             cpu: 100m
-            memory: 30Mi
+            memory: 100Mi
           requests:
             cpu: 100m
-            memory: 20Mi
+            memory: 100Mi
       terminationGracePeriodSeconds: 10
       serviceAccount: redis-operator
       serviceAccountName: redis-operator
diff --git a/config/rbac/rediscluster_editor_role.yaml b/config/rbac/rediscluster_editor_role.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..efec1abeff8488b4ea969acd47eba88274dbea8c
--- /dev/null
+++ b/config/rbac/rediscluster_editor_role.yaml
@@ -0,0 +1,24 @@
+# permissions for end users to edit redisclusters.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: rediscluster-editor-role
+rules:
+- apiGroups:
+  - redis.redis.opstreelabs.in
+  resources:
+  - redisclusters
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - redis.redis.opstreelabs.in
+  resources:
+  - redisclusters/status
+  verbs:
+  - get
diff --git a/config/rbac/rediscluster_viewer_role.yaml b/config/rbac/rediscluster_viewer_role.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..7b0cd98496df6cd346359cca03492b9bdf02f346
--- /dev/null
+++ b/config/rbac/rediscluster_viewer_role.yaml
@@ -0,0 +1,20 @@
+# permissions for end users to view redisclusters.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: rediscluster-viewer-role
+rules:
+- apiGroups:
+  - redis.redis.opstreelabs.in
+  resources:
+  - redisclusters
+  verbs:
+  - get
+  - list
+  - watch
+- apiGroups:
+  - redis.redis.opstreelabs.in
+  resources:
+  - redisclusters/status
+  verbs:
+  - get
diff --git a/config/rbac/serviceaccount.yaml b/config/rbac/serviceaccount.yaml
index 9b500d196d8d145bf34d7929fec3df3505e94853..5bdfaf0544a80bbf69defc570dee935b7e7710fc 100644
--- a/config/rbac/serviceaccount.yaml
+++ b/config/rbac/serviceaccount.yaml
@@ -3,4 +3,3 @@ kind: ServiceAccount
 metadata:
   name: redis-operator
   namespace: ot-operators
-
diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml
index 17a2f1bd6eb3b42cd90c809dd5b765acabea4706..5428c77aa3f51b919e5afb50771685fc6b31ab4e 100644
--- a/config/samples/kustomization.yaml
+++ b/config/samples/kustomization.yaml
@@ -1,4 +1,5 @@
 ## Append samples you want in your CSV to this file as resources ##
 resources:
 - redis_v1beta1_redis.yaml
+- redis_v1beta1_rediscluster.yaml
 # +kubebuilder:scaffold:manifestskustomizesamples
diff --git a/controllers/redis_controller.go b/controllers/redis_controller.go
index 365f676ac0ef732c941e2048bb8f514729b334b6..989fa9d4da9a349c3db625817cf1cbfac7c82a9b 100644
--- a/controllers/redis_controller.go
+++ b/controllers/redis_controller.go
@@ -18,15 +18,11 @@ package controllers
 
 import (
 	"context"
-	"strconv"
 	"time"
 
 	"github.com/go-logr/logr"
-	appsv1 "k8s.io/api/apps/v1"
 	"k8s.io/apimachinery/pkg/api/errors"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/apimachinery/pkg/types"
 	"redis-operator/k8sutils"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
@@ -42,22 +38,10 @@ type RedisReconciler struct {
 	Scheme *runtime.Scheme
 }
 
-// +kubebuilder:rbac:groups=redis.redis.opstreelabs.in,resources=redis,verbs=get;list;watch;create;update;patch;delete
-// +kubebuilder:rbac:groups=redis.redis.opstreelabs.in,resources=redis/status,verbs=get;update;patch
-// +kubebuilder:rbac:groups=redis.redis.opstreelabs.in,resources=redis/finalizers,verbs=update
-
-// Reconcile is part of the main kubernetes reconciliation loop which aims to
-// move the current state of the cluster closer to the desired state.
-// TODO(user): Modify the Reconcile function to compare the state specified by
-// the Redis object against the actual cluster state, and then
-// perform operations to make the cluster state reflect the state specified by
-// the user.
-//
-// For more details, check Reconcile and its Result here:
-// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.7.0/pkg/reconcile
+// Reconcile is part of the main kubernetes reconciliation loop which aims
 func (r *RedisReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
 	reqLogger := r.Log.WithValues("Request.Namespace", req.Namespace, "Request.Name", req.Name)
-	reqLogger.Info("Reconciling Opstree Redis controller")
+	reqLogger.Info("Reconciling opstree redis controller")
 	instance := &redisv1beta1.Redis{}
 
 	err := r.Client.Get(context.TODO(), req.NamespacedName, instance)
@@ -71,59 +55,17 @@ func (r *RedisReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
 	if err := controllerutil.SetControllerReference(instance, instance, r.Scheme); err != nil {
 		return ctrl.Result{}, err
 	}
+	err = k8sutils.CreateStandAloneRedis(instance)
+	if err != nil {
+		return ctrl.Result{}, err
+	}
+	err = k8sutils.CreateStandAloneService(instance)
 
-	found := &appsv1.StatefulSet{}
-	err = r.Client.Get(context.TODO(), types.NamespacedName{Name: instance.Name, Namespace: instance.Namespace}, found)
-	if err != nil && errors.IsNotFound(err) {
-		if instance.Spec.GlobalConfig.Password != nil && instance.Spec.GlobalConfig.ExistingPasswordSecret == nil {
-			k8sutils.CreateRedisSecret(instance)
-		}
-		if instance.Spec.Mode == "cluster" {
-			k8sutils.CreateRedisMaster(instance)
-			k8sutils.CreateMasterService(instance)
-			k8sutils.CreateMasterHeadlessService(instance)
-			k8sutils.CreateRedisSlave(instance)
-			k8sutils.CreateSlaveService(instance)
-			k8sutils.CreateSlaveHeadlessService(instance)
-			redisMasterInfo, err := k8sutils.GenerateK8sClient().AppsV1().StatefulSets(instance.Namespace).Get(context.TODO(), instance.ObjectMeta.Name+"-master", metav1.GetOptions{})
-			if err != nil {
-				return ctrl.Result{}, err
-			}
-			redisSlaveInfo, err := k8sutils.GenerateK8sClient().AppsV1().StatefulSets(instance.Namespace).Get(context.TODO(), instance.ObjectMeta.Name+"-slave", metav1.GetOptions{})
-			if err != nil {
-				return ctrl.Result{}, err
-			}
-			if int(redisMasterInfo.Status.ReadyReplicas) != int(*instance.Spec.Size) && int(redisSlaveInfo.Status.ReadyReplicas) != int(*instance.Spec.Size) {
-				reqLogger.Info("Redis master and slave nodes are not ready yet", "Ready.Replicas", strconv.Itoa(int(redisMasterInfo.Status.ReadyReplicas)), "Expected.Replicas", instance.Spec.Size)
-				return ctrl.Result{RequeueAfter: time.Second * 120}, nil
-			}
-			reqLogger.Info("Creating redis cluster by executing cluster creation commands", "Ready.Replicas", strconv.Itoa(int(redisMasterInfo.Status.ReadyReplicas)))
-			if k8sutils.CheckRedisNodeCount(instance, "") != int(*instance.Spec.Size)*2 {
-				masterCount := k8sutils.CheckRedisNodeCount(instance, "master")
-				if masterCount != int(*instance.Spec.Size) {
-					reqLogger.Info("Not all masters are part of the cluster...", "Masters.Count", masterCount, "Instance.Size", instance.Spec.Size)
-					k8sutils.ExecuteRedisClusterCommand(instance)
-				} else {
-					reqLogger.Info("All masters are part of the cluster, adding slaves/replicas", "Masters.Count", masterCount, "Instance.Size", instance.Spec.Size)
-					k8sutils.ExecuteRedisReplicationCommand(instance)
-				}
-			} else {
-				reqLogger.Info("Redis master count is desired")
-				if k8sutils.CheckRedisClusterState(instance) >= int(*instance.Spec.Size)*2-1 {
-					k8sutils.ExecuteFaioverOperation(instance)
-				}
-				return ctrl.Result{RequeueAfter: time.Second * 120}, nil
-			}
-		} else if instance.Spec.Mode == "standalone" {
-			k8sutils.CreateRedisStandalone(instance)
-			k8sutils.CreateStandaloneService(instance)
-			k8sutils.CreateStandaloneHeadlessService(instance)
-		}
-	} else if err != nil {
+	if err != nil {
 		return ctrl.Result{}, err
 	}
 
-	reqLogger.Info("Will reconcile in again 10 seconds")
+	reqLogger.Info("Will reconcile redis operator in again 10 seconds")
 	return ctrl.Result{RequeueAfter: time.Second * 10}, nil
 }
 
diff --git a/controllers/rediscluster_controller.go b/controllers/rediscluster_controller.go
new file mode 100644
index 0000000000000000000000000000000000000000..2bad5a0c2874563d32bab971f59eda93f4b315fb
--- /dev/null
+++ b/controllers/rediscluster_controller.go
@@ -0,0 +1,115 @@
+/*
+Copyright 2020 Opstree Solutions.
+
+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
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package controllers
+
+import (
+	"context"
+	"strconv"
+	"time"
+
+	"github.com/go-logr/logr"
+	"k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/runtime"
+	"redis-operator/k8sutils"
+	ctrl "sigs.k8s.io/controller-runtime"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
+
+	redisv1beta1 "redis-operator/api/v1beta1"
+)
+
+// RedisClusterReconciler reconciles a RedisCluster object
+type RedisClusterReconciler struct {
+	client.Client
+	Log    logr.Logger
+	Scheme *runtime.Scheme
+}
+
+// Reconcile is part of the main kubernetes reconciliation loop
+func (r *RedisClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
+	reqLogger := r.Log.WithValues("Request.Namespace", req.Namespace, "Request.Name", req.Name)
+	reqLogger.Info("Reconciling opstree redis Cluster controller")
+	instance := &redisv1beta1.RedisCluster{}
+
+	err := r.Client.Get(context.TODO(), req.NamespacedName, instance)
+	if err != nil {
+		if errors.IsNotFound(err) {
+			return ctrl.Result{}, nil
+		}
+		return ctrl.Result{}, err
+	}
+
+	if err := controllerutil.SetControllerReference(instance, instance, r.Scheme); err != nil {
+		return ctrl.Result{}, err
+	}
+	err = k8sutils.CreateRedisLeader(instance)
+	if err != nil {
+		return ctrl.Result{}, err
+	}
+	err = k8sutils.CreateRedisLeaderService(instance)
+	if err != nil {
+		return ctrl.Result{}, err
+	}
+	err = k8sutils.CreateRedisFollower(instance)
+	if err != nil {
+		return ctrl.Result{}, err
+	}
+	err = k8sutils.CreateRedisFollowerService(instance)
+	if err != nil {
+		return ctrl.Result{}, err
+	}
+
+	redisLeaderInfo, err := k8sutils.GetStateFulSet(instance.Namespace, instance.ObjectMeta.Name+"-leader")
+	if err != nil {
+		return ctrl.Result{}, err
+	}
+	redisFollowerInfo, err := k8sutils.GetStateFulSet(instance.Namespace, instance.ObjectMeta.Name+"-follower")
+	if err != nil {
+		return ctrl.Result{}, err
+	}
+	if int(redisLeaderInfo.Status.ReadyReplicas) != int(*instance.Spec.Size) && int(redisFollowerInfo.Status.ReadyReplicas) != int(*instance.Spec.Size) {
+		reqLogger.Info("Redis leader and follower nodes are not ready yet", "Ready.Replicas", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)), "Expected.Replicas", instance.Spec.Size)
+		return ctrl.Result{RequeueAfter: time.Second * 120}, nil
+	}
+	reqLogger.Info("Creating redis cluster by executing cluster creation commands", "Ready.Replicas", strconv.Itoa(int(redisLeaderInfo.Status.ReadyReplicas)))
+	if k8sutils.CheckRedisNodeCount(instance, "") != int(*instance.Spec.Size)*2 {
+		leaderCount := k8sutils.CheckRedisNodeCount(instance, "leader")
+		if leaderCount != int(*instance.Spec.Size) {
+			reqLogger.Info("Not all leader are part of the cluster...", "Leaders.Count", leaderCount, "Instance.Size", instance.Spec.Size)
+			k8sutils.ExecuteRedisClusterCommand(instance)
+		} else {
+			reqLogger.Info("All leader are part of the cluster, adding follower/replicas", "Leaders.Count", leaderCount, "Instance.Size", instance.Spec.Size)
+			k8sutils.ExecuteRedisReplicationCommand(instance)
+		}
+	} else {
+		reqLogger.Info("Redis leader count is desired")
+		if k8sutils.CheckRedisClusterState(instance) >= int(*instance.Spec.Size)*2-1 {
+			reqLogger.Info("Redis leader is not desired, executing failover operation")
+			k8sutils.ExecuteFaioverOperation(instance)
+		}
+		return ctrl.Result{RequeueAfter: time.Second * 120}, nil
+	}
+	reqLogger.Info("Will reconcile redis cluster operator in again 10 seconds")
+	return ctrl.Result{RequeueAfter: time.Second * 10}, nil
+}
+
+// SetupWithManager sets up the controller with the Manager.
+func (r *RedisClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
+	return ctrl.NewControllerManagedBy(mgr).
+		For(&redisv1beta1.RedisCluster{}).
+		Complete(r)
+}
diff --git a/controllers/suite_test.go b/controllers/suite_test.go
index 0e15f713052e8a01b2e909702d24fb770422f6ce..4d9f786f56c2524bee863e51af26a0a14b3d970c 100644
--- a/controllers/suite_test.go
+++ b/controllers/suite_test.go
@@ -23,6 +23,7 @@ import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 	"k8s.io/client-go/kubernetes/scheme"
+
 	// "k8s.io/client-go/rest"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/envtest"
@@ -64,6 +65,9 @@ var _ = BeforeSuite(func() {
 	err = redisv1beta1.AddToScheme(scheme.Scheme)
 	Expect(err).NotTo(HaveOccurred())
 
+	err = redisv1beta1.AddToScheme(scheme.Scheme)
+	Expect(err).NotTo(HaveOccurred())
+
 	// +kubebuilder:scaffold:scheme
 
 	k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
diff --git a/docs/src/.vuepress/config.js b/docs/src/.vuepress/config.js
index 3e92114048fe4b09f57049f11d1307b54795ec7e..5c17187f02f1a353840e8ad5a2e3ca848ddf117e 100755
--- a/docs/src/.vuepress/config.js
+++ b/docs/src/.vuepress/config.js
@@ -59,10 +59,17 @@ module.exports = {
           children: [
             'installation.md',
             'setup.md',
-            'configuration.md',
             'failover.md',
           ]
         },
+        {
+          title: 'Configuration',
+          collapsable: false,
+          children: [
+            'redis-config.md',
+            'redis-cluster-config.md',
+          ]
+        },
         {
           title: 'Monitoring',
           collapsable: false,
diff --git a/docs/src/guide/README.md b/docs/src/guide/README.md
index 944e7c6b44556fbbcb4f0a334c9951f116b7c876..0d128ab63e80ad2363abbaffb785d5e5f8702684 100755
--- a/docs/src/guide/README.md
+++ b/docs/src/guide/README.md
@@ -10,14 +10,14 @@ Documentation is available here:- https://ot-container-kit.github.io/redis-opera
 
 The type of Redis setup which is currently supported:-
 
-- Redis in-build master slave with sharding and replication mode
+- Redis Cluster (in-built leader follower with sharding and replication mode)
 - Redis standalone setup
 
 ## Supported Features
 
 Here the features which are supported by this operator:-
 
-- Redis cluster(master-slave in sharding and replication mode) and standalone setup
+- Redis cluster(leader-follower in sharding and replication mode) and standalone setup
 - Inbuilt monitoring support using the Redis Exporter to give detailed insights
 - Dynamic storage provisioning using the PVC template
 - Performance tuned best practices in redis configuration
@@ -28,9 +28,10 @@ Here the features which are supported by this operator:-
     - Resource and Limits
     - Tolerations
     - SecurityContext
+    - Storage
 
 ## Architecture
 
 <div align="center">
-    <img src="./images/redis-operator-arc.png" style="padding-top: 45px;">
+    <img src="./images/redis-operator-architecture.png" style="padding-top: 45px;">
 </div>
diff --git a/docs/src/guide/changelog.md b/docs/src/guide/changelog.md
index ee5974baafc0568918b23150ece0b7f6191b4c21..37121482a8990e7ca3f1eb6c5049ee4d9474d58c 100644
--- a/docs/src/guide/changelog.md
+++ b/docs/src/guide/changelog.md
@@ -1,3 +1,19 @@
+### v0.6.0
+**June 12, 2021**
+
+**:tada: Features**
+
+- Breaked the CRDs into Redis standalone cluster setup
+- Optimized code configuration for creating Redis cluster
+- Removed string secret type and secret type password is only supported
+- Structured and optimized golang based codebase
+- Removed divisive terminlogies
+
+**:beetle: Bug Fixes**
+
+- Fixed logic for service and statefulset comparison in K8s
+- Removed the monitor label to resolve service endpoint issue
+
 ### v0.5.0
 **May 1, 2021**
 
diff --git a/docs/src/guide/configuration.md b/docs/src/guide/configuration.md
deleted file mode 100644
index 6b25dbe35e358133b47202f0a98621c791ff39f3..0000000000000000000000000000000000000000
--- a/docs/src/guide/configuration.md
+++ /dev/null
@@ -1,175 +0,0 @@
-# Configuration
-
-The redis setup in standalone or cluster mode can be customized using custom configuration. If redis setup is done by **Helm**, in that case [values.yaml](https://github.com/OT-CONTAINER-KIT/helm-charts/blob/main/charts/redis-setup/values.yaml) can be updated.
-
-But if the setup is not done via Helm, in that scenario we may have to customize the CRD parameters.
-
-In this configuration section, we have these configuration parameters:-
-
-- [Helm Parameters](configuration.html#helm-parameters)
-- [CRD Parameters](configuration.html#crd-parameters)
-
-## Helm Parameters
-
-|**Name**|**Default Value**|**Required**|**Description**|
-|--------|-----------------|------------|---------------|
-|`name` | redis | true | Name of the redis setup whether it is standalone or cluster |
-|`setupMode` | standalone | true | Mode of the redis setup, expected values:- `standalone` or `cluster` |
-|`cluster.size` | 3 | false | The number of master and slaves in redis cluster mode setup |
-|`cluster.master` | | false | Custom configurations for redis master |
-|`cluster.slave` | | false | Custom configurations for redis slave |
-|`existingPasswordSecret.enabled` | false | false | To use existing created password secret in Kubernetes |
-|`existingPasswordSecret.name` | redis-secret | false | Name of the existing secret in Kubernetes |
-|`existingPasswordSecret.key` | password | false | Name of the existing secret key in Kubernetes |
-|`global.image` | quay.io/opstree/redis | true | Name of the redis image |
-|`global.tag` | v6.2 | true | Tag of the redis image |
-|`global.imagePullPolicy` | IfNotPresent | true | Image Pull Policy of the redis image |
-|`global.password` | Opstree@1234 | false | Password for the redis setup, leave it blank in case you don't want password |
-|`exporter.enabled` | true | true | Redis exporter should be deployed or not |
-|`exporter.image` | quay.io/opstree/redis-exporter | true | Name of the redis exporter image |
-|`exporter.tag` | v6.2 | true | Tag of the redis exporter image |
-|`exporter.imagePullPolicy` | IfNotPresent | true | Image Pull Policy of the redis exporter image |
-|`nodeSelector` | {} | false | NodeSelector for redis pods |
-|`storageSpec` | {} | false | Storage configuration for redis setup |
-|`securityContext` | {} | false | Security Context for redis pods |
-|`affinity` | {} | false | Affinity for node and pod for redis pods |
-|`tolerations` | {} | false | Tolerations for redis pods |
-
-## CRD Parameters
-
-These are the CRD Parameters which is currently supported by Redis Exporter.
-
-**Mode**
-
-Mode of the redis setup. Available Options:-
-
-- cluster - For cluster mode setup of redis
-- standalone - For standalone setup of redis
-
-```yaml
-mode: cluster
-```
-
-**Size**
-
-Size of the redis cluster pods.
-
-```yaml
-size: 3
-```
-
-**Global**
-
-In the global section, we define similar configurations across the redis nodes.
-
-```yaml
-global:
-  image: quay.io/opstree/redis:v6.2
-  imagePullPolicy: IfNotPresent
-  existingPasswordSecret:
-    name: redis-secret
-    key: password
-  resources:
-    requests:
-      cpu: 100m
-      memory: 128Mi
-    limits:
-      cpu: 100m
-      memory: 128Mi
-```
-
-**Master**
-
-Configuration specific to master nodes of Redis, like:- redis configuration parameters and type of service for master.
-
-```yaml
-master:
-  service:
-    type: ClusterIP
-```
-
-**Slave**
-
-Configuration specific to slave nodes of Redis, like:- redis configuration parameters and type of service for slave.
-
-```yaml
-slave:
-  service:
-    type: ClusterIP
-```
-
-**Redis Exporter**
-
-Redis Exporter configuration which enable the metrics for Redis Database to get monitored by Prometheus.
-
-```yaml
-redisExporter:
-  enabled: true
-  image: quay.io/opstree/redis-exporter:1.0
-  imagePullPolicy: Always
-  resources:
-    requests:
-      cpu: 100m
-      memory: 128Mi
-    limits:
-      cpu: 100m
-      memory: 128Mi
-```
-
-**Storage**
-
-Storage configuration for Redis Statefulset pods.
-
-```yaml
-storage:
-  volumeClaimTemplate:
-    spec:
-      storageClassName: csi-cephfs-sc
-      accessModes: ["ReadWriteOnce"]
-      resources:
-        requests:
-          storage: 1Gi
-    selector: {}
-```
-
-**Priority Class**
-
-Name of the Kubernetes priority class which you want to associate with redis setup.
-
-```yaml
-priorityClassName: priority-100
-```
-
-**Node Selector**
-
-Map of the labels which you want to use as nodeSelector.
-
-```yaml
-nodeSelector:
-  memory: medium
-```
-
-**Security Context**
-
-Kubernetes security context for redis pods.
-
-```yaml
-securityContext:
-  runAsUser: 1000
-```
-
-**Affinity**
-
-Affinity for node and pod for redis setup.
-
-```yaml
-affinity:
-  nodeAffinity:
-    requiredDuringSchedulingIgnoredDuringExecution:
-      nodeSelectorTerms:
-      - matchExpressions:
-        - key: disktype
-          operator: In
-          values:
-          - ssd
-```
\ No newline at end of file
diff --git a/docs/src/guide/failover.md b/docs/src/guide/failover.md
index 6cf3d5a33a900d835d34590c5960b91abbbfe56f..0d84b73c92cd71c83393f68191e6eef63cbac2ef 100644
--- a/docs/src/guide/failover.md
+++ b/docs/src/guide/failover.md
@@ -3,11 +3,11 @@
 Before failover testing, we have to write some dummy data inside the Redis cluster, we can write the dummy data using the `redis-cli`.
 
 ```shell
-$ kubectl exec -it redis-master-0 -n redis-operator \
+$ kubectl exec -it redis-leader-0 -n redis-operator \
     -- redis-cli -a Opstree@1234 -c set tony stark
 ...
-Defaulting container name to redis-master.
-Use 'kubectl describe pod/redis-master-0 -n redis-operator' to see all of the containers in this pod.
+Defaulting container name to redis-leader.
+Use 'kubectl describe pod/redis-leader-0 -n redis-operator' to see all of the containers in this pod.
 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
 OK
 ```
@@ -15,30 +15,30 @@ OK
 Verify the key has been inserted properly by fetching its value.
 
 ```shell
-$ kubectl exec -it redis-master-0 -n redis-operator \
+$ kubectl exec -it redis-leader-0 -n redis-operator \
     -- redis-cli -a Opstree@1234 -c get tony
 ...
-Use 'kubectl describe pod/redis-master-0 -n redis-operator' to see all of the containers in this pod.
+Use 'kubectl describe pod/redis-leader-0 -n redis-operator' to see all of the containers in this pod.
 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
 "stark"
 ```
 
-Let’s restart the pod name `redis-master-0` and see the redis node behavior.
+Let’s restart the pod name `redis-leader-0` and see the redis node behavior.
 
 ```shell
-$ kubectl delete pod redis-master-0 -n redis-operator
+$ kubectl delete pod redis-leader-0 -n redis-operator
 ...
-pod "redis-master-0" deleted
+pod "redis-leader-0" deleted
 ```
 
-Now we can again try to list redis cluster nodes from `redis-master-0` pod and from some other pod as well like:- `redis-slave-2`
+Now we can again try to list redis cluster nodes from `redis-leader-0` pod and from some other pod as well like:- `redis-follower-2`
 
 ```shell
-$ kubectl exec -it redis-master-0 -n redis-operator \
+$ kubectl exec -it redis-leader-0 -n redis-operator \
     -- redis-cli -a Opstree@1234 cluster nodes
 ...
-Defaulting container name to redis-master.
-Use 'kubectl describe pod/redis-master-0 -n redis-operator' to see all of the containers in this pod.
+Defaulting container name to redis-leader.
+Use 'kubectl describe pod/redis-leader-0 -n redis-operator' to see all of the containers in this pod.
 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
 eef84b7dada737051c32d592bd66652b9af0cb35 10.42.2.184:6379@16379 slave 0a36dc5064b0a61afa8bd850e93ff0a1c2267704 0 1619958171517 3 connected
 a7c424b5ec0e696aa7be15a691846c8820e48cd1 10.42.1.181:6379@16379 master - 0 1619958172520 4 connected 0-5460
@@ -48,16 +48,16 @@ a7c424b5ec0e696aa7be15a691846c8820e48cd1 10.42.1.181:6379@16379 master - 0 16199
 85747fe5cabf96e00fd0365737996a93e05cf947 10.42.2.182:6379@16379 master - 0 1619958173523 2 connected 5461-10922
 ```
 
-So if you notice the output of cluster nodes command, the node IP is updated and it’s connected as a master.
+So if you notice the output of cluster nodes command, the node IP is updated and it’s connected as a leader.
 
 Let's try to get value of key from some other pod
 
 ```shell
-$ kubectl exec -it redis-slave-1 -n redis-operator \
+$ kubectl exec -it redis-follower-1 -n redis-operator \
     -- redis-cli -a Opstree@1234 -c get tony
 ...
-Defaulting container name to redis-slave.
-Use 'kubectl describe pod/redis-slave-1 -n redis-operator' to see all of the containers in this pod.
+Defaulting container name to redis-follower.
+Use 'kubectl describe pod/redis-follower-1 -n redis-operator' to see all of the containers in this pod.
 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
 "stark"
 ```
diff --git a/docs/src/guide/images/redis-operator-architecture.png b/docs/src/guide/images/redis-operator-architecture.png
new file mode 100644
index 0000000000000000000000000000000000000000..670d2f5f1125564c51f895cbd9c418a116790de5
Binary files /dev/null and b/docs/src/guide/images/redis-operator-architecture.png differ
diff --git a/docs/src/guide/monitoring.md b/docs/src/guide/monitoring.md
index 87494244dacaabb413e7b66e0cc07a7523301903..f7c0391ba32adc0ba8603d6e1b8c80e8f038663a 100644
--- a/docs/src/guide/monitoring.md
+++ b/docs/src/guide/monitoring.md
@@ -25,14 +25,14 @@ Once the exporter is configured, we may have to update Prometheus to monitor thi
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
 metadata:
-  name: redis-monitoring-master
+  name: redis-monitoring-leader
   labels:
     redis-operator: "true"
     env: production
 spec:
   selector:
     matchLabels:
-      role: master
+      role: leader
   endpoints:
   - port: redis-exporter
 ```
@@ -42,14 +42,14 @@ spec:
 apiVersion: monitoring.coreos.com/v1
 kind: ServiceMonitor
 metadata:
-  name: redis-monitoring-slave
+  name: redis-monitoring-follower
   labels:
     redis-operator: "true"
     env: production
 spec:
   selector:
     matchLabels:
-      role: slave
+      role: follower
   endpoints:
   - port: redis-exporter
 ```
diff --git a/docs/src/guide/redis-cluster-config.md b/docs/src/guide/redis-cluster-config.md
new file mode 100644
index 0000000000000000000000000000000000000000..d1acad9e32a8daec0f6b226e643d20dfb2127332
--- /dev/null
+++ b/docs/src/guide/redis-cluster-config.md
@@ -0,0 +1,174 @@
+# Redis Cluster
+
+The redis setup cluster mode can be customized using custom configuration. If redis setup is done by **Helm**, in that case `values.yaml` can be updated.
+
+- [Redis cluster values](https://github.com/OT-CONTAINER-KIT/helm-charts/blob/main/charts/redis-cluster/values.yaml) 
+
+But if the setup is not done via Helm, in that scenario we may have to customize the CRD parameters.
+
+In this configuration section, we have these configuration parameters:-
+
+- [Helm Parameters](configuration.html#helm-parameters)
+- [CRD Parameters](configuration.html#crd-parameters)
+
+## Helm Parameters
+
+|**Name**|**Default Value**|**Required**|**Description**|
+|--------|-----------------|------------|---------------|
+|`redisCluster.clusterSize` | 3 | false | Size of the redis cluster leader and follower nodes |
+|`redisCluster.secretName` | redis-secret | false | Name of the existing secret in Kubernetes |
+|`redisCluster.secretKey` | password | false | Name of the existing secret key in Kubernetes |
+|`redisCluster.image` | quay.io/opstree/redis | true | Name of the redis image |
+|`redisCluster.tag` | v6.2 | true | Tag of the redis image |
+|`redisCluster.imagePullPolicy` | IfNotPresent | true | Image Pull Policy of the redis image |
+|`redisCluster.leaderServiceType` | ClusterIP | false | Kubernetes service type for Redis Leader |
+|`redisCluster.followerServiceType` | ClusterIP | false | Kubernetes service type for Redis Follower |
+|`redisExporter.enabled` | true | true | Redis exporter should be deployed or not |
+|`redisExporter.image` | quay.io/opstree/redis-exporter | true | Name of the redis exporter image |
+|`redisExporter.tag` | v6.2 | true | Tag of the redis exporter image |
+|`redisExporter.imagePullPolicy` | IfNotPresent | true | Image Pull Policy of the redis exporter image |
+|`nodeSelector` | {} | false | NodeSelector for redis pods |
+|`storageSpec` | {} | false | Storage configuration for redis setup |
+|`securityContext` | {} | false | Security Context for redis pods |
+|`affinity` | {} | false | Affinity for node and pod for redis pods |
+|`tolerations` | {} | false | Tolerations for redis pods |
+
+# CRD Parameters
+
+These are the CRD Parameters which is currently supported by Redis Exporter for standalone CRD.
+
+**clusterSize**
+
+`clusterSize` is size of the Redis leader and follower nodes.
+
+```yaml
+  clusterSize: 3
+```
+
+**redisLeader**
+
+`redisLeader` is the field for Redis leader related configurations.
+
+```yaml
+  redisLeader:
+    serviceType: ClusterIP
+```
+
+**redisFollower**
+
+`redisFollower` is the field for Redis follower related configurations.
+
+```yaml
+  redisFollower:
+    serviceType: ClusterIP
+```
+
+**kubernetesConfig**
+
+In the `kubernetesConfig` section, we define configuration related to Kubernetes.
+
+```yaml
+  kubernetesConfig:
+    image: quay.io/opstree/redis:v6.2
+    imagePullPolicy: IfNotPresent
+    resources:
+      requests:
+        cpu: 101m
+        memory: 128Mi
+      limits:
+        cpu: 101m
+        memory: 128Mi
+    redisSecret:
+      name: redis-secret
+      key: password
+    serviceType: LoadBalancer
+```
+
+
+**redisExporter**
+
+`redisExporter` configuration which enable the metrics for Redis Database to get monitored by Prometheus.
+
+```yaml
+  redisExporter:
+    enabled: true
+    image: quay.io/opstree/redis-exporter:1.0
+    imagePullPolicy: Always
+    resources:
+      requests:
+        cpu: 100m
+        memory: 128Mi
+      limits:
+        cpu: 100m
+        memory: 128Mi
+```
+
+**storage**
+
+`storage` configuration for Redis Statefulset pods.
+
+```yaml
+  storage:
+    volumeClaimTemplate:
+      spec:
+        storageClassName: standard
+        accessModes: ["ReadWriteOnce"]
+        resources:
+          requests:
+            storage: 1Gi
+```
+
+**priorityClassName**
+
+Name of the Kubernetes priority class which you want to associate with redis setup.
+
+```yaml
+priorityClassName: priority-100
+```
+
+**nodeSelector**
+
+Map of the labels which you want to use as nodeSelector.
+
+```yaml
+  nodeSelector:
+    kubernetes.io/hostname: minikube
+```
+
+**securityContext**
+
+Kubernetes security context for redis pods.
+
+```yaml
+  securityContext:
+    runAsUser: 1000
+```
+
+**affinity**
+
+Affinity for node and pod for redis setup.
+
+```yaml
+  affinity:
+    nodeAffinity:
+      requiredDuringSchedulingIgnoredDuringExecution:
+        nodeSelectorTerms:
+        - matchExpressions:
+          - key: disktype
+            operator: In
+            values:
+            - ssd
+```
+
+**tolerations**
+
+Tolerations for nodes and pods in Kubernetes.
+
+```yaml
+  tolerations:
+  - key: "key1"
+    operator: "Equal"
+    value: "value1"
+    effect: "NoSchedule"
+```
+
diff --git a/docs/src/guide/redis-config.md b/docs/src/guide/redis-config.md
new file mode 100644
index 0000000000000000000000000000000000000000..87567911ccd607c744be25b21fcbdb6a632d0bf7
--- /dev/null
+++ b/docs/src/guide/redis-config.md
@@ -0,0 +1,146 @@
+# Redis Standalone
+
+The redis setup in standalone mode can be customized using custom configuration. If redis setup is done by **Helm**, in that case `values.yaml` can be updated.
+
+- [Redis standalone values](https://github.com/OT-CONTAINER-KIT/helm-charts/blob/main/charts/redis/values.yaml) 
+
+But if the setup is not done via Helm, in that scenario we may have to customize the CRD parameters.
+
+In this configuration section, we have these configuration parameters:-
+
+- [Helm Parameters](configuration.html#helm-parameters)
+- [CRD Parameters](configuration.html#crd-parameters)
+
+## Helm Parameters
+
+|**Name**|**Default Value**|**Required**|**Description**|
+|--------|-----------------|------------|---------------|
+|`redisStandalone.secretName` | redis-secret | false | Name of the existing secret in Kubernetes |
+|`redisStandalone.secretKey` | password | false | Name of the existing secret key in Kubernetes |
+|`redisStandalone.image` | quay.io/opstree/redis | true | Name of the redis image |
+|`redisStandalone.tag` | v6.2 | true | Tag of the redis image |
+|`redisStandalone.imagePullPolicy` | IfNotPresent | true | Image Pull Policy of the redis image |
+|`redisStandalone.serviceType` | ClusterIP | false | Kubernetes service type for Redis |
+|`redisExporter.enabled` | true | true | Redis exporter should be deployed or not |
+|`redisExporter.image` | quay.io/opstree/redis-exporter | true | Name of the redis exporter image |
+|`redisExporter.tag` | v6.2 | true | Tag of the redis exporter image |
+|`redisExporter.imagePullPolicy` | IfNotPresent | true | Image Pull Policy of the redis exporter image |
+|`nodeSelector` | {} | false | NodeSelector for redis pods |
+|`storageSpec` | {} | false | Storage configuration for redis setup |
+|`securityContext` | {} | false | Security Context for redis pods |
+|`affinity` | {} | false | Affinity for node and pod for redis pods |
+|`tolerations` | {} | false | Tolerations for redis pods |
+
+# CRD Parameters
+
+These are the CRD Parameters which is currently supported by Redis Exporter for standalone CRD.
+
+**kubernetesConfig**
+
+In the `kubernetesConfig` section, we define configuration related to Kubernetes.
+
+```yaml
+  kubernetesConfig:
+    image: quay.io/opstree/redis:v6.2
+    imagePullPolicy: IfNotPresent
+    resources:
+      requests:
+        cpu: 101m
+        memory: 128Mi
+      limits:
+        cpu: 101m
+        memory: 128Mi
+    redisSecret:
+      name: redis-secret
+      key: password
+    serviceType: LoadBalancer
+```
+
+
+**redisExporter**
+
+`redisExporter` configuration which enable the metrics for Redis Database to get monitored by Prometheus.
+
+```yaml
+  redisExporter:
+    enabled: true
+    image: quay.io/opstree/redis-exporter:1.0
+    imagePullPolicy: Always
+    resources:
+      requests:
+        cpu: 100m
+        memory: 128Mi
+      limits:
+        cpu: 100m
+        memory: 128Mi
+```
+
+**storage**
+
+`storage` configuration for Redis Statefulset pods.
+
+```yaml
+  storage:
+    volumeClaimTemplate:
+      spec:
+        storageClassName: standard
+        accessModes: ["ReadWriteOnce"]
+        resources:
+          requests:
+            storage: 1Gi
+```
+
+**priorityClassName**
+
+Name of the Kubernetes priority class which you want to associate with redis setup.
+
+```yaml
+priorityClassName: priority-100
+```
+
+**nodeSelector**
+
+Map of the labels which you want to use as nodeSelector.
+
+```yaml
+  nodeSelector:
+    kubernetes.io/hostname: minikube
+```
+
+**securityContext**
+
+Kubernetes security context for redis pods.
+
+```yaml
+  securityContext:
+    runAsUser: 1000
+```
+
+**affinity**
+
+Affinity for node and pod for redis setup.
+
+```yaml
+  affinity:
+    nodeAffinity:
+      requiredDuringSchedulingIgnoredDuringExecution:
+        nodeSelectorTerms:
+        - matchExpressions:
+          - key: disktype
+            operator: In
+            values:
+            - ssd
+```
+
+**tolerations**
+
+Tolerations for nodes and pods in Kubernetes.
+
+```yaml
+  tolerations:
+  - key: "key1"
+    operator: "Equal"
+    value: "value1"
+    effect: "NoSchedule"
+```
+
diff --git a/docs/src/guide/redis.md b/docs/src/guide/redis.md
index 954405149477af2e0ae493c8c5e9e6b1e03ff79e..f67224ce58df3c89a1c4b87c69252e348c08d182 100644
--- a/docs/src/guide/redis.md
+++ b/docs/src/guide/redis.md
@@ -8,9 +8,9 @@ Sometimes getting data from disks can be time-consuming. In order to increase th
 
 ![](./images/redis-as-database.png)
 
-## Redis Master-Slave Replication
+## Redis Leader-Follower Replication
 
-Beginning with the explanation about Redis Master-Slave. In this phenomenon, Redis can replicate data to any number of nodes. ie. it lets the slave have the exact copy of their master. This helps in performance optimizations.
+Beginning with the explanation about Redis Leader-Follower. In this phenomenon, Redis can replicate data to any number of nodes. ie. it lets the follower have the exact copy of their leader. This helps in performance optimizations.
 
 ## Redis Cluster
 
@@ -18,7 +18,7 @@ A Redis cluster is simply a [data sharding strategy](https://www.digitalocean.co
 
 ## Replication vs Sharding
 
-Replication is also known as mirroring of data. In replication, all the data get copied from the master node to the slave node.
+Replication is also known as mirroring of data. In replication, all the data get copied from the leader node to the follower node.
 Sharding is also known as partitioning. It splits up the data by the key to multiple nodes.
 
 <div align="center">
diff --git a/docs/src/guide/setup.md b/docs/src/guide/setup.md
index e4dcb8d01a0879309c9b57d236c8ca414d1e5633..57ab8fecac061d8b9733d60dec37d60d4bd1f326 100644
--- a/docs/src/guide/setup.md
+++ b/docs/src/guide/setup.md
@@ -2,11 +2,18 @@
 
 This redis operator supports below deployment strategies for redis:-
 
-- Redis in-build master slave with sharding and replication mode
+- Redis cluster setup (in-built leader follower with sharding and replication mode)
 - Redis standalone setup
 
 Here we will see how we can leverage these strategies.
 
+If we want to use password based authentication inside Redis, we need to create a secret for it. By default the name of the secret is `redis-secret` and key name is `password`, but it can be overidden in helm charts.
+
+```shell
+$ kubectl create secret generic redis-secret \ 
+    --from-literal=password=password -n ot-operators
+```
+
 ## Redis Standalone
 
 <div align="center">
@@ -16,14 +23,12 @@ Here we will see how we can leverage these strategies.
 In redis standalone mode, we deploy redis as a single Stateful pod which means ease of setup, no complexity, no high availability, and no resilience.
 
 ```shell
-$ helm upgrade redis ot-helm/redis-setup \
-    --set setupMode="standalone" \
-    --install --namespace redis-operator
+$ helm upgrade redis ot-helm/redis --install --namespace ot-operators
 ...
 Release "redis" does not exist. Installing it now.
 NAME: redis
 LAST DEPLOYED: Sun May  2 15:59:48 2021
-NAMESPACE: redis-operator
+NAMESPACE: ot-operators
 STATUS: deployed
 REVISION: 1
 TEST SUITE: None
@@ -32,7 +37,7 @@ TEST SUITE: None
 Verify the standalone redis setup by `kubectl` command line.
 
 ```shell
-$ kubectl get pods -n redis-operator
+$ kubectl get pods -n ot-operators
 ...
 NAME                              READY   STATUS    RESTARTS   AGE
 redis-operator-74b6cbf5c5-td8t7   1/1     Running   0          81m
@@ -50,41 +55,40 @@ A Redis cluster is simply a [data sharding strategy](https://www.digitalocean.co
 For redis cluster setup we can use same helm command but with different parameters.
 
 ```shell
-$ helm upgrade redis-cluster ot-helm/redis-setup \
-    --set setupMode="cluster" --set cluster.size=3 \
-    --install --namespace redis-operator
+$ helm upgrade redis-cluster ot-helm/redis-cluster \
+  --set redisCluster.clusterSize=3 --install --namespace ot-operators
 ...
 Release "redis-cluster" does not exist. Installing it now.
 NAME: redis-cluster
 LAST DEPLOYED: Sun May  2 16:11:38 2021
-NAMESPACE: redis-operator
+NAMESPACE: ot-operators
 STATUS: deployed
 REVISION: 1
 TEST SUITE: None
 ```
 
-Verify the cluster by checking the pod status of master and slave pods.
+Verify the cluster by checking the pod status of leader and follower pods.
 
 ```shell
-$ kubectl get pods -n redis-operator
+$ kubectl get pods -n ot-operators
 ...
 NAME                              READY   STATUS    RESTARTS   AGE
 redis-operator-74b6cbf5c5-td8t7   1/1     Running   1          90m
-redis-slave-0                     2/2     Running   0          75s
-redis-master-0                    2/2     Running   0          76s
-redis-slave-1                     2/2     Running   0          54s
-redis-master-1                    2/2     Running   0          49s
-redis-slave-2                     2/2     Running   0          35s
-redis-master-2                    2/2     Running   0          26s
+redis-follower-0                     2/2     Running   0          75s
+redis-leader-0                    2/2     Running   0          76s
+redis-follower-1                     2/2     Running   0          54s
+redis-leader-1                    2/2     Running   0          49s
+redis-follower-2                     2/2     Running   0          35s
+redis-leader-2                    2/2     Running   0          26s
 ```
 
-If all the pods are in the running state of master and slave Statefulsets, then we can check the health of the redis cluster by using `redis-cli`
+If all the pods are in the running state of leader and follower Statefulsets, then we can check the health of the redis cluster by using `redis-cli`.
 
 ```shell
-$ kubectl exec -it redis-master-0 -n redis-operator -- redis-cli -a Opstree@1234 cluster nodes
+$ kubectl exec -it redis-leader-0 -n ot-operators -- redis-cli -a Opstree@1234 cluster nodes
 ...
-Defaulting container name to redis-master.
-Use 'kubectl describe pod/redis-master-0 -n redis-operator' to see all of the containers in this pod.
+Defaulting container name to redis-leader.
+Use 'kubectl describe pod/redis-leader-0 -n ot-operators' to see all of the containers in this pod.
 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
 528438a759cee4528c3071d17d75b27b0818555d 10.42.0.219:6379@16379 myself,master - 0 1619952294000 1 connected 0-5460
 8ec7812903b7e046bec2f2a7bce4a9ccadfa4188 10.42.0.221:6379@16379 slave d0ff3892d2eba0b2707199cb5df57adbba214bcd 0 1619952297241 3 connected
@@ -92,4 +96,4 @@ Warning: Using a password with '-a' or '-u' option on the command line interface
 6e80da4902802ebffa94cbac9b7d98e9fd74121f 10.42.2.178:6379@16379 master - 0 1619952297000 2 connected 5461-10922
 d0ff3892d2eba0b2707199cb5df57adbba214bcd 10.42.1.178:6379@16379 master - 0 1619952298245 3 connected 10923-16383
 c2b74bd2a360068db01dfc8f00b8d0b012e21215 10.42.1.177:6379@16379 slave 528438a759cee4528c3071d17d75b27b0818555d 0 1619952297000 1 connected
-```
\ No newline at end of file
+```
diff --git a/example/redis-cluster.yaml b/example/redis-cluster.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a79f94657fdd621e7d6c34a309ded344d2c78831
--- /dev/null
+++ b/example/redis-cluster.yaml
@@ -0,0 +1,51 @@
+---
+apiVersion: redis.redis.opstreelabs.in/v1beta1
+kind: RedisCluster
+metadata:
+  name: redis-cluster
+spec:
+  clusterSize: 3
+  kubernetesConfig:
+    image: quay.io/opstree/redis:v6.2
+    imagePullPolicy: IfNotPresent
+    resources:
+      requests:
+        cpu: 101m
+        memory: 128Mi
+      limits:
+        cpu: 101m
+        memory: 128Mi
+    redisSecret:
+      name: redis-secret
+      key: password
+    serviceType: ClusterIP
+  redisExporter:
+    enabled: true
+    image: quay.io/opstree/redis-exporter:1.0
+    imagePullPolicy: Always
+    resources:
+      requests:
+        cpu: 100m
+        memory: 128Mi
+      limits:
+        cpu: 100m
+        memory: 128Mi
+  redisLeader:
+    serviceType: LoadBalancer
+  redisFollower:
+    serviceType: LoadBalancer
+  # redisConfig: {}
+  storage:
+    volumeClaimTemplate:
+      spec:
+        storageClassName: standard
+        accessModes: ["ReadWriteOnce"]
+        resources:
+          requests:
+            storage: 1Gi
+  # nodeSelector:
+  #   kubernetes.io/hostname: minikube
+  # securityContext: {}
+  # priorityClassName:
+  # Affinity:
+  # Tolerations: []
diff --git a/example/redis-standalone-example.yaml b/example/redis-standalone.yaml
similarity index 70%
rename from example/redis-standalone-example.yaml
rename to example/redis-standalone.yaml
index 4efa4ee1529e4668e447215e0d8cfbc7151e2ce2..5b7f806ed1fbcbfb3993e84d506b87f0f975f8f1 100644
--- a/example/redis-standalone-example.yaml
+++ b/example/redis-standalone.yaml
@@ -2,13 +2,12 @@
 apiVersion: redis.redis.opstreelabs.in/v1beta1
 kind: Redis
 metadata:
-  name: opstree-redis
+  name: redis-standalone
 spec:
-  mode: standalone
-  global:
-    image: quay.io/opstree/redis:v6.2
-    imagePullPolicy: IfNotPresent
-    password: "Opstree@1234"
+  redisExporter:
+    enabled: true
+    image: quay.io/opstree/redis-exporter:1.0
+    imagePullPolicy: Always
     resources:
       requests:
         cpu: 100m
@@ -16,27 +15,32 @@ spec:
       limits:
         cpu: 100m
         memory: 128Mi
-  service:
-    type: ClusterIP
-  redisConfig: {}
-  redisExporter:
-    enabled: true
-    image: quay.io/opstree/redis-exporter:1.0
-    imagePullPolicy: Always
+  kubernetesConfig:
+    image: quay.io/opstree/redis:v6.2
+    imagePullPolicy: IfNotPresent
     resources:
       requests:
-        cpu: 100m
+        cpu: 101m
         memory: 128Mi
       limits:
-        cpu: 100m
+        cpu: 101m
         memory: 128Mi
+    redisSecret:
+      name: redis-secret
+      key: password
+    serviceType: LoadBalancer
+  redisConfig: {}
   storage:
     volumeClaimTemplate:
       spec:
-        storageClassName: csi-cephfs-sc
+        storageClassName: standard
         accessModes: ["ReadWriteOnce"]
         resources:
           requests:
             storage: 1Gi
   # nodeSelector:
   #   kubernetes.io/hostname: minikube
+  # securityContext: {}
+  # priorityClassName:
+  # affinity:
+  # Tolerations: []
diff --git a/go.mod b/go.mod
index 6aaef171c8cf0805fdc17e83e634c5c092c4b36a..16cd7eb39eee27cd6135a0551f7aaa90dc0a3574 100644
--- a/go.mod
+++ b/go.mod
@@ -3,13 +3,22 @@ module redis-operator
 go 1.15
 
 require (
+	github.com/banzaicloud/k8s-objectmatcher v1.5.1 // indirect
+	github.com/coreos/go-etcd v2.0.0+incompatible // indirect
+	github.com/cpuguy83/go-md2man v1.0.10 // indirect
+	github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0 // indirect
 	github.com/go-logr/logr v0.3.0
 	github.com/go-redis/redis v6.15.9+incompatible
-	github.com/google/go-cmp v0.5.2 // indirect
+	github.com/goph/emperror v0.17.2 // indirect
+	github.com/gophercloud/gophercloud v0.1.0 // indirect
 	github.com/onsi/ginkgo v1.14.1
 	github.com/onsi/gomega v1.10.2
+	github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8 // indirect
+	gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e // indirect
 	k8s.io/api v0.19.2
 	k8s.io/apimachinery v0.19.2
 	k8s.io/client-go v0.19.2
+	k8s.io/klog v1.0.0 // indirect
 	sigs.k8s.io/controller-runtime v0.7.0
+	sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06 // indirect
 )
diff --git a/go.sum b/go.sum
index 15b5b2708e8fa95498ee476a969cec0c1a8dc489..f893c15bb9de4d88ca37fff90811e0ab7a228c2c 100644
--- a/go.sum
+++ b/go.sum
@@ -12,6 +12,8 @@ cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7
 cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
 cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+emperror.dev/errors v0.8.0 h1:4lycVEx0sdJkwDUfQ9pdu6SR0x7rgympt5f4+ok8jDk=
+emperror.dev/errors v0.8.0/go.mod h1:YcRvLPh626Ubn2xqtoprejnA5nFha+TJ+2vew48kWuE=
 github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
 github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
 github.com/Azure/go-autorest/autorest v0.9.6 h1:5YWtOnckcudzIw8lPPBcWOnmIFWMtHci1ZWAZulMSx0=
@@ -41,6 +43,7 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
 github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
+github.com/airbrake/gobrake v3.6.1+incompatible/go.mod h1:wM4gu3Cn0W0K7GUuVWnlXZU11AGBXMILnrdOU8Kn00o=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@@ -49,13 +52,20 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo
 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
+github.com/banzaicloud/k8s-objectmatcher v1.5.1 h1:u3Ic1JzIUQe0pGGjVQJvCWTNa+t9CiW49IPPovYqAss=
+github.com/banzaicloud/k8s-objectmatcher v1.5.1/go.mod h1:9MWY5HsM/OaTmoTirczhlO8UALbH722WgdpaaR7Y8OE=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
+github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
 github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
+github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
+github.com/bugsnag/bugsnag-go v1.4.0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
+github.com/bugsnag/panicwrap v1.2.0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/certifi/gocertifi v0.0.0-20190105021004-abcd57078448/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4=
 github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
@@ -67,6 +77,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
 github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
 github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
+github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
 github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
 github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -74,6 +85,7 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7
 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
 github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -82,6 +94,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
+github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg=
@@ -89,6 +102,7 @@ github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZ
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
 github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc=
 github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
 github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
 github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
@@ -101,6 +115,7 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
 github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
@@ -162,6 +177,7 @@ github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85n
 github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
 github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
 github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
@@ -211,6 +227,8 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
 github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
 github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM=
 github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
+github.com/goph/emperror v0.17.2/go.mod h1:+ZbQ+fUNO/6FNiUo0ujtMjhgad9Xa6fQL9KhH4LNHic=
+github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
 github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
@@ -238,6 +256,7 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
 github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
@@ -283,11 +302,13 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn
 github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
 github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
 github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4=
 github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
 github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
+github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
@@ -324,8 +345,11 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
 github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
 github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
+github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rollbar/rollbar-go v1.0.2/go.mod h1:AcFs5f0I+c71bpHlXNNDbOWJiKwjFDtISeXco0L5PKQ=
+github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
@@ -359,6 +383,7 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV
 github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
+github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
@@ -378,11 +403,15 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
 go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
 go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
 go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
+go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
 go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
 go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
@@ -390,6 +419,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM=
 go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -401,7 +431,9 @@ golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
 golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
 golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
@@ -465,6 +497,7 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -506,6 +539,7 @@ golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGm
 golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
@@ -536,6 +570,9 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gomodules.xyz/jsonpatch/v2 v2.1.0 h1:Phva6wqu+xR//Njw6iorylFFgn/z547tw5Ne3HZPQ+k=
 gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU=
+gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
+gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
+gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ=
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
 google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
 google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -622,6 +659,8 @@ k8s.io/component-base v0.19.2 h1:jW5Y9RcZTb79liEhW3XDVTW7MuvEGP0tQZnfSX6/+gs=
 k8s.io/component-base v0.19.2/go.mod h1:g5LrsiTiabMLZ40AR6Hl45f088DevyGY+cCE2agEIVo=
 k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
+k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
+k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
 k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
 k8s.io/klog/v2 v2.2.0 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A=
 k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
@@ -630,10 +669,17 @@ k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H
 k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 k8s.io/utils v0.0.0-20200912215256-4140de9c8800 h1:9ZNvfPvVIEsp/T1ez4GQuzCcCTEQWhovSofhqR73A6g=
 k8s.io/utils v0.0.0-20200912215256-4140de9c8800/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
+modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
+modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
+modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
+modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
+modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQbTRyDlZPJX2SUPEqvnB+j7AJjtlox7PEwigU0=
 sigs.k8s.io/controller-runtime v0.7.0 h1:bU20IBBEPccWz5+zXpLnpVsgBYxqclaHu1pVDl/gEt8=
 sigs.k8s.io/controller-runtime v0.7.0/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU=
+sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06 h1:zD2IemQ4LmOcAumeiyDWXKUI2SO0NYDe3H6QGvPOVgU=
+sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18=
 sigs.k8s.io/structured-merge-diff/v4 v4.0.1 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA=
 sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
 sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
diff --git a/k8sutils/client.go b/k8sutils/client.go
index 13a365d6d469cea5d3435a3573d96e79da427cd5..1c5ce2a267685d23625970eeac671c49067248e0 100644
--- a/k8sutils/client.go
+++ b/k8sutils/client.go
@@ -6,9 +6,9 @@ import (
 	"k8s.io/client-go/tools/clientcmd"
 )
 
-// GenerateK8sClient create client for kubernetes
-func GenerateK8sClient() *kubernetes.Clientset {
-	config, err := GenerateK8sConfig()
+// generateK8sClient create client for kubernetes
+func generateK8sClient() *kubernetes.Clientset {
+	config, err := generateK8sConfig()
 	if err != nil {
 		panic(err.Error())
 	}
@@ -19,7 +19,8 @@ func GenerateK8sClient() *kubernetes.Clientset {
 	return clientset
 }
 
-func GenerateK8sConfig() (*rest.Config, error) {
+// generateK8sConfig will load the kube config file
+func generateK8sConfig() (*rest.Config, error) {
 	loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
 	// if you want to change the loading rules (which files in which order), you can do so here
 	configOverrides := &clientcmd.ConfigOverrides{}
diff --git a/k8sutils/labels.go b/k8sutils/labels.go
index 762dc3a1c5c779cba4d1256fd742662ed1b0cf64..edfed90ce9062220fda5d71421e92d35560b8af6 100644
--- a/k8sutils/labels.go
+++ b/k8sutils/labels.go
@@ -6,16 +6,16 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
-// GenerateMetaInformation generates the meta information
-func GenerateMetaInformation(resourceKind string, apiVersion string) metav1.TypeMeta {
+// generateMetaInformation generates the meta information
+func generateMetaInformation(resourceKind string, apiVersion string) metav1.TypeMeta {
 	return metav1.TypeMeta{
 		Kind:       resourceKind,
 		APIVersion: apiVersion,
 	}
 }
 
-// GenerateObjectMetaInformation generates the object meta information
-func GenerateObjectMetaInformation(name string, namespace string, labels map[string]string, annotations map[string]string) metav1.ObjectMeta {
+// generateObjectMetaInformation generates the object meta information
+func generateObjectMetaInformation(name string, namespace string, labels map[string]string, annotations map[string]string) metav1.ObjectMeta {
 	return metav1.ObjectMeta{
 		Name:        name,
 		Namespace:   namespace,
@@ -41,17 +41,32 @@ func AsOwner(cr *redisv1beta1.Redis) metav1.OwnerReference {
 	}
 }
 
-// GenerateStatefulSetsAnots generates and returns statefulsets annotations
-func GenerateStatefulSetsAnots() map[string]string {
-	return map[string]string{
-		"redis.opstreelabs.in": "true",
-		"prometheus.io/scrape": "true",
-		"prometheus.io/port":   "9121",
+// redisAsOwner generates and returns object refernece
+func redisAsOwner(cr *redisv1beta1.Redis) metav1.OwnerReference {
+	trueVar := true
+	return metav1.OwnerReference{
+		APIVersion: cr.APIVersion,
+		Kind:       cr.Kind,
+		Name:       cr.Name,
+		UID:        cr.UID,
+		Controller: &trueVar,
 	}
 }
 
-// GenerateServiceAnots generates and returns service annotations
-func GenerateServiceAnots() map[string]string {
+// redisClusterAsOwner generates and returns object refernece
+func redisClusterAsOwner(cr *redisv1beta1.RedisCluster) metav1.OwnerReference {
+	trueVar := true
+	return metav1.OwnerReference{
+		APIVersion: cr.APIVersion,
+		Kind:       cr.Kind,
+		Name:       cr.Name,
+		UID:        cr.UID,
+		Controller: &trueVar,
+	}
+}
+
+// generateStatefulSetsAnots generates and returns statefulsets annotations
+func generateStatefulSetsAnots() map[string]string {
 	return map[string]string{
 		"redis.opstreelabs.in": "true",
 		"prometheus.io/scrape": "true",
@@ -59,10 +74,12 @@ func GenerateServiceAnots() map[string]string {
 	}
 }
 
-// GenerateSecretAnots generates and returns secrets annotations
-func GenerateSecretAnots() map[string]string {
+// generateServiceAnots generates and returns service annotations
+func generateServiceAnots() map[string]string {
 	return map[string]string{
 		"redis.opstreelabs.in": "true",
+		"prometheus.io/scrape": "true",
+		"prometheus.io/port":   "9121",
 	}
 }
 
diff --git a/k8sutils/redis-cluster.go b/k8sutils/redis-cluster.go
new file mode 100644
index 0000000000000000000000000000000000000000..d7c50d0917b8b05685178b4d4da50da9670cb2b5
--- /dev/null
+++ b/k8sutils/redis-cluster.go
@@ -0,0 +1,133 @@
+package k8sutils
+
+import (
+	redisv1beta1 "redis-operator/api/v1beta1"
+)
+
+// RedisClusterSTS is a interface to call Redis Statefulset function
+type RedisClusterSTS struct {
+	RedisStateFulType string
+}
+
+// RedisClusterService is a interface to call Redis Service function
+type RedisClusterService struct {
+	RedisServiceRole string
+	RedisServiceType string
+}
+
+// generateRedisStandalone generates Redis standalone information
+func generateRedisClusterarams(cr *redisv1beta1.RedisCluster) statefulSetParameters {
+	return statefulSetParameters{
+		Replicas:              cr.Spec.Size,
+		NodeSelector:          cr.Spec.NodeSelector,
+		SecurityContext:       cr.Spec.SecurityContext,
+		PriorityClassName:     cr.Spec.PriorityClassName,
+		Affinity:              cr.Spec.Affinity,
+		Tolerations:           cr.Spec.Tolerations,
+		EnableMetrics:         cr.Spec.RedisExporter.Enabled,
+		PersistentVolumeClaim: cr.Spec.Storage.VolumeClaimTemplate,
+	}
+}
+
+// generateRedisStandaloneContainerParams generates Redis container information
+func generateRedisClusterContainerParams(cr *redisv1beta1.RedisCluster) containerParameters {
+	trueProperty := true
+	containerProp := containerParameters{
+		Role:                         "cluster",
+		Image:                        cr.Spec.KubernetesConfig.Image,
+		ImagePullPolicy:              cr.Spec.KubernetesConfig.ImagePullPolicy,
+		Resources:                    cr.Spec.KubernetesConfig.Resources,
+		RedisExporterImage:           cr.Spec.RedisExporter.Image,
+		RedisExporterImagePullPolicy: cr.Spec.RedisExporter.ImagePullPolicy,
+		RedisExporterResources:       cr.Spec.RedisExporter.Resources,
+	}
+	if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil {
+		containerProp.EnabledPassword = &trueProperty
+		containerProp.SecretName = cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name
+		containerProp.SecretKey = cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key
+	}
+	if cr.Spec.Storage != nil {
+		containerProp.PersistenceEnabled = &trueProperty
+	}
+	return containerProp
+}
+
+// CreateRedisLeader will create a leader redis setup
+func CreateRedisLeader(cr *redisv1beta1.RedisCluster) error {
+	prop := RedisClusterSTS{
+		RedisStateFulType: "leader",
+	}
+	return prop.CreateRedisClusterSetup(cr)
+}
+
+// CreateRedisFollower will create a follower redis setup
+func CreateRedisFollower(cr *redisv1beta1.RedisCluster) error {
+	prop := RedisClusterSTS{
+		RedisStateFulType: "follower",
+	}
+	return prop.CreateRedisClusterSetup(cr)
+}
+
+// CreateRedisLeaderService method will create service for Redis Leader
+func CreateRedisLeaderService(cr *redisv1beta1.RedisCluster) error {
+	prop := RedisClusterService{
+		RedisServiceType: cr.Spec.RedisLeader.Service,
+		RedisServiceRole: "leader",
+	}
+	return prop.CreateRedisClusterService(cr)
+}
+
+// CreateRedisFollowerService method will create service for Redis Follower
+func CreateRedisFollowerService(cr *redisv1beta1.RedisCluster) error {
+	prop := RedisClusterService{
+		RedisServiceType: cr.Spec.RedisLeader.Service,
+		RedisServiceRole: "follower",
+	}
+	return prop.CreateRedisClusterService(cr)
+}
+
+// CreateRedisSetup will create Redis Setup for leader and follower
+func (service RedisClusterSTS) CreateRedisClusterSetup(cr *redisv1beta1.RedisCluster) error {
+	stateFulName := cr.ObjectMeta.Name + "-" + service.RedisStateFulType
+	logger := stateFulSetLogger(cr.Namespace, stateFulName)
+	labels := getRedisLabels(stateFulName, "cluster", service.RedisStateFulType)
+	objectMetaInfo := generateObjectMetaInformation(stateFulName, cr.Namespace, labels, generateStatefulSetsAnots())
+	err := CreateOrUpdateStateFul(cr.Namespace, objectMetaInfo, labels, generateRedisClusterarams(cr), redisClusterAsOwner(cr), generateRedisClusterContainerParams(cr))
+	if err != nil {
+		logger.Error(err, "Cannot create statfulset for Redis", "Setup.Type", service.RedisStateFulType)
+		return err
+	}
+	return nil
+}
+
+// CreateRedisClusterService method will create service for Redis
+func (service RedisClusterService) CreateRedisClusterService(cr *redisv1beta1.RedisCluster) error {
+	serviceName := cr.ObjectMeta.Name + "-" + service.RedisServiceRole
+	logger := serviceLogger(cr.Namespace, serviceName)
+	labels := getRedisLabels(serviceName, "cluster", service.RedisServiceRole)
+	if cr.Spec.RedisExporter != nil && cr.Spec.RedisExporter.Enabled {
+		enableMetrics = true
+	}
+	k8sServiceType = service.RedisServiceType
+	objectMetaInfo := generateObjectMetaInformation(serviceName, cr.Namespace, labels, generateServiceAnots())
+	headlessObjectMetaInfo := generateObjectMetaInformation(serviceName+"-headless", cr.Namespace, labels, generateServiceAnots())
+	err := CreateOrUpdateHeadlessService(cr.Namespace, headlessObjectMetaInfo, labels, redisClusterAsOwner(cr))
+	if err != nil {
+		logger.Error(err, "Cannot create headless service for Redis", "Setup.Type", service.RedisServiceRole)
+		return err
+	}
+	err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, labels, redisClusterAsOwner(cr), k8sServiceType, enableMetrics)
+	if err != nil {
+		logger.Error(err, "Cannot create service for Redis", "Setup.Type", service.RedisServiceRole)
+		return err
+	}
+	return nil
+}
+
+func getRedisLabels(name, setupType, role string) map[string]string {
+	return map[string]string{
+		"app":              name,
+		"redis_setup_type": setupType,
+		"role":             role,
+	}
+}
diff --git a/k8sutils/redis-standalone.go b/k8sutils/redis-standalone.go
new file mode 100644
index 0000000000000000000000000000000000000000..e8fb54e3a8f1a0d3b6326de96d9e25643b50cf59
--- /dev/null
+++ b/k8sutils/redis-standalone.go
@@ -0,0 +1,84 @@
+package k8sutils
+
+import (
+	redisv1beta1 "redis-operator/api/v1beta1"
+)
+
+var (
+	k8sServiceType string
+	enableMetrics  bool
+)
+
+// CreateStandAloneService method will create standalone service for Redis
+func CreateStandAloneService(cr *redisv1beta1.Redis) error {
+	logger := serviceLogger(cr.Namespace, cr.ObjectMeta.Name)
+	labels := getRedisLabels(cr.ObjectMeta.Name, "standalone", "standalone")
+	if cr.Spec.RedisExporter != nil && cr.Spec.RedisExporter.Enabled {
+		enableMetrics = true
+	}
+	k8sServiceType = cr.Spec.KubernetesConfig.ServiceType
+	objectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name, cr.Namespace, labels, generateServiceAnots())
+	headlessObjectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name+"-headless", cr.Namespace, labels, generateServiceAnots())
+	err := CreateOrUpdateHeadlessService(cr.Namespace, headlessObjectMetaInfo, labels, redisAsOwner(cr))
+	if err != nil {
+		logger.Error(err, "Cannot create standalone headless service for Redis")
+		return err
+	}
+	err = CreateOrUpdateService(cr.Namespace, objectMetaInfo, labels, redisAsOwner(cr), k8sServiceType, enableMetrics)
+	if err != nil {
+		logger.Error(err, "Cannot create standalone service for Redis")
+		return err
+	}
+	return nil
+}
+
+// CreateStandAloneRedis will create a standalone redis setup
+func CreateStandAloneRedis(cr *redisv1beta1.Redis) error {
+	logger := stateFulSetLogger(cr.Namespace, cr.ObjectMeta.Name)
+	labels := getRedisLabels(cr.ObjectMeta.Name, "standalone", "standalone")
+	objectMetaInfo := generateObjectMetaInformation(cr.ObjectMeta.Name, cr.Namespace, labels, generateStatefulSetsAnots())
+	err := CreateOrUpdateStateFul(cr.Namespace, objectMetaInfo, labels, generateRedisStandaloneParams(cr), redisAsOwner(cr), generateRedisStandaloneContainerParams(cr))
+	if err != nil {
+		logger.Error(err, "Cannot create standalone statfulset for Redis")
+		return err
+	}
+	return nil
+}
+
+// generateRedisStandalone generates Redis standalone information
+func generateRedisStandaloneParams(cr *redisv1beta1.Redis) statefulSetParameters {
+	replicas := int32(1)
+	return statefulSetParameters{
+		Replicas:              &replicas,
+		NodeSelector:          cr.Spec.NodeSelector,
+		SecurityContext:       cr.Spec.SecurityContext,
+		PriorityClassName:     cr.Spec.PriorityClassName,
+		Affinity:              cr.Spec.Affinity,
+		Tolerations:           cr.Spec.Tolerations,
+		EnableMetrics:         cr.Spec.RedisExporter.Enabled,
+		PersistentVolumeClaim: cr.Spec.Storage.VolumeClaimTemplate,
+	}
+}
+
+// generateRedisStandaloneContainerParams generates Redis container information
+func generateRedisStandaloneContainerParams(cr *redisv1beta1.Redis) containerParameters {
+	trueProperty := true
+	containerProp := containerParameters{
+		Role:                         "standalone",
+		Image:                        cr.Spec.KubernetesConfig.Image,
+		ImagePullPolicy:              cr.Spec.KubernetesConfig.ImagePullPolicy,
+		Resources:                    cr.Spec.KubernetesConfig.Resources,
+		RedisExporterImage:           cr.Spec.RedisExporter.Image,
+		RedisExporterImagePullPolicy: cr.Spec.RedisExporter.ImagePullPolicy,
+		RedisExporterResources:       cr.Spec.RedisExporter.Resources,
+	}
+	if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil {
+		containerProp.EnabledPassword = &trueProperty
+		containerProp.SecretName = cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name
+		containerProp.SecretKey = cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key
+	}
+	if cr.Spec.Storage != nil {
+		containerProp.PersistenceEnabled = &trueProperty
+	}
+	return containerProp
+}
diff --git a/k8sutils/redis.go b/k8sutils/redis.go
index 1187df74039583eb3b31996d40d1783365e7f5dc..a50b21a3037b1249151f5eb1f429ef560361e061 100644
--- a/k8sutils/redis.go
+++ b/k8sutils/redis.go
@@ -4,15 +4,16 @@ import (
 	"bytes"
 	"context"
 	"encoding/csv"
-	redisv1beta1 "redis-operator/api/v1beta1"
 	"strconv"
 	"strings"
 
+	"github.com/go-logr/logr"
 	"github.com/go-redis/redis"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/kubernetes/scheme"
 	"k8s.io/client-go/tools/remotecommand"
+	redisv1beta1 "redis-operator/api/v1beta1"
 )
 
 // RedisDetails will hold the information for Redis Pod
@@ -23,212 +24,205 @@ type RedisDetails struct {
 
 // getRedisServerIP will return the IP of redis service
 func getRedisServerIP(redisInfo RedisDetails) string {
-	reqLogger := log.WithValues("Request.Namespace", redisInfo.Namespace, "Request.PodName", redisInfo.PodName)
-	redisIP, _ := GenerateK8sClient().CoreV1().Pods(redisInfo.Namespace).
-		Get(context.TODO(), redisInfo.PodName, metav1.GetOptions{})
+	logger := generateRedisManagerLogger(redisInfo.Namespace, redisInfo.PodName)
+	redisIP, err := generateK8sClient().CoreV1().Pods(redisInfo.Namespace).Get(context.TODO(), redisInfo.PodName, metav1.GetOptions{})
+	if err != nil {
+		logger.Error(err, "Error in getting redis pod IP")
+	}
 
-	reqLogger.Info("Successfully got the ip for redis", "ip", redisIP.Status.PodIP)
+	logger.Info("Successfully got the ip for redis", "ip", redisIP.Status.PodIP)
 	return redisIP.Status.PodIP
 }
 
 // ExecuteRedisClusterCommand will execute redis cluster creation command
-func ExecuteRedisClusterCommand(cr *redisv1beta1.Redis) {
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name)
+func ExecuteRedisClusterCommand(cr *redisv1beta1.RedisCluster) {
+	logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name)
 	replicas := cr.Spec.Size
 	cmd := []string{"redis-cli", "--cluster", "create"}
 	for podCount := 0; podCount <= int(*replicas)-1; podCount++ {
 		pod := RedisDetails{
-			PodName:   cr.ObjectMeta.Name + "-master-" + strconv.Itoa(podCount),
+			PodName:   cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(podCount),
 			Namespace: cr.Namespace,
 		}
 		cmd = append(cmd, getRedisServerIP(pod)+":6379")
 	}
 	cmd = append(cmd, "--cluster-yes")
-	if cr.Spec.GlobalConfig.Password != nil && cr.Spec.GlobalConfig.ExistingPasswordSecret == nil {
-		cmd = append(cmd, "-a")
-		cmd = append(cmd, *cr.Spec.GlobalConfig.Password)
-	}
 
-	if cr.Spec.GlobalConfig.ExistingPasswordSecret != nil {
-		pass := getRedisPassword(cr)
+	if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil {
+		pass, err := getRedisPassword(cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key)
+		if err != nil {
+			logger.Error(err, "Error in getting redis password")
+		}
 		cmd = append(cmd, "-a")
 		cmd = append(cmd, pass)
 	}
-	reqLogger.Info("Redis cluster creation command is", "Command", cmd)
-	executeCommand(cr, cmd, cr.ObjectMeta.Name+"-master-0")
+	logger.Info("Redis cluster creation command is", "Command", cmd)
+	executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0")
 }
 
 // createRedisReplicationCommand will create redis replication creation command
-func createRedisReplicationCommand(cr *redisv1beta1.Redis, slavePod RedisDetails, nodeNumber string) []string {
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name)
+func createRedisReplicationCommand(cr *redisv1beta1.RedisCluster, leaderPod RedisDetails, followerPod RedisDetails) []string {
+	logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name)
 	cmd := []string{"redis-cli", "--cluster", "add-node"}
-	masterPod := RedisDetails{
-		PodName:   cr.ObjectMeta.Name + "-master-" + nodeNumber,
-		Namespace: cr.Namespace,
-	}
-
-	cmd = append(cmd, getRedisServerIP(slavePod)+":6379")
-	cmd = append(cmd, getRedisServerIP(masterPod)+":6379")
+	cmd = append(cmd, getRedisServerIP(followerPod)+":6379")
+	cmd = append(cmd, getRedisServerIP(leaderPod)+":6379")
 	cmd = append(cmd, "--cluster-slave")
 
-	if cr.Spec.GlobalConfig.Password != nil && cr.Spec.GlobalConfig.ExistingPasswordSecret == nil {
-		cmd = append(cmd, "-a")
-		cmd = append(cmd, *cr.Spec.GlobalConfig.Password)
-	}
-	if cr.Spec.GlobalConfig.ExistingPasswordSecret != nil {
-		pass := getRedisPassword(cr)
+	if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil {
+		pass, err := getRedisPassword(cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key)
+		if err != nil {
+			logger.Error(err, "Error in getting redis password")
+		}
 		cmd = append(cmd, "-a")
 		cmd = append(cmd, pass)
 	}
-	reqLogger.Info("Redis replication creation command is", "Command", cmd)
+	logger.Info("Redis replication creation command is", "Command", cmd)
 	return cmd
 }
 
 // ExecuteRedisReplicationCommand will execute the replication command
-func ExecuteRedisReplicationCommand(cr *redisv1beta1.Redis) {
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name)
+func ExecuteRedisReplicationCommand(cr *redisv1beta1.RedisCluster) {
+	logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name)
 	replicas := cr.Spec.Size
 	nodes := checkRedisCluster(cr)
 	for podCount := 0; podCount <= int(*replicas)-1; podCount++ {
-		slavePod := RedisDetails{
-			PodName:   cr.ObjectMeta.Name + "-slave-" + strconv.Itoa(podCount),
+		followerPod := RedisDetails{
+			PodName:   cr.ObjectMeta.Name + "-follower-" + strconv.Itoa(podCount),
+			Namespace: cr.Namespace,
+		}
+		leaderPod := RedisDetails{
+			PodName:   cr.ObjectMeta.Name + "-leader-" + strconv.Itoa(podCount),
 			Namespace: cr.Namespace,
 		}
-		podIP := getRedisServerIP(slavePod)
-		if !CheckRedisNodePresence(cr, nodes, podIP) {
-			reqLogger.Info("Adding node to cluster.", "Node.IP", podIP, "Slave.Pod", slavePod)
-			cmd := createRedisReplicationCommand(cr, slavePod, strconv.Itoa(podCount))
-			executeCommand(cr, cmd, cr.ObjectMeta.Name+"-master-0")
+		podIP := getRedisServerIP(followerPod)
+		if !checkRedisNodePresence(cr, nodes, podIP) {
+			logger.Info("Adding node to cluster.", "Node.IP", podIP, "Follower.Pod", followerPod)
+			cmd := createRedisReplicationCommand(cr, leaderPod, followerPod)
+			executeCommand(cr, cmd, cr.ObjectMeta.Name+"-leader-0")
 		} else {
-			reqLogger.Info("Skipping Adding node to cluster, already present.", "Slave.Pod", slavePod)
+			logger.Info("Skipping Adding node to cluster, already present.", "Follower.Pod", followerPod)
 		}
 	}
 }
 
 // checkRedisCluster will check the redis cluster have sufficient nodes or not
-func checkRedisCluster(cr *redisv1beta1.Redis) [][]string {
+func checkRedisCluster(cr *redisv1beta1.RedisCluster) [][]string {
 	var client *redis.Client
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name)
-
-	client = configureRedisClient(cr, cr.ObjectMeta.Name+"-master-0")
+	logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name)
+	client = configureRedisClient(cr, cr.ObjectMeta.Name+"-leader-0")
 	cmd := redis.NewStringCmd("cluster", "nodes")
 	err := client.Process(cmd)
 	if err != nil {
-		reqLogger.Error(err, "Redis command failed with this error")
+		logger.Error(err, "Redis command failed with this error")
 	}
 
 	output, err := cmd.Result()
 	if err != nil {
-		reqLogger.Error(err, "Redis command failed with this error")
+		logger.Error(err, "Redis command failed with this error")
 	}
-	reqLogger.Info("Redis cluster nodes are listed", "Output", output)
+	logger.Info("Redis cluster nodes are listed", "Output", output)
 
-	r := csv.NewReader(strings.NewReader(output))
-	r.Comma = ' '          // Output is space seperated
-	r.FieldsPerRecord = -1 // Negative as there can be variable column lengths
-	records, err := r.ReadAll()
+	csvOutput := csv.NewReader(strings.NewReader(output))
+	csvOutput.Comma = ' '
+	csvOutput.FieldsPerRecord = -1
+	csvOutputRecords, err := csvOutput.ReadAll()
 	if err != nil {
-		reqLogger.Error(err, "Error parsing Node Counts", "output", output)
+		logger.Error(err, "Error parsing Node Counts", "output", output)
 	}
-	return records
+	return csvOutputRecords
 }
 
 // ExecuteFaioverOperation will execute redis failover operations
-func ExecuteFaioverOperation(cr *redisv1beta1.Redis) {
-	executeFailoverCommand(cr, "master")
-	executeFailoverCommand(cr, "slave")
+func ExecuteFaioverOperation(cr *redisv1beta1.RedisCluster) {
+	executeFailoverCommand(cr, "leader")
+	executeFailoverCommand(cr, "follower")
 }
 
 // executeFailoverCommand will execute failover command
-func executeFailoverCommand(cr *redisv1beta1.Redis, role string) {
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name)
+func executeFailoverCommand(cr *redisv1beta1.RedisCluster, role string) {
+	logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name)
 	replicas := cr.Spec.Size
 	podName := cr.ObjectMeta.Name + "-" + role + "-"
 	for podCount := 0; podCount <= int(*replicas)-1; podCount++ {
-		reqLogger.Info("Executing redis failover operations", "Redis Node", podName+strconv.Itoa(podCount))
+		logger.Info("Executing redis failover operations", "Redis Node", podName+strconv.Itoa(podCount))
 		client := configureRedisClient(cr, podName+strconv.Itoa(podCount))
 		cmd := redis.NewStringCmd("cluster", "reset")
 		err := client.Process(cmd)
 		if err != nil {
-			reqLogger.Error(err, "Redis command failed with this error")
+			logger.Error(err, "Redis command failed with this error")
 			flushcommand := redis.NewStringCmd("flushall")
 			err := client.Process(flushcommand)
 			if err != nil {
-				reqLogger.Error(err, "Redis flush command failed with this error")
+				logger.Error(err, "Redis flush command failed with this error")
 			}
 		}
 
 		output, err := cmd.Result()
 		if err != nil {
-			reqLogger.Error(err, "Redis command failed with this error")
+			logger.Error(err, "Redis command failed with this error")
 		}
-		reqLogger.Info("Redis cluster failover executed", "Output", output)
+		logger.Info("Redis cluster failover executed", "Output", output)
 	}
 }
 
 // CheckRedisNodeCount will check the count of redis nodes
-func CheckRedisNodeCount(cr *redisv1beta1.Redis, nodetype string) int {
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name)
+func CheckRedisNodeCount(cr *redisv1beta1.RedisCluster, nodeType string) int {
+	var redisNodeType string
+	logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name)
 	clusterNodes := checkRedisCluster(cr)
-
 	count := len(clusterNodes)
-	if nodetype != "" {
+
+	switch nodeType {
+	case "leader":
+		redisNodeType = "master"
+	case "follower":
+		redisNodeType = "slave"
+	default:
+		redisNodeType = nodeType
+	}
+	if nodeType != "" {
 		count = 0
 		for _, node := range clusterNodes {
-			// Check for contains.. as we may get self,master or just master/slave
-			if strings.Contains(node[2], nodetype) {
+			if strings.Contains(node[2], redisNodeType) {
 				count++
 			}
 		}
-		reqLogger.Info("Number of redis nodes are", "Nodes", strconv.Itoa(count), "Type", nodetype)
+		logger.Info("Number of redis nodes are", "Nodes", strconv.Itoa(count), "Type", nodeType)
 	} else {
-		reqLogger.Info("Total number of redis nodes are", "Nodes", strconv.Itoa(count))
+		logger.Info("Total number of redis nodes are", "Nodes", strconv.Itoa(count))
 	}
 	return count
 }
 
-func CheckRedisNodePresence(cr *redisv1beta1.Redis, nodeList [][]string, nodeName string) bool {
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name)
-	reqLogger.Info("Checking if Node is in cluster", "Node", nodeName)
-	for _, node := range nodeList {
-		if strings.Contains(node[1], nodeName) {
-			return true
-		}
-	}
-	return false
-}
-
 // CheckRedisClusterState will check the redis cluster state
-func CheckRedisClusterState(cr *redisv1beta1.Redis) int {
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name)
-	output := checkRedisCluster(cr)
+func CheckRedisClusterState(cr *redisv1beta1.RedisCluster) int {
+	logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name)
+	clusterNodes := checkRedisCluster(cr)
 	count := 0
-	for _, node := range output {
-		//If connection or the role contains fail.
+
+	for _, node := range clusterNodes {
 		if strings.Contains(node[2], "fail") || strings.Contains(node[7], "disconnected") {
 			count++
 		}
 	}
-	reqLogger.Info("Number of failed nodes in cluster", "Failed Node Count", count)
+	logger.Info("Number of failed nodes in cluster", "Failed Node Count", count)
 	return count
 }
 
 // configureRedisClient will configure the Redis Client
-func configureRedisClient(cr *redisv1beta1.Redis, podName string) *redis.Client {
+func configureRedisClient(cr *redisv1beta1.RedisCluster, podName string) *redis.Client {
+	logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name)
 	redisInfo := RedisDetails{
 		PodName:   podName,
 		Namespace: cr.Namespace,
 	}
 	var client *redis.Client
 
-	if cr.Spec.GlobalConfig.Password != nil && cr.Spec.GlobalConfig.ExistingPasswordSecret == nil {
-		client = redis.NewClient(&redis.Options{
-			Addr:     getRedisServerIP(redisInfo) + ":6379",
-			Password: *cr.Spec.GlobalConfig.Password,
-			DB:       0,
-		})
-	} else if cr.Spec.GlobalConfig.ExistingPasswordSecret != nil {
-		pass := getRedisPassword(cr)
+	if cr.Spec.KubernetesConfig.ExistingPasswordSecret != nil {
+		pass, err := getRedisPassword(cr.Namespace, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Name, *cr.Spec.KubernetesConfig.ExistingPasswordSecret.Key)
+		if err != nil {
+			logger.Error(err, "Error in getting redis password")
+		}
 		client = redis.NewClient(&redis.Options{
 			Addr:     getRedisServerIP(redisInfo) + ":6379",
 			Password: pass,
@@ -245,18 +239,22 @@ func configureRedisClient(cr *redisv1beta1.Redis, podName string) *redis.Client
 }
 
 // executeCommand will execute the commands in pod
-func executeCommand(cr *redisv1beta1.Redis, cmd []string, podName string) {
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name, "podName", podName)
-	config, err := GenerateK8sConfig()
+func executeCommand(cr *redisv1beta1.RedisCluster, cmd []string, podName string) {
+	var (
+		execOut bytes.Buffer
+		execErr bytes.Buffer
+	)
+	logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name)
+	config, err := generateK8sConfig()
 	if err != nil {
-		reqLogger.Error(err, "Error while reading Cluster config")
+		logger.Error(err, "Could not find pod to execute")
 	}
 	targetContainer, pod := getContainerID(cr, podName)
 	if targetContainer < 0 {
-		reqLogger.Error(err, "Could not find pod to execute")
+		logger.Error(err, "Could not find pod to execute")
 	}
 
-	req := GenerateK8sClient().CoreV1().RESTClient().Post().Resource("pods").Name(podName).Namespace(cr.Namespace).SubResource("exec")
+	req := generateK8sClient().CoreV1().RESTClient().Post().Resource("pods").Name(podName).Namespace(cr.Namespace).SubResource("exec")
 	req.VersionedParams(&corev1.PodExecOptions{
 		Container: pod.Spec.Containers[targetContainer].Name,
 		Command:   cmd,
@@ -265,12 +263,8 @@ func executeCommand(cr *redisv1beta1.Redis, cmd []string, podName string) {
 	}, scheme.ParameterCodec)
 	exec, err := remotecommand.NewSPDYExecutor(config, "POST", req.URL())
 	if err != nil {
-		reqLogger.Error(err, "Failed to init executor")
+		logger.Error(err, "Failed to init executor")
 	}
-	var (
-		execOut bytes.Buffer
-		execErr bytes.Buffer
-	)
 
 	err = exec.Stream(remotecommand.StreamOptions{
 		Stdout: &execOut,
@@ -278,26 +272,44 @@ func executeCommand(cr *redisv1beta1.Redis, cmd []string, podName string) {
 		Tty:    false,
 	})
 	if err != nil {
-		reqLogger.Error(err, "Could not execute command", "Command", cmd, "Output", execOut.String(), "Error", execErr.String())
+		logger.Error(err, "Could not execute command", "Command", cmd, "Output", execOut.String(), "Error", execErr.String())
 	}
-	reqLogger.Info("Successfully executed the command", "Command", cmd, "Output", execOut.String())
+	logger.Info("Successfully executed the command", "Command", cmd, "Output", execOut.String())
 }
 
 // getContainerID will return the id of container from pod
-func getContainerID(cr *redisv1beta1.Redis, podName string) (int, *corev1.Pod) {
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name)
-	pod, err := GenerateK8sClient().CoreV1().Pods(cr.Namespace).Get(context.TODO(), podName, metav1.GetOptions{})
+func getContainerID(cr *redisv1beta1.RedisCluster, podName string) (int, *corev1.Pod) {
+	logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name)
+	pod, err := generateK8sClient().CoreV1().Pods(cr.Namespace).Get(context.TODO(), podName, metav1.GetOptions{})
 	if err != nil {
-		reqLogger.Error(err, "Could not get pod info")
+		logger.Error(err, "Could not get pod info")
 	}
 
 	targetContainer := -1
 	for containerID, tr := range pod.Spec.Containers {
-		reqLogger.Info("Pod Counted successfully", "Count", containerID, "Container Name", tr.Name)
-		if tr.Name == cr.ObjectMeta.Name+"-master" {
+		logger.Info("Pod Counted successfully", "Count", containerID, "Container Name", tr.Name)
+		if tr.Name == cr.ObjectMeta.Name+"-leader" {
 			targetContainer = containerID
 			break
 		}
 	}
 	return targetContainer, pod
 }
+
+// checkRedisNodePresence will check if the redis node exist in cluster or not
+func checkRedisNodePresence(cr *redisv1beta1.RedisCluster, nodeList [][]string, nodeName string) bool {
+	logger := generateRedisManagerLogger(cr.Namespace, cr.ObjectMeta.Name)
+	logger.Info("Checking if Node is in cluster", "Node", nodeName)
+	for _, node := range nodeList {
+		if strings.Contains(node[1], nodeName) {
+			return true
+		}
+	}
+	return false
+}
+
+// generateRedisManagerLogger will generate logging interface for Redis operations
+func generateRedisManagerLogger(namespace, name string) logr.Logger {
+	reqLogger := log.WithValues("Request.RedisManager.Namespace", namespace, "Request.RedisManager.Name", name)
+	return reqLogger
+}
diff --git a/k8sutils/secrets.go b/k8sutils/secrets.go
index ea92fd2aebbf54b81055bdd151e16342a39fdc49..2490b0af478828babb432e5ff7c5b0b5d4f7b6d4 100644
--- a/k8sutils/secrets.go
+++ b/k8sutils/secrets.go
@@ -2,64 +2,30 @@ package k8sutils
 
 import (
 	"context"
-	corev1 "k8s.io/api/core/v1"
+	"github.com/go-logr/logr"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	redisv1beta1 "redis-operator/api/v1beta1"
 	logf "sigs.k8s.io/controller-runtime/pkg/log"
 )
 
 var log = logf.Log.WithName("controller_redis")
 
-// GenerateSecret is a method that will generate a secret interface
-func GenerateSecret(cr *redisv1beta1.Redis) *corev1.Secret {
-	password := []byte(*cr.Spec.GlobalConfig.Password)
-	labels := map[string]string{
-		"app": cr.ObjectMeta.Name,
-	}
-	secret := &corev1.Secret{
-		TypeMeta:   GenerateMetaInformation("Secret", "v1"),
-		ObjectMeta: GenerateObjectMetaInformation(cr.ObjectMeta.Name, cr.Namespace, labels, GenerateSecretAnots()),
-		Data: map[string][]byte{
-			"password": password,
-		},
-	}
-	AddOwnerRefToObject(secret, AsOwner(cr))
-	return secret
-}
-
-// CreateRedisSecret method will create a redis secret
-func CreateRedisSecret(cr *redisv1beta1.Redis) {
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name)
-	secretBody := GenerateSecret(cr)
-	secretName, err := GenerateK8sClient().CoreV1().Secrets(cr.Namespace).Get(context.TODO(), cr.ObjectMeta.Name, metav1.GetOptions{})
-	if err != nil {
-		reqLogger.Info("Creating secret for redis", "Secret.Name", cr.ObjectMeta.Name)
-		_, err := GenerateK8sClient().CoreV1().Secrets(cr.Namespace).Create(context.TODO(), secretBody, metav1.CreateOptions{})
-		if err != nil {
-			reqLogger.Error(err, "Failed in creating secret for redis")
-		}
-	} else if secretBody != secretName {
-		reqLogger.Info("Reconciling secret for redis", "Secret.Name", cr.ObjectMeta.Name)
-		_, err := GenerateK8sClient().CoreV1().Secrets(cr.Namespace).Update(context.TODO(), secretBody, metav1.UpdateOptions{})
-		if err != nil {
-			reqLogger.Error(err, "Failed in updating secret for redis")
-		}
-	} else {
-		reqLogger.Info("Secret for redis are in sync", "Secret.Name", cr.ObjectMeta.Name)
-	}
-}
-
 // getRedisPassword method will return the redis password
-func getRedisPassword(cr *redisv1beta1.Redis) string {
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name)
-	secretName, err := GenerateK8sClient().CoreV1().Secrets(cr.Namespace).Get(context.TODO(), *cr.Spec.GlobalConfig.ExistingPasswordSecret.Name, metav1.GetOptions{})
+func getRedisPassword(namespace, name, secretKey string) (string, error) {
+	logger := secretLogger(namespace, name)
+	secretName, err := generateK8sClient().CoreV1().Secrets(namespace).Get(context.TODO(), name, metav1.GetOptions{})
 	if err != nil {
-		reqLogger.Error(err, "Failed in getting existing secret for redis")
+		logger.Error(err, "Failed in getting existing secret for redis")
+		return "", err
 	}
 	for key, value := range secretName.Data {
-		if key == *cr.Spec.GlobalConfig.ExistingPasswordSecret.Key {
-			return string(value)
+		if key == secretKey {
+			return string(value), nil
 		}
 	}
-	return ""
+	return "", nil
+}
+
+func secretLogger(namespace string, name string) logr.Logger {
+	reqLogger := log.WithValues("Request.Secret.Namespace", namespace, "Request.Secret.Name", name)
+	return reqLogger
 }
diff --git a/k8sutils/services.go b/k8sutils/services.go
index dda54012fac8b9a952b9c4977586ce06925455a1..02fade577158736280e6edc1017060b894e502ad 100644
--- a/k8sutils/services.go
+++ b/k8sutils/services.go
@@ -2,229 +2,197 @@ package k8sutils
 
 import (
 	"context"
+	"github.com/banzaicloud/k8s-objectmatcher/patch"
+	"github.com/go-logr/logr"
 	corev1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/intstr"
-	redisv1beta1 "redis-operator/api/v1beta1"
 )
 
 const (
-	redisPort = 6379
+	redisPort         = 6379
+	redisExporterPort = 9121
 )
 
-// ServiceInterface is the interface to pass service information accross methods
-type ServiceInterface struct {
-	ExistingService      *corev1.Service
-	NewServiceDefinition *corev1.Service
-	ServiceType          string
-}
+var (
+	serviceType corev1.ServiceType
+)
 
-// GenerateHeadlessServiceDef generate service definition
-func GenerateHeadlessServiceDef(cr *redisv1beta1.Redis, labels map[string]string, portNumber int32, role string, serviceName string, clusterIP string) *corev1.Service {
-	var redisExporterPort int32 = 9121
+// generateHeadlessServiceDef generates service definition for headless service
+func generateHeadlessServiceDef(serviceMeta metav1.ObjectMeta, labels map[string]string, ownerDef metav1.OwnerReference) *corev1.Service {
 	service := &corev1.Service{
-		TypeMeta:   GenerateMetaInformation("Service", "core/v1"),
-		ObjectMeta: GenerateObjectMetaInformation(serviceName, cr.Namespace, labels, GenerateServiceAnots()),
+		TypeMeta:   generateMetaInformation("Service", "core/v1"),
+		ObjectMeta: serviceMeta,
 		Spec: corev1.ServiceSpec{
-			ClusterIP: clusterIP,
+			ClusterIP: "None",
 			Selector:  labels,
 			Ports: []corev1.ServicePort{
 				{
-					Name:       cr.ObjectMeta.Name + "-" + role,
-					Port:       portNumber,
-					TargetPort: intstr.FromInt(int(portNumber)),
+					Name:       "redis-client",
+					Port:       redisPort,
+					TargetPort: intstr.FromInt(int(redisPort)),
 					Protocol:   corev1.ProtocolTCP,
 				},
 			},
 		},
 	}
-	if !cr.Spec.RedisExporter.Enabled {
-		service.Spec.Ports = append(service.Spec.Ports, corev1.ServicePort{
-			Name:       "redis-exporter",
-			Port:       redisExporterPort,
-			TargetPort: intstr.FromInt(int(redisExporterPort)),
-			Protocol:   corev1.ProtocolTCP,
-		})
-	}
-	AddOwnerRefToObject(service, AsOwner(cr))
+	AddOwnerRefToObject(service, ownerDef)
 	return service
 }
 
-// GenerateServiceDef generate service definition
-func GenerateServiceDef(cr *redisv1beta1.Redis, labels map[string]string, portNumber int32, role string, serviceName string, typeService string) *corev1.Service {
-	var redisExporterPort int32 = 9121
-	var serviceType corev1.ServiceType
-
-	if typeService == "LoadBalancer" {
-		serviceType = corev1.ServiceTypeLoadBalancer
-	} else if typeService == "NodePort" {
-		serviceType = corev1.ServiceTypeNodePort
-	} else {
-		serviceType = corev1.ServiceTypeClusterIP
-	}
-
+// generateServiceDef generates service definition for Redis
+func generateServiceDef(serviceMeta metav1.ObjectMeta, labels map[string]string, k8sServiceType string, enableMetrics bool, ownerDef metav1.OwnerReference) *corev1.Service {
 	service := &corev1.Service{
-		TypeMeta:   GenerateMetaInformation("Service", "core/v1"),
-		ObjectMeta: GenerateObjectMetaInformation(serviceName, cr.Namespace, labels, GenerateServiceAnots()),
+		TypeMeta:   generateMetaInformation("Service", "core/v1"),
+		ObjectMeta: serviceMeta,
 		Spec: corev1.ServiceSpec{
-			Type:     serviceType,
+			Type:     generateServiceType(k8sServiceType),
 			Selector: labels,
 			Ports: []corev1.ServicePort{
 				{
-					Name:       cr.ObjectMeta.Name + "-" + role,
-					Port:       portNumber,
-					TargetPort: intstr.FromInt(int(portNumber)),
+					Name:       "redis-client",
+					Port:       redisPort,
+					TargetPort: intstr.FromInt(int(redisPort)),
 					Protocol:   corev1.ProtocolTCP,
 				},
 			},
 		},
 	}
-	if cr.Spec.RedisExporter.Enabled {
-		service.Spec.Ports = append(service.Spec.Ports, corev1.ServicePort{
-			Name:       "redis-exporter",
-			Port:       redisExporterPort,
-			TargetPort: intstr.FromInt(int(redisExporterPort)),
-			Protocol:   corev1.ProtocolTCP,
-		})
+	if enableMetrics {
+		redisExporterService := enableMetricsPort()
+		service.Spec.Ports = append(service.Spec.Ports, *redisExporterService)
 	}
-	AddOwnerRefToObject(service, AsOwner(cr))
+	AddOwnerRefToObject(service, ownerDef)
 	return service
 }
 
-// CreateMasterHeadlessService creates master headless service
-func CreateMasterHeadlessService(cr *redisv1beta1.Redis) {
-	labels := map[string]string{
-		"app":  cr.ObjectMeta.Name + "-master",
-		"role": "master",
-	}
-	serviceDefinition := GenerateHeadlessServiceDef(cr, labels, int32(redisPort), "master", cr.ObjectMeta.Name+"-master-headless", "None")
-	serviceBody, err := GenerateK8sClient().CoreV1().Services(cr.Namespace).Get(context.TODO(), cr.ObjectMeta.Name+"-master-headless", metav1.GetOptions{})
-	service := ServiceInterface{
-		ExistingService:      serviceBody,
-		NewServiceDefinition: serviceDefinition,
-		ServiceType:          "master",
+// enableMetricsPort will enable the metrics for Redis service
+func enableMetricsPort() *corev1.ServicePort {
+	return &corev1.ServicePort{
+		Name:       "redis-exporter",
+		Port:       redisExporterPort,
+		TargetPort: intstr.FromInt(int(redisExporterPort)),
+		Protocol:   corev1.ProtocolTCP,
 	}
-	CompareAndCreateHeadlessService(cr, service, err)
 }
 
-// CreateMasterService creates different services for master
-func CreateMasterService(cr *redisv1beta1.Redis) {
-	labels := map[string]string{
-		"app":  cr.ObjectMeta.Name + "-master",
-		"role": "master",
-	}
-	serviceDefinition := GenerateServiceDef(cr, labels, int32(redisPort), "master", cr.ObjectMeta.Name+"-master", cr.Spec.Master.Service.Type)
-	serviceBody, err := GenerateK8sClient().CoreV1().Services(cr.Namespace).Get(context.TODO(), cr.ObjectMeta.Name+"-master", metav1.GetOptions{})
-	service := ServiceInterface{
-		ExistingService:      serviceBody,
-		NewServiceDefinition: serviceDefinition,
-		ServiceType:          "master",
+// generateServiceType generates service type
+func generateServiceType(k8sServiceType string) corev1.ServiceType {
+	switch k8sServiceType {
+	case "LoadBalancer":
+		serviceType = corev1.ServiceTypeLoadBalancer
+	case "NodePort":
+		serviceType = corev1.ServiceTypeNodePort
+	case "ClusterIP":
+		serviceType = corev1.ServiceTypeClusterIP
+	default:
+		serviceType = corev1.ServiceTypeClusterIP
 	}
-	CompareAndCreateService(cr, service, err)
+	return serviceType
 }
 
-// CreateSlaveHeadlessService creates slave headless service
-func CreateSlaveHeadlessService(cr *redisv1beta1.Redis) {
-	labels := map[string]string{
-		"app":  cr.ObjectMeta.Name + "-slave",
-		"role": "slave",
-	}
-	serviceDefinition := GenerateHeadlessServiceDef(cr, labels, int32(redisPort), "slave", cr.ObjectMeta.Name+"-slave-headless", "None")
-	serviceBody, err := GenerateK8sClient().CoreV1().Services(cr.Namespace).Get(context.TODO(), cr.ObjectMeta.Name+"-slave-headless", metav1.GetOptions{})
-	service := ServiceInterface{
-		ExistingService:      serviceBody,
-		NewServiceDefinition: serviceDefinition,
-		ServiceType:          "slave",
+// createService is a method to create service is Kubernetes
+func createService(namespace string, service *corev1.Service) error {
+	logger := serviceLogger(namespace, service.Name)
+	_, err := generateK8sClient().CoreV1().Services(namespace).Create(context.TODO(), service, metav1.CreateOptions{})
+	if err != nil {
+		logger.Error(err, "Redis service creation is failed")
+		return err
 	}
-	CompareAndCreateHeadlessService(cr, service, err)
+	logger.Info("Redis service creation is successful")
+	return nil
 }
 
-// CreateSlaveService creates different services for slave
-func CreateSlaveService(cr *redisv1beta1.Redis) {
-	labels := map[string]string{
-		"app":  cr.ObjectMeta.Name + "-slave",
-		"role": "slave",
-	}
-	serviceDefinition := GenerateServiceDef(cr, labels, int32(redisPort), "slave", cr.ObjectMeta.Name+"-slave", cr.Spec.Slave.Service.Type)
-	serviceBody, err := GenerateK8sClient().CoreV1().Services(cr.Namespace).Get(context.TODO(), cr.ObjectMeta.Name+"-slave", metav1.GetOptions{})
-	service := ServiceInterface{
-		ExistingService:      serviceBody,
-		NewServiceDefinition: serviceDefinition,
-		ServiceType:          "slave",
+// updateService is a method to update service is Kubernetes
+func updateService(namespace string, service *corev1.Service) error {
+	logger := serviceLogger(namespace, service.Name)
+	_, err := generateK8sClient().CoreV1().Services(namespace).Update(context.TODO(), service, metav1.UpdateOptions{})
+	if err != nil {
+		logger.Error(err, "Redis service updation is failed")
+		return err
 	}
-	CompareAndCreateService(cr, service, err)
+	logger.Info("Redis service updation is successful")
+	return nil
 }
 
-// CreateStandaloneService creates redis standalone service
-func CreateStandaloneService(cr *redisv1beta1.Redis) {
-	labels := map[string]string{
-		"app":  cr.ObjectMeta.Name + "-" + "standalone",
-		"role": "standalone",
-	}
-	serviceDefinition := GenerateServiceDef(cr, labels, int32(redisPort), "standalone", cr.ObjectMeta.Name, cr.Spec.Service.Type)
-	serviceBody, err := GenerateK8sClient().CoreV1().Services(cr.Namespace).Get(context.TODO(), cr.ObjectMeta.Name, metav1.GetOptions{})
-
-	service := ServiceInterface{
-		ExistingService:      serviceBody,
-		NewServiceDefinition: serviceDefinition,
-		ServiceType:          "standalone",
+// getService is a method to get service is Kubernetes
+func getService(namespace string, service string) (*corev1.Service, error) {
+	logger := serviceLogger(namespace, service)
+	serviceInfo, err := generateK8sClient().CoreV1().Services(namespace).Get(context.TODO(), service, metav1.GetOptions{})
+	if err != nil {
+		logger.Info("Redis service get action is failed")
+		return nil, err
 	}
-	CompareAndCreateService(cr, service, err)
+	logger.Info("Redis service get action is successful")
+	return serviceInfo, nil
 }
 
-// CreateStandaloneHeadlessService creates redis standalone service
-func CreateStandaloneHeadlessService(cr *redisv1beta1.Redis) {
-	labels := map[string]string{
-		"app":  cr.ObjectMeta.Name + "-" + "standalone",
-		"role": "standalone",
-	}
-	serviceDefinition := GenerateHeadlessServiceDef(cr, labels, int32(redisPort), "standalone", cr.ObjectMeta.Name+"-headless", "None")
-	serviceBody, err := GenerateK8sClient().CoreV1().Services(cr.Namespace).Get(context.TODO(), cr.ObjectMeta.Name+"-headless", metav1.GetOptions{})
-
-	service := ServiceInterface{
-		ExistingService:      serviceBody,
-		NewServiceDefinition: serviceDefinition,
-		ServiceType:          "standalone",
-	}
-	CompareAndCreateHeadlessService(cr, service, err)
+func serviceLogger(namespace string, name string) logr.Logger {
+	reqLogger := log.WithValues("Request.Service.Namespace", namespace, "Request.Service.Name", name)
+	return reqLogger
 }
 
-// CompareAndCreateService compares and creates service
-func CompareAndCreateService(cr *redisv1beta1.Redis, service ServiceInterface, err error) {
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name)
-
+// CreateOrUpdateHeadlessService method will create or update Redis headless service
+func CreateOrUpdateHeadlessService(namespace string, serviceMeta metav1.ObjectMeta, labels map[string]string, ownerDef metav1.OwnerReference) error {
+	logger := serviceLogger(namespace, serviceMeta.Name)
+	storedService, err := getService(namespace, serviceMeta.Name)
+	serviceDef := generateHeadlessServiceDef(serviceMeta, labels, ownerDef)
 	if err != nil {
-		reqLogger.Info("Creating redis service", "Redis.Name", cr.ObjectMeta.Name+"-"+service.ServiceType, "Service.Type", service.ServiceType)
-		_, err := GenerateK8sClient().CoreV1().Services(cr.Namespace).Create(context.TODO(), service.NewServiceDefinition, metav1.CreateOptions{})
-		if err != nil {
-			reqLogger.Error(err, "Failed in creating service for redis")
+		if errors.IsNotFound(err) {
+			if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(serviceDef); err != nil {
+				logger.Error(err, "Unable to patch redis service with comparison object")
+				return err
+			}
+			return createService(namespace, serviceDef)
 		}
+		return err
 	}
+	return patchService(storedService, serviceDef, namespace)
+}
 
-	if service.ExistingService != nil {
-		if service.ExistingService.Spec.Type != service.NewServiceDefinition.Spec.Type {
-			existingService := service.ExistingService
-			existingService.Spec.Type = service.NewServiceDefinition.Spec.Type
-			if existingService.ObjectMeta.Name != "" && existingService != nil {
-				reqLogger.Info("Service type has been updated for the service", "Redis.Name", cr.ObjectMeta.Name+"-"+service.ServiceType, "Service.Type", service.ServiceType)
-				_, err := GenerateK8sClient().CoreV1().Services(cr.Namespace).Update(context.TODO(), existingService, metav1.UpdateOptions{})
-				if err != nil {
-					reqLogger.Error(err, "Failed in updating service for redis")
-				}
+// CreateOrUpdateService method will create or update Redis service
+func CreateOrUpdateService(namespace string, serviceMeta metav1.ObjectMeta, labels map[string]string, ownerDef metav1.OwnerReference, k8sServiceType string, enableMetrics bool) error {
+	logger := serviceLogger(namespace, serviceMeta.Name)
+	serviceDef := generateServiceDef(serviceMeta, labels, k8sServiceType, enableMetrics, ownerDef)
+	storedService, err := getService(namespace, serviceMeta.Name)
+	if err != nil {
+		if errors.IsNotFound(err) {
+			if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(serviceDef); err != nil {
+				logger.Error(err, "Unable to patch redis service with compare annotations")
 			}
+			return createService(namespace, serviceDef)
 		}
+		return err
 	}
+	return patchService(storedService, serviceDef, namespace)
 }
 
-// CompareAndCreateService compares and creates service
-func CompareAndCreateHeadlessService(cr *redisv1beta1.Redis, service ServiceInterface, err error) {
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name)
-
+// patchService will patch Redis Kubernetes service
+func patchService(storedService *corev1.Service, newService *corev1.Service, namespace string) error {
+	logger := serviceLogger(namespace, storedService.Name)
+	patchResult, err := patch.DefaultPatchMaker.Calculate(storedService, newService, patch.IgnoreStatusFields())
 	if err != nil {
-		reqLogger.Info("Creating redis service", "Redis.Name", cr.ObjectMeta.Name+"-"+service.ServiceType, "Service.Type", service.ServiceType)
-		_, err := GenerateK8sClient().CoreV1().Services(cr.Namespace).Create(context.TODO(), service.NewServiceDefinition, metav1.CreateOptions{})
-		if err != nil {
-			reqLogger.Error(err, "Failed in creating service for redis")
+		logger.Error(err, "Unable to patch redis service with comparison object")
+		return err
+	}
+	if !patchResult.IsEmpty() {
+		newService.Spec.ClusterIP = storedService.Spec.ClusterIP
+		newService.ResourceVersion = storedService.ResourceVersion
+		newService.CreationTimestamp = storedService.CreationTimestamp
+		newService.ManagedFields = storedService.ManagedFields
+		for key, value := range storedService.Annotations {
+			if _, present := newService.Annotations[key]; !present {
+				newService.Annotations[key] = value
+			}
+		}
+		if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(newService); err != nil {
+			logger.Error(err, "Unable to patch redis service with comparison object")
+			return err
 		}
+		logger.Info("Syncing Redis service with defined properties")
+		return updateService(namespace, newService)
 	}
+	logger.Info("Redis service is already in-sync")
+	return nil
 }
diff --git a/k8sutils/statefulset.go b/k8sutils/statefulset.go
index eb4c8d99c913072e71e073ffc02bcf05b99351ba..dd18f45549b246b71d112bf8e039cb97718ab7f6 100644
--- a/k8sutils/statefulset.go
+++ b/k8sutils/statefulset.go
@@ -2,340 +2,266 @@ package k8sutils
 
 import (
 	"context"
-	// "github.com/google/go-cmp/cmp"
+	"github.com/banzaicloud/k8s-objectmatcher/patch"
+	"github.com/go-logr/logr"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
-	apiequality "k8s.io/apimachinery/pkg/api/equality"
-	"k8s.io/apimachinery/pkg/api/resource"
+	"k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-
-	redisv1beta1 "redis-operator/api/v1beta1"
 )
 
 const (
-	constRedisExpoterName = "redis-exporter"
-	graceTime             = 15
+	redisExporterContainer = "redis-exporter"
+	graceTime              = 15
 )
 
-// StatefulInterface is the interface to pass statefulset information accross methods
-type StatefulInterface struct {
-	Existing *appsv1.StatefulSet
-	Desired  *appsv1.StatefulSet
-	Type     string
+// statefulSetParameters will define statefulsets input params
+type statefulSetParameters struct {
+	Replicas              *int32
+	NodeSelector          map[string]string
+	SecurityContext       *corev1.PodSecurityContext
+	PriorityClassName     string
+	Affinity              *corev1.Affinity
+	Tolerations           *[]corev1.Toleration
+	EnableMetrics         bool
+	PersistentVolumeClaim corev1.PersistentVolumeClaim
+}
+
+// containerParameters will define container input params
+type containerParameters struct {
+	Image                        string
+	ImagePullPolicy              corev1.PullPolicy
+	Resources                    *corev1.ResourceRequirements
+	RedisExporterImage           string
+	RedisExporterImagePullPolicy corev1.PullPolicy
+	RedisExporterResources       *corev1.ResourceRequirements
+	Role                         string
+	EnabledPassword              *bool
+	SecretName                   *string
+	SecretKey                    *string
+	PersistenceEnabled           *bool
+}
+
+// CreateOrUpdateService method will create or update Redis service
+func CreateOrUpdateStateFul(namespace string, stsMeta metav1.ObjectMeta, labels map[string]string, params statefulSetParameters, ownerDef metav1.OwnerReference, containerParams containerParameters) error {
+	logger := stateFulSetLogger(namespace, stsMeta.Name)
+	storedStateful, err := GetStateFulSet(namespace, stsMeta.Name)
+	statefulSetDef := generateStateFulSetsDef(stsMeta, labels, params, ownerDef, containerParams)
+	if err != nil {
+		if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(statefulSetDef); err != nil {
+			logger.Error(err, "Unable to patch redis statefulset with comparison object")
+			return err
+		}
+		if errors.IsNotFound(err) {
+			return createStateFulSet(namespace, statefulSetDef)
+		}
+		return err
+	}
+	return patchStateFulSet(storedStateful, statefulSetDef, namespace)
+}
+
+// patchStateFulSet will patch Redis Kubernetes StateFulSet
+func patchStateFulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.StatefulSet, namespace string) error {
+	logger := stateFulSetLogger(namespace, storedStateful.Name)
+	patchResult, err := patch.DefaultPatchMaker.Calculate(storedStateful, newStateful)
+	if err != nil {
+		logger.Error(err, "Unable to patch redis statefulset with comparison object")
+		return err
+	}
+	if !patchResult.IsEmpty() {
+		newStateful.ResourceVersion = storedStateful.ResourceVersion
+		newStateful.CreationTimestamp = storedStateful.CreationTimestamp
+		newStateful.ManagedFields = storedStateful.ManagedFields
+		for key, value := range storedStateful.Annotations {
+			if _, present := newStateful.Annotations[key]; !present {
+				newStateful.Annotations[key] = value
+			}
+		}
+		if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(newStateful); err != nil {
+			logger.Error(err, "Unable to patch redis statefulset with comparison object")
+			return err
+		}
+		return updateStateFulSet(namespace, newStateful)
+	}
+	return nil
 }
 
-// GenerateStateFulSetsDef generates the statefulsets definition
-func GenerateStateFulSetsDef(cr *redisv1beta1.Redis, labels map[string]string, role string, replicas *int32) *appsv1.StatefulSet {
+// generateStateFulSetsDef generates the statefulsets definition of Redis
+func generateStateFulSetsDef(stsMeta metav1.ObjectMeta, labels map[string]string, params statefulSetParameters, ownerDef metav1.OwnerReference, containerParams containerParameters) *appsv1.StatefulSet {
 	statefulset := &appsv1.StatefulSet{
-		TypeMeta:   GenerateMetaInformation("StatefulSet", "apps/v1"),
-		ObjectMeta: GenerateObjectMetaInformation(cr.ObjectMeta.Name+"-"+role, cr.Namespace, labels, GenerateStatefulSetsAnots()),
+		TypeMeta:   generateMetaInformation("StatefulSet", "apps/v1"),
+		ObjectMeta: stsMeta,
 		Spec: appsv1.StatefulSetSpec{
 			Selector:    LabelSelectors(labels),
-			ServiceName: cr.ObjectMeta.Name + "-" + role,
-			Replicas:    replicas,
+			ServiceName: stsMeta.Name,
+			Replicas:    params.Replicas,
 			Template: corev1.PodTemplateSpec{
 				ObjectMeta: metav1.ObjectMeta{
 					Labels: labels,
 				},
 				Spec: corev1.PodSpec{
-					Containers:        FinalContainerDef(cr, role),
-					NodeSelector:      cr.Spec.NodeSelector,
-					SecurityContext:   cr.Spec.SecurityContext,
-					PriorityClassName: cr.Spec.PriorityClassName,
-					Affinity:          cr.Spec.Affinity,
+					Containers:        generateContainerDef(stsMeta.Name, containerParams, params.EnableMetrics),
+					NodeSelector:      params.NodeSelector,
+					SecurityContext:   params.SecurityContext,
+					PriorityClassName: params.PriorityClassName,
+					Affinity:          params.Affinity,
 				},
 			},
 		},
 	}
-	if cr.Spec.Tolerations != nil {
-		statefulset.Spec.Template.Spec.Tolerations = *cr.Spec.Tolerations
+	if params.Tolerations != nil {
+		statefulset.Spec.Template.Spec.Tolerations = *params.Tolerations
+	}
+	if *containerParams.PersistenceEnabled {
+		statefulset.Spec.VolumeClaimTemplates = append(statefulset.Spec.VolumeClaimTemplates, createPVCTemplate(stsMeta.Name, params.PersistentVolumeClaim))
 	}
-	AddOwnerRefToObject(statefulset, AsOwner(cr))
+	AddOwnerRefToObject(statefulset, ownerDef)
 	return statefulset
 }
 
-// GenerateContainerDef generates container definition
-func GenerateContainerDef(cr *redisv1beta1.Redis, role string) corev1.Container {
-	containerDefinition := corev1.Container{
-		Name:            cr.ObjectMeta.Name + "-" + role,
-		Image:           cr.Spec.GlobalConfig.Image,
-		ImagePullPolicy: cr.Spec.GlobalConfig.ImagePullPolicy,
-		Env: []corev1.EnvVar{
-			{
-				Name:  "SERVER_MODE",
-				Value: role,
-			},
-		},
-		Resources: corev1.ResourceRequirements{
-			Limits: corev1.ResourceList{}, Requests: corev1.ResourceList{},
-		},
-		VolumeMounts: []corev1.VolumeMount{},
-		ReadinessProbe: &corev1.Probe{
-			InitialDelaySeconds: graceTime,
-			PeriodSeconds:       15,
-			FailureThreshold:    5,
-			TimeoutSeconds:      5,
-			Handler: corev1.Handler{
-				Exec: &corev1.ExecAction{
-					Command: []string{
-						"bash",
-						"/usr/bin/healthcheck.sh",
-					},
-				},
-			},
-		},
-		LivenessProbe: &corev1.Probe{
-			InitialDelaySeconds: graceTime,
-			TimeoutSeconds:      5,
-			Handler: corev1.Handler{
-				Exec: &corev1.ExecAction{
-					Command: []string{
-						"bash",
-						"/usr/bin/healthcheck.sh",
-					},
-				},
-			},
-		},
-	}
-	if cr.Spec.GlobalConfig.Resources != nil {
-		containerDefinition.Resources.Limits[corev1.ResourceCPU] = resource.MustParse(cr.Spec.GlobalConfig.Resources.ResourceLimits.CPU)
-		containerDefinition.Resources.Requests[corev1.ResourceCPU] = resource.MustParse(cr.Spec.GlobalConfig.Resources.ResourceRequests.CPU)
-		containerDefinition.Resources.Limits[corev1.ResourceMemory] = resource.MustParse(cr.Spec.GlobalConfig.Resources.ResourceLimits.Memory)
-		containerDefinition.Resources.Requests[corev1.ResourceMemory] = resource.MustParse(cr.Spec.GlobalConfig.Resources.ResourceRequests.Memory)
-	}
-	if cr.Spec.Storage != nil {
-		VolumeMounts := corev1.VolumeMount{
-			Name:      cr.ObjectMeta.Name + "-" + role,
-			MountPath: "/data",
-		}
-		containerDefinition.VolumeMounts = append(containerDefinition.VolumeMounts, VolumeMounts)
-	}
-	if cr.Spec.GlobalConfig.Password != nil && cr.Spec.GlobalConfig.ExistingPasswordSecret == nil {
-		containerDefinition.Env = append(containerDefinition.Env, corev1.EnvVar{
-			Name: "REDIS_PASSWORD",
-			ValueFrom: &corev1.EnvVarSource{
-				SecretKeyRef: &corev1.SecretKeySelector{
-					LocalObjectReference: corev1.LocalObjectReference{
-						Name: cr.ObjectMeta.Name,
-					},
-					Key: "password",
-				},
-			},
-		})
-	}
-
-	if cr.Spec.GlobalConfig.ExistingPasswordSecret != nil {
-		containerDefinition.Env = append(containerDefinition.Env, corev1.EnvVar{
-			Name: "REDIS_PASSWORD",
-			ValueFrom: &corev1.EnvVarSource{
-				SecretKeyRef: &corev1.SecretKeySelector{
-					LocalObjectReference: corev1.LocalObjectReference{
-						Name: *cr.Spec.GlobalConfig.ExistingPasswordSecret.Name,
-					},
-					Key: *cr.Spec.GlobalConfig.ExistingPasswordSecret.Key,
-				},
-			},
-		})
-	}
-
-	if cr.Spec.Mode != "cluster" {
-		containerDefinition.Env = append(containerDefinition.Env, corev1.EnvVar{
-			Name:  "SETUP_MODE",
-			Value: "standalone",
-		})
+// createPVCTemplate will create the persistent volume claim template
+func createPVCTemplate(name string, storageSpec corev1.PersistentVolumeClaim) corev1.PersistentVolumeClaim {
+	pvcTemplate := storageSpec
+	pvcTemplate.CreationTimestamp = metav1.Time{}
+	pvcTemplate.Name = name
+	if storageSpec.Spec.AccessModes == nil {
+		pvcTemplate.Spec.AccessModes = []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}
 	} else {
-		containerDefinition.Env = append(containerDefinition.Env, corev1.EnvVar{
-			Name:  "SETUP_MODE",
-			Value: "cluster",
-		})
+		pvcTemplate.Spec.AccessModes = storageSpec.Spec.AccessModes
 	}
+	pvcTemplate.Spec.Resources = storageSpec.Spec.Resources
+	pvcTemplate.Spec.Selector = storageSpec.Spec.Selector
+	pvcTemplate.Spec.Selector = storageSpec.Spec.Selector
+	return pvcTemplate
+}
 
-	if cr.Spec.Storage != nil {
-		containerDefinition.Env = append(containerDefinition.Env, corev1.EnvVar{
-			Name:  "PERSISTENCE_ENABLED",
-			Value: "true",
-		})
+// generateContainerDef generates container fefinition for Redis
+func generateContainerDef(name string, containerParams containerParameters, enableMetrics bool) []corev1.Container {
+	containerDefinition := []corev1.Container{
+		{
+			Name:            name,
+			Image:           containerParams.Image,
+			ImagePullPolicy: containerParams.ImagePullPolicy,
+			Env:             getEnvironmentVariables(containerParams.Role, containerParams.EnabledPassword, containerParams.SecretName, containerParams.SecretKey, containerParams.PersistenceEnabled),
+			Resources:       *containerParams.Resources,
+			ReadinessProbe:  getProbeInfo(),
+			LivenessProbe:   getProbeInfo(),
+			VolumeMounts:    getVolumeMount(name, containerParams.PersistenceEnabled),
+		},
 	}
+	containerDefinition = append(containerDefinition, enableRedisMonitoring(containerParams))
 	return containerDefinition
 }
 
-// FinalContainerDef will generate the final statefulset definition
-func FinalContainerDef(cr *redisv1beta1.Redis, role string) []corev1.Container {
-	var containerDefinition []corev1.Container
-	var exporterDefinition corev1.Container
-	var exporterEnvDetails []corev1.EnvVar
-
-	containerDefinition = append(containerDefinition, GenerateContainerDef(cr, role))
-
-	if !cr.Spec.RedisExporter.Enabled {
-		return containerDefinition
+// enableRedisMonitoring will add Redis Exporter as sidecar container
+func enableRedisMonitoring(params containerParameters) corev1.Container {
+	exporterDefinition := corev1.Container{
+		Name:            redisExporterContainer,
+		Image:           params.RedisExporterImage,
+		ImagePullPolicy: params.RedisExporterImagePullPolicy,
+		Env:             getEnvironmentVariables(params.Role, params.EnabledPassword, params.SecretName, params.SecretKey, params.PersistenceEnabled),
+		Resources:       *params.RedisExporterResources,
 	}
+	return exporterDefinition
+}
 
-	if cr.Spec.GlobalConfig.Password != nil {
-		exporterEnvDetails = []corev1.EnvVar{
+// getVolumeMount gives information about persistence mount
+func getVolumeMount(name string, persistenceEnabled *bool) []corev1.VolumeMount {
+	var VolumeMounts []corev1.VolumeMount
+	if *persistenceEnabled && persistenceEnabled != nil {
+		VolumeMounts = []corev1.VolumeMount{
 			{
-				Name: "REDIS_PASSWORD",
-				ValueFrom: &corev1.EnvVarSource{
-					SecretKeyRef: &corev1.SecretKeySelector{
-						LocalObjectReference: corev1.LocalObjectReference{
-							Name: cr.ObjectMeta.Name,
-						},
-						Key: "password",
-					},
-				},
-			}, {
-				Name:  "REDIS_ADDR",
-				Value: "redis://localhost:6379",
+				Name:      name,
+				MountPath: "/data",
 			},
 		}
-	} else {
-		exporterEnvDetails = []corev1.EnvVar{
-			{
-				Name:  "REDIS_ADDR",
-				Value: "redis://localhost:6379",
-			},
-		}
-	}
-	exporterDefinition = corev1.Container{
-		Name:            constRedisExpoterName,
-		Image:           cr.Spec.RedisExporter.Image,
-		ImagePullPolicy: cr.Spec.RedisExporter.ImagePullPolicy,
-		Env:             exporterEnvDetails,
-		Resources: corev1.ResourceRequirements{
-			Limits: corev1.ResourceList{}, Requests: corev1.ResourceList{},
-		},
-	}
-
-	if cr.Spec.RedisExporter.Resources != nil {
-		exporterDefinition.Resources.Limits[corev1.ResourceCPU] = resource.MustParse(cr.Spec.RedisExporter.Resources.ResourceLimits.CPU)
-		exporterDefinition.Resources.Requests[corev1.ResourceCPU] = resource.MustParse(cr.Spec.RedisExporter.Resources.ResourceRequests.CPU)
-		exporterDefinition.Resources.Limits[corev1.ResourceMemory] = resource.MustParse(cr.Spec.RedisExporter.Resources.ResourceLimits.Memory)
-		exporterDefinition.Resources.Requests[corev1.ResourceMemory] = resource.MustParse(cr.Spec.RedisExporter.Resources.ResourceRequests.Memory)
+		return VolumeMounts
 	}
-
-	containerDefinition = append(containerDefinition, exporterDefinition)
-	return containerDefinition
+	return VolumeMounts
 }
 
-// CreateRedisMaster will create a Redis Master
-func CreateRedisMaster(cr *redisv1beta1.Redis) {
-
-	labels := map[string]string{
-		"app":  cr.ObjectMeta.Name + "-master",
-		"role": "master",
-	}
-	statefulDefinition := GenerateStateFulSetsDef(cr, labels, "master", cr.Spec.Size)
-	statefulObject, err := GenerateK8sClient().AppsV1().StatefulSets(cr.Namespace).Get(context.TODO(), cr.ObjectMeta.Name+"-master", metav1.GetOptions{})
-
-	if cr.Spec.Storage != nil {
-		statefulDefinition.Spec.VolumeClaimTemplates = append(statefulDefinition.Spec.VolumeClaimTemplates, CreatePVCTemplate(cr, "master"))
-	}
-
-	stateful := StatefulInterface{
-		Existing: statefulObject,
-		Desired:  statefulDefinition,
-		Type:     "master",
+// getProbeInfo generates probe information for Redis
+func getProbeInfo() *corev1.Probe {
+	return &corev1.Probe{
+		InitialDelaySeconds: graceTime,
+		PeriodSeconds:       15,
+		FailureThreshold:    5,
+		TimeoutSeconds:      5,
+		Handler: corev1.Handler{
+			Exec: &corev1.ExecAction{
+				Command: []string{
+					"bash",
+					"/usr/bin/healthcheck.sh",
+				},
+			},
+		},
 	}
-	CompareAndCreateStateful(cr, stateful, err, "master")
 }
 
-// CreateRedisSlave will create a Redis Slave
-func CreateRedisSlave(cr *redisv1beta1.Redis) {
-	labels := map[string]string{
-		"app":  cr.ObjectMeta.Name + "-slave",
-		"role": "slave",
+// getEnvironmentVariables returns all the required Environment Variables
+func getEnvironmentVariables(role string, enabledPassword *bool, secretName *string, secretKey *string, persistenceEnabled *bool) []corev1.EnvVar {
+	envVars := []corev1.EnvVar{
+		{Name: "SERVER_MODE", Value: role},
+		{Name: "SETUP_MODE", Value: role},
+		{Name: "REDIS_ADDR", Value: "redis://localhost:6379"},
 	}
-	statefulDefinition := GenerateStateFulSetsDef(cr, labels, "slave", cr.Spec.Size)
-	statefulObject, err := GenerateK8sClient().AppsV1().StatefulSets(cr.Namespace).Get(context.TODO(), cr.ObjectMeta.Name+"-slave", metav1.GetOptions{})
-
-	if cr.Spec.Storage != nil {
-		statefulDefinition.Spec.VolumeClaimTemplates = append(statefulDefinition.Spec.VolumeClaimTemplates, CreatePVCTemplate(cr, "slave"))
+	if *enabledPassword && enabledPassword != nil {
+		envVars = append(envVars, corev1.EnvVar{
+			Name: "REDIS_PASSWORD",
+			ValueFrom: &corev1.EnvVarSource{
+				SecretKeyRef: &corev1.SecretKeySelector{
+					LocalObjectReference: corev1.LocalObjectReference{
+						Name: *secretName,
+					},
+					Key: *secretKey,
+				},
+			},
+		})
 	}
-
-	stateful := StatefulInterface{
-		Existing: statefulObject,
-		Desired:  statefulDefinition,
-		Type:     "slave",
+	if *persistenceEnabled && persistenceEnabled != nil {
+		envVars = append(envVars, corev1.EnvVar{Name: "PERSISTENCE_ENABLED", Value: "true"})
 	}
-	CompareAndCreateStateful(cr, stateful, err, "slave")
+	return envVars
 }
 
-// CreateRedisStandalone will create a Redis Standalone server
-func CreateRedisStandalone(cr *redisv1beta1.Redis) {
-	var standaloneReplica int32 = 1
-
-	labels := map[string]string{
-		"app":  cr.ObjectMeta.Name + "-" + "standalone",
-		"role": "standalone",
-	}
-	statefulDefinition := GenerateStateFulSetsDef(cr, labels, "standalone", &standaloneReplica)
-	statefulObject, err := GenerateK8sClient().AppsV1().StatefulSets(cr.Namespace).Get(context.TODO(), cr.ObjectMeta.Name+"-standalone", metav1.GetOptions{})
-	if cr.Spec.Storage != nil {
-		statefulDefinition.Spec.VolumeClaimTemplates = append(statefulDefinition.Spec.VolumeClaimTemplates, CreatePVCTemplate(cr, "standalone"))
-	}
-
-	stateful := StatefulInterface{
-		Existing: statefulObject,
-		Desired:  statefulDefinition,
-		Type:     "standalone",
+// createStateFulSet is a method to create statefulset in Kubernetes
+func createStateFulSet(namespace string, stateful *appsv1.StatefulSet) error {
+	logger := stateFulSetLogger(namespace, stateful.Name)
+	_, err := generateK8sClient().AppsV1().StatefulSets(namespace).Create(context.TODO(), stateful, metav1.CreateOptions{})
+	if err != nil {
+		logger.Error(err, "Redis stateful creation is failed")
+		return err
 	}
-	CompareAndCreateStateful(cr, stateful, err, "standalone")
+	logger.Info("Redis stateful creation is successful")
+	return nil
 }
 
-// CompareAndCreateStateful will compare and create a statefulset pod
-func CompareAndCreateStateful(cr *redisv1beta1.Redis, clusterInfo StatefulInterface, err error, role string) {
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name)
-
+// updateStateFulSet is a method to update statefulset in Kubernetes
+func updateStateFulSet(namespace string, stateful *appsv1.StatefulSet) error {
+	logger := stateFulSetLogger(namespace, stateful.Name)
+	_, err := generateK8sClient().AppsV1().StatefulSets(namespace).Update(context.TODO(), stateful, metav1.UpdateOptions{})
 	if err != nil {
-		reqLogger.Info("Creating redis setup", "Redis.Name", cr.ObjectMeta.Name+"-"+clusterInfo.Type, "Setup.Type", clusterInfo.Type)
-		_, err := GenerateK8sClient().AppsV1().StatefulSets(cr.Namespace).Create(context.TODO(), clusterInfo.Desired, metav1.CreateOptions{})
-		if err != nil {
-			reqLogger.Error(err, "Failed in creating statefulset for redis")
-		}
-	}
-
-	state := compareState(clusterInfo)
-
-	if clusterInfo.Existing != nil {
-		if !state {
-			reqLogger.Info("Reconciling redis setup because spec has changed", "Redis.Name", cr.ObjectMeta.Name+"-"+clusterInfo.Type, "Setup.Type", clusterInfo.Type)
-			_, err := GenerateK8sClient().AppsV1().StatefulSets(cr.Namespace).Update(context.TODO(), clusterInfo.Desired, metav1.UpdateOptions{})
-			if err != nil {
-				reqLogger.Error(err, "Failed in updating statefulset for redis")
-			}
-		}
+		logger.Error(err, "Redis stateful updation is failed")
+		return err
 	}
+	logger.Info("Redis stateful updation is successful")
+	return nil
 }
 
-// compareState method will compare the statefulsets
-func compareState(clusterInfo StatefulInterface) bool {
-	if apiequality.Semantic.DeepDerivative(clusterInfo.Existing.Spec, clusterInfo.Desired.Spec) {
-		return true
-	} else {
-		return false
+// GetStateFulSet is a method to get statefulset in Kubernetes
+func GetStateFulSet(namespace string, stateful string) (*appsv1.StatefulSet, error) {
+	logger := stateFulSetLogger(namespace, stateful)
+	statefulInfo, err := generateK8sClient().AppsV1().StatefulSets(namespace).Get(context.TODO(), stateful, metav1.GetOptions{})
+	if err != nil {
+		logger.Info("Redis statefulset get action is failed")
+		return nil, err
 	}
+	logger.Info("Redis statefulset get action is successful")
+	return statefulInfo, err
 }
 
-// CreatePVCTemplate will create the persistent volume claim template
-func CreatePVCTemplate(cr *redisv1beta1.Redis, role string) corev1.PersistentVolumeClaim {
-	reqLogger := log.WithValues("Request.Namespace", cr.Namespace, "Request.Name", cr.ObjectMeta.Name)
-	storageSpec := cr.Spec.Storage
-	var pvcTemplate corev1.PersistentVolumeClaim
-
-	if storageSpec == nil {
-		reqLogger.Info("No storage is defined for redis", "Redis.Name", cr.ObjectMeta.Name)
-	} else {
-		pvcTemplate = storageSpec.VolumeClaimTemplate
-		pvcTemplate.CreationTimestamp = metav1.Time{}
-		pvcTemplate.Name = cr.ObjectMeta.Name + "-" + role
-		if storageSpec.VolumeClaimTemplate.Spec.AccessModes == nil {
-			pvcTemplate.Spec.AccessModes = []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}
-		} else {
-			pvcTemplate.Spec.AccessModes = storageSpec.VolumeClaimTemplate.Spec.AccessModes
-		}
-		pvcTemplate.Spec.Resources = storageSpec.VolumeClaimTemplate.Spec.Resources
-		pvcTemplate.Spec.Selector = storageSpec.VolumeClaimTemplate.Spec.Selector
-		pvcTemplate.Spec.Selector = storageSpec.VolumeClaimTemplate.Spec.Selector
-	}
-	return pvcTemplate
+// stateFulSetLogger will generate logging interface for Statfulsets
+func stateFulSetLogger(namespace string, name string) logr.Logger {
+	reqLogger := log.WithValues("Request.StateFulSet.Namespace", namespace, "Request.StateFulSet.Name", name)
+	return reqLogger
 }
diff --git a/main.go b/main.go
index 3dbe7c796af4ffe9ddfe04c7f706d54efafffce7..3ce025143f8645a17ddd5afa908b35a3d6ccad50 100644
--- a/main.go
+++ b/main.go
@@ -86,6 +86,14 @@ func main() {
 		setupLog.Error(err, "unable to create controller", "controller", "Redis")
 		os.Exit(1)
 	}
+	if err = (&controllers.RedisClusterReconciler{
+		Client: mgr.GetClient(),
+		Log:    ctrl.Log.WithName("controllers").WithName("RedisCluster"),
+		Scheme: mgr.GetScheme(),
+	}).SetupWithManager(mgr); err != nil {
+		setupLog.Error(err, "unable to create controller", "controller", "RedisCluster")
+		os.Exit(1)
+	}
 	// +kubebuilder:scaffold:builder
 
 	if err := mgr.AddHealthzCheck("health", healthz.Ping); err != nil {
diff --git a/static/redis-operator-architecture.png b/static/redis-operator-architecture.png
new file mode 100644
index 0000000000000000000000000000000000000000..670d2f5f1125564c51f895cbd9c418a116790de5
Binary files /dev/null and b/static/redis-operator-architecture.png differ