From 5ed909d5e5ddaad86dd68218420da299b92dd256 Mon Sep 17 00:00:00 2001 From: Jwalant Modi Date: Mon, 20 Jan 2025 14:04:28 +0530 Subject: [PATCH 1/3] Added a validation check to ensure that MRT fields are allowed only in SC namespaces. --- api/v1/aerospikecluster_validating_webhook.go | 22 +++++++++ test/cluster/strong_consistency_test.go | 45 +++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/api/v1/aerospikecluster_validating_webhook.go b/api/v1/aerospikecluster_validating_webhook.go index 5c08d6af..8079f4cc 100644 --- a/api/v1/aerospikecluster_validating_webhook.go +++ b/api/v1/aerospikecluster_validating_webhook.go @@ -1047,6 +1047,10 @@ func validateNamespaceConfig( return nErr } + if mErr := validateMRTFields(nsConf); mErr != nil { + return mErr + } + if nsStorage, ok := nsConf["storage-engine"]; ok { if nsStorage == nil { return fmt.Errorf( @@ -1235,6 +1239,24 @@ func validateNamespaceConfig( return nil } +func validateMRTFields(nsConf map[string]interface{}) error { + mrtField := isMRTFieldSet(nsConf) + scEnabled := IsNSSCEnabled(nsConf) + + if !scEnabled && mrtField { + return fmt.Errorf("MRT fields are not allowed in non-SC namespace %v", nsConf) + } + + return nil +} + +func isMRTFieldSet(nsConf map[string]interface{}) bool { + _, isMRTDurationSet := nsConf["mrt-duration"] + disableMRTWrites, ok := nsConf["disable-mrt-writes"] + + return (ok && disableMRTWrites.(bool)) || isMRTDurationSet +} + func validateNamespaceReplicationFactor( nsConf map[string]interface{}, clSize int, ) error { diff --git a/test/cluster/strong_consistency_test.go b/test/cluster/strong_consistency_test.go index 020431fa..42a3cb2d 100644 --- a/test/cluster/strong_consistency_test.go +++ b/test/cluster/strong_consistency_test.go @@ -200,6 +200,28 @@ var _ = Describe("SCMode", func() { validateRoster(k8sClient, ctx, clusterNamespacedName, scNamespace) }) + + It("Should allow MRT fields in SC namespace", func() { + aeroCluster := createDummyAerospikeCluster(clusterNamespacedName, 3) + racks := getDummyRackConf(1) + + sc1Path := "/test/dev/" + sc1Name + aeroCluster.Spec.Storage.Volumes = append( + aeroCluster.Spec.Storage.Volumes, getStorageVolumeForAerospike(sc1Name, sc1Path)) + + conf := getSCNamespaceConfig(sc1Name, sc1Path) + conf["mrt-duration"] = 15 + + racks[0].InputAerospikeConfig = &asdbv1.AerospikeConfigSpec{ + Value: map[string]interface{}{ + "namespaces": []interface{}{conf}, + }, + } + aeroCluster.Spec.RackConfig.Racks = racks + + err := deployCluster(k8sClient, ctx, aeroCluster) + Expect(err).ToNot(HaveOccurred()) + }) }) Context("When doing invalid operation", func() { @@ -322,6 +344,29 @@ var _ = Describe("SCMode", func() { Expect(err).To(HaveOccurred()) }) + It("Should not allow MRT fields in non-SC namespace", func() { + aeroCluster := createDummyAerospikeCluster(clusterNamespacedName, 3) + racks := getDummyRackConf(1) + + sc1Path := "/test/dev/" + sc1Name + aeroCluster.Spec.Storage.Volumes = append( + aeroCluster.Spec.Storage.Volumes, getStorageVolumeForAerospike(sc1Name, sc1Path)) + + conf := getSCNamespaceConfig(sc1Name, sc1Path) + conf["strong-consistency"] = false + conf["mrt-duration"] = 10 + + racks[0].InputAerospikeConfig = &asdbv1.AerospikeConfigSpec{ + Value: map[string]interface{}{ + "namespaces": []interface{}{conf}, + }, + } + aeroCluster.Spec.RackConfig.Racks = racks + + err := deployCluster(k8sClient, ctx, aeroCluster) + Expect(err).To(HaveOccurred()) + }) + }) }) From 48f61c3b260b608d7729794b10ebacbf6a8e2ad7 Mon Sep 17 00:00:00 2001 From: Jwalant Modi Date: Tue, 28 Jan 2025 13:09:26 +0530 Subject: [PATCH 2/3] Incorporate changes. --- api/v1/aerospikecluster_validating_webhook.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v1/aerospikecluster_validating_webhook.go b/api/v1/aerospikecluster_validating_webhook.go index 8079f4cc..079b8ae0 100644 --- a/api/v1/aerospikecluster_validating_webhook.go +++ b/api/v1/aerospikecluster_validating_webhook.go @@ -1252,9 +1252,9 @@ func validateMRTFields(nsConf map[string]interface{}) error { func isMRTFieldSet(nsConf map[string]interface{}) bool { _, isMRTDurationSet := nsConf["mrt-duration"] - disableMRTWrites, ok := nsConf["disable-mrt-writes"] + _, isDisableMRTWritesSet := nsConf["disable-mrt-writes"] - return (ok && disableMRTWrites.(bool)) || isMRTDurationSet + return isDisableMRTWritesSet || isMRTDurationSet } func validateNamespaceReplicationFactor( From aa2bc571872620aca5f41c3fc3147676036b1d90 Mon Sep 17 00:00:00 2001 From: Jwalant Modi Date: Wed, 29 Jan 2025 12:30:54 +0530 Subject: [PATCH 3/3] Incorporate requested change. --- api/v1/aerospikecluster_validating_webhook.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/api/v1/aerospikecluster_validating_webhook.go b/api/v1/aerospikecluster_validating_webhook.go index 079b8ae0..f43a7307 100644 --- a/api/v1/aerospikecluster_validating_webhook.go +++ b/api/v1/aerospikecluster_validating_webhook.go @@ -1251,10 +1251,15 @@ func validateMRTFields(nsConf map[string]interface{}) error { } func isMRTFieldSet(nsConf map[string]interface{}) bool { - _, isMRTDurationSet := nsConf["mrt-duration"] - _, isDisableMRTWritesSet := nsConf["disable-mrt-writes"] + mrtFields := []string{"mrt-duration", "disable-mrt-writes"} - return isDisableMRTWritesSet || isMRTDurationSet + for _, field := range mrtFields { + if _, exists := nsConf[field]; exists { + return true + } + } + + return false } func validateNamespaceReplicationFactor(