From eda074adc9daaad46b287923a0ac927429ba76c4 Mon Sep 17 00:00:00 2001 From: prabhaker24 Date: Mon, 12 Oct 2020 18:27:48 +0530 Subject: [PATCH 1/9] added support for jvmOption customization Signed-off-by: prabhaker24 --- .../pravegacluster_controller.go | 118 +++++++++++++++++- 1 file changed, 112 insertions(+), 6 deletions(-) diff --git a/pkg/controller/pravegacluster/pravegacluster_controller.go b/pkg/controller/pravegacluster/pravegacluster_controller.go index 001e9bee8..5322a90a0 100644 --- a/pkg/controller/pravegacluster/pravegacluster_controller.go +++ b/pkg/controller/pravegacluster/pravegacluster_controller.go @@ -14,6 +14,7 @@ import ( "context" "fmt" "strconv" + "strings" "time" pravegav1beta1 "github.com/pravega/pravega-operator/pkg/apis/pravega/v1beta1" @@ -316,11 +317,32 @@ func (r *ReconcilePravegaCluster) deployController(p *pravegav1beta1.PravegaClus return err } + var eq bool = true + currentConfigMap := &corev1.ConfigMap{} configMap := pravega.MakeControllerConfigMap(p) controllerutil.SetControllerReference(p, configMap, r.scheme) - err = r.client.Create(context.TODO(), configMap) - if err != nil && !errors.IsAlreadyExists(err) { - return err + err = r.client.Get(context.TODO(), types.NamespacedName{Name: configMap.Name, Namespace: p.Namespace}, currentConfigMap) + if err != nil { + if errors.IsNotFound(err) { + err = r.client.Create(context.TODO(), configMap) + if err != nil && !errors.IsAlreadyExists(err) { + return err + } + } + } else { + currentConfigMap := &corev1.ConfigMap{} + err = r.client.Get(context.TODO(), types.NamespacedName{Namespace: configMap.Namespace, Name: configMap.Name}, currentConfigMap) + currentjavaOptsList := currentConfigMap.Data["JAVA_OPTS"] + for _, jvmopts := range p.Spec.Pravega.ControllerJvmOptions { + eq = strings.Contains(currentjavaOptsList, jvmopts) + if !eq { + err := r.client.Update(context.TODO(), configMap) + if err != nil { + return err + } + break + } + } } deployment := pravega.MakeControllerDeployment(p) @@ -329,6 +351,29 @@ func (r *ReconcilePravegaCluster) deployController(p *pravegav1beta1.PravegaClus if err != nil && !errors.IsAlreadyExists(err) { return err } + if !eq { + currentDeployment := &appsv1.Deployment{} + err := r.client.Get(context.TODO(), types.NamespacedName{Name: deployment.Name, Namespace: deployment.Namespace}, currentDeployment) + selector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{ + MatchLabels: deployment.Spec.Template.Labels, + }) + if err != nil { + return fmt.Errorf("failed to convert label selector: %v", err) + } + podList := &corev1.PodList{} + podlistOps := &client.ListOptions{ + Namespace: deployment.Namespace, + LabelSelector: selector, + } + err = r.client.List(context.TODO(), podList, podlistOps) + if err != nil { + return err + } + err = r.restartPod(podList) + if err != nil { + return err + } + } service := pravega.MakeControllerService(p) controllerutil.SetControllerReference(p, service, r.scheme) @@ -367,11 +412,32 @@ func (r *ReconcilePravegaCluster) deploySegmentStore(p *pravegav1beta1.PravegaCl return err } + var eq bool = true + currentConfigMap := &corev1.ConfigMap{} configMap := pravega.MakeSegmentstoreConfigMap(p) controllerutil.SetControllerReference(p, configMap, r.scheme) - err = r.client.Create(context.TODO(), configMap) - if err != nil && !errors.IsAlreadyExists(err) { - return err + err = r.client.Get(context.TODO(), types.NamespacedName{Name: configMap.Name, Namespace: p.Namespace}, currentConfigMap) + if err != nil { + if errors.IsNotFound(err) { + err = r.client.Create(context.TODO(), configMap) + if err != nil && !errors.IsAlreadyExists(err) { + return err + } + } + } else { + currentConfigMap := &corev1.ConfigMap{} + err = r.client.Get(context.TODO(), types.NamespacedName{Namespace: configMap.Namespace, Name: configMap.Name}, currentConfigMap) + currentjavaOptsList := currentConfigMap.Data["JAVA_OPTS"] + for _, jvmopts := range p.Spec.Pravega.SegmentStoreJVMOptions { + eq = strings.Contains(currentjavaOptsList, jvmopts) + if !eq { + err := r.client.Update(context.TODO(), configMap) + if err != nil { + return err + } + break + } + } } statefulSet := pravega.MakeSegmentStoreStatefulSet(p) @@ -404,6 +470,29 @@ func (r *ReconcilePravegaCluster) deploySegmentStore(p *pravegav1beta1.PravegaCl } } } + if !eq { + currentSts := &appsv1.StatefulSet{} + err := r.client.Get(context.TODO(), types.NamespacedName{Name: statefulSet.Name, Namespace: statefulSet.Namespace}, currentSts) + selector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{ + MatchLabels: statefulSet.Spec.Template.Labels, + }) + if err != nil { + return fmt.Errorf("failed to convert label selector: %v", err) + } + podList := &corev1.PodList{} + podlistOps := &client.ListOptions{ + Namespace: statefulSet.Namespace, + LabelSelector: selector, + } + err = r.client.List(context.TODO(), podList, podlistOps) + if err != nil { + return err + } + err = r.restartPod(podList) + if err != nil { + return err + } + } return nil } @@ -416,6 +505,23 @@ func hasOldVersionOwnerReference(ownerreference []metav1.OwnerReference) bool { return false } +func (r *ReconcilePravegaCluster) restartPod(podList *corev1.PodList) error { + for _, podItem := range podList.Items { + err := r.client.Delete(context.TODO(), &podItem) + if err != nil { + return err + } else { + time.Sleep(10 * time.Second) + pod := &corev1.Pod{} + err = r.client.Get(context.TODO(), types.NamespacedName{Name: podItem.ObjectMeta.Name, Namespace: podItem.ObjectMeta.Namespace}, pod) + for !util.IsPodReady(pod) { + err = r.client.Get(context.TODO(), types.NamespacedName{Name: podItem.ObjectMeta.Name, Namespace: podItem.ObjectMeta.Namespace}, pod) + } + } + } + return nil +} + func (r *ReconcilePravegaCluster) syncClusterSize(p *pravegav1beta1.PravegaCluster) (err error) { /*We skip calling syncSegmentStoreSize() during upgrade/rollback from version 07*/ if !r.IsClusterUpgradingTo07(p) && !r.IsClusterRollbackingFrom07(p) { From f7a1df1067f1a0210b6739cb7c5b66a571e42793 Mon Sep 17 00:00:00 2001 From: prabhaker24 Date: Mon, 12 Oct 2020 21:26:56 +0530 Subject: [PATCH 2/9] removed sleep Signed-off-by: prabhaker24 --- pkg/controller/pravegacluster/pravegacluster_controller.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/controller/pravegacluster/pravegacluster_controller.go b/pkg/controller/pravegacluster/pravegacluster_controller.go index 5322a90a0..226be15a4 100644 --- a/pkg/controller/pravegacluster/pravegacluster_controller.go +++ b/pkg/controller/pravegacluster/pravegacluster_controller.go @@ -511,9 +511,12 @@ func (r *ReconcilePravegaCluster) restartPod(podList *corev1.PodList) error { if err != nil { return err } else { - time.Sleep(10 * time.Second) pod := &corev1.Pod{} err = r.client.Get(context.TODO(), types.NamespacedName{Name: podItem.ObjectMeta.Name, Namespace: podItem.ObjectMeta.Namespace}, pod) + for util.IsPodReady(pod) { + err = r.client.Get(context.TODO(), types.NamespacedName{Name: podItem.ObjectMeta.Name, Namespace: podItem.ObjectMeta.Namespace}, pod) + } + err = r.client.Get(context.TODO(), types.NamespacedName{Name: podItem.ObjectMeta.Name, Namespace: podItem.ObjectMeta.Namespace}, pod) for !util.IsPodReady(pod) { err = r.client.Get(context.TODO(), types.NamespacedName{Name: podItem.ObjectMeta.Name, Namespace: podItem.ObjectMeta.Namespace}, pod) } From 3d1e53ca03cca37915bcbe857540db7b82e16674 Mon Sep 17 00:00:00 2001 From: prabhaker24 Date: Mon, 12 Oct 2020 23:18:03 +0530 Subject: [PATCH 3/9] added timeout and made restart pod function modular as well Signed-off-by: prabhaker24 --- .../pravegacluster_controller.go | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/pkg/controller/pravegacluster/pravegacluster_controller.go b/pkg/controller/pravegacluster/pravegacluster_controller.go index 226be15a4..f9df79315 100644 --- a/pkg/controller/pravegacluster/pravegacluster_controller.go +++ b/pkg/controller/pravegacluster/pravegacluster_controller.go @@ -369,7 +369,7 @@ func (r *ReconcilePravegaCluster) deployController(p *pravegav1beta1.PravegaClus if err != nil { return err } - err = r.restartPod(podList) + err = r.restartDeploymentPod(podList) if err != nil { return err } @@ -488,7 +488,7 @@ func (r *ReconcilePravegaCluster) deploySegmentStore(p *pravegav1beta1.PravegaCl if err != nil { return err } - err = r.restartPod(podList) + err = r.restartStsPod(podList) if err != nil { return err } @@ -505,19 +505,46 @@ func hasOldVersionOwnerReference(ownerreference []metav1.OwnerReference) bool { return false } -func (r *ReconcilePravegaCluster) restartPod(podList *corev1.PodList) error { +func (r *ReconcilePravegaCluster) restartStsPod(podList *corev1.PodList) error { for _, podItem := range podList.Items { err := r.client.Delete(context.TODO(), &podItem) if err != nil { return err } else { + start := time.Now() pod := &corev1.Pod{} err = r.client.Get(context.TODO(), types.NamespacedName{Name: podItem.ObjectMeta.Name, Namespace: podItem.ObjectMeta.Namespace}, pod) for util.IsPodReady(pod) { + if time.Since(start) > 10*time.Minute { + return fmt.Errorf("failed to delete Segmentstore pod (%s) for 10 mins ", podItem.ObjectMeta.Name) + } err = r.client.Get(context.TODO(), types.NamespacedName{Name: podItem.ObjectMeta.Name, Namespace: podItem.ObjectMeta.Namespace}, pod) } + start = time.Now() err = r.client.Get(context.TODO(), types.NamespacedName{Name: podItem.ObjectMeta.Name, Namespace: podItem.ObjectMeta.Namespace}, pod) for !util.IsPodReady(pod) { + if time.Since(start) > 10*time.Minute { + return fmt.Errorf("failed to get Segmentstore pod (%s) as ready for 10 mins ", podItem.ObjectMeta.Name) + } + err = r.client.Get(context.TODO(), types.NamespacedName{Name: podItem.ObjectMeta.Name, Namespace: podItem.ObjectMeta.Namespace}, pod) + } + } + } + return nil +} +func (r *ReconcilePravegaCluster) restartDeploymentPod(podList *corev1.PodList) error { + for _, podItem := range podList.Items { + err := r.client.Delete(context.TODO(), &podItem) + if err != nil { + return err + } else { + start := time.Now() + pod := &corev1.Pod{} + err = r.client.Get(context.TODO(), types.NamespacedName{Name: podItem.ObjectMeta.Name, Namespace: podItem.ObjectMeta.Namespace}, pod) + for util.IsPodReady(pod) { + if time.Since(start) > 10*time.Minute { + return fmt.Errorf("failed to delete controller pod (%s) for 10 mins ", podItem.ObjectMeta.Name) + } err = r.client.Get(context.TODO(), types.NamespacedName{Name: podItem.ObjectMeta.Name, Namespace: podItem.ObjectMeta.Namespace}, pod) } } From 7ac694851fffa9e8baaf9c52c7b534032656859c Mon Sep 17 00:00:00 2001 From: prabhaker24 Date: Tue, 13 Oct 2020 00:36:12 +0530 Subject: [PATCH 4/9] changed restart logic for controller pods Signed-off-by: prabhaker24 --- .../pravegacluster_controller.go | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/pkg/controller/pravegacluster/pravegacluster_controller.go b/pkg/controller/pravegacluster/pravegacluster_controller.go index f9df79315..959214b7b 100644 --- a/pkg/controller/pravegacluster/pravegacluster_controller.go +++ b/pkg/controller/pravegacluster/pravegacluster_controller.go @@ -369,7 +369,7 @@ func (r *ReconcilePravegaCluster) deployController(p *pravegav1beta1.PravegaClus if err != nil { return err } - err = r.restartDeploymentPod(podList) + err = r.restartDeploymentPod(podList, p) if err != nil { return err } @@ -532,7 +532,7 @@ func (r *ReconcilePravegaCluster) restartStsPod(podList *corev1.PodList) error { } return nil } -func (r *ReconcilePravegaCluster) restartDeploymentPod(podList *corev1.PodList) error { +func (r *ReconcilePravegaCluster) restartDeploymentPod(podList *corev1.PodList, p *pravegav1beta1.PravegaCluster) error { for _, podItem := range podList.Items { err := r.client.Delete(context.TODO(), &podItem) if err != nil { @@ -547,6 +547,22 @@ func (r *ReconcilePravegaCluster) restartDeploymentPod(podList *corev1.PodList) } err = r.client.Get(context.TODO(), types.NamespacedName{Name: podItem.ObjectMeta.Name, Namespace: podItem.ObjectMeta.Namespace}, pod) } + deploy := &appsv1.Deployment{} + name := p.DeploymentNameForController() + err = r.client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: p.Namespace}, deploy) + if err != nil { + return fmt.Errorf("failed to get deployment (%s): %v", deploy.Name, err) + } + start = time.Now() + for deploy.Status.ReadyReplicas != deploy.Status.Replicas { + if time.Since(start) > 10*time.Minute { + return fmt.Errorf("failed to make controller pod ready for 10 mins ") + } + err = r.client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: p.Namespace}, deploy) + if err != nil { + return fmt.Errorf("failed to get deployment (%s): %v", deploy.Name, err) + } + } } } return nil From 92df7858d4ba690582beafdcfa0a5e75edd30dbc Mon Sep 17 00:00:00 2001 From: prabhaker24 Date: Fri, 16 Oct 2020 14:42:36 +0530 Subject: [PATCH 5/9] added reconcileconfigmap and validation Signed-off-by: prabhaker24 --- .../pravega/v1beta1/pravegacluster_types.go | 68 ++++- pkg/controller/pravega/pravega_controller.go | 3 + .../pravega/pravega_segmentstore.go | 4 + .../pravegacluster_controller.go | 237 ++++++++++-------- pkg/util/pravegacluster.go | 10 + 5 files changed, 216 insertions(+), 106 deletions(-) diff --git a/pkg/apis/pravega/v1beta1/pravegacluster_types.go b/pkg/apis/pravega/v1beta1/pravegacluster_types.go index 02204a5af..e33d2cf00 100644 --- a/pkg/apis/pravega/v1beta1/pravegacluster_types.go +++ b/pkg/apis/pravega/v1beta1/pravegacluster_types.go @@ -889,7 +889,15 @@ func (p *PravegaCluster) ValidateCreate() error { // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type func (p *PravegaCluster) ValidateUpdate(old runtime.Object) error { log.Printf("validate update %s", p.Name) - return p.validatePravegaVersion() + err := p.validatePravegaVersion() + if err != nil { + return err + } + err = p.validateConfigMap() + if err != nil { + return err + } + return nil } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type @@ -995,6 +1003,64 @@ func (p *PravegaCluster) validatePravegaVersion() error { return nil } +func (p *PravegaCluster) validateConfigMap() error { + + configmap := &corev1.ConfigMap{} + err := Mgr.GetClient().Get(context.TODO(), + types.NamespacedName{Name: p.ConfigMapNameForController(), Namespace: p.Namespace}, configmap) + if err != nil { + if errors.IsNotFound(err) { + return nil + } else { + return fmt.Errorf("failed to get configmap (%s): %v", configmap.Name, err) + } + } + if val, ok := p.Spec.Pravega.Options["controller.containerCount"]; ok { + checkstring := fmt.Sprintf("-Dcontroller.containerCount=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("controller.containerCount should not be changed ") + } + } + if val, ok := p.Spec.Pravega.Options["controller.container.count"]; ok { + checkstring := fmt.Sprintf("-Dcontroller.container.count=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("controller.container.count should not be changed ") + } + } + if val, ok := p.Spec.Pravega.Options["pravegaservice.containerCount"]; ok { + checkstring := fmt.Sprintf("-Dpravegaservice.containerCount=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("pravegaservice.containerCount should not be changed ") + } + } + if val, ok := p.Spec.Pravega.Options["pravegaservice.container.count"]; ok { + checkstring := fmt.Sprintf("-Dpravegaservice.container.count=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("pravegaservice.container.count should not be changed ") + } + } + if val, ok := p.Spec.Pravega.Options["bookkeeper.bkLedgerPath"]; ok { + checkstring := fmt.Sprintf("-Dbookkeeper.bkLedgerPath=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("bookkeeper.bkLedgerPath should not be changed ") + } + } + if val, ok := p.Spec.Pravega.Options["bookkeeper.ledger.path"]; ok { + checkstring := fmt.Sprintf("-Dbookkeeper.ledger.path=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("bookkeeper.ledger.path should not be changed ") + } + } + log.Print("validateConfigMap:: No error found...returning...") + return nil +} + //to return name of segmentstore based on the version func (p *PravegaCluster) StatefulSetNameForSegmentstore() string { if util.IsVersionBelow07(p.Spec.Version) { diff --git a/pkg/controller/pravega/pravega_controller.go b/pkg/controller/pravega/pravega_controller.go index 678f2c8a9..ae70c7950 100644 --- a/pkg/controller/pravega/pravega_controller.go +++ b/pkg/controller/pravega/pravega_controller.go @@ -12,6 +12,7 @@ package pravega import ( "fmt" + "sort" "strings" api "github.com/pravega/pravega-operator/pkg/apis/pravega/v1beta1" @@ -201,6 +202,8 @@ func MakeControllerConfigMap(p *api.PravegaCluster) *corev1.ConfigMap { javaOpts = append(javaOpts, fmt.Sprintf("-D%v=%v", name, value)) } + sort.Strings(javaOpts) + authEnabledStr := fmt.Sprint(p.Spec.Authentication.IsEnabled()) configData := map[string]string{ "CLUSTER_NAME": p.Name, diff --git a/pkg/controller/pravega/pravega_segmentstore.go b/pkg/controller/pravega/pravega_segmentstore.go index 3f70f928f..39ddff1e4 100644 --- a/pkg/controller/pravega/pravega_segmentstore.go +++ b/pkg/controller/pravega/pravega_segmentstore.go @@ -12,6 +12,7 @@ package pravega import ( "fmt" + "sort" "strings" api "github.com/pravega/pravega-operator/pkg/apis/pravega/v1beta1" @@ -220,6 +221,9 @@ func MakeSegmentstoreConfigMap(p *api.PravegaCluster) *corev1.ConfigMap { for name, value := range p.Spec.Pravega.Options { javaOpts = append(javaOpts, fmt.Sprintf("-D%v=%v", name, value)) } + + sort.Strings(javaOpts) + authEnabledStr := fmt.Sprint(p.Spec.Authentication.IsEnabled()) configData := map[string]string{ "AUTHORIZATION_ENABLED": authEnabledStr, diff --git a/pkg/controller/pravegacluster/pravegacluster_controller.go b/pkg/controller/pravegacluster/pravegacluster_controller.go index 959214b7b..f39bd3cde 100644 --- a/pkg/controller/pravegacluster/pravegacluster_controller.go +++ b/pkg/controller/pravegacluster/pravegacluster_controller.go @@ -14,7 +14,6 @@ import ( "context" "fmt" "strconv" - "strings" "time" pravegav1beta1 "github.com/pravega/pravega-operator/pkg/apis/pravega/v1beta1" @@ -130,6 +129,11 @@ func (r *ReconcilePravegaCluster) run(p *pravegav1beta1.PravegaCluster) (err err return fmt.Errorf("failed to reconcile finalizers %v", err) } + err = r.reconcileConfigMap(p) + if err != nil { + return fmt.Errorf("failed to reconcile configMap %v", err) + } + err = r.deployCluster(p) if err != nil { return fmt.Errorf("failed to deploy cluster: %v", err) @@ -188,6 +192,86 @@ func (r *ReconcilePravegaCluster) reconcileFinalizers(p *pravegav1beta1.PravegaC return nil } +func (r *ReconcilePravegaCluster) reconcileConfigMap(p *pravegav1beta1.PravegaCluster) (err error) { + + err = r.reconcileControllerConfigMap(p) + if err != nil { + return err + } + + err = r.reconcileSegmentStoreConfigMap(p) + if err != nil { + return err + } + + return nil + +} + +func (r *ReconcilePravegaCluster) reconcileControllerConfigMap(p *pravegav1beta1.PravegaCluster) (err error) { + + currentConfigMap := &corev1.ConfigMap{} + configMap := pravega.MakeControllerConfigMap(p) + controllerutil.SetControllerReference(p, configMap, r.scheme) + err = r.client.Get(context.TODO(), types.NamespacedName{Name: p.ConfigMapNameForController(), Namespace: p.Namespace}, currentConfigMap) + if err != nil { + if errors.IsNotFound(err) { + err = r.client.Create(context.TODO(), configMap) + if err != nil && !errors.IsAlreadyExists(err) { + return err + } + } + } else { + currentConfigMap := &corev1.ConfigMap{} + err = r.client.Get(context.TODO(), types.NamespacedName{Name: p.ConfigMapNameForController(), Namespace: p.Namespace}, currentConfigMap) + eq := util.CompareConfigMap(currentConfigMap, configMap) + if !eq { + err := r.client.Update(context.TODO(), configMap) + if err != nil { + return err + } + //restarting controller pods + err = r.restartDeploymentPod(p) + if err != nil { + return err + } + } + } + return nil +} + +func (r *ReconcilePravegaCluster) reconcileSegmentStoreConfigMap(p *pravegav1beta1.PravegaCluster) (err error) { + + currentConfigMap := &corev1.ConfigMap{} + configMap := pravega.MakeSegmentstoreConfigMap(p) + controllerutil.SetControllerReference(p, configMap, r.scheme) + err = r.client.Get(context.TODO(), types.NamespacedName{Name: p.ConfigMapNameForSegmentstore(), Namespace: p.Namespace}, currentConfigMap) + if err != nil { + if errors.IsNotFound(err) { + err = r.client.Create(context.TODO(), configMap) + if err != nil && !errors.IsAlreadyExists(err) { + return err + } + } + } else { + currentConfigMap := &corev1.ConfigMap{} + err = r.client.Get(context.TODO(), types.NamespacedName{Name: p.ConfigMapNameForSegmentstore(), Namespace: p.Namespace}, currentConfigMap) + eq := util.CompareConfigMap(currentConfigMap, configMap) + if !eq { + err := r.client.Update(context.TODO(), configMap) + if err != nil { + return err + } + //restarting sts pods + err = r.restartStsPod(p) + if err != nil { + return err + } + } + } + return nil +} + func (r *ReconcilePravegaCluster) cleanUpZookeeperMeta(p *pravegav1beta1.PravegaCluster) (err error) { if err = p.WaitForClusterToTerminate(r.client); err != nil { return fmt.Errorf("failed to wait for cluster pods termination (%s): %v", p.Name, err) @@ -317,63 +401,12 @@ func (r *ReconcilePravegaCluster) deployController(p *pravegav1beta1.PravegaClus return err } - var eq bool = true - currentConfigMap := &corev1.ConfigMap{} - configMap := pravega.MakeControllerConfigMap(p) - controllerutil.SetControllerReference(p, configMap, r.scheme) - err = r.client.Get(context.TODO(), types.NamespacedName{Name: configMap.Name, Namespace: p.Namespace}, currentConfigMap) - if err != nil { - if errors.IsNotFound(err) { - err = r.client.Create(context.TODO(), configMap) - if err != nil && !errors.IsAlreadyExists(err) { - return err - } - } - } else { - currentConfigMap := &corev1.ConfigMap{} - err = r.client.Get(context.TODO(), types.NamespacedName{Namespace: configMap.Namespace, Name: configMap.Name}, currentConfigMap) - currentjavaOptsList := currentConfigMap.Data["JAVA_OPTS"] - for _, jvmopts := range p.Spec.Pravega.ControllerJvmOptions { - eq = strings.Contains(currentjavaOptsList, jvmopts) - if !eq { - err := r.client.Update(context.TODO(), configMap) - if err != nil { - return err - } - break - } - } - } - deployment := pravega.MakeControllerDeployment(p) controllerutil.SetControllerReference(p, deployment, r.scheme) err = r.client.Create(context.TODO(), deployment) if err != nil && !errors.IsAlreadyExists(err) { return err } - if !eq { - currentDeployment := &appsv1.Deployment{} - err := r.client.Get(context.TODO(), types.NamespacedName{Name: deployment.Name, Namespace: deployment.Namespace}, currentDeployment) - selector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{ - MatchLabels: deployment.Spec.Template.Labels, - }) - if err != nil { - return fmt.Errorf("failed to convert label selector: %v", err) - } - podList := &corev1.PodList{} - podlistOps := &client.ListOptions{ - Namespace: deployment.Namespace, - LabelSelector: selector, - } - err = r.client.List(context.TODO(), podList, podlistOps) - if err != nil { - return err - } - err = r.restartDeploymentPod(podList, p) - if err != nil { - return err - } - } service := pravega.MakeControllerService(p) controllerutil.SetControllerReference(p, service, r.scheme) @@ -412,34 +445,6 @@ func (r *ReconcilePravegaCluster) deploySegmentStore(p *pravegav1beta1.PravegaCl return err } - var eq bool = true - currentConfigMap := &corev1.ConfigMap{} - configMap := pravega.MakeSegmentstoreConfigMap(p) - controllerutil.SetControllerReference(p, configMap, r.scheme) - err = r.client.Get(context.TODO(), types.NamespacedName{Name: configMap.Name, Namespace: p.Namespace}, currentConfigMap) - if err != nil { - if errors.IsNotFound(err) { - err = r.client.Create(context.TODO(), configMap) - if err != nil && !errors.IsAlreadyExists(err) { - return err - } - } - } else { - currentConfigMap := &corev1.ConfigMap{} - err = r.client.Get(context.TODO(), types.NamespacedName{Namespace: configMap.Namespace, Name: configMap.Name}, currentConfigMap) - currentjavaOptsList := currentConfigMap.Data["JAVA_OPTS"] - for _, jvmopts := range p.Spec.Pravega.SegmentStoreJVMOptions { - eq = strings.Contains(currentjavaOptsList, jvmopts) - if !eq { - err := r.client.Update(context.TODO(), configMap) - if err != nil { - return err - } - break - } - } - } - statefulSet := pravega.MakeSegmentStoreStatefulSet(p) controllerutil.SetControllerReference(p, statefulSet, r.scheme) if statefulSet.Spec.VolumeClaimTemplates != nil { @@ -470,29 +475,6 @@ func (r *ReconcilePravegaCluster) deploySegmentStore(p *pravegav1beta1.PravegaCl } } } - if !eq { - currentSts := &appsv1.StatefulSet{} - err := r.client.Get(context.TODO(), types.NamespacedName{Name: statefulSet.Name, Namespace: statefulSet.Namespace}, currentSts) - selector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{ - MatchLabels: statefulSet.Spec.Template.Labels, - }) - if err != nil { - return fmt.Errorf("failed to convert label selector: %v", err) - } - podList := &corev1.PodList{} - podlistOps := &client.ListOptions{ - Namespace: statefulSet.Namespace, - LabelSelector: selector, - } - err = r.client.List(context.TODO(), podList, podlistOps) - if err != nil { - return err - } - err = r.restartStsPod(podList) - if err != nil { - return err - } - } return nil } @@ -505,7 +487,29 @@ func hasOldVersionOwnerReference(ownerreference []metav1.OwnerReference) bool { return false } -func (r *ReconcilePravegaCluster) restartStsPod(podList *corev1.PodList) error { +func (r *ReconcilePravegaCluster) restartStsPod(p *pravegav1beta1.PravegaCluster) error { + + currentSts := &appsv1.StatefulSet{} + err := r.client.Get(context.TODO(), types.NamespacedName{Name: p.StatefulSetNameForSegmentstore(), Namespace: p.Namespace}, currentSts) + if err != nil { + return err + } + selector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{ + MatchLabels: currentSts.Spec.Template.Labels, + }) + if err != nil { + return fmt.Errorf("failed to convert label selector: %v", err) + } + podList := &corev1.PodList{} + podlistOps := &client.ListOptions{ + Namespace: currentSts.Namespace, + LabelSelector: selector, + } + err = r.client.List(context.TODO(), podList, podlistOps) + if err != nil { + return err + } + for _, podItem := range podList.Items { err := r.client.Delete(context.TODO(), &podItem) if err != nil { @@ -532,7 +536,30 @@ func (r *ReconcilePravegaCluster) restartStsPod(podList *corev1.PodList) error { } return nil } -func (r *ReconcilePravegaCluster) restartDeploymentPod(podList *corev1.PodList, p *pravegav1beta1.PravegaCluster) error { + +func (r *ReconcilePravegaCluster) restartDeploymentPod(p *pravegav1beta1.PravegaCluster) error { + + currentDeployment := &appsv1.Deployment{} + err := r.client.Get(context.TODO(), types.NamespacedName{Name: p.DeploymentNameForController(), Namespace: p.Namespace}, currentDeployment) + if err != nil { + return err + } + selector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{ + MatchLabels: currentDeployment.Spec.Template.Labels, + }) + if err != nil { + return fmt.Errorf("failed to convert label selector: %v", err) + } + podList := &corev1.PodList{} + podlistOps := &client.ListOptions{ + Namespace: currentDeployment.Namespace, + LabelSelector: selector, + } + err = r.client.List(context.TODO(), podList, podlistOps) + if err != nil { + return err + } + for _, podItem := range podList.Items { err := r.client.Delete(context.TODO(), &podItem) if err != nil { diff --git a/pkg/util/pravegacluster.go b/pkg/util/pravegacluster.go index 5c948a5c3..70bec8cac 100644 --- a/pkg/util/pravegacluster.go +++ b/pkg/util/pravegacluster.go @@ -12,6 +12,7 @@ package util import ( "fmt" + "reflect" "regexp" "strconv" "strings" @@ -46,6 +47,15 @@ func IsVersionBelow07(ver string) bool { return false } +func CompareConfigMap(cm1 *corev1.ConfigMap, cm2 *corev1.ConfigMap) bool { + + eq := reflect.DeepEqual(cm1.Data, cm2.Data) + if eq { + return true + } + return false +} + func IsOrphan(k8sObjectName string, replicas int32) bool { index := strings.LastIndexAny(k8sObjectName, "-") if index == -1 { From a46951295fd17fabc9454bed0ffd77e882c73bf1 Mon Sep 17 00:00:00 2001 From: prabhaker24 Date: Fri, 16 Oct 2020 16:59:59 +0530 Subject: [PATCH 6/9] ut for compareConfigMap added Signed-off-by: prabhaker24 --- pkg/util/pravegacluster.go | 1 - pkg/util/pravegacluster_test.go | 44 ++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/pkg/util/pravegacluster.go b/pkg/util/pravegacluster.go index 70bec8cac..109db05be 100644 --- a/pkg/util/pravegacluster.go +++ b/pkg/util/pravegacluster.go @@ -48,7 +48,6 @@ func IsVersionBelow07(ver string) bool { } func CompareConfigMap(cm1 *corev1.ConfigMap, cm2 *corev1.ConfigMap) bool { - eq := reflect.DeepEqual(cm1.Data, cm2.Data) if eq { return true diff --git a/pkg/util/pravegacluster_test.go b/pkg/util/pravegacluster_test.go index e6830f6a5..0f04622d3 100644 --- a/pkg/util/pravegacluster_test.go +++ b/pkg/util/pravegacluster_test.go @@ -14,6 +14,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -258,6 +259,48 @@ var _ = Describe("pravegacluster", func() { }) }) + Context("CompareConfigMap", func() { + var output1, output2 bool + BeforeEach(func() { + configData1 := map[string]string{ + "TEST_DATA": "testdata", + } + configData2 := map[string]string{ + "TEST_DATA": "testdata1", + } + configMap1 := &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: "v1", + }, + Data: configData1, + } + configMap2 := &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: "v1", + }, + Data: configData1, + } + configMap3 := &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: "v1", + }, + Data: configData2, + } + output1 = CompareConfigMap(configMap1, configMap2) + output2 = CompareConfigMap(configMap1, configMap3) + }) + + It("output1 should be true", func() { + Ω(output1).To(Equal(true)) + }) + It("output2 should be false", func() { + Ω(output2).To(Equal(false)) + }) + }) + Context("GetPodVersion", func() { var out string BeforeEach(func() { @@ -272,5 +315,4 @@ var _ = Describe("pravegacluster", func() { Ω(out).To(Equal("0.7.0")) }) }) - }) From d29cd94e8678d6090ec043c0a178bd77ba1c1ad4 Mon Sep 17 00:00:00 2001 From: prabhaker24 Date: Mon, 19 Oct 2020 15:58:33 +0530 Subject: [PATCH 7/9] adding e2e for cm changes added Signed-off-by: prabhaker24 --- pkg/test/e2e/e2eutil/pravegacluster_util.go | 61 +++++++++++++++- test/e2e/cmchanges_test.go | 77 +++++++++++++++++++++ test/e2e/pravegacluster_test.go | 1 + 3 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 test/e2e/cmchanges_test.go diff --git a/pkg/test/e2e/e2eutil/pravegacluster_util.go b/pkg/test/e2e/e2eutil/pravegacluster_util.go index d5698a8af..53db66d45 100644 --- a/pkg/test/e2e/e2eutil/pravegacluster_util.go +++ b/pkg/test/e2e/e2eutil/pravegacluster_util.go @@ -19,6 +19,7 @@ import ( framework "github.com/operator-framework/operator-sdk/pkg/test" bkapi "github.com/pravega/bookkeeper-operator/pkg/apis/bookkeeper/v1alpha1" api "github.com/pravega/pravega-operator/pkg/apis/pravega/v1beta1" + "github.com/pravega/pravega-operator/pkg/util" zkapi "github.com/pravega/zookeeper-operator/pkg/apis/zookeeper/v1beta1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -156,6 +157,9 @@ func DeleteBKCluster(t *testing.T, f *framework.Framework, ctx *framework.TestCt t.Logf("deleting bookkeeper cluster: %s", b.Name) err := f.Client.Delete(goctx.TODO(), b) if err != nil { + if apierrors.IsNotFound(err) { + return nil + } return fmt.Errorf("failed to delete CR: %v", err) } @@ -168,6 +172,9 @@ func DeletePravegaCluster(t *testing.T, f *framework.Framework, ctx *framework.T t.Logf("deleting pravega cluster: %s", p.Name) err := f.Client.Delete(goctx.TODO(), p) if err != nil { + if apierrors.IsNotFound(err) { + return nil + } return fmt.Errorf("failed to delete CR: %v", err) } @@ -180,9 +187,11 @@ func DeleteZKCluster(t *testing.T, f *framework.Framework, ctx *framework.TestCt t.Logf("deleting zookeeper cluster: %s", z.Name) err := f.Client.Delete(goctx.TODO(), z) if err != nil { + if apierrors.IsNotFound(err) { + return nil + } return fmt.Errorf("failed to delete CR: %v", err) } - t.Logf("deleted zookeeper cluster: %s", z.Name) return nil } @@ -344,6 +353,56 @@ func WaitForPravegaClusterToUpgrade(t *testing.T, f *framework.Framework, ctx *f return nil } +func WaitForCMPravegaClusterToUpgrade(t *testing.T, f *framework.Framework, ctx *framework.TestCtx, p *api.PravegaCluster) error { + t.Logf("waiting for cluster to upgrade post cm changes: %s", p.Name) + + listOptions := metav1.ListOptions{ + LabelSelector: labels.SelectorFromSet(p.LabelsForPravegaCluster()).String(), + } + + // Checking if all pods are getting restarted + podList, err := f.KubeClient.CoreV1().Pods(p.Namespace).List(listOptions) + if err != nil { + return err + } + + for i := range podList.Items { + pod := &podList.Items[i] + name := pod.Name + t.Logf("waiting for pods to terminate, running pods (%v)", pod.Name) + err = f.Client.Get(goctx.TODO(), types.NamespacedName{Namespace: p.Namespace, Name: name}, pod) + start := time.Now() + for util.IsPodReady(pod) { + if time.Since(start) > 5*time.Minute { + return fmt.Errorf("failed to delete Segmentstore pod (%s) for 5 mins ", name) + } + err = f.Client.Get(goctx.TODO(), types.NamespacedName{Namespace: p.Namespace, Name: name}, pod) + } + } + + //Checking if all pods are in ready state + podList, err = f.KubeClient.CoreV1().Pods(p.Namespace).List(listOptions) + if err != nil { + return err + } + + for i := range podList.Items { + pod := &podList.Items[i] + name := pod.Name + t.Logf("waiting for pods to terminate, running pods (%v)", pod.Name) + err = f.Client.Get(goctx.TODO(), types.NamespacedName{Namespace: p.Namespace, Name: name}, pod) + start := time.Now() + for !util.IsPodReady(pod) { + if time.Since(start) > 5*time.Minute { + return fmt.Errorf("failed to delete Segmentstore pod (%s) for 5 mins ", name) + } + err = f.Client.Get(goctx.TODO(), types.NamespacedName{Namespace: p.Namespace, Name: name}, pod) + } + } + + return nil +} + // WaitForPravegaClusterToTerminate will wait until all cluster pods are terminated func WaitForPravegaClusterToTerminate(t *testing.T, f *framework.Framework, ctx *framework.TestCtx, p *api.PravegaCluster) error { t.Logf("waiting for pravega cluster to terminate: %s", p.Name) diff --git a/test/e2e/cmchanges_test.go b/test/e2e/cmchanges_test.go new file mode 100644 index 000000000..4c92998d1 --- /dev/null +++ b/test/e2e/cmchanges_test.go @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2018 Dell Inc., or its subsidiaries. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +package e2e + +import ( + "testing" + + . "github.com/onsi/gomega" + framework "github.com/operator-framework/operator-sdk/pkg/test" + pravega_e2eutil "github.com/pravega/pravega-operator/pkg/test/e2e/e2eutil" +) + +func testCMUpgradeCluster(t *testing.T) { + g := NewGomegaWithT(t) + + doCleanup := true + ctx := framework.NewTestCtx(t) + defer func() { + if doCleanup { + ctx.Cleanup() + } + }() + + namespace, err := ctx.GetNamespace() + g.Expect(err).NotTo(HaveOccurred()) + f := framework.Global + + //creating the setup for running the test + err = pravega_e2eutil.InitialSetup(t, f, ctx, namespace) + g.Expect(err).NotTo(HaveOccurred()) + + cluster := pravega_e2eutil.NewDefaultCluster(namespace) + + cluster.WithDefaults() + + pravega, err := pravega_e2eutil.CreatePravegaCluster(t, f, ctx, cluster) + g.Expect(err).NotTo(HaveOccurred()) + + // A default Pravega cluster should have 2 pods: 1 controller, 1 segment store + podSize := 2 + err = pravega_e2eutil.WaitForPravegaClusterToBecomeReady(t, f, ctx, pravega, podSize) + g.Expect(err).NotTo(HaveOccurred()) + + // This is to get the latest Pravega cluster object + pravega, err = pravega_e2eutil.GetPravegaCluster(t, f, ctx, pravega) + g.Expect(err).NotTo(HaveOccurred()) + + //updating pravega option + pravega.Spec.Pravega.Options["bookkeeper.bkAckQuorumSize"] = "2" + + //updating pravegacluster + err = pravega_e2eutil.UpdatePravegaCluster(t, f, ctx, pravega) + g.Expect(err).NotTo(HaveOccurred()) + + //checking if the upgrade of options was successfull + err = pravega_e2eutil.WaitForCMPravegaClusterToUpgrade(t, f, ctx, pravega) + g.Expect(err).NotTo(HaveOccurred()) + + // Delete cluster + err = pravega_e2eutil.DeletePravegaCluster(t, f, ctx, pravega) + g.Expect(err).NotTo(HaveOccurred()) + + // No need to do cleanup since the cluster CR has already been deleted + doCleanup = false + + err = pravega_e2eutil.WaitForPravegaClusterToTerminate(t, f, ctx, pravega) + g.Expect(err).NotTo(HaveOccurred()) + +} diff --git a/test/e2e/pravegacluster_test.go b/test/e2e/pravegacluster_test.go index 6fe8c0eca..e3b377b8e 100644 --- a/test/e2e/pravegacluster_test.go +++ b/test/e2e/pravegacluster_test.go @@ -61,6 +61,7 @@ func testPravegaCluster(t *testing.T) { "testScaleCluster": testScaleCluster, "testUpgradeCluster": testUpgradeCluster, "testWebhook": testWebhook, + "testCMUpgradeCluster": testCMUpgradeCluster, } for name, f := range testFuncs { From 4a2632c66aa292e166610ed63696622018c1acdd Mon Sep 17 00:00:00 2001 From: prabhaker24 Date: Mon, 19 Oct 2020 17:48:40 +0530 Subject: [PATCH 8/9] more validation added Signed-off-by: prabhaker24 --- .../pravega/v1beta1/pravegacluster_types.go | 92 +++++++- .../v1beta1/pravegacluster_types_test.go | 217 ++++++++++++++++++ test/e2e/cmchanges_test.go | 16 ++ 3 files changed, 316 insertions(+), 9 deletions(-) diff --git a/pkg/apis/pravega/v1beta1/pravegacluster_types.go b/pkg/apis/pravega/v1beta1/pravegacluster_types.go index e33d2cf00..6ebf94461 100644 --- a/pkg/apis/pravega/v1beta1/pravegacluster_types.go +++ b/pkg/apis/pravega/v1beta1/pravegacluster_types.go @@ -883,13 +883,13 @@ func (p *PravegaCluster) SetupWebhookWithManager(mgr ctrl.Manager) error { // ValidateCreate implements webhook.Validator so a webhook will be registered for the type func (p *PravegaCluster) ValidateCreate() error { log.Printf("validate create %s", p.Name) - return p.validatePravegaVersion() + return p.ValidatePravegaVersion("") } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type func (p *PravegaCluster) ValidateUpdate(old runtime.Object) error { log.Printf("validate update %s", p.Name) - err := p.validatePravegaVersion() + err := p.ValidatePravegaVersion("") if err != nil { return err } @@ -907,9 +907,14 @@ func (p *PravegaCluster) ValidateDelete() error { return nil } -func getSupportedVersions() (map[string]string, error) { +func getSupportedVersions(filename string) (map[string]string, error) { var supportedVersions = map[string]string{} - file, err := os.Open("/tmp/config/keys") + filepath := filename + if filename == "" { + filepath = "/tmp/config/keys" + } + + file, err := os.Open(filepath) if err != nil { log.Fatalf("failed opening file: %v", err) @@ -932,8 +937,8 @@ func getSupportedVersions() (map[string]string, error) { return supportedVersions, nil } -func (p *PravegaCluster) validatePravegaVersion() error { - supportedVersions, err := getSupportedVersions() +func (p *PravegaCluster) ValidatePravegaVersion(filename string) error { + supportedVersions, err := getSupportedVersions(filename) if err != nil { return fmt.Errorf("Error retrieving suported versions %v", err) } @@ -989,7 +994,7 @@ func (p *PravegaCluster) validatePravegaVersion() error { return fmt.Errorf("found version is not in valid format, something bad happens: %v", err) } - log.Printf("validatePravegaVersion:: normFoundVersion %s", normFoundVersion) + log.Printf("ValidatePravegaVersion:: normFoundVersion %s", normFoundVersion) upgradeString, ok := supportedVersions[normFoundVersion] if !ok { // It should never happen @@ -999,12 +1004,11 @@ func (p *PravegaCluster) validatePravegaVersion() error { if !util.ContainsVersion(upgradeList, normRequestVersion) { return fmt.Errorf("unsupported upgrade from version %s to %s", p.Status.CurrentVersion, requestVersion) } - log.Print("validatePravegaVersion:: No error found...returning...") + log.Print("ValidatePravegaVersion:: No error found...returning...") return nil } func (p *PravegaCluster) validateConfigMap() error { - configmap := &corev1.ConfigMap{} err := Mgr.GetClient().Get(context.TODO(), types.NamespacedName{Name: p.ConfigMapNameForController(), Namespace: p.Namespace}, configmap) @@ -1057,6 +1061,76 @@ func (p *PravegaCluster) validateConfigMap() error { return fmt.Errorf("bookkeeper.ledger.path should not be changed ") } } + if val, ok := p.Spec.Pravega.Options["controller.retention.bucketCount"]; ok { + checkstring := fmt.Sprintf("-Dcontroller.retention.bucketCount=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("controller.retention.bucketCount should not be changed ") + } + } + if val, ok := p.Spec.Pravega.Options["controller.retention.bucket.count"]; ok { + checkstring := fmt.Sprintf("-Dcontroller.retention.bucket.count=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("controller.retention.bucket.count should not be changed ") + } + } + if val, ok := p.Spec.Pravega.Options["controller.watermarking.bucketCount"]; ok { + checkstring := fmt.Sprintf("-Dcontroller.watermarking.bucketCount=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("controller.watermarking.bucketCount should not be changed ") + } + } + if val, ok := p.Spec.Pravega.Options["controller.watermarking.bucket.count"]; ok { + checkstring := fmt.Sprintf("-Dcontroller.watermarking.bucket.count=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("controller.watermarking.bucket.count should not be changed ") + } + } + if val, ok := p.Spec.Pravega.Options["pravegaservice.dataLogImplementation"]; ok { + checkstring := fmt.Sprintf("-Dpravegaservice.dataLogImplementation=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("pravegaservice.dataLogImplementation should not be changed ") + } + } + if val, ok := p.Spec.Pravega.Options["pravegaservice.dataLog.impl.name"]; ok { + checkstring := fmt.Sprintf("-Dpravegaservice.dataLog.impl.name=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("pravegaservice.dataLog.impl.name should not be changed ") + } + } + if val, ok := p.Spec.Pravega.Options["pravegaservice.storageImplementation"]; ok { + checkstring := fmt.Sprintf("-Dpravegaservice.storageImplementation=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("pravegaservice.storageImplementation should not be changed ") + } + } + if val, ok := p.Spec.Pravega.Options["pravegaservice.storage.impl.name"]; ok { + checkstring := fmt.Sprintf("-Dpravegaservice.storage.impl.name=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("pravegaservice.storage.impl.name should not be changed ") + } + } + if val, ok := p.Spec.Pravega.Options["storageextra.storageNoOpMode"]; ok { + checkstring := fmt.Sprintf("-Dstorageextra.storageNoOpMode=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("storageextra.storageNoOpMode should not be changed ") + } + } + if val, ok := p.Spec.Pravega.Options["storageextra.noOp.mode.enable"]; ok { + checkstring := fmt.Sprintf("-Dstorageextra.noOp.mode.enable=%v", val) + eq := strings.Contains(configmap.Data["JAVA_OPTS"], checkstring) + if !eq { + return fmt.Errorf("storageextra.noOp.mode.enable should not be changed ") + } + } log.Print("validateConfigMap:: No error found...returning...") return nil } diff --git a/pkg/apis/pravega/v1beta1/pravegacluster_types_test.go b/pkg/apis/pravega/v1beta1/pravegacluster_types_test.go index a64333a24..9d75d3ee5 100644 --- a/pkg/apis/pravega/v1beta1/pravegacluster_types_test.go +++ b/pkg/apis/pravega/v1beta1/pravegacluster_types_test.go @@ -11,6 +11,8 @@ package v1beta1_test import ( + "os" + "strings" "testing" . "github.com/onsi/ginkgo" @@ -95,6 +97,221 @@ var _ = Describe("PravegaCluster Types Spec", func() { Ω(p.Spec.ExternalAccess.DomainName).Should(Equal("")) }) }) + + Context("ValidatePravegaVersion", func() { + var ( + p *v1beta1.PravegaCluster + file1 *os.File + ) + BeforeEach(func() { + p = &v1beta1.PravegaCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "default", + }, + } + p.WithDefaults() + file1, _ = os.Create("filename") + file1, _ = os.OpenFile("filename", os.O_RDWR, 0644) + file1.WriteString("0.1.0:0.1.0 \n") + file1.WriteString("0.2.0:0.2.0 \n") + file1.WriteString("0.3.0:0.3.0,0.3.1,0.3.2 \n") + file1.WriteString("0.3.1:0.3.1,0.3.2 \n") + file1.WriteString("0.4.0:0.4.0 \n") + file1.WriteString("0.5.0:0.5.0,0.5.1,0.6.0,0.6.1,0.6.2,0.7.0,0.7.1 \n") + file1.WriteString("0.5.1:0.5.1,0.6.0,0.6.1,0.6.2,0.7.0,0.7.1 \n") + file1.WriteString("0.6.0:0.6.0,0.6.1,0.6.2,0.7.0,0.7.1 \n") + file1.WriteString("0.6.1:0.6.1,0.6.2,0.7.0,0.7.1 \n") + file1.WriteString("0.6.2:0.6.2,0.7.0,0.7.1 \n") + file1.WriteString("0.7.0:0.7.0,0.7.1 \n") + file1.WriteString("0.7.1:0.7.1 \n") + file1.WriteString("0.7.2:0.7.1 \n") + }) + Context("Spec version empty", func() { + var ( + err error + ) + BeforeEach(func() { + p.Spec.Version = "" + err = p.ValidatePravegaVersion("filename") + }) + It("should return nil", func() { + Ω(err).To(BeNil()) + }) + }) + Context("Version not in valid format", func() { + var ( + err error + ) + BeforeEach(func() { + p.Spec.Version = "999" + err = p.ValidatePravegaVersion("filename") + }) + It("should return error", func() { + Ω(strings.ContainsAny(err.Error(), "request version is not in valid format")).Should(Equal(true)) + }) + }) + + Context("Version not supported", func() { + var ( + err error + ) + BeforeEach(func() { + p.Spec.Version = "0.9.0" + err = p.ValidatePravegaVersion("filename") + }) + It("should return error", func() { + Ω(strings.ContainsAny(err.Error(), "unsupported Bookkeeper cluster version")).Should(Equal(true)) + }) + }) + Context("Spec version and current version same", func() { + var ( + err error + ) + BeforeEach(func() { + p.Spec.Version = "0.7.0" + p.Status.CurrentVersion = "0.7.0" + err = p.ValidatePravegaVersion("filename") + }) + It("should return nil", func() { + Ω(err).To(BeNil()) + }) + }) + Context("Unsupported current version", func() { + var ( + err error + ) + BeforeEach(func() { + p.Spec.Version = "0.7.0" + p.Status.CurrentVersion = "0.9.0" + err = p.ValidatePravegaVersion("filename") + }) + It("should return error", func() { + Ω(strings.ContainsAny(err.Error(), "failed to find current cluster version in the supported versions")).Should(Equal(true)) + }) + + }) + Context("current version not in correct format", func() { + var ( + err error + ) + BeforeEach(func() { + p.Spec.Version = "0.7.0" + p.Status.CurrentVersion = "999" + err = p.ValidatePravegaVersion("filename") + }) + It("should return error", func() { + Ω(strings.ContainsAny(err.Error(), "found version is not in valid format")).Should(Equal(true)) + }) + + }) + Context("unsupported upgrade to a version", func() { + var ( + err error + ) + BeforeEach(func() { + p.Status.CurrentVersion = "0.7.0" + p.Spec.Version = "0.7.2" + err = p.ValidatePravegaVersion("filename") + }) + It("should return error", func() { + Ω(strings.ContainsAny(err.Error(), "unsupported upgrade from version")).Should(Equal(true)) + }) + + }) + Context("supported upgrade to a version", func() { + var ( + err error + ) + BeforeEach(func() { + p.Status.CurrentVersion = "0.7.0" + p.Spec.Version = "0.7.1" + err = p.ValidatePravegaVersion("filename") + }) + It("should return nil", func() { + Ω(err).To(BeNil()) + }) + }) + Context("validation while cluster upgrade in progress", func() { + var ( + err error + ) + BeforeEach(func() { + p.Status.SetUpgradingConditionTrue(" ", " ") + p.Spec.Version = "0.7.1" + p.Status.TargetVersion = "0.7.0" + err = p.ValidatePravegaVersion("filename") + }) + It("should return error", func() { + Ω(strings.ContainsAny(err.Error(), "failed to process the request, cluster is upgrading")).Should(Equal(true)) + }) + }) + Context("validation while cluster rollback in progress", func() { + var ( + err error + ) + BeforeEach(func() { + p.Status.CurrentVersion = "0.7.0" + p.Status.Init() + p.Status.AddToVersionHistory("0.6.0") + p.Status.SetRollbackConditionTrue(" ", " ") + p.Spec.Version = "0.7.0" + err = p.ValidatePravegaVersion("filename") + }) + It("should return error", func() { + Ω(strings.ContainsAny(err.Error(), "failed to process the request, rollback in progress")).Should(Equal(true)) + }) + }) + Context("validation while cluster in error state", func() { + var ( + err error + ) + BeforeEach(func() { + p.Status.SetErrorConditionTrue("some err", " ") + p.Spec.Version = "0.7.0" + err = p.ValidatePravegaVersion("filename") + }) + It("should return error", func() { + Ω(strings.ContainsAny(err.Error(), "failed to process the request, cluster is in error state")).Should(Equal(true)) + }) + }) + Context("validation while cluster in upgradefailed state", func() { + var ( + err error + ) + BeforeEach(func() { + p.Status.CurrentVersion = "0.7.0" + p.Status.Init() + p.Status.AddToVersionHistory("0.6.0") + p.Status.SetErrorConditionTrue("UpgradeFailed", " ") + p.Spec.Version = "0.7.0" + err = p.ValidatePravegaVersion("filename") + }) + It("should return error", func() { + Ω(strings.ContainsAny(err.Error(), "Rollback to version 0.7.0 not supported")).Should(Equal(true)) + }) + }) + Context("validation while cluster in upgradefailed state and supported rollback version", func() { + var ( + err error + ) + BeforeEach(func() { + p.Status.CurrentVersion = "0.6.0" + p.Status.Init() + p.Status.AddToVersionHistory("0.6.0") + p.Status.SetErrorConditionTrue("UpgradeFailed", " ") + p.Spec.Version = "0.6.0" + err = p.ValidatePravegaVersion("filename") + }) + It("should return nil", func() { + Ω(err).To(BeNil()) + }) + }) + AfterEach(func() { + file1.Close() + os.Remove("filename") + }) + }) + Context("Setting TLS and Autentication to nil", func() { BeforeEach(func() { p.Spec.Version = "0.6.0" diff --git a/test/e2e/cmchanges_test.go b/test/e2e/cmchanges_test.go index 4c92998d1..031b251f5 100644 --- a/test/e2e/cmchanges_test.go +++ b/test/e2e/cmchanges_test.go @@ -11,6 +11,7 @@ package e2e import ( + "strings" "testing" . "github.com/onsi/gomega" @@ -41,6 +42,8 @@ func testCMUpgradeCluster(t *testing.T) { cluster.WithDefaults() + cluster.Spec.Pravega.Options["pravegaservice.containerCount"] = "3" + pravega, err := pravega_e2eutil.CreatePravegaCluster(t, f, ctx, cluster) g.Expect(err).NotTo(HaveOccurred()) @@ -64,6 +67,19 @@ func testCMUpgradeCluster(t *testing.T) { err = pravega_e2eutil.WaitForCMPravegaClusterToUpgrade(t, f, ctx, pravega) g.Expect(err).NotTo(HaveOccurred()) + // This is to get the latest Pravega cluster object + pravega, err = pravega_e2eutil.GetPravegaCluster(t, f, ctx, pravega) + g.Expect(err).NotTo(HaveOccurred()) + + //updating pravega option + pravega.Spec.Pravega.Options["pravegaservice.containerCount"] = "10" + + //updating pravegacluster + err = pravega_e2eutil.UpdatePravegaCluster(t, f, ctx, pravega) + + //should give an errors + g.Expect(strings.ContainsAny(err.Error(), "controller.containerCount should not be changed")).To(Equal(true)) + // Delete cluster err = pravega_e2eutil.DeletePravegaCluster(t, f, ctx, pravega) g.Expect(err).NotTo(HaveOccurred()) From 991a6fef497aba797a63a6f62fd8a6b71c6d0bfc Mon Sep 17 00:00:00 2001 From: prabhaker24 Date: Tue, 20 Oct 2020 12:13:37 +0530 Subject: [PATCH 9/9] fixed typo Signed-off-by: prabhaker24 --- test/e2e/cmchanges_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/e2e/cmchanges_test.go b/test/e2e/cmchanges_test.go index 031b251f5..6b5fb313f 100644 --- a/test/e2e/cmchanges_test.go +++ b/test/e2e/cmchanges_test.go @@ -63,7 +63,7 @@ func testCMUpgradeCluster(t *testing.T) { err = pravega_e2eutil.UpdatePravegaCluster(t, f, ctx, pravega) g.Expect(err).NotTo(HaveOccurred()) - //checking if the upgrade of options was successfull + //checking if the upgrade of options was successful err = pravega_e2eutil.WaitForCMPravegaClusterToUpgrade(t, f, ctx, pravega) g.Expect(err).NotTo(HaveOccurred()) @@ -77,7 +77,7 @@ func testCMUpgradeCluster(t *testing.T) { //updating pravegacluster err = pravega_e2eutil.UpdatePravegaCluster(t, f, ctx, pravega) - //should give an errors + //should give an error g.Expect(strings.ContainsAny(err.Error(), "controller.containerCount should not be changed")).To(Equal(true)) // Delete cluster