From 53d14500c0703369150dd7f25f65cca5fd5cda37 Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Tue, 10 Dec 2024 13:45:03 -0500 Subject: [PATCH 01/20] Adding WIP ZoneValidation() to PowerFlex PreChecks that calls into drivers.ExtractZones. Fixed up existing unit-tests to pass around a proper secret, rather than the "csm" value currently used, as this causes the ExtractZones() to fail on parsing during unit-testing. --- controllers/csm_controller.go | 41 ++++++++++++++++++++++++++++-- controllers/csm_controller_test.go | 32 ++++++++++++----------- pkg/drivers/powerflex.go | 9 ++++++- tests/shared/common.go | 41 ++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 18 deletions(-) diff --git a/controllers/csm_controller.go b/controllers/csm_controller.go index 05a1054d..7b9c82ac 100644 --- a/controllers/csm_controller.go +++ b/controllers/csm_controller.go @@ -278,7 +278,7 @@ func (r *ContainerStorageModuleReconciler) Reconcile(_ context.Context, req ctrl } // perform prechecks - err = r.PreChecks(ctx, csm, *operatorConfig) + err = r.PreChecks(ctx, csm, *operatorConfig, req.Namespace) if err != nil { csm.GetCSMStatus().State = constants.InvalidConfig r.EventRecorder.Event(csm, corev1.EventTypeWarning, csmv1.EventUpdated, fmt.Sprintf("Failed Prechecks: %s", err)) @@ -1314,7 +1314,7 @@ func (r *ContainerStorageModuleReconciler) removeModule(ctx context.Context, ins } // PreChecks - validate input values -func (r *ContainerStorageModuleReconciler) PreChecks(ctx context.Context, cr *csmv1.ContainerStorageModule, operatorConfig utils.OperatorConfig) error { +func (r *ContainerStorageModuleReconciler) PreChecks(ctx context.Context, cr *csmv1.ContainerStorageModule, operatorConfig utils.OperatorConfig, namespace string) error { log := logger.GetLogger(ctx) // Check drivers switch cr.Spec.Driver.CSIDriverType { @@ -1328,6 +1328,14 @@ func (r *ContainerStorageModuleReconciler) PreChecks(ctx context.Context, cr *cs if err != nil { return fmt.Errorf("failed powerflex validation: %v", err) } + // zoning initially applies only to pflex + zonesAreValid, err := r.ZoneValidation(ctx, cr, namespace) + if err != nil { + return fmt.Errorf("error during zone validation: %v", err) + } + if zonesAreValid == false { + return fmt.Errorf("failed zone validation.") + } case csmv1.PowerStore: err := drivers.PrecheckPowerStore(ctx, cr, operatorConfig, r.GetClient()) if err != nil { @@ -1527,3 +1535,32 @@ func (r *ContainerStorageModuleReconciler) GetMatchingNodes(ctx context.Context, return nodeList, err } + +func (r *ContainerStorageModuleReconciler) ZoneValidation(ctx context.Context, cr *csmv1.ContainerStorageModule, namespace string) (bool, error) { + log := logger.GetLogger(ctx) + validZoneConfiguration := true + nodeList := &corev1.NodeList{} + log.Infof(" nodeList len %d", len(nodeList.Items)) + for _, node := range nodeList.Items { + log.Infof(" nodeList name %s", node.Name) + } + zones, err := drivers.ExtractZones(ctx, cr, r.Client, namespace) + if err != nil { + log.Infof("ZoneValidation failed with error: %v", err) + return false, err + } + + log.Infof("ZoneValidation zones returned from ExtractZones: %v", zones) + // TBD: make sure all zone keys are the same, if not fail + // extract first key from first node + // zoneKeyLabelRow := zones[nodeList[0].name] + // zoneKey := zoneKeyLabelRow[0][0] + // The labelKey, GetMatchingNodes with labelKey, value="", verify that the list + // returned is the same size as the current number of nodes on the cluster + // i.e. all nodes must have this zoning label key. if the number of nodes returned + // does not match the number of nodes on the cluster, then fail, otherwise return + // true + //GetMatchingNodes(ctx, labelKey, labelValue); + + return validZoneConfiguration, err +} diff --git a/controllers/csm_controller_test.go b/controllers/csm_controller_test.go index 3b80ecbe..1a058ad2 100644 --- a/controllers/csm_controller_test.go +++ b/controllers/csm_controller_test.go @@ -585,7 +585,8 @@ func (suite *CSMControllerTestSuite) TestCsmDowngrade() { if err != nil { panic(err) } - sec := shared.MakeSecret(csmName+"-config", suite.namespace, pFlexConfigVersion) + //sec := shared.MakeSecret(csmName+"-config", suite.namespace, pFlexConfigVersion) + sec := shared.MakeSecretPowerFlex(csmName+"-config", suite.namespace, pFlexConfigVersion) err = suite.fakeClient.Create(ctx, sec) if err != nil { panic(err) @@ -653,7 +654,8 @@ func (suite *CSMControllerTestSuite) TestCsmDowngradeSkipVersion() { if err != nil { panic(err) } - sec := shared.MakeSecret(csmName+"-config", suite.namespace, pFlexConfigVersion) + //sec := shared.MakeSecret(csmName+"-config", suite.namespace, pFlexConfigVersion) + sec := shared.MakeSecretPowerFlex(csmName+"-config", suite.namespace, pFlexConfigVersion) err = suite.fakeClient.Create(ctx, sec) if err != nil { panic(err) @@ -1030,32 +1032,32 @@ func (suite *CSMControllerTestSuite) TestCsmPreCheckModuleError() { // error in Authorization csm.Spec.Modules = getAuthModule() - err = reconciler.PreChecks(ctx, &csm, badOperatorConfig) + err = reconciler.PreChecks(ctx, &csm, badOperatorConfig, "") assert.NotNil(suite.T(), err) // error in Authorization Proxy Server csm.Spec.Modules = getAuthProxyServer() - err = reconciler.PreChecks(ctx, &csm, badOperatorConfig) + err = reconciler.PreChecks(ctx, &csm, badOperatorConfig, "") assert.NotNil(suite.T(), err) // error in App-Mobility csm.Spec.Modules = getAppMob() - err = reconciler.PreChecks(ctx, &csm, badOperatorConfig) + err = reconciler.PreChecks(ctx, &csm, badOperatorConfig, "") assert.NotNil(suite.T(), err) // error in Replication csm.Spec.Modules = getReplicaModule() - err = reconciler.PreChecks(ctx, &csm, badOperatorConfig) + err = reconciler.PreChecks(ctx, &csm, badOperatorConfig, "") assert.NotNil(suite.T(), err) // error in Resiliency csm.Spec.Modules = getResiliencyModule() - err = reconciler.PreChecks(ctx, &csm, badOperatorConfig) + err = reconciler.PreChecks(ctx, &csm, badOperatorConfig, "") assert.NotNil(suite.T(), err) // error in Observability csm.Spec.Modules = getObservabilityModule() - err = reconciler.PreChecks(ctx, &csm, badOperatorConfig) + err = reconciler.PreChecks(ctx, &csm, badOperatorConfig, "") assert.NotNil(suite.T(), err) // error unsupported module @@ -1065,7 +1067,7 @@ func (suite *CSMControllerTestSuite) TestCsmPreCheckModuleError() { Enabled: true, }, } - err = reconciler.PreChecks(ctx, &csm, badOperatorConfig) + err = reconciler.PreChecks(ctx, &csm, badOperatorConfig, "") assert.NotNil(suite.T(), err) } @@ -1091,31 +1093,31 @@ func (suite *CSMControllerTestSuite) TestCsmPreCheckModuleUnsupportedVersion() { // error in Authorization csm.Spec.Modules = getAuthModule() csm.Spec.Modules[0].ConfigVersion = "1.0.0" - err = reconciler.PreChecks(ctx, &csm, operatorConfig) + err = reconciler.PreChecks(ctx, &csm, operatorConfig, "") assert.NotNil(suite.T(), err) // error in Authorization Proxy Server csm.Spec.Modules = getAuthProxyServer() csm.Spec.Modules[0].ConfigVersion = "1.0.0" - err = reconciler.PreChecks(ctx, &csm, operatorConfig) + err = reconciler.PreChecks(ctx, &csm, operatorConfig, "") assert.NotNil(suite.T(), err) // error in Replication csm.Spec.Modules = getReplicaModule() csm.Spec.Modules[0].ConfigVersion = "1.0.0" - err = reconciler.PreChecks(ctx, &csm, operatorConfig) + err = reconciler.PreChecks(ctx, &csm, operatorConfig, "") assert.NotNil(suite.T(), err) // error in Resiliency csm.Spec.Modules = getResiliencyModule() csm.Spec.Modules[0].ConfigVersion = "1.0.0" - err = reconciler.PreChecks(ctx, &csm, operatorConfig) + err = reconciler.PreChecks(ctx, &csm, operatorConfig, "") assert.NotNil(suite.T(), err) // error in Observability csm.Spec.Modules = getObservabilityModule() csm.Spec.Modules[0].ConfigVersion = "1.0.0" - err = reconciler.PreChecks(ctx, &csm, operatorConfig) + err = reconciler.PreChecks(ctx, &csm, operatorConfig, "") assert.NotNil(suite.T(), err) // error unsupported module @@ -1125,7 +1127,7 @@ func (suite *CSMControllerTestSuite) TestCsmPreCheckModuleUnsupportedVersion() { Enabled: true, }, } - err = reconciler.PreChecks(ctx, &csm, operatorConfig) + err = reconciler.PreChecks(ctx, &csm, operatorConfig, "") assert.NotNil(suite.T(), err) } diff --git a/pkg/drivers/powerflex.go b/pkg/drivers/powerflex.go index 56d88e4b..6b0e367e 100644 --- a/pkg/drivers/powerflex.go +++ b/pkg/drivers/powerflex.go @@ -347,6 +347,13 @@ func ModifyPowerflexCR(yamlString string, cr csmv1.ContainerStorageModule, fileT return yamlString } +func ExtractZones(ctx context.Context, cr *csmv1.ContainerStorageModule, ct client.Client, namespace string) (map[string]string, error) { + + secretName := cr.Name + "-config" + zonesMapData, err := ExtractZonesFromSecret(ctx, ct, namespace, secretName) + return zonesMapData, err +} + // ExtractZonesFromSecret - Reads the array config secret and returns the zone label information func ExtractZonesFromSecret(ctx context.Context, kube client.Client, namespace string, secret string) (map[string]string, error) { log := logger.GetLogger(ctx) @@ -376,7 +383,7 @@ func ExtractZonesFromSecret(ctx context.Context, kube client.Client, namespace s } err = yaml.Unmarshal(configs, &yamlConfig) if err != nil { - return nil, fmt.Errorf("unable to unmarshal multi-array configuration[%v]", err) + return nil, fmt.Errorf("unable to unmarshal no Zone or Name or LabelKey found multi-array configuration[%v]", err) } for _, configParam := range yamlConfig { diff --git a/tests/shared/common.go b/tests/shared/common.go index fc48d6ae..74b4eecc 100644 --- a/tests/shared/common.go +++ b/tests/shared/common.go @@ -144,6 +144,47 @@ func MakeModule(configVersion string) csmv1.Module { return moduleObj } +// MakeSecret returns a driver pre-req secret array-config +func MakeSecretPowerFlex(name, ns, _ string) *corev1.Secret { + // data := map[string][]byte{ + // "config": []byte("csm"), + // } + // object := metav1.ObjectMeta{Name: name, Namespace: ns} + // secret := &corev1.Secret{Data: data, ObjectMeta: object} + /* + dataWithZone := ` + - username: "admin" + password: "password" + systemID: "2b11bb111111bb1b" + endpoint: "https://127.0.0.2" + skipCertificateValidation: true + mdm: "10.0.0.3,10.0.0.4" + zone: + name: "US-EAST" + labelKey: "zone.csi-vxflexos.dellemc.com" + ` + */ + dataWithoutZone := ` +- username: "admin" + password: "password" + systemID: "2b11bb111111bb1b" + endpoint: "https://127.0.0.2" + skipCertificateValidation: true + mdm: "10.0.0.3,10.0.0.4" +` + + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: ns, + }, + Data: map[string][]byte{ + "config": []byte(dataWithoutZone), + }, + } + return secret +} + // MakeSecret returns a driver pre-req secret array-config func MakeSecret(name, ns, _ string) *corev1.Secret { data := map[string][]byte{ From b7b9198579f0054dae874504517534680244e46b Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Sun, 15 Dec 2024 21:20:37 -0500 Subject: [PATCH 02/20] GetMatchingNodes() using HasLabes() to match on Key rather than key-value pair. ZoneValidation function filled in to continue correct zone validation. Unit Test code updated including infra client List code to match on labels. --- controllers/csm_controller.go | 55 +++++++++++++++++++---- controllers/csm_controller_test.go | 72 ++++++++++++++++++++++++++++-- tests/shared/crclient/client.go | 50 ++++++++++++++++++--- 3 files changed, 158 insertions(+), 19 deletions(-) diff --git a/controllers/csm_controller.go b/controllers/csm_controller.go index 7b9c82ac..fd558b46 100644 --- a/controllers/csm_controller.go +++ b/controllers/csm_controller.go @@ -1529,18 +1529,25 @@ func (r *ContainerStorageModuleReconciler) GetK8sClient() kubernetes.Interface { func (r *ContainerStorageModuleReconciler) GetMatchingNodes(ctx context.Context, labelKey string, labelValue string) (*corev1.NodeList, error) { nodeList := &corev1.NodeList{} opts := []client.ListOption{ - client.MatchingLabels{labelKey: labelValue}, + client.HasLabels{labelKey}, } err := r.List(ctx, nodeList, opts...) return nodeList, err } +// Invalid zoning configurations: +// 1. Some arrays have a zone label A, but one of the arrays has zone label B, or no label +// 2. Array secret has zone label A, but one of the nodes has zone label B, or no label +// 3. Some of the nodes have a zone label, but arrays have no zone labels. +// 4. All of the arrays have a zone label, but nodes have no zone label. func (r *ContainerStorageModuleReconciler) ZoneValidation(ctx context.Context, cr *csmv1.ContainerStorageModule, namespace string) (bool, error) { log := logger.GetLogger(ctx) validZoneConfiguration := true nodeList := &corev1.NodeList{} log.Infof(" nodeList len %d", len(nodeList.Items)) + var numberOfNodes = len(nodeList.Items) + for _, node := range nodeList.Items { log.Infof(" nodeList name %s", node.Name) } @@ -1551,16 +1558,46 @@ func (r *ContainerStorageModuleReconciler) ZoneValidation(ctx context.Context, c } log.Infof("ZoneValidation zones returned from ExtractZones: %v", zones) - // TBD: make sure all zone keys are the same, if not fail - // extract first key from first node - // zoneKeyLabelRow := zones[nodeList[0].name] - // zoneKey := zoneKeyLabelRow[0][0] + // Make sure all zone keys are the same, if not fail + i := 0 + var firstKeyLabel string = "" + for key, value := range zones { + if i == 0 { + firstKeyLabel = key + log.Infof("firstKeyLabel %s\n", firstKeyLabel) + i = i + 1 + continue + } + if key != firstKeyLabel { + log.Infof("mismatch Keys\n") + break + } + log.Infof("Zones Key: %s, Value: %s\n", key, value) + } + // TBD: also check if there any arrays specified in the secret that do not have + // a zone label. this constitutes a zone configuration failure. + // Determine how many arrays are configured and match that with the len(map) + // The labelKey, GetMatchingNodes with labelKey, value="", verify that the list // returned is the same size as the current number of nodes on the cluster - // i.e. all nodes must have this zoning label key. if the number of nodes returned - // does not match the number of nodes on the cluster, then fail, otherwise return - // true - //GetMatchingNodes(ctx, labelKey, labelValue); + // i.e. all nodes must have this zoning label key. if the number of nodes + // returned does not match the number of nodes on the cluster, then fail, + // otherwise return true + if firstKeyLabel != "" { + matchingNodeList, err := r.GetMatchingNodes(ctx, firstKeyLabel, "") + if err != nil { + log.Errorw("Failed to retrieve list of nodes for label", firstKeyLabel) + return validZoneConfiguration, err + } + log.Infof(" number of nodes with this label %d", len(matchingNodeList.Items)) + for _, node := range matchingNodeList.Items { + log.Infof(" matching node found with node name %s", node.Name) + } + if len(matchingNodeList.Items) != numberOfNodes { + validZoneConfiguration = false + log.Errorw("Zone configuration mismatch ", len(matchingNodeList.Items)) + } + } return validZoneConfiguration, err } diff --git a/controllers/csm_controller_test.go b/controllers/csm_controller_test.go index 1a058ad2..ed455c0e 100644 --- a/controllers/csm_controller_test.go +++ b/controllers/csm_controller_test.go @@ -2386,9 +2386,6 @@ func (suite *CSMControllerTestSuite) makeFakeRevProxyCSM(name string, ns string, } func (suite *CSMControllerTestSuite) TestGetNodeLabels() { - // TBD: crclient/client.go needs to be augmented to filter on labels during - // the List return for a viable thorough test. Since this functionality is - // missing, this test is quite elementary as a result. csm := shared.MakeCSM(csmName, suite.namespace, configVersion) csm.Spec.Driver.CSIDriverType = csmv1.PowerScale @@ -2416,12 +2413,19 @@ func (suite *CSMControllerTestSuite) TestGetNodeLabels() { err = suite.fakeClient.Create(ctx, &node) assert.Nil(suite.T(), err) + // create node object, add to fakeclient, reconcile.GetMatchingNodes + node2 := shared.MakeNode("node2", suite.namespace) + // node2.Labels["topology.kubernetes.io/zone"] = "US-EAST" + + err = suite.fakeClient.Create(ctx, &node2) + assert.Nil(suite.T(), err) + nodeList := &corev1.NodeList{} err = suite.fakeClient.List(ctx, nodeList, nil) assert.Nil(suite.T(), err) nodeListMatching, err := reconciler.GetMatchingNodes(ctx, "topology.kubernetes.io/zone", "US-EAST") - ctrl.Log.Info("node list response (1)", "number of nodes is: ", len(nodeListMatching.Items)) + ctrl.Log.Info("node list response expecting (1)", "number of nodes matching is: ", len(nodeListMatching.Items)) // Check the len to be 1 else fail if len(nodeListMatching.Items) != 1 { @@ -2438,3 +2442,63 @@ func (suite *CSMControllerTestSuite) TestGetNodeLabels() { } assert.Nil(suite.T(), err) } + +func (suite *CSMControllerTestSuite) TestZoneValidation() { + + csm := shared.MakeCSM(csmName, suite.namespace, configVersion) + csm.Spec.Driver.CSIDriverType = csmv1.PowerScale + csm.Spec.Driver.Common.Image = "image" + csm.Annotations[configVersionKey] = configVersion + + /* + sec := shared.MakeSecret(csmName+"-creds", suite.namespace, configVersion) + err := suite.fakeClient.Create(ctx, sec) + if err != nil { + panic(err) + } + */ + + csm.ObjectMeta.Finalizers = []string{CSMFinalizerName} + err := suite.fakeClient.Create(ctx, &csm) + if err != nil { + panic(err) + } + + reconciler := suite.createReconciler() + + // create node object, add to fakeclient, reconcile.GetMatchingNodes + node := shared.MakeNode("node1", suite.namespace) + node.Labels["topology.kubernetes.io/zone"] = "US-EAST" + + err = suite.fakeClient.Create(ctx, &node) + assert.Nil(suite.T(), err) + + // create node object, add to fakeclient, reconcile.GetMatchingNodes + node2 := shared.MakeNode("node2", suite.namespace) + // node2.Labels["topology.kubernetes.io/zone"] = "US-EAST" + + err = suite.fakeClient.Create(ctx, &node2) + assert.Nil(suite.T(), err) + + nodeList := &corev1.NodeList{} + err = suite.fakeClient.List(ctx, nodeList, nil) + assert.Nil(suite.T(), err) + + // add secret with NO zone to the namespace + sec := shared.MakeSecretPowerFlex(csmName+"-config", suite.namespace, pFlexConfigVersion) + err = suite.fakeClient.Create(ctx, sec) + if err != nil { + panic(err) + } + + zoneConfigValid, err := reconciler.ZoneValidation(ctx, &csm, suite.namespace) + if err != nil { + panic(err) + } + if zoneConfigValid != true { + // fail + panic(err) + } + + assert.Nil(suite.T(), err) +} diff --git a/tests/shared/crclient/client.go b/tests/shared/crclient/client.go index ee6be344..dcd90bb2 100644 --- a/tests/shared/crclient/client.go +++ b/tests/shared/crclient/client.go @@ -19,6 +19,7 @@ import ( "reflect" "time" + "github.com/dell/csm-operator/pkg/logger" "github.com/dell/csm-operator/tests/shared" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -97,7 +98,9 @@ func (f Client) Get(_ context.Context, key client.ObjectKey, obj client.Object, } // List implements client.Client. -func (f Client) List(ctx context.Context, list client.ObjectList, _ ...client.ListOption) error { +func (f Client) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { + _, log := logger.GetNewContextWithLogger("0") + if f.ErrorInjector != nil { if err := f.ErrorInjector.ShouldFail("List", list); err != nil { return err @@ -107,7 +110,27 @@ func (f Client) List(ctx context.Context, list client.ObjectList, _ ...client.Li case *corev1.PodList: return f.listPodList(l) case *corev1.NodeList: - return f.listNodeList(l) + + var labelValue string = "" + // Initialize ListOptions + listOpts := &client.ListOptions{} + // Apply each ListOption to listOpts + if opts != nil { + for _, opt := range opts { + if opt != nil { + opt.ApplyToList(listOpts) + //log.Infof("\t client.go List 2 opt %v %s\n", opt, opt) + //log.Infof("\t client.go List 2 listOpts %v\n", listOpts) + } + } + } + s := listOpts.LabelSelector + if s != nil { + log.Infof("\t client.go labelValue is non null set to '%s'\n", s.String()) + labelValue = s.String() + } + + return f.listNodeList(l, labelValue, "") case *appsv1.DeploymentList: return f.listDeploymentList(ctx, &appsv1.DeploymentList{}) default: @@ -124,13 +147,28 @@ func (f Client) listPodList(list *corev1.PodList) error { return nil } -func (f Client) listNodeList(list *corev1.NodeList) error { +func (f Client) listNodeList(list *corev1.NodeList, label string, value string) error { + _, log := logger.GetNewContextWithLogger("0") for k, v := range f.Objects { if k.Kind == "Node" { - node, ok := v.(*corev1.Node) - if ok { - list.Items = append(list.Items, *node) + node := *v.(*corev1.Node) + for key, value := range node.ObjectMeta.Labels { + //log.Infof("\tnode key:%v value:%v\n", key, value) + //log.Infof("\t%v \n", client.ListOption.labelKey) + // if key == client.ListOption.labelKey + if label != "" { + if label == key { + log.Infof("\tMatching node found. node key:%v incoming label:%v value:%v\n", + key, label, value) + list.Items = append(list.Items, *v.(*corev1.Node)) + } else { + log.Infof("\tnon-matching node found. node key:%v incoming label:%v\n", key, label) + } + } else { + list.Items = append(list.Items, *v.(*corev1.Node)) + } } + } } return nil From 967ba93498f161e878070044573fbd22dffeb150 Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Tue, 17 Dec 2024 16:22:23 -0500 Subject: [PATCH 03/20] 2 code fixes, unit-test fakeclient fixes and ut augmentation, and unit-test bring up back to 90.0% coverage. --- controllers/csm_controller.go | 51 +++++------- controllers/csm_controller_test.go | 120 ++++++++++++++++++++++------- tests/shared/common.go | 76 +++++++++++++----- tests/shared/crclient/client.go | 27 +++---- 4 files changed, 183 insertions(+), 91 deletions(-) diff --git a/controllers/csm_controller.go b/controllers/csm_controller.go index fd558b46..6a765470 100644 --- a/controllers/csm_controller.go +++ b/controllers/csm_controller.go @@ -1329,13 +1329,10 @@ func (r *ContainerStorageModuleReconciler) PreChecks(ctx context.Context, cr *cs return fmt.Errorf("failed powerflex validation: %v", err) } // zoning initially applies only to pflex - zonesAreValid, err := r.ZoneValidation(ctx, cr, namespace) + err = r.ZoneValidation(ctx, cr, namespace) if err != nil { return fmt.Errorf("error during zone validation: %v", err) } - if zonesAreValid == false { - return fmt.Errorf("failed zone validation.") - } case csmv1.PowerStore: err := drivers.PrecheckPowerStore(ctx, cr, operatorConfig, r.GetClient()) if err != nil { @@ -1526,7 +1523,7 @@ func (r *ContainerStorageModuleReconciler) GetK8sClient() kubernetes.Interface { return r.K8sClient } -func (r *ContainerStorageModuleReconciler) GetMatchingNodes(ctx context.Context, labelKey string, labelValue string) (*corev1.NodeList, error) { +func (r *ContainerStorageModuleReconciler) GetMatchingNodes(ctx context.Context, labelKey string) (*corev1.NodeList, error) { nodeList := &corev1.NodeList{} opts := []client.ListOption{ client.HasLabels{labelKey}, @@ -1541,63 +1538,55 @@ func (r *ContainerStorageModuleReconciler) GetMatchingNodes(ctx context.Context, // 2. Array secret has zone label A, but one of the nodes has zone label B, or no label // 3. Some of the nodes have a zone label, but arrays have no zone labels. // 4. All of the arrays have a zone label, but nodes have no zone label. -func (r *ContainerStorageModuleReconciler) ZoneValidation(ctx context.Context, cr *csmv1.ContainerStorageModule, namespace string) (bool, error) { +func (r *ContainerStorageModuleReconciler) ZoneValidation(ctx context.Context, cr *csmv1.ContainerStorageModule, namespace string) (error) { log := logger.GetLogger(ctx) - validZoneConfiguration := true nodeList := &corev1.NodeList{} - log.Infof(" nodeList len %d", len(nodeList.Items)) - var numberOfNodes = len(nodeList.Items) - for _, node := range nodeList.Items { - log.Infof(" nodeList name %s", node.Name) + err := r.Client.List(ctx, nodeList) + if err != nil { + return fmt.Errorf("error listing nodes %v", err) } + numberOfNodes := len(nodeList.Items) + zones, err := drivers.ExtractZones(ctx, cr, r.Client, namespace) if err != nil { - log.Infof("ZoneValidation failed with error: %v", err) - return false, err + return fmt.Errorf("ZoneValidation failed with error: %v", err) } - log.Infof("ZoneValidation zones returned from ExtractZones: %v", zones) // Make sure all zone keys are the same, if not fail - i := 0 - var firstKeyLabel string = "" - for key, value := range zones { - if i == 0 { + var firstKeyLabel string + for key, _ := range zones { + if firstKeyLabel == "" { firstKeyLabel = key - log.Infof("firstKeyLabel %s\n", firstKeyLabel) - i = i + 1 + //log.Infof("firstKeyLabel %s\n", firstKeyLabel) continue } if key != firstKeyLabel { - log.Infof("mismatch Keys\n") - break + return fmt.Errorf("detected mismatched Keys in zones") } - log.Infof("Zones Key: %s, Value: %s\n", key, value) + //log.Infof("Zones Key: %s, Value: %s\n", key, value) } // TBD: also check if there any arrays specified in the secret that do not have // a zone label. this constitutes a zone configuration failure. // Determine how many arrays are configured and match that with the len(map) - // The labelKey, GetMatchingNodes with labelKey, value="", verify that the list + // The labelKey, GetMatchingNodes with labelKey, verify that the list // returned is the same size as the current number of nodes on the cluster // i.e. all nodes must have this zoning label key. if the number of nodes // returned does not match the number of nodes on the cluster, then fail, // otherwise return true if firstKeyLabel != "" { - matchingNodeList, err := r.GetMatchingNodes(ctx, firstKeyLabel, "") + matchingNodeList, err := r.GetMatchingNodes(ctx, firstKeyLabel) if err != nil { - log.Errorw("Failed to retrieve list of nodes for label", firstKeyLabel) - return validZoneConfiguration, err + return fmt.Errorf("Failed to retrieve list of nodes for label: %s", firstKeyLabel) } - log.Infof(" number of nodes with this label %d", len(matchingNodeList.Items)) for _, node := range matchingNodeList.Items { log.Infof(" matching node found with node name %s", node.Name) } if len(matchingNodeList.Items) != numberOfNodes { - validZoneConfiguration = false - log.Errorw("Zone configuration mismatch ", len(matchingNodeList.Items)) + return fmt.Errorf("zone and node configuration mismatch %d", len(matchingNodeList.Items)) } } - return validZoneConfiguration, err + return err } diff --git a/controllers/csm_controller_test.go b/controllers/csm_controller_test.go index ed455c0e..7078993c 100644 --- a/controllers/csm_controller_test.go +++ b/controllers/csm_controller_test.go @@ -2413,18 +2413,12 @@ func (suite *CSMControllerTestSuite) TestGetNodeLabels() { err = suite.fakeClient.Create(ctx, &node) assert.Nil(suite.T(), err) - // create node object, add to fakeclient, reconcile.GetMatchingNodes node2 := shared.MakeNode("node2", suite.namespace) - // node2.Labels["topology.kubernetes.io/zone"] = "US-EAST" err = suite.fakeClient.Create(ctx, &node2) assert.Nil(suite.T(), err) - nodeList := &corev1.NodeList{} - err = suite.fakeClient.List(ctx, nodeList, nil) - assert.Nil(suite.T(), err) - - nodeListMatching, err := reconciler.GetMatchingNodes(ctx, "topology.kubernetes.io/zone", "US-EAST") + nodeListMatching, err := reconciler.GetMatchingNodes(ctx, "topology.kubernetes.io/zone") ctrl.Log.Info("node list response expecting (1)", "number of nodes matching is: ", len(nodeListMatching.Items)) // Check the len to be 1 else fail @@ -2446,18 +2440,10 @@ func (suite *CSMControllerTestSuite) TestGetNodeLabels() { func (suite *CSMControllerTestSuite) TestZoneValidation() { csm := shared.MakeCSM(csmName, suite.namespace, configVersion) - csm.Spec.Driver.CSIDriverType = csmv1.PowerScale + csm.Spec.Driver.CSIDriverType = csmv1.PowerFlex csm.Spec.Driver.Common.Image = "image" csm.Annotations[configVersionKey] = configVersion - /* - sec := shared.MakeSecret(csmName+"-creds", suite.namespace, configVersion) - err := suite.fakeClient.Create(ctx, sec) - if err != nil { - panic(err) - } - */ - csm.ObjectMeta.Finalizers = []string{CSMFinalizerName} err := suite.fakeClient.Create(ctx, &csm) if err != nil { @@ -2466,24 +2452,17 @@ func (suite *CSMControllerTestSuite) TestZoneValidation() { reconciler := suite.createReconciler() - // create node object, add to fakeclient, reconcile.GetMatchingNodes node := shared.MakeNode("node1", suite.namespace) node.Labels["topology.kubernetes.io/zone"] = "US-EAST" err = suite.fakeClient.Create(ctx, &node) assert.Nil(suite.T(), err) - // create node object, add to fakeclient, reconcile.GetMatchingNodes node2 := shared.MakeNode("node2", suite.namespace) - // node2.Labels["topology.kubernetes.io/zone"] = "US-EAST" err = suite.fakeClient.Create(ctx, &node2) assert.Nil(suite.T(), err) - nodeList := &corev1.NodeList{} - err = suite.fakeClient.List(ctx, nodeList, nil) - assert.Nil(suite.T(), err) - // add secret with NO zone to the namespace sec := shared.MakeSecretPowerFlex(csmName+"-config", suite.namespace, pFlexConfigVersion) err = suite.fakeClient.Create(ctx, sec) @@ -2491,14 +2470,103 @@ func (suite *CSMControllerTestSuite) TestZoneValidation() { panic(err) } - zoneConfigValid, err := reconciler.ZoneValidation(ctx, &csm, suite.namespace) + err = reconciler.ZoneValidation(ctx, &csm, suite.namespace) if err != nil { panic(err) } - if zoneConfigValid != true { - // fail +} + +func (suite *CSMControllerTestSuite) TestZoneValidation2() { + + csm := shared.MakeCSM(csmName, suite.namespace, configVersion) + csm.Spec.Driver.CSIDriverType = csmv1.PowerFlex + csm.Spec.Driver.Common.Image = "image" + csm.Annotations[configVersionKey] = configVersion + + csm.ObjectMeta.Finalizers = []string{CSMFinalizerName} + err := suite.fakeClient.Create(ctx, &csm) + if err != nil { panic(err) } + reconciler := suite.createReconciler() + + node := shared.MakeNode("node1", suite.namespace) + node.Labels["zone.csi-vxflexos.dellemc.com"] = "US-WEST" + err = suite.fakeClient.Create(ctx, &node) + assert.Nil(suite.T(), err) + + node2 := shared.MakeNode("node2", suite.namespace) + node2.Labels["zone.csi-vxflexos.dellemc.com"] = "US-EAST" + err = suite.fakeClient.Create(ctx, &node2) + assert.Nil(suite.T(), err) + + node3 := shared.MakeNode("node3", suite.namespace) + node3.Labels["zone.csi-vxflexos.dellemc.com"] = "US-SOUTH" + err = suite.fakeClient.Create(ctx, &node3) assert.Nil(suite.T(), err) + + + // add secret with zone to the namespace + secretZone := shared.MakeSecretPowerFlexWithZone(csmName+"-config", suite.namespace, pFlexConfigVersion) + err = suite.fakeClient.Create(ctx, secretZone) + if err != nil { + panic(err) + } + + err = reconciler.ZoneValidation(ctx, &csm, suite.namespace) + if err != nil { + panic(err) + } + + // Add node4 that has a different zone label, and zone validate should fail + node4 := shared.MakeNode("node4", suite.namespace) + node4.Labels["my-special-zone-label"] = "mydrzone" + err = suite.fakeClient.Create(ctx, &node4) + assert.Nil(suite.T(), err) + + err = reconciler.ZoneValidation(ctx, &csm, suite.namespace) + if err == nil { + panic(err) + } +} + +func (suite *CSMControllerTestSuite) TestZoneValidation3() { + + csm := shared.MakeCSM(csmName, suite.namespace, configVersion) + csm.Spec.Driver.CSIDriverType = csmv1.PowerFlex + csm.Spec.Driver.Common.Image = "image" + csm.Annotations[configVersionKey] = configVersion + + csm.ObjectMeta.Finalizers = []string{CSMFinalizerName} + err := suite.fakeClient.Create(ctx, &csm) + if err != nil { + panic(err) + } + + reconciler := suite.createReconciler() + + node := shared.MakeNode("node1", suite.namespace) + node.Labels["zone.csi-vxflexos.dellemc.com"] = "US-SOUTH" + + err = suite.fakeClient.Create(ctx, &node) + assert.Nil(suite.T(), err) + + node2 := shared.MakeNode("node2", suite.namespace) + node2.Labels["zone.csi-vxflexos.dellemc.com"] = "US-SOUTH" + + err = suite.fakeClient.Create(ctx, &node2) + assert.Nil(suite.T(), err) + + // add secret with invalid Multi zone to the namespace + sec := shared.MakeSecretPowerFlexMultiZone(csmName+"-config", suite.namespace, pFlexConfigVersion) + err = suite.fakeClient.Create(ctx, sec) + if err != nil { + panic(err) + } + + err = reconciler.ZoneValidation(ctx, &csm, suite.namespace) + if err == nil { + panic(err) + } } diff --git a/tests/shared/common.go b/tests/shared/common.go index 74b4eecc..76a5e212 100644 --- a/tests/shared/common.go +++ b/tests/shared/common.go @@ -144,26 +144,32 @@ func MakeModule(configVersion string) csmv1.Module { return moduleObj } +func MakeSecretPowerFlexWithZone(name, ns, _ string) *corev1.Secret { + dataWithZone := ` +- username: "admin" + password: "password" + systemID: "2b11bb111111bb1b" + endpoint: "https://127.0.0.2" + skipCertificateValidation: true + mdm: "10.0.0.3,10.0.0.4" + zone: + name: "US-EAST" + labelKey: "zone.csi-vxflexos.dellemc.com" +` + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: ns, + }, + Data: map[string][]byte{ + "config": []byte(dataWithZone), + }, + } + return secret +} + // MakeSecret returns a driver pre-req secret array-config func MakeSecretPowerFlex(name, ns, _ string) *corev1.Secret { - // data := map[string][]byte{ - // "config": []byte("csm"), - // } - // object := metav1.ObjectMeta{Name: name, Namespace: ns} - // secret := &corev1.Secret{Data: data, ObjectMeta: object} - /* - dataWithZone := ` - - username: "admin" - password: "password" - systemID: "2b11bb111111bb1b" - endpoint: "https://127.0.0.2" - skipCertificateValidation: true - mdm: "10.0.0.3,10.0.0.4" - zone: - name: "US-EAST" - labelKey: "zone.csi-vxflexos.dellemc.com" - ` - */ dataWithoutZone := ` - username: "admin" password: "password" @@ -185,6 +191,40 @@ func MakeSecretPowerFlex(name, ns, _ string) *corev1.Secret { return secret } +func MakeSecretPowerFlexMultiZone(name, ns, _ string) *corev1.Secret { + dataWithInvalidZone := ` +- username: "admin" + password: "password" + systemID: "2b11bb111111bb1b" + endpoint: "https://127.0.0.2" + skipCertificateValidation: true + mdm: "10.0.0.3,10.0.0.4" + zone: + name: "US-EAST" + labelKey: "zone.csi-vxflexos.dellemc.com" +- username: "admin" + password: "password" + systemID: "2b11bb111111bb1b" + endpoint: "https://127.0.0.2" + skipCertificateValidation: true + mdm: "10.0.0.3,10.0.0.4" + zone: + name: "US-EAST" + labelKey: "myzone.csi-vxflexos.dellemc.com" +` + + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: ns, + }, + Data: map[string][]byte{ + "config": []byte(dataWithInvalidZone), + }, + } + return secret +} + // MakeSecret returns a driver pre-req secret array-config func MakeSecret(name, ns, _ string) *corev1.Secret { data := map[string][]byte{ diff --git a/tests/shared/crclient/client.go b/tests/shared/crclient/client.go index dcd90bb2..6a946a55 100644 --- a/tests/shared/crclient/client.go +++ b/tests/shared/crclient/client.go @@ -147,28 +147,23 @@ func (f Client) listPodList(list *corev1.PodList) error { return nil } -func (f Client) listNodeList(list *corev1.NodeList, label string, value string) error { +func (f Client) listNodeList(list *corev1.NodeList, label string) error { _, log := logger.GetNewContextWithLogger("0") for k, v := range f.Objects { if k.Kind == "Node" { node := *v.(*corev1.Node) - for key, value := range node.ObjectMeta.Labels { - //log.Infof("\tnode key:%v value:%v\n", key, value) - //log.Infof("\t%v \n", client.ListOption.labelKey) - // if key == client.ListOption.labelKey - if label != "" { - if label == key { - log.Infof("\tMatching node found. node key:%v incoming label:%v value:%v\n", - key, label, value) - list.Items = append(list.Items, *v.(*corev1.Node)) - } else { - log.Infof("\tnon-matching node found. node key:%v incoming label:%v\n", key, label) - } - } else { - list.Items = append(list.Items, *v.(*corev1.Node)) + if label != "" { + for key, _ := range node.ObjectMeta.Labels { + if label == key { + log.Infof("\tadding node name:%v to list matching label key \n", node.Name) + list.Items = append(list.Items, *v.(*corev1.Node)) + } else { + log.Infof("\tnon-matching node found. node key:%v incoming label:%v\n", key, label) + } } + } else { + list.Items = append(list.Items, *v.(*corev1.Node)) } - } } return nil From 3573bd1351b88da9039482dccedc105458f8861e Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Tue, 17 Dec 2024 16:43:28 -0500 Subject: [PATCH 04/20] Updated client.go. --- tests/shared/crclient/client.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/shared/crclient/client.go b/tests/shared/crclient/client.go index 6a946a55..a7c9f3de 100644 --- a/tests/shared/crclient/client.go +++ b/tests/shared/crclient/client.go @@ -111,7 +111,7 @@ func (f Client) List(ctx context.Context, list client.ObjectList, opts ...client return f.listPodList(l) case *corev1.NodeList: - var labelValue string = "" + var labelKey string // Initialize ListOptions listOpts := &client.ListOptions{} // Apply each ListOption to listOpts @@ -119,18 +119,15 @@ func (f Client) List(ctx context.Context, list client.ObjectList, opts ...client for _, opt := range opts { if opt != nil { opt.ApplyToList(listOpts) - //log.Infof("\t client.go List 2 opt %v %s\n", opt, opt) - //log.Infof("\t client.go List 2 listOpts %v\n", listOpts) } } } s := listOpts.LabelSelector if s != nil { - log.Infof("\t client.go labelValue is non null set to '%s'\n", s.String()) - labelValue = s.String() + labelKey = s.String() } - return f.listNodeList(l, labelValue, "") + return f.listNodeList(l, labelKey) case *appsv1.DeploymentList: return f.listDeploymentList(ctx, &appsv1.DeploymentList{}) default: From 03f67f47619c10ccb682a4d64737e8ef38c836e1 Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Tue, 17 Dec 2024 16:54:56 -0500 Subject: [PATCH 05/20] Updating client.go. --- tests/shared/crclient/client.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/tests/shared/crclient/client.go b/tests/shared/crclient/client.go index a7c9f3de..fea0c0bc 100644 --- a/tests/shared/crclient/client.go +++ b/tests/shared/crclient/client.go @@ -99,8 +99,6 @@ func (f Client) Get(_ context.Context, key client.ObjectKey, obj client.Object, // List implements client.Client. func (f Client) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { - _, log := logger.GetNewContextWithLogger("0") - if f.ErrorInjector != nil { if err := f.ErrorInjector.ShouldFail("List", list); err != nil { return err @@ -151,15 +149,15 @@ func (f Client) listNodeList(list *corev1.NodeList, label string) error { node := *v.(*corev1.Node) if label != "" { for key, _ := range node.ObjectMeta.Labels { - if label == key { - log.Infof("\tadding node name:%v to list matching label key \n", node.Name) - list.Items = append(list.Items, *v.(*corev1.Node)) - } else { - log.Infof("\tnon-matching node found. node key:%v incoming label:%v\n", key, label) - } + if label == key { + log.Infof("\tadding node name:%v to list matching label key \n", node.Name) + list.Items = append(list.Items, *v.(*corev1.Node)) + } else { + log.Infof("\tnon-matching node found. node key:%v incoming label:%v\n", key, label) + } } } else { - list.Items = append(list.Items, *v.(*corev1.Node)) + list.Items = append(list.Items, *v.(*corev1.Node)) } } } From ee5355caa680f3a33fd4329726955394c728b89b Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Tue, 17 Dec 2024 17:14:18 -0500 Subject: [PATCH 06/20] lint updates. --- controllers/csm_controller.go | 2 +- controllers/csm_controller_test.go | 1 - tests/shared/crclient/client.go | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/controllers/csm_controller.go b/controllers/csm_controller.go index 6a765470..e49ae8a3 100644 --- a/controllers/csm_controller.go +++ b/controllers/csm_controller.go @@ -1538,7 +1538,7 @@ func (r *ContainerStorageModuleReconciler) GetMatchingNodes(ctx context.Context, // 2. Array secret has zone label A, but one of the nodes has zone label B, or no label // 3. Some of the nodes have a zone label, but arrays have no zone labels. // 4. All of the arrays have a zone label, but nodes have no zone label. -func (r *ContainerStorageModuleReconciler) ZoneValidation(ctx context.Context, cr *csmv1.ContainerStorageModule, namespace string) (error) { +func (r *ContainerStorageModuleReconciler) ZoneValidation(ctx context.Context, cr *csmv1.ContainerStorageModule, namespace string) error { log := logger.GetLogger(ctx) nodeList := &corev1.NodeList{} diff --git a/controllers/csm_controller_test.go b/controllers/csm_controller_test.go index 7078993c..e57f9380 100644 --- a/controllers/csm_controller_test.go +++ b/controllers/csm_controller_test.go @@ -2506,7 +2506,6 @@ func (suite *CSMControllerTestSuite) TestZoneValidation2() { err = suite.fakeClient.Create(ctx, &node3) assert.Nil(suite.T(), err) - // add secret with zone to the namespace secretZone := shared.MakeSecretPowerFlexWithZone(csmName+"-config", suite.namespace, pFlexConfigVersion) err = suite.fakeClient.Create(ctx, secretZone) diff --git a/tests/shared/crclient/client.go b/tests/shared/crclient/client.go index fea0c0bc..52cbfe22 100644 --- a/tests/shared/crclient/client.go +++ b/tests/shared/crclient/client.go @@ -148,7 +148,7 @@ func (f Client) listNodeList(list *corev1.NodeList, label string) error { if k.Kind == "Node" { node := *v.(*corev1.Node) if label != "" { - for key, _ := range node.ObjectMeta.Labels { + for key := range node.ObjectMeta.Labels { if label == key { log.Infof("\tadding node name:%v to list matching label key \n", node.Name) list.Items = append(list.Items, *v.(*corev1.Node)) From d238c96858597c398dccf7cc6b27762cb5c1a697 Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Tue, 17 Dec 2024 17:26:41 -0500 Subject: [PATCH 07/20] lint update on csm controller. --- controllers/csm_controller.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/csm_controller.go b/controllers/csm_controller.go index e49ae8a3..9a66a540 100644 --- a/controllers/csm_controller.go +++ b/controllers/csm_controller.go @@ -1555,7 +1555,7 @@ func (r *ContainerStorageModuleReconciler) ZoneValidation(ctx context.Context, c // Make sure all zone keys are the same, if not fail var firstKeyLabel string - for key, _ := range zones { + for key := range zones { if firstKeyLabel == "" { firstKeyLabel = key //log.Infof("firstKeyLabel %s\n", firstKeyLabel) From 580c5da4cd20411b9c0d8627e79bffeb938ce4a2 Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Tue, 17 Dec 2024 17:51:30 -0500 Subject: [PATCH 08/20] fixing gofumpt errors. --- controllers/csm_controller.go | 2 -- controllers/csm_controller_test.go | 8 ++------ pkg/drivers/powerflex.go | 1 - 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/controllers/csm_controller.go b/controllers/csm_controller.go index 9a66a540..cfa4ceec 100644 --- a/controllers/csm_controller.go +++ b/controllers/csm_controller.go @@ -1558,13 +1558,11 @@ func (r *ContainerStorageModuleReconciler) ZoneValidation(ctx context.Context, c for key := range zones { if firstKeyLabel == "" { firstKeyLabel = key - //log.Infof("firstKeyLabel %s\n", firstKeyLabel) continue } if key != firstKeyLabel { return fmt.Errorf("detected mismatched Keys in zones") } - //log.Infof("Zones Key: %s, Value: %s\n", key, value) } // TBD: also check if there any arrays specified in the secret that do not have // a zone label. this constitutes a zone configuration failure. diff --git a/controllers/csm_controller_test.go b/controllers/csm_controller_test.go index e57f9380..16403c05 100644 --- a/controllers/csm_controller_test.go +++ b/controllers/csm_controller_test.go @@ -585,7 +585,7 @@ func (suite *CSMControllerTestSuite) TestCsmDowngrade() { if err != nil { panic(err) } - //sec := shared.MakeSecret(csmName+"-config", suite.namespace, pFlexConfigVersion) + // sec := shared.MakeSecret(csmName+"-config", suite.namespace, pFlexConfigVersion) sec := shared.MakeSecretPowerFlex(csmName+"-config", suite.namespace, pFlexConfigVersion) err = suite.fakeClient.Create(ctx, sec) if err != nil { @@ -654,7 +654,7 @@ func (suite *CSMControllerTestSuite) TestCsmDowngradeSkipVersion() { if err != nil { panic(err) } - //sec := shared.MakeSecret(csmName+"-config", suite.namespace, pFlexConfigVersion) + // sec := shared.MakeSecret(csmName+"-config", suite.namespace, pFlexConfigVersion) sec := shared.MakeSecretPowerFlex(csmName+"-config", suite.namespace, pFlexConfigVersion) err = suite.fakeClient.Create(ctx, sec) if err != nil { @@ -2386,7 +2386,6 @@ func (suite *CSMControllerTestSuite) makeFakeRevProxyCSM(name string, ns string, } func (suite *CSMControllerTestSuite) TestGetNodeLabels() { - csm := shared.MakeCSM(csmName, suite.namespace, configVersion) csm.Spec.Driver.CSIDriverType = csmv1.PowerScale csm.Spec.Driver.Common.Image = "image" @@ -2438,7 +2437,6 @@ func (suite *CSMControllerTestSuite) TestGetNodeLabels() { } func (suite *CSMControllerTestSuite) TestZoneValidation() { - csm := shared.MakeCSM(csmName, suite.namespace, configVersion) csm.Spec.Driver.CSIDriverType = csmv1.PowerFlex csm.Spec.Driver.Common.Image = "image" @@ -2477,7 +2475,6 @@ func (suite *CSMControllerTestSuite) TestZoneValidation() { } func (suite *CSMControllerTestSuite) TestZoneValidation2() { - csm := shared.MakeCSM(csmName, suite.namespace, configVersion) csm.Spec.Driver.CSIDriverType = csmv1.PowerFlex csm.Spec.Driver.Common.Image = "image" @@ -2531,7 +2528,6 @@ func (suite *CSMControllerTestSuite) TestZoneValidation2() { } func (suite *CSMControllerTestSuite) TestZoneValidation3() { - csm := shared.MakeCSM(csmName, suite.namespace, configVersion) csm.Spec.Driver.CSIDriverType = csmv1.PowerFlex csm.Spec.Driver.Common.Image = "image" diff --git a/pkg/drivers/powerflex.go b/pkg/drivers/powerflex.go index 6b0e367e..17d072e2 100644 --- a/pkg/drivers/powerflex.go +++ b/pkg/drivers/powerflex.go @@ -348,7 +348,6 @@ func ModifyPowerflexCR(yamlString string, cr csmv1.ContainerStorageModule, fileT } func ExtractZones(ctx context.Context, cr *csmv1.ContainerStorageModule, ct client.Client, namespace string) (map[string]string, error) { - secretName := cr.Name + "-config" zonesMapData, err := ExtractZonesFromSecret(ctx, ct, namespace, secretName) return zonesMapData, err From 7a2560e9e6e8d075f0bd8d3583c021c9d24f4830 Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Wed, 18 Dec 2024 21:36:38 -0500 Subject: [PATCH 09/20] Removing node label code since we do not need to validate against node labels anymore. Removing the directly associated unit test code as well. Fixing powerflex validate zone code to check that all arrays have zone detail if there is at least one array with zone detail. --- controllers/csm_controller.go | 58 +---------- controllers/csm_controller_test.go | 153 ++--------------------------- pkg/drivers/powerflex.go | 45 ++++++--- 3 files changed, 37 insertions(+), 219 deletions(-) diff --git a/controllers/csm_controller.go b/controllers/csm_controller.go index 0066a309..a2565b48 100644 --- a/controllers/csm_controller.go +++ b/controllers/csm_controller.go @@ -1529,68 +1529,12 @@ func (r *ContainerStorageModuleReconciler) GetK8sClient() kubernetes.Interface { return r.K8sClient } -func (r *ContainerStorageModuleReconciler) GetMatchingNodes(ctx context.Context, labelKey string) (*corev1.NodeList, error) { - nodeList := &corev1.NodeList{} - opts := []client.ListOption{ - client.HasLabels{labelKey}, - } - err := r.List(ctx, nodeList, opts...) - - return nodeList, err -} - -// Invalid zoning configurations: -// 1. Some arrays have a zone label A, but one of the arrays has zone label B, or no label -// 2. Array secret has zone label A, but one of the nodes has zone label B, or no label -// 3. Some of the nodes have a zone label, but arrays have no zone labels. -// 4. All of the arrays have a zone label, but nodes have no zone label. func (r *ContainerStorageModuleReconciler) ZoneValidation(ctx context.Context, cr *csmv1.ContainerStorageModule, namespace string) error { - log := logger.GetLogger(ctx) - nodeList := &corev1.NodeList{} - err := r.Client.List(ctx, nodeList) - if err != nil { - return fmt.Errorf("error listing nodes %v", err) - } - numberOfNodes := len(nodeList.Items) - - zones, err := drivers.ExtractZones(ctx, cr, r.Client, namespace) + err := drivers.ValidateZones(ctx, cr, r.Client, namespace) if err != nil { return fmt.Errorf("ZoneValidation failed with error: %v", err) } - // Make sure all zone keys are the same, if not fail - var firstKeyLabel string - for key := range zones { - if firstKeyLabel == "" { - firstKeyLabel = key - continue - } - if key != firstKeyLabel { - return fmt.Errorf("detected mismatched Keys in zones") - } - } - // TBD: also check if there any arrays specified in the secret that do not have - // a zone label. this constitutes a zone configuration failure. - // Determine how many arrays are configured and match that with the len(map) - - // The labelKey, GetMatchingNodes with labelKey, verify that the list - // returned is the same size as the current number of nodes on the cluster - // i.e. all nodes must have this zoning label key. if the number of nodes - // returned does not match the number of nodes on the cluster, then fail, - // otherwise return true - if firstKeyLabel != "" { - matchingNodeList, err := r.GetMatchingNodes(ctx, firstKeyLabel) - if err != nil { - return fmt.Errorf("Failed to retrieve list of nodes for label: %s", firstKeyLabel) - } - for _, node := range matchingNodeList.Items { - log.Infof(" matching node found with node name %s", node.Name) - } - if len(matchingNodeList.Items) != numberOfNodes { - return fmt.Errorf("zone and node configuration mismatch %d", len(matchingNodeList.Items)) - } - } - return err } diff --git a/controllers/csm_controller_test.go b/controllers/csm_controller_test.go index 701a546c..d43a7c3e 100644 --- a/controllers/csm_controller_test.go +++ b/controllers/csm_controller_test.go @@ -2385,57 +2385,6 @@ func (suite *CSMControllerTestSuite) makeFakeRevProxyCSM(name string, ns string, assert.Nil(suite.T(), err) } -func (suite *CSMControllerTestSuite) TestGetNodeLabels() { - csm := shared.MakeCSM(csmName, suite.namespace, configVersion) - csm.Spec.Driver.CSIDriverType = csmv1.PowerScale - csm.Spec.Driver.Common.Image = "image" - csm.Annotations[configVersionKey] = configVersion - - sec := shared.MakeSecret(csmName+"-creds", suite.namespace, configVersion) - err := suite.fakeClient.Create(ctx, sec) - if err != nil { - panic(err) - } - - csm.ObjectMeta.Finalizers = []string{CSMFinalizerName} - err = suite.fakeClient.Create(ctx, &csm) - if err != nil { - panic(err) - } - - reconciler := suite.createReconciler() - - // create node object, add to fakeclient, reconcile.GetMatchingNodes - node := shared.MakeNode("node1", suite.namespace) - node.Labels["topology.kubernetes.io/zone"] = "US-EAST" - - err = suite.fakeClient.Create(ctx, &node) - assert.Nil(suite.T(), err) - - node2 := shared.MakeNode("node2", suite.namespace) - - err = suite.fakeClient.Create(ctx, &node2) - assert.Nil(suite.T(), err) - - nodeListMatching, err := reconciler.GetMatchingNodes(ctx, "topology.kubernetes.io/zone") - ctrl.Log.Info("node list response expecting (1)", "number of nodes matching is: ", len(nodeListMatching.Items)) - - // Check the len to be 1 else fail - if len(nodeListMatching.Items) != 1 { - ctrl.Log.Error(err, "Unexpected length on node list.", "length", len(nodeListMatching.Items)) - panic(err) - } - - for _, node := range nodeListMatching.Items { - ctrl.Log.Info("Matching node item", "name ", node.ObjectMeta.GetName()) - } - if node.ObjectMeta.GetName() != "node1" { - ctrl.Log.Error(err, "Unmatched label on node.") - panic(err) - } - assert.Nil(suite.T(), err) -} - func (suite *CSMControllerTestSuite) TestZoneValidation() { csm := shared.MakeCSM(csmName, suite.namespace, configVersion) csm.Spec.Driver.CSIDriverType = csmv1.PowerFlex @@ -2444,90 +2393,20 @@ func (suite *CSMControllerTestSuite) TestZoneValidation() { csm.ObjectMeta.Finalizers = []string{CSMFinalizerName} err := suite.fakeClient.Create(ctx, &csm) - if err != nil { - panic(err) - } - - reconciler := suite.createReconciler() - - node := shared.MakeNode("node1", suite.namespace) - node.Labels["topology.kubernetes.io/zone"] = "US-EAST" - - err = suite.fakeClient.Create(ctx, &node) assert.Nil(suite.T(), err) - node2 := shared.MakeNode("node2", suite.namespace) - - err = suite.fakeClient.Create(ctx, &node2) - assert.Nil(suite.T(), err) + reconciler := suite.createReconciler() // add secret with NO zone to the namespace sec := shared.MakeSecretPowerFlex(csmName+"-config", suite.namespace, pFlexConfigVersion) err = suite.fakeClient.Create(ctx, sec) - if err != nil { - panic(err) - } - - err = reconciler.ZoneValidation(ctx, &csm, suite.namespace) - if err != nil { - panic(err) - } -} - -func (suite *CSMControllerTestSuite) TestZoneValidation2() { - csm := shared.MakeCSM(csmName, suite.namespace, configVersion) - csm.Spec.Driver.CSIDriverType = csmv1.PowerFlex - csm.Spec.Driver.Common.Image = "image" - csm.Annotations[configVersionKey] = configVersion - - csm.ObjectMeta.Finalizers = []string{CSMFinalizerName} - err := suite.fakeClient.Create(ctx, &csm) - if err != nil { - panic(err) - } - - reconciler := suite.createReconciler() - - node := shared.MakeNode("node1", suite.namespace) - node.Labels["zone.csi-vxflexos.dellemc.com"] = "US-WEST" - err = suite.fakeClient.Create(ctx, &node) assert.Nil(suite.T(), err) - node2 := shared.MakeNode("node2", suite.namespace) - node2.Labels["zone.csi-vxflexos.dellemc.com"] = "US-EAST" - err = suite.fakeClient.Create(ctx, &node2) - assert.Nil(suite.T(), err) - - node3 := shared.MakeNode("node3", suite.namespace) - node3.Labels["zone.csi-vxflexos.dellemc.com"] = "US-SOUTH" - err = suite.fakeClient.Create(ctx, &node3) - assert.Nil(suite.T(), err) - - // add secret with zone to the namespace - secretZone := shared.MakeSecretPowerFlexWithZone(csmName+"-config", suite.namespace, pFlexConfigVersion) - err = suite.fakeClient.Create(ctx, secretZone) - if err != nil { - panic(err) - } - err = reconciler.ZoneValidation(ctx, &csm, suite.namespace) - if err != nil { - panic(err) - } - - // Add node4 that has a different zone label, and zone validate should fail - node4 := shared.MakeNode("node4", suite.namespace) - node4.Labels["my-special-zone-label"] = "mydrzone" - err = suite.fakeClient.Create(ctx, &node4) assert.Nil(suite.T(), err) - - err = reconciler.ZoneValidation(ctx, &csm, suite.namespace) - if err == nil { - panic(err) - } } -func (suite *CSMControllerTestSuite) TestZoneValidation3() { +func (suite *CSMControllerTestSuite) TestZoneValidation2() { csm := shared.MakeCSM(csmName, suite.namespace, configVersion) csm.Spec.Driver.CSIDriverType = csmv1.PowerFlex csm.Spec.Driver.Common.Image = "image" @@ -2535,33 +2414,15 @@ func (suite *CSMControllerTestSuite) TestZoneValidation3() { csm.ObjectMeta.Finalizers = []string{CSMFinalizerName} err := suite.fakeClient.Create(ctx, &csm) - if err != nil { - panic(err) - } - - reconciler := suite.createReconciler() - - node := shared.MakeNode("node1", suite.namespace) - node.Labels["zone.csi-vxflexos.dellemc.com"] = "US-SOUTH" - - err = suite.fakeClient.Create(ctx, &node) assert.Nil(suite.T(), err) - node2 := shared.MakeNode("node2", suite.namespace) - node2.Labels["zone.csi-vxflexos.dellemc.com"] = "US-SOUTH" + reconciler := suite.createReconciler() - err = suite.fakeClient.Create(ctx, &node2) + // add secret with an invalid multi zone to the namespace + secretZone := shared.MakeSecretPowerFlexMultiZoneInvalid(csmName+"-config", suite.namespace, pFlexConfigVersion) + err = suite.fakeClient.Create(ctx, secretZone) assert.Nil(suite.T(), err) - // add secret with invalid Multi zone to the namespace - sec := shared.MakeSecretPowerFlexMultiZone(csmName+"-config", suite.namespace, pFlexConfigVersion) - err = suite.fakeClient.Create(ctx, sec) - if err != nil { - panic(err) - } - err = reconciler.ZoneValidation(ctx, &csm, suite.namespace) - if err == nil { - panic(err) - } + assert.NotNil(suite.T(), err) } diff --git a/pkg/drivers/powerflex.go b/pkg/drivers/powerflex.go index 55784bbe..aaaebd56 100644 --- a/pkg/drivers/powerflex.go +++ b/pkg/drivers/powerflex.go @@ -347,25 +347,25 @@ func ModifyPowerflexCR(yamlString string, cr csmv1.ContainerStorageModule, fileT return yamlString } -func ExtractZones(ctx context.Context, cr *csmv1.ContainerStorageModule, ct client.Client, namespace string) (map[string]string, error) { +func ValidateZones(ctx context.Context, cr *csmv1.ContainerStorageModule, ct client.Client, namespace string) error { secretName := cr.Name + "-config" - zonesMapData, err := ExtractZonesFromSecret(ctx, ct, namespace, secretName) - return zonesMapData, err + err := ValidateZonesInSecret(ctx, ct, cr.Namespace, secretName) + return err } -// ExtractZonesFromSecret - Reads the array config secret and returns the zone label information -func ExtractZonesFromSecret(ctx context.Context, kube client.Client, namespace string, secret string) (map[string]string, error) { +func ValidateZonesInSecret(ctx context.Context, kube client.Client, namespace string, secret string) error { log := logger.GetLogger(ctx) arraySecret, err := utils.GetSecret(ctx, secret, namespace, kube) if err != nil { - return nil, fmt.Errorf("reading secret [%s] error [%s]", secret, err) + return fmt.Errorf("reading secret [%s] error [%s]", secret, err) } type StorageArrayConfig struct { - SystemID string `json:"systemId"` + SystemID string `json:"systemID"` Zone struct { - Name string `json:"name"` + Name string `json:"name"` + LabelKey string `json:"labelKey"` } `json:"zone"` } @@ -377,28 +377,41 @@ func ExtractZonesFromSecret(ctx context.Context, kube client.Client, namespace s yamlConfig := make([]StorageArrayConfig, 0) configs, err := yaml.JSONToYAML(configBytes) if err != nil { - return nil, fmt.Errorf("unable to parse multi-array configuration[%v]", err) + return fmt.Errorf("unable to parse multi-array configuration %v", err) } err = yaml.Unmarshal(configs, &yamlConfig) if err != nil { - return nil, fmt.Errorf("unable to unmarshal no Zone or Name or LabelKey found multi-array configuration[%v]", err) + return fmt.Errorf("unable to unmarshal multi-array configuration %v", err) } + var labelKey string + var numArrays, numArraysWithZone int + numArrays = len(yamlConfig) for _, configParam := range yamlConfig { if configParam.SystemID == "" { - return nil, fmt.Errorf("invalid value for SystemID") + return fmt.Errorf("invalid value for SystemID") + } + if labelKey == "" { + labelKey = configParam.Zone.LabelKey + } else { + if labelKey != configParam.Zone.LabelKey { + return fmt.Errorf("labelKey not consistent across all arrays") + } } if configParam.Zone.Name != "" { + numArraysWithZone++ zonesMapData[configParam.SystemID] = configParam.Zone.Name log.Infof("Zoning information configured for systemID %s: %v ", configParam.SystemID, zonesMapData) - } else { - log.Info("Zoning information not found in the array config. Continue with topology-unaware driver installation mode") - return zonesMapData, nil } } + if numArraysWithZone > 0 && numArrays != numArraysWithZone { + return fmt.Errorf("not all arrays have zoning configured. Check the array info secret, zone key should be the same for all arrays.") + } else if numArraysWithZone == 0 { + log.Info("Zoning information not found in the array config. Continue with topology-unaware driver installation mode") + } } else { - return nil, fmt.Errorf("Array details are not provided in vxflexos-config secret") + return fmt.Errorf("array details are not provided in vxflexos-config secret") } - return zonesMapData, nil + return nil } From cfb6a41fef7aec1ddbb7991b649b198a1b9bf002 Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Wed, 18 Dec 2024 21:51:52 -0500 Subject: [PATCH 10/20] Updates to infra test code. --- pkg/drivers/powerflex_test.go | 34 +++++++++++++++++++++++++++++++-- tests/shared/common.go | 5 +---- tests/shared/crclient/client.go | 29 ++++++++++++---------------- 3 files changed, 45 insertions(+), 23 deletions(-) diff --git a/pkg/drivers/powerflex_test.go b/pkg/drivers/powerflex_test.go index 03f0fade..162f5cd2 100644 --- a/pkg/drivers/powerflex_test.go +++ b/pkg/drivers/powerflex_test.go @@ -240,6 +240,23 @@ func TestExtractZonesFromSecret(t *testing.T) { zone: name: "ZONE-2" labelKey: "zone.csi-vxflexos.dellemc.com" +` + zoneDataWithMultiArraySomeZone := ` +- username: "admin" + password: "password" + systemID: "2b11bb111111bb1b" + endpoint: "https://127.0.0.2" + skipCertificateValidation: true + mdm: "10.0.0.3,10.0.0.4" +- username: "admin" + password: "password" + systemID: "1a99aa999999aa9a" + endpoint: "https://127.0.0.1" + skipCertificateValidation: true + mdm: "10.0.0.5,10.0.0.6" + zone: + name: "ZONE-2" + labelKey: "zone.csi-vxflexos.dellemc.com" ` dataWithoutZone := ` - username: "admin" @@ -279,6 +296,19 @@ func TestExtractZonesFromSecret(t *testing.T) { client := fake.NewClientBuilder().WithObjects(secret).Build() return client, map[string]string{"2b11bb111111bb1b": "ZONE-1", "1a99aa999999aa9a": "ZONE-2"}, "vxflexos-config", false }, + "fail multi array but only some zone": func() (client.WithWatch, map[string]string, string, bool) { + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "vxflexos-config", + Namespace: "vxflexos", + }, + Data: map[string][]byte{ + "config": []byte(zoneDataWithMultiArraySomeZone), + }, + } + client := fake.NewClientBuilder().WithObjects(secret).Build() + return client, map[string]string{"2b11bb111111bb1b": "ZONE-1", "1a99aa999999aa9a": "ZONE-2"}, "vxflexos-config", true + }, "success no zone": func() (client.WithWatch, map[string]string, string, bool) { secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ @@ -344,12 +374,12 @@ func TestExtractZonesFromSecret(t *testing.T) { for name, tc := range tests { t.Run(name, func(t *testing.T) { client, wantZones, secret, wantErr := tc() - zones, err := ExtractZonesFromSecret(ctx, client, "vxflexos", secret) + err := ValidateZonesInSecret(ctx, client, "vxflexos", secret) if wantErr { assert.NotNil(t, err) } else { assert.Nil(t, err) - assert.Equal(t, wantZones, zones) + _ = wantZones } }) } diff --git a/tests/shared/common.go b/tests/shared/common.go index 76a5e212..6db741c7 100644 --- a/tests/shared/common.go +++ b/tests/shared/common.go @@ -191,7 +191,7 @@ func MakeSecretPowerFlex(name, ns, _ string) *corev1.Secret { return secret } -func MakeSecretPowerFlexMultiZone(name, ns, _ string) *corev1.Secret { +func MakeSecretPowerFlexMultiZoneInvalid(name, ns, _ string) *corev1.Secret { dataWithInvalidZone := ` - username: "admin" password: "password" @@ -199,9 +199,6 @@ func MakeSecretPowerFlexMultiZone(name, ns, _ string) *corev1.Secret { endpoint: "https://127.0.0.2" skipCertificateValidation: true mdm: "10.0.0.3,10.0.0.4" - zone: - name: "US-EAST" - labelKey: "zone.csi-vxflexos.dellemc.com" - username: "admin" password: "password" systemID: "2b11bb111111bb1b" diff --git a/tests/shared/crclient/client.go b/tests/shared/crclient/client.go index 52cbfe22..b9cab262 100644 --- a/tests/shared/crclient/client.go +++ b/tests/shared/crclient/client.go @@ -19,7 +19,6 @@ import ( "reflect" "time" - "github.com/dell/csm-operator/pkg/logger" "github.com/dell/csm-operator/tests/shared" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -113,11 +112,9 @@ func (f Client) List(ctx context.Context, list client.ObjectList, opts ...client // Initialize ListOptions listOpts := &client.ListOptions{} // Apply each ListOption to listOpts - if opts != nil { - for _, opt := range opts { - if opt != nil { - opt.ApplyToList(listOpts) - } + for _, opt := range opts { + if opt != nil { + opt.ApplyToList(listOpts) } } s := listOpts.LabelSelector @@ -143,21 +140,19 @@ func (f Client) listPodList(list *corev1.PodList) error { } func (f Client) listNodeList(list *corev1.NodeList, label string) error { - _, log := logger.GetNewContextWithLogger("0") for k, v := range f.Objects { if k.Kind == "Node" { - node := *v.(*corev1.Node) - if label != "" { - for key := range node.ObjectMeta.Labels { - if label == key { - log.Infof("\tadding node name:%v to list matching label key \n", node.Name) - list.Items = append(list.Items, *v.(*corev1.Node)) - } else { - log.Infof("\tnon-matching node found. node key:%v incoming label:%v\n", key, label) + node, ok := v.(*corev1.Node) + if ok { + if label != "" { + for key := range (*node).ObjectMeta.Labels { + if label == key { + list.Items = append(list.Items, *node) + } } + } else { + list.Items = append(list.Items, *node) } - } else { - list.Items = append(list.Items, *v.(*corev1.Node)) } } } From fee6efcdf2d644d65bb023f89807da4a9806a8a0 Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Wed, 18 Dec 2024 22:12:18 -0500 Subject: [PATCH 11/20] Removing redundant namespace param. --- controllers/csm_controller.go | 6 +++--- pkg/drivers/powerflex.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/controllers/csm_controller.go b/controllers/csm_controller.go index a2565b48..c563e156 100644 --- a/controllers/csm_controller.go +++ b/controllers/csm_controller.go @@ -1335,7 +1335,7 @@ func (r *ContainerStorageModuleReconciler) PreChecks(ctx context.Context, cr *cs return fmt.Errorf("failed powerflex validation: %v", err) } // zoning initially applies only to pflex - err = r.ZoneValidation(ctx, cr, namespace) + err = r.ZoneValidation(ctx, cr) if err != nil { return fmt.Errorf("error during zone validation: %v", err) } @@ -1529,9 +1529,9 @@ func (r *ContainerStorageModuleReconciler) GetK8sClient() kubernetes.Interface { return r.K8sClient } -func (r *ContainerStorageModuleReconciler) ZoneValidation(ctx context.Context, cr *csmv1.ContainerStorageModule, namespace string) error { +func (r *ContainerStorageModuleReconciler) ZoneValidation(ctx context.Context, cr *csmv1.ContainerStorageModule) error { - err := drivers.ValidateZones(ctx, cr, r.Client, namespace) + err := drivers.ValidateZones(ctx, cr, r.Client) if err != nil { return fmt.Errorf("ZoneValidation failed with error: %v", err) } diff --git a/pkg/drivers/powerflex.go b/pkg/drivers/powerflex.go index aaaebd56..5bf41482 100644 --- a/pkg/drivers/powerflex.go +++ b/pkg/drivers/powerflex.go @@ -347,7 +347,7 @@ func ModifyPowerflexCR(yamlString string, cr csmv1.ContainerStorageModule, fileT return yamlString } -func ValidateZones(ctx context.Context, cr *csmv1.ContainerStorageModule, ct client.Client, namespace string) error { +func ValidateZones(ctx context.Context, cr *csmv1.ContainerStorageModule, ct client.Client) error { secretName := cr.Name + "-config" err := ValidateZonesInSecret(ctx, ct, cr.Namespace, secretName) return err From 03db965ecf5308177581047a7c0a2bdb81b3ae98 Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Wed, 18 Dec 2024 22:24:14 -0500 Subject: [PATCH 12/20] Remove namespace param from prechecks and callers. --- controllers/csm_controller.go | 4 ++-- controllers/csm_controller_test.go | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/controllers/csm_controller.go b/controllers/csm_controller.go index c563e156..56014b50 100644 --- a/controllers/csm_controller.go +++ b/controllers/csm_controller.go @@ -284,7 +284,7 @@ func (r *ContainerStorageModuleReconciler) Reconcile(_ context.Context, req ctrl } // perform prechecks - err = r.PreChecks(ctx, csm, *operatorConfig, req.Namespace) + err = r.PreChecks(ctx, csm, *operatorConfig) if err != nil { csm.GetCSMStatus().State = constants.InvalidConfig r.EventRecorder.Event(csm, corev1.EventTypeWarning, csmv1.EventUpdated, fmt.Sprintf("Failed Prechecks: %s", err)) @@ -1320,7 +1320,7 @@ func (r *ContainerStorageModuleReconciler) removeModule(ctx context.Context, ins } // PreChecks - validate input values -func (r *ContainerStorageModuleReconciler) PreChecks(ctx context.Context, cr *csmv1.ContainerStorageModule, operatorConfig utils.OperatorConfig, namespace string) error { +func (r *ContainerStorageModuleReconciler) PreChecks(ctx context.Context, cr *csmv1.ContainerStorageModule, operatorConfig utils.OperatorConfig) error { log := logger.GetLogger(ctx) // Check drivers switch cr.Spec.Driver.CSIDriverType { diff --git a/controllers/csm_controller_test.go b/controllers/csm_controller_test.go index d43a7c3e..7893787c 100644 --- a/controllers/csm_controller_test.go +++ b/controllers/csm_controller_test.go @@ -1032,32 +1032,32 @@ func (suite *CSMControllerTestSuite) TestCsmPreCheckModuleError() { // error in Authorization csm.Spec.Modules = getAuthModule() - err = reconciler.PreChecks(ctx, &csm, badOperatorConfig, "") + err = reconciler.PreChecks(ctx, &csm, badOperatorConfig) assert.NotNil(suite.T(), err) // error in Authorization Proxy Server csm.Spec.Modules = getAuthProxyServer() - err = reconciler.PreChecks(ctx, &csm, badOperatorConfig, "") + err = reconciler.PreChecks(ctx, &csm, badOperatorConfig) assert.NotNil(suite.T(), err) // error in App-Mobility csm.Spec.Modules = getAppMob() - err = reconciler.PreChecks(ctx, &csm, badOperatorConfig, "") + err = reconciler.PreChecks(ctx, &csm, badOperatorConfig) assert.NotNil(suite.T(), err) // error in Replication csm.Spec.Modules = getReplicaModule() - err = reconciler.PreChecks(ctx, &csm, badOperatorConfig, "") + err = reconciler.PreChecks(ctx, &csm, badOperatorConfig) assert.NotNil(suite.T(), err) // error in Resiliency csm.Spec.Modules = getResiliencyModule() - err = reconciler.PreChecks(ctx, &csm, badOperatorConfig, "") + err = reconciler.PreChecks(ctx, &csm, badOperatorConfig) assert.NotNil(suite.T(), err) // error in Observability csm.Spec.Modules = getObservabilityModule() - err = reconciler.PreChecks(ctx, &csm, badOperatorConfig, "") + err = reconciler.PreChecks(ctx, &csm, badOperatorConfig) assert.NotNil(suite.T(), err) // error unsupported module @@ -1067,7 +1067,7 @@ func (suite *CSMControllerTestSuite) TestCsmPreCheckModuleError() { Enabled: true, }, } - err = reconciler.PreChecks(ctx, &csm, badOperatorConfig, "") + err = reconciler.PreChecks(ctx, &csm, badOperatorConfig) assert.NotNil(suite.T(), err) } @@ -1093,31 +1093,31 @@ func (suite *CSMControllerTestSuite) TestCsmPreCheckModuleUnsupportedVersion() { // error in Authorization csm.Spec.Modules = getAuthModule() csm.Spec.Modules[0].ConfigVersion = "1.0.0" - err = reconciler.PreChecks(ctx, &csm, operatorConfig, "") + err = reconciler.PreChecks(ctx, &csm, operatorConfig) assert.NotNil(suite.T(), err) // error in Authorization Proxy Server csm.Spec.Modules = getAuthProxyServer() csm.Spec.Modules[0].ConfigVersion = "1.0.0" - err = reconciler.PreChecks(ctx, &csm, operatorConfig, "") + err = reconciler.PreChecks(ctx, &csm, operatorConfig) assert.NotNil(suite.T(), err) // error in Replication csm.Spec.Modules = getReplicaModule() csm.Spec.Modules[0].ConfigVersion = "1.0.0" - err = reconciler.PreChecks(ctx, &csm, operatorConfig, "") + err = reconciler.PreChecks(ctx, &csm, operatorConfig) assert.NotNil(suite.T(), err) // error in Resiliency csm.Spec.Modules = getResiliencyModule() csm.Spec.Modules[0].ConfigVersion = "1.0.0" - err = reconciler.PreChecks(ctx, &csm, operatorConfig, "") + err = reconciler.PreChecks(ctx, &csm, operatorConfig) assert.NotNil(suite.T(), err) // error in Observability csm.Spec.Modules = getObservabilityModule() csm.Spec.Modules[0].ConfigVersion = "1.0.0" - err = reconciler.PreChecks(ctx, &csm, operatorConfig, "") + err = reconciler.PreChecks(ctx, &csm, operatorConfig) assert.NotNil(suite.T(), err) // error unsupported module @@ -1127,7 +1127,7 @@ func (suite *CSMControllerTestSuite) TestCsmPreCheckModuleUnsupportedVersion() { Enabled: true, }, } - err = reconciler.PreChecks(ctx, &csm, operatorConfig, "") + err = reconciler.PreChecks(ctx, &csm, operatorConfig) assert.NotNil(suite.T(), err) } From 3529b41cf9c758f4a438ca089af19822837e2776 Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Wed, 18 Dec 2024 22:32:07 -0500 Subject: [PATCH 13/20] Removing namespace param from Precheck callers in test code. --- controllers/csm_controller_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/csm_controller_test.go b/controllers/csm_controller_test.go index 7893787c..ff144b0d 100644 --- a/controllers/csm_controller_test.go +++ b/controllers/csm_controller_test.go @@ -2402,7 +2402,7 @@ func (suite *CSMControllerTestSuite) TestZoneValidation() { err = suite.fakeClient.Create(ctx, sec) assert.Nil(suite.T(), err) - err = reconciler.ZoneValidation(ctx, &csm, suite.namespace) + err = reconciler.ZoneValidation(ctx, &csm) assert.Nil(suite.T(), err) } @@ -2423,6 +2423,6 @@ func (suite *CSMControllerTestSuite) TestZoneValidation2() { err = suite.fakeClient.Create(ctx, secretZone) assert.Nil(suite.T(), err) - err = reconciler.ZoneValidation(ctx, &csm, suite.namespace) + err = reconciler.ZoneValidation(ctx, &csm) assert.NotNil(suite.T(), err) } From aa2da54803a3f2d34d5ff68a892d087f3afd186d Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Wed, 18 Dec 2024 22:39:55 -0500 Subject: [PATCH 14/20] fix golang lint error. --- pkg/drivers/powerflex.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/drivers/powerflex.go b/pkg/drivers/powerflex.go index 5bf41482..88de486d 100644 --- a/pkg/drivers/powerflex.go +++ b/pkg/drivers/powerflex.go @@ -405,7 +405,7 @@ func ValidateZonesInSecret(ctx context.Context, kube client.Client, namespace st } } if numArraysWithZone > 0 && numArrays != numArraysWithZone { - return fmt.Errorf("not all arrays have zoning configured. Check the array info secret, zone key should be the same for all arrays.") + return fmt.Errorf("not all arrays have zoning configured. Check the array info secret, zone key should be the same for all arrays") } else if numArraysWithZone == 0 { log.Info("Zoning information not found in the array config. Continue with topology-unaware driver installation mode") } From 326523d22ccf4573acf5bdd9a84ff9111527a7f5 Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Wed, 18 Dec 2024 22:44:30 -0500 Subject: [PATCH 15/20] gofumpt file. --- controllers/csm_controller.go | 1 - 1 file changed, 1 deletion(-) diff --git a/controllers/csm_controller.go b/controllers/csm_controller.go index 56014b50..7b812732 100644 --- a/controllers/csm_controller.go +++ b/controllers/csm_controller.go @@ -1530,7 +1530,6 @@ func (r *ContainerStorageModuleReconciler) GetK8sClient() kubernetes.Interface { } func (r *ContainerStorageModuleReconciler) ZoneValidation(ctx context.Context, cr *csmv1.ContainerStorageModule) error { - err := drivers.ValidateZones(ctx, cr, r.Client) if err != nil { return fmt.Errorf("ZoneValidation failed with error: %v", err) From af9f31a83d64768fb3e1a927a722a99dab182b1a Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Thu, 19 Dec 2024 09:56:23 -0500 Subject: [PATCH 16/20] Addressing review comments. --- controllers/csm_controller.go | 3 ++- controllers/csm_controller_test.go | 2 -- pkg/drivers/powerflex.go | 2 ++ tests/shared/common.go | 4 +++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/controllers/csm_controller.go b/controllers/csm_controller.go index 7b812732..02e68cca 100644 --- a/controllers/csm_controller.go +++ b/controllers/csm_controller.go @@ -1529,10 +1529,11 @@ func (r *ContainerStorageModuleReconciler) GetK8sClient() kubernetes.Interface { return r.K8sClient } +// ZoneValidation - If zones are configured performs validation and returns an error if the zone validation fails func (r *ContainerStorageModuleReconciler) ZoneValidation(ctx context.Context, cr *csmv1.ContainerStorageModule) error { err := drivers.ValidateZones(ctx, cr, r.Client) if err != nil { - return fmt.Errorf("ZoneValidation failed with error: %v", err) + return fmt.Errorf("zone validation failed with error: %v", err) } return err diff --git a/controllers/csm_controller_test.go b/controllers/csm_controller_test.go index ff144b0d..ca1ceda0 100644 --- a/controllers/csm_controller_test.go +++ b/controllers/csm_controller_test.go @@ -585,7 +585,6 @@ func (suite *CSMControllerTestSuite) TestCsmDowngrade() { if err != nil { panic(err) } - // sec := shared.MakeSecret(csmName+"-config", suite.namespace, pFlexConfigVersion) sec := shared.MakeSecretPowerFlex(csmName+"-config", suite.namespace, pFlexConfigVersion) err = suite.fakeClient.Create(ctx, sec) if err != nil { @@ -654,7 +653,6 @@ func (suite *CSMControllerTestSuite) TestCsmDowngradeSkipVersion() { if err != nil { panic(err) } - // sec := shared.MakeSecret(csmName+"-config", suite.namespace, pFlexConfigVersion) sec := shared.MakeSecretPowerFlex(csmName+"-config", suite.namespace, pFlexConfigVersion) err = suite.fakeClient.Create(ctx, sec) if err != nil { diff --git a/pkg/drivers/powerflex.go b/pkg/drivers/powerflex.go index 88de486d..cb28d7b5 100644 --- a/pkg/drivers/powerflex.go +++ b/pkg/drivers/powerflex.go @@ -347,12 +347,14 @@ func ModifyPowerflexCR(yamlString string, cr csmv1.ContainerStorageModule, fileT return yamlString } +// ValidateZones - zone validation for topology aware clusters func ValidateZones(ctx context.Context, cr *csmv1.ContainerStorageModule, ct client.Client) error { secretName := cr.Name + "-config" err := ValidateZonesInSecret(ctx, ct, cr.Namespace, secretName) return err } +// ValidateZonesInSecret - inspects incoming secret for zone validity func ValidateZonesInSecret(ctx context.Context, kube client.Client, namespace string, secret string) error { log := logger.GetLogger(ctx) diff --git a/tests/shared/common.go b/tests/shared/common.go index 6db741c7..f73b34d0 100644 --- a/tests/shared/common.go +++ b/tests/shared/common.go @@ -144,6 +144,7 @@ func MakeModule(configVersion string) csmv1.Module { return moduleObj } +// MakeSecretPowerFlexWithZone returns a driver pre-req secret with zoning specified func MakeSecretPowerFlexWithZone(name, ns, _ string) *corev1.Secret { dataWithZone := ` - username: "admin" @@ -168,7 +169,7 @@ func MakeSecretPowerFlexWithZone(name, ns, _ string) *corev1.Secret { return secret } -// MakeSecret returns a driver pre-req secret array-config +// MakeSecretPowerFlex returns a pflex driver pre-req secret func MakeSecretPowerFlex(name, ns, _ string) *corev1.Secret { dataWithoutZone := ` - username: "admin" @@ -191,6 +192,7 @@ func MakeSecretPowerFlex(name, ns, _ string) *corev1.Secret { return secret } +// MakeSecretPowerFlexMultiZoneInvalid returns a pflex driver pre-req secret with invalid zone config func MakeSecretPowerFlexMultiZoneInvalid(name, ns, _ string) *corev1.Secret { dataWithInvalidZone := ` - username: "admin" From 5779f0d89442be613d02392d4f7c664fe8c6c718 Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Thu, 19 Dec 2024 17:32:11 -0500 Subject: [PATCH 17/20] Changed validation code to handle corner cases in zone struct where labelValue or Name are either not specified or are empty values. Cleaned up test code and added test cases for these scenarios. --- pkg/drivers/powerflex.go | 51 ++++++---- pkg/drivers/powerflex_test.go | 182 ++++++++++++++++++++++++++++++---- 2 files changed, 196 insertions(+), 37 deletions(-) diff --git a/pkg/drivers/powerflex.go b/pkg/drivers/powerflex.go index cb28d7b5..44b9e289 100644 --- a/pkg/drivers/powerflex.go +++ b/pkg/drivers/powerflex.go @@ -16,6 +16,7 @@ import ( "context" "fmt" "os" + "reflect" "regexp" "strings" @@ -360,30 +361,31 @@ func ValidateZonesInSecret(ctx context.Context, kube client.Client, namespace st arraySecret, err := utils.GetSecret(ctx, secret, namespace, kube) if err != nil { - return fmt.Errorf("reading secret [%s] error [%s]", secret, err) + return fmt.Errorf("reading secret [%s] error %v", secret, err) + } + + type Zone struct { + Name string `json:"name,omitempty"` + LabelKey string `json:"labelKey,omitempty"` } type StorageArrayConfig struct { SystemID string `json:"systemID"` - Zone struct { - Name string `json:"name"` - LabelKey string `json:"labelKey"` - } `json:"zone"` + Zone Zone `json:"zone,omitempty"` } data := arraySecret.Data configBytes := data["config"] - zonesMapData := make(map[string]string) if string(configBytes) != "" { yamlConfig := make([]StorageArrayConfig, 0) configs, err := yaml.JSONToYAML(configBytes) if err != nil { - return fmt.Errorf("unable to parse multi-array configuration %v", err) + return fmt.Errorf("malformed json in array secret - unable to parse multi-array configuration %v", err) } err = yaml.Unmarshal(configs, &yamlConfig) if err != nil { - return fmt.Errorf("unable to unmarshal multi-array configuration %v", err) + return fmt.Errorf("unable to unmarshal array secret %v", err) } var labelKey string @@ -393,26 +395,39 @@ func ValidateZonesInSecret(ctx context.Context, kube client.Client, namespace st if configParam.SystemID == "" { return fmt.Errorf("invalid value for SystemID") } - if labelKey == "" { - labelKey = configParam.Zone.LabelKey + if reflect.DeepEqual(configParam.Zone, Zone{}) { + log.Infof("Zone is not specified for SystemID:", configParam.SystemID) } else { - if labelKey != configParam.Zone.LabelKey { - return fmt.Errorf("labelKey not consistent across all arrays") + log.Infof("Zone is specified for SystemID:", configParam.SystemID) + if configParam.Zone.LabelKey == "" { + return fmt.Errorf("Zone LabelKey is empty or not specified for SystemID: %s", + configParam.SystemID) + } + + if labelKey == "" { + labelKey = configParam.Zone.LabelKey + } else { + if labelKey != configParam.Zone.LabelKey { + return fmt.Errorf("labelKey is not consistent across all arrays in secret") + } + } + + if configParam.Zone.Name == "" { + return fmt.Errorf("Zone name is empty or not specified for SystemID: %s", + configParam.SystemID) } - } - if configParam.Zone.Name != "" { numArraysWithZone++ - zonesMapData[configParam.SystemID] = configParam.Zone.Name - log.Infof("Zoning information configured for systemID %s: %v ", configParam.SystemID, zonesMapData) } } + + log.Infof("found %d arrays zoning on %d", numArrays, numArraysWithZone) if numArraysWithZone > 0 && numArrays != numArraysWithZone { return fmt.Errorf("not all arrays have zoning configured. Check the array info secret, zone key should be the same for all arrays") } else if numArraysWithZone == 0 { - log.Info("Zoning information not found in the array config. Continue with topology-unaware driver installation mode") + log.Info("Zoning information not found in the array secret. Continue with topology-unaware driver installation mode") } } else { - return fmt.Errorf("array details are not provided in vxflexos-config secret") + return fmt.Errorf("array details are not provided in secret") } return nil diff --git a/pkg/drivers/powerflex_test.go b/pkg/drivers/powerflex_test.go index 162f5cd2..6deb8ddd 100644 --- a/pkg/drivers/powerflex_test.go +++ b/pkg/drivers/powerflex_test.go @@ -257,6 +257,35 @@ func TestExtractZonesFromSecret(t *testing.T) { zone: name: "ZONE-2" labelKey: "zone.csi-vxflexos.dellemc.com" +` + zoneDataWithMultiArraySomeZone2 := ` +- username: "admin" + password: "password" + systemID: "2b11bb111111bb1b" + endpoint: "https://127.0.0.2" + skipCertificateValidation: true + mdm: "10.0.0.3,10.0.0.4" +- username: "admin" + password: "password" + systemID: "1a99aa999999aa9a" + endpoint: "https://127.0.0.1" + skipCertificateValidation: true + mdm: "10.0.0.5,10.0.0.6" +- username: "admin" + password: "password" + systemID: "1a99aa999999aa9a" + endpoint: "https://127.0.0.1" + skipCertificateValidation: true + mdm: "10.0.0.5,10.0.0.6" + zone: + name: "ZONE-2" + labelKey: "zone.csi-vxflexos.dellemc.com" +- username: "admin" + password: "password" + systemID: "1a99aa999999aa9a" + endpoint: "https://127.0.0.1" + skipCertificateValidation: true + mdm: "10.0.0.5,10.0.0.6" ` dataWithoutZone := ` - username: "admin" @@ -266,9 +295,69 @@ func TestExtractZonesFromSecret(t *testing.T) { skipCertificateValidation: true mdm: "10.0.0.3,10.0.0.4" ` + zoneDataWithMultiArrayPartialZone1 := ` +- username: "admin" + password: "password" + systemID: "2b11bb111111bb1b" + endpoint: "https://127.0.0.2" + skipCertificateValidation: true + mdm: "10.0.0.3,10.0.0.4" + zone: + name: "ZONE-1" + labelKey: "zone.csi-vxflexos.dellemc.com" +- username: "admin" + password: "password" + systemID: "1a99aa999999aa9a" + endpoint: "https://127.0.0.1" + skipCertificateValidation: true + mdm: "10.0.0.5,10.0.0.6" + zone: + name: "" + labelKey: "zone.csi-vxflexos.dellemc.com" +` + zoneDataWithMultiArrayPartialZone2 := ` +- username: "admin" + password: "password" + systemID: "2b11bb111111bb1b" + endpoint: "https://127.0.0.2" + skipCertificateValidation: true + mdm: "10.0.0.3,10.0.0.4" + zone: + name: "ZONE-1" + labelKey: "zone.csi-vxflexos.dellemc.com" +- username: "admin" + password: "password" + systemID: "1a99aa999999aa9a" + endpoint: "https://127.0.0.1" + skipCertificateValidation: true + mdm: "10.0.0.5,10.0.0.6" + zone: + name: "myname" +` + zoneDataWithMultiArrayPartialZone3 := ` +- username: "admin" + password: "password" + systemID: "2b11bb111111bb1b" + endpoint: "https://127.0.0.2" + skipCertificateValidation: true + mdm: "10.0.0.3,10.0.0.4" + zone: + name: "ZONE-1" + labelKey: "" +- username: "admin" + password: "password" + systemID: "1a99aa999999aa9a" + endpoint: "https://127.0.0.1" + skipCertificateValidation: true + mdm: "10.0.0.5,10.0.0.6" + zone: + name: "myname" + labelKey: "zone.csi-vxflexos.dellemc.com" +` + ctx := context.Background() - tests := map[string]func() (client.WithWatch, map[string]string, string, bool){ - "success with zone": func() (client.WithWatch, map[string]string, string, bool) { + tests := map[string]func() (client.WithWatch, string, bool){ + "success with zone": func() (client.WithWatch, string, bool) { secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "vxflexos-config", @@ -280,9 +369,9 @@ func TestExtractZonesFromSecret(t *testing.T) { } client := fake.NewClientBuilder().WithObjects(secret).Build() - return client, map[string]string{"2b11bb111111bb1b": "US-EAST"}, "vxflexos-config", false + return client, "vxflexos-config", false }, - "success with zone and multi array": func() (client.WithWatch, map[string]string, string, bool) { + "success with zone and multi array": func() (client.WithWatch, string, bool) { secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "vxflexos-config", @@ -294,9 +383,9 @@ func TestExtractZonesFromSecret(t *testing.T) { } client := fake.NewClientBuilder().WithObjects(secret).Build() - return client, map[string]string{"2b11bb111111bb1b": "ZONE-1", "1a99aa999999aa9a": "ZONE-2"}, "vxflexos-config", false + return client, "vxflexos-config", false }, - "fail multi array but only some zone": func() (client.WithWatch, map[string]string, string, bool) { + "fail multi array but only some zone": func() (client.WithWatch, string, bool) { secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "vxflexos-config", @@ -307,9 +396,22 @@ func TestExtractZonesFromSecret(t *testing.T) { }, } client := fake.NewClientBuilder().WithObjects(secret).Build() - return client, map[string]string{"2b11bb111111bb1b": "ZONE-1", "1a99aa999999aa9a": "ZONE-2"}, "vxflexos-config", true + return client, "vxflexos-config", true }, - "success no zone": func() (client.WithWatch, map[string]string, string, bool) { + "fail multi array but only some zone test two": func() (client.WithWatch, string, bool) { + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "vxflexos-config", + Namespace: "vxflexos", + }, + Data: map[string][]byte{ + "config": []byte(zoneDataWithMultiArraySomeZone2), + }, + } + client := fake.NewClientBuilder().WithObjects(secret).Build() + return client, "vxflexos-config", true + }, + "success no zone": func() (client.WithWatch, string, bool) { secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "vxflexos-config", @@ -321,13 +423,13 @@ func TestExtractZonesFromSecret(t *testing.T) { } client := fake.NewClientBuilder().WithObjects(secret).Build() - return client, map[string]string{}, "vxflexos-config", false + return client, "vxflexos-config", false }, - "error getting secret": func() (client.WithWatch, map[string]string, string, bool) { + "error getting secret": func() (client.WithWatch, string, bool) { client := fake.NewClientBuilder().Build() - return client, nil, "vxflexos-not-found", true + return client, "vxflexos-not-found", true }, - "error parsing empty secret": func() (client.WithWatch, map[string]string, string, bool) { + "error parsing empty secret": func() (client.WithWatch, string, bool) { secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "vxflexos-config", @@ -339,9 +441,9 @@ func TestExtractZonesFromSecret(t *testing.T) { } client := fake.NewClientBuilder().WithObjects(secret).Build() - return client, nil, "vxflexos-config", true + return client, "vxflexos-config", true }, - "error with no system id": func() (client.WithWatch, map[string]string, string, bool) { + "error with no system id": func() (client.WithWatch, string, bool) { secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "vxflexos-config", @@ -353,9 +455,10 @@ func TestExtractZonesFromSecret(t *testing.T) { } client := fake.NewClientBuilder().WithObjects(secret).Build() - return client, nil, "vxflexos-config", true + return client, "vxflexos-config", true }, - "error unmarshaling config": func() (client.WithWatch, map[string]string, string, bool) { + + "error unmarshaling config": func() (client.WithWatch, string, bool) { secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "vxflexos-config", @@ -367,19 +470,60 @@ func TestExtractZonesFromSecret(t *testing.T) { } client := fake.NewClientBuilder().WithObjects(secret).Build() - return client, nil, "vxflexos-config", true + return client, "vxflexos-config", true + }, + "Fail Partial Zone Config 1": func() (client.WithWatch, string, bool) { + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "vxflexos-config", + Namespace: "vxflexos", + }, + Data: map[string][]byte{ + "config": []byte(zoneDataWithMultiArrayPartialZone1), + }, + } + + client := fake.NewClientBuilder().WithObjects(secret).Build() + return client, "vxflexos-config", true + }, + "Fail Partial Zone Config 2": func() (client.WithWatch, string, bool) { + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "vxflexos-config", + Namespace: "vxflexos", + }, + Data: map[string][]byte{ + "config": []byte(zoneDataWithMultiArrayPartialZone2), + }, + } + + client := fake.NewClientBuilder().WithObjects(secret).Build() + return client, "vxflexos-config", true + }, + "Fail Partial Zone Config 3": func() (client.WithWatch, string, bool) { + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "vxflexos-config", + Namespace: "vxflexos", + }, + Data: map[string][]byte{ + "config": []byte(zoneDataWithMultiArrayPartialZone3), + }, + } + + client := fake.NewClientBuilder().WithObjects(secret).Build() + return client, "vxflexos-config", true }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { - client, wantZones, secret, wantErr := tc() + client, secret, wantErr := tc() err := ValidateZonesInSecret(ctx, client, "vxflexos", secret) if wantErr { assert.NotNil(t, err) } else { assert.Nil(t, err) - _ = wantZones } }) } From 4b26187e82df3d9fc023012b08061a5055a9f7cc Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Thu, 19 Dec 2024 17:53:56 -0500 Subject: [PATCH 18/20] Updating only library golang.org/x/net to v0.33.0 for image scan. --- go.mod | 2 +- tests/e2e/go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 22887007..56bbf508 100644 --- a/go.mod +++ b/go.mod @@ -55,7 +55,7 @@ require ( github.com/x448/float16 v0.8.4 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect - golang.org/x/net v0.31.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sys v0.27.0 // indirect golang.org/x/term v0.26.0 // indirect diff --git a/tests/e2e/go.mod b/tests/e2e/go.mod index c49678cb..8e0cad3c 100644 --- a/tests/e2e/go.mod +++ b/tests/e2e/go.mod @@ -91,7 +91,7 @@ require ( go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.31.0 // indirect golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect - golang.org/x/net v0.31.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.28.0 // indirect From 52e9bd53104ea9169271f5015d977a93458a060f Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Thu, 19 Dec 2024 18:01:40 -0500 Subject: [PATCH 19/20] more updates. --- go.mod | 6 +++--- go.sum | 16 ++++++++-------- tests/e2e/go.sum | 22 ++-------------------- 3 files changed, 13 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index 56bbf508..6ec4b3a0 100644 --- a/go.mod +++ b/go.mod @@ -57,9 +57,9 @@ require ( golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect golang.org/x/net v0.33.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sys v0.27.0 // indirect - golang.org/x/term v0.26.0 // indirect - golang.org/x/text v0.20.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/term v0.27.0 // indirect + golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.5.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/protobuf v1.35.1 // indirect diff --git a/go.sum b/go.sum index 15dfc3f1..b9d36c8e 100644 --- a/go.sum +++ b/go.sum @@ -120,8 +120,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -130,14 +130,14 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= -golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/tests/e2e/go.sum b/tests/e2e/go.sum index 3380003e..7e63d281 100644 --- a/tests/e2e/go.sum +++ b/tests/e2e/go.sum @@ -75,8 +75,6 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= -github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -120,12 +118,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4= -github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag= github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= -github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= -github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= github.com/onsi/gomega v1.36.0 h1:Pb12RlruUtj4XUuPUqeEWc6j5DkVVVA49Uf6YLfC95Y= github.com/onsi/gomega v1.36.0/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -214,8 +208,6 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= -golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= @@ -228,32 +220,24 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= -golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= @@ -262,8 +246,6 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 09fe8dbac20c867020e4c080c3f615cb7d9656bd Mon Sep 17 00:00:00 2001 From: Aly Nathoo Date: Thu, 19 Dec 2024 18:31:35 -0500 Subject: [PATCH 20/20] Error msg must start with small letters plus minor formatting issues. --- pkg/drivers/powerflex.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/drivers/powerflex.go b/pkg/drivers/powerflex.go index 44b9e289..419459d6 100644 --- a/pkg/drivers/powerflex.go +++ b/pkg/drivers/powerflex.go @@ -396,11 +396,11 @@ func ValidateZonesInSecret(ctx context.Context, kube client.Client, namespace st return fmt.Errorf("invalid value for SystemID") } if reflect.DeepEqual(configParam.Zone, Zone{}) { - log.Infof("Zone is not specified for SystemID:", configParam.SystemID) + log.Infof("Zone is not specified for SystemID: %s", configParam.SystemID) } else { - log.Infof("Zone is specified for SystemID:", configParam.SystemID) + log.Infof("Zone is specified for SystemID: %s", configParam.SystemID) if configParam.Zone.LabelKey == "" { - return fmt.Errorf("Zone LabelKey is empty or not specified for SystemID: %s", + return fmt.Errorf("zone LabelKey is empty or not specified for SystemID: %s", configParam.SystemID) } @@ -413,7 +413,7 @@ func ValidateZonesInSecret(ctx context.Context, kube client.Client, namespace st } if configParam.Zone.Name == "" { - return fmt.Errorf("Zone name is empty or not specified for SystemID: %s", + return fmt.Errorf("zone name is empty or not specified for SystemID: %s", configParam.SystemID) } numArraysWithZone++