diff --git a/internal/controller/cluster/access_control.go b/internal/controller/cluster/access_control.go index 19440f8b..917fb803 100644 --- a/internal/controller/cluster/access_control.go +++ b/internal/controller/cluster/access_control.go @@ -37,29 +37,6 @@ func AerospikeAdminCredentials( desiredState, currentState *asdbv1.AerospikeClusterSpec, passwordProvider AerospikeUserPasswordProvider, ) (user, pass string, err error) { - var ( - enabled bool - currentSecurityErr error - desiredSecurityErr error - ) - - enabled, desiredSecurityErr = asdbv1.IsSecurityEnabled(desiredState.AerospikeConfig.Value) - if !enabled { - if currentState.AerospikeConfig != nil { - // It is possible that this is a new cluster and the current state is empty. - enabled, currentSecurityErr = asdbv1.IsSecurityEnabled(currentState.AerospikeConfig.Value) - } - - if currentSecurityErr != nil && desiredSecurityErr != nil { - return "", "", desiredSecurityErr - } - } - - if !enabled { - // Return zero strings if this is not a security enabled cluster. - return "", "", nil - } - if currentState.AerospikeAccessControl == nil { // We haven't yet set up access control. Use default password. return asdbv1.AdminUsername, passwordProvider.GetDefaultPassword(desiredState), nil @@ -190,6 +167,13 @@ func (r *SingleClusterReconciler) reconcileUsers( currentUserNames = append(currentUserNames, userName) } + if len(desired) == 0 { + // If no users are desired, do not drop admin user. + desired[asdbv1.AdminUsername] = asdbv1.AerospikeUserSpec{ + Roles: []string{"user-admin", "sys-admin"}, + } + } + // List users needed in the desired list. requiredUserNames := make([]string, 0, len(desired)) for userName := range desired { @@ -213,9 +197,18 @@ func (r *SingleClusterReconciler) reconcileUsers( for userName := range desired { userSpec := desired[userName] - password, err := passwordProvider.Get(userName, &userSpec) - if err != nil { - return err + var ( + password string + err error + ) + + if userName == asdbv1.AdminUsername && userSpec.SecretName == "" { + password = passwordProvider.GetDefaultPassword(&r.aeroCluster.Spec) + } else { + password, err = passwordProvider.Get(userName, &userSpec) + if err != nil { + return err + } } cmd := aerospikeUserCreateUpdate{ diff --git a/internal/controller/cluster/aero_info_calls.go b/internal/controller/cluster/aero_info_calls.go index 7ba8d6ce..f342665e 100644 --- a/internal/controller/cluster/aero_info_calls.go +++ b/internal/controller/cluster/aero_info_calls.go @@ -104,6 +104,17 @@ func (r *SingleClusterReconciler) quiescePods( return deployment.InfoQuiesce(r.Log, policy, allHostConns, selectedHostConns, r.removedNamespaces(nodesNamespaces)) } +func (r *SingleClusterReconciler) getClusterSecurityConfig( + policy *as.ClientPolicy, podList *corev1.PodList, ignorablePodNames sets.Set[string], +) (map[string]deployment.InfoResult, error) { + hostConns, err := r.newPodsHostConnWithOption(podList.Items, ignorablePodNames) + if err != nil { + return nil, err + } + + return deployment.GetInfoOnHosts(r.Log, policy, hostConns, "get-config:context=security") +} + // TODO: Check only for migration func (r *SingleClusterReconciler) waitForClusterStability( policy *as.ClientPolicy, allHostConns []*deployment.HostConn, @@ -235,11 +246,7 @@ func (r *SingleClusterReconciler) newPodsHostConnWithOption(pods []corev1.Pod, i func (r *SingleClusterReconciler) newAsConn(pod *corev1.Pod) *deployment.ASConn { // Use pod IP and direct service port from within the operator for info calls. - tlsName, port := r.getServiceTLSNameAndPortIfConfigured() - - if tlsName == "" || port == nil { - port = asdbv1.GetServicePort(r.aeroCluster.Spec.AerospikeConfig) - } + tlsName, port := r.getResolvedTLSNameAndPort() host := pod.Status.PodIP asConn := &deployment.ASConn{ diff --git a/internal/controller/cluster/rack.go b/internal/controller/cluster/rack.go index 33b54dc3..fcb309fe 100644 --- a/internal/controller/cluster/rack.go +++ b/internal/controller/cluster/rack.go @@ -386,12 +386,10 @@ func (r *SingleClusterReconciler) upgradeOrRollingRestartRack( return found, common.ReconcileError(err) } - // Handle enable security just after updating configMap. - // This code will run only when security is being enabled in an existing cluster - // Update for security is verified by checking the config hash of the pod with the - // config hash present in config map - if err := r.handleEnableSecurity(rackState, ignorablePodNames); err != nil { - return found, common.ReconcileError(err) + if failedPods == nil { + if err := r.handleClusterSecurity(ignorablePodNames); err != nil { + return found, common.ReconcileError(err) + } } // Upgrade @@ -1775,25 +1773,26 @@ func (r *SingleClusterReconciler) getCurrentRackList() ( return rackList, nil } -func (r *SingleClusterReconciler) handleEnableSecurity(rackState *RackState, ignorablePodNames sets.Set[string]) error { - if !r.enablingSecurity() { +func (r *SingleClusterReconciler) handleClusterSecurity( + ignorablePodNames sets.Set[string]) error { + if !r.needACLReconcile() { // No need to proceed if security is not to be enabling return nil } // Get pods where security-enabled config is applied - securityEnabledPods, err := r.getPodsWithUpdatedConfigForRack(rackState) + securityEnabledPod, err := r.getAnyPodWithEnabledSecurity(ignorablePodNames) if err != nil { return err } - if len(securityEnabledPods) == 0 { - // No security-enabled pods found + if securityEnabledPod == nil { + // No security-enabled pod found return nil } // Setup access control. - if err := r.validateAndReconcileAccessControl(securityEnabledPods, ignorablePodNames); err != nil { + if err := r.validateAndReconcileAccessControl(securityEnabledPod, ignorablePodNames); err != nil { r.Log.Error(err, "Failed to Reconcile access control") r.Recorder.Eventf( r.aeroCluster, corev1.EventTypeWarning, "ACLUpdateFailed", @@ -1807,41 +1806,40 @@ func (r *SingleClusterReconciler) handleEnableSecurity(rackState *RackState, ign return nil } -func (r *SingleClusterReconciler) enablingSecurity() bool { - return r.aeroCluster.Spec.AerospikeAccessControl != nil && r.aeroCluster.Status.AerospikeAccessControl == nil +func (r *SingleClusterReconciler) needACLReconcile() bool { + isAccessControlSpecNil := r.aeroCluster.Spec.AerospikeAccessControl == nil + isAccessControlStatusNil := r.aeroCluster.Status.AerospikeAccessControl == nil + + return !r.IsStatusEmpty() && isAccessControlSpecNil != isAccessControlStatusNil } -func (r *SingleClusterReconciler) getPodsWithUpdatedConfigForRack(rackState *RackState) ([]corev1.Pod, error) { - pods, err := r.getOrderedRackPodList(rackState.Rack.ID) +func (r *SingleClusterReconciler) getAnyPodWithEnabledSecurity( + ignorablePodNames sets.Set[string]) (*corev1.Pod, error) { + podList, err := r.getClusterPodList() if err != nil { - return nil, fmt.Errorf("failed to list pods: %v", err) + return nil, err } - if len(pods) == 0 { - // No pod found for the rack + if len(podList.Items) == 0 { return nil, nil } - confMap, err := r.getConfigMap(rackState.Rack.ID) + securityConfigs, err := r.getClusterSecurityConfig(r.getClientPolicy(), podList, ignorablePodNames) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get security config: %v", err) } - requiredConfHash := confMap.Data[aerospikeConfHashFileName] - - updatedPods := make([]corev1.Pod, 0, len(pods)) - - for idx := range pods { - podName := pods[idx].Name - podStatus := r.aeroCluster.Status.Pods[podName] + _, port := r.getResolvedTLSNameAndPort() - if podStatus.AerospikeConfigHash == requiredConfHash { - // Config hash is matching, it means config has been applied - updatedPods = append(updatedPods, *pods[idx]) + for idx := range podList.Items { + if security, ok := securityConfigs[hostID(podList.Items[idx].Status.PodIP, int(*port))]; ok { + if securityEnabled, ok := security["enable-security"]; ok && securityEnabled == "true" { + return &podList.Items[idx], nil + } } } - return updatedPods, nil + return nil, nil } func isContainerNameInStorageVolumeAttachments( diff --git a/internal/controller/cluster/reconciler.go b/internal/controller/cluster/reconciler.go index 70b3d35c..1d1d50c0 100644 --- a/internal/controller/cluster/reconciler.go +++ b/internal/controller/cluster/reconciler.go @@ -328,29 +328,34 @@ func (r *SingleClusterReconciler) recoverIgnorablePods(ignorablePodNames sets.Se } func (r *SingleClusterReconciler) validateAndReconcileAccessControl( - selectedPods []corev1.Pod, + selectedPod *corev1.Pod, ignorablePodNames sets.Set[string], ) error { - enabled, err := asdbv1.IsSecurityEnabled(r.aeroCluster.Spec.AerospikeConfig.Value) - if err != nil { - return fmt.Errorf("failed to get cluster security status: %v", err) - } + var ( + conns []*deployment.HostConn + err error + ) - if !enabled { - r.Log.Info("Cluster is not security enabled, please enable security for this cluster.") - return nil - } + // Create client + if selectedPod == nil { + var enabled bool - var conns []*deployment.HostConn + enabled, err = asdbv1.IsSecurityEnabled(r.aeroCluster.Spec.AerospikeConfig.Value) + if err != nil { + return fmt.Errorf("failed to get cluster security status: %v", err) + } + + if !enabled { + r.Log.Info("Cluster is not security enabled, please enable security for this cluster.") + return nil + } - // Create client - if selectedPods == nil { conns, err = r.newAllHostConnWithOption(ignorablePodNames) if err != nil { return fmt.Errorf("failed to get host info: %v", err) } } else { - conns, err = r.newPodsHostConnWithOption(selectedPods, ignorablePodNames) + conns, err = r.newPodsHostConnWithOption([]corev1.Pod{*selectedPod}, ignorablePodNames) if err != nil { return fmt.Errorf("failed to get host info: %v", err) } @@ -512,10 +517,6 @@ func (r *SingleClusterReconciler) getClusterReadinessStatus() (bool, error) { } func (r *SingleClusterReconciler) updateAccessControlStatus() error { - if r.aeroCluster.Spec.AerospikeAccessControl == nil { - return nil - } - r.Log.Info("Update access control status for AerospikeCluster") // Get the old object, it may have been updated in between. diff --git a/internal/controller/cluster/service.go b/internal/controller/cluster/service.go index d5fc08bc..eaf9cd79 100644 --- a/internal/controller/cluster/service.go +++ b/internal/controller/cluster/service.go @@ -519,6 +519,16 @@ func (r *SingleClusterReconciler) getServiceTLSNameAndPortIfConfigured() (tlsNam return tlsName, port } +func (r *SingleClusterReconciler) getResolvedTLSNameAndPort() (tlsName string, port *int32) { + tlsName, port = r.getServiceTLSNameAndPortIfConfigured() + + if tlsName == "" || port == nil { + port = asdbv1.GetServicePort(r.aeroCluster.Spec.AerospikeConfig) + } + + return tlsName, port +} + func (r *SingleClusterReconciler) isServiceMetadataUpdated( service *corev1.Service, statusMetadata, diff --git a/internal/webhook/v1/aerospikecluster_validating_webhook.go b/internal/webhook/v1/aerospikecluster_validating_webhook.go index 2f2049ef..ea7d043d 100644 --- a/internal/webhook/v1/aerospikecluster_validating_webhook.go +++ b/internal/webhook/v1/aerospikecluster_validating_webhook.go @@ -81,7 +81,7 @@ func (acv *AerospikeClusterCustomValidator) ValidateDelete(_ context.Context, ob return nil, nil } -// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type +// ValidateUpdate implement webhook.CustomValidator so a webhook will be registered for the type func (acv *AerospikeClusterCustomValidator) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object, ) (admission.Warnings, error) { aerospikeCluster, ok := newObj.(*asdbv1.AerospikeCluster) @@ -147,6 +147,10 @@ func (acv *AerospikeClusterCustomValidator) ValidateUpdate(_ context.Context, ol return warnings, err } + if err := validateAccessControlUpdate(&oldObject.Spec, &aerospikeCluster.Spec, &aerospikeCluster.Status); err != nil { + return warnings, err + } + // Validate AerospikeConfig update if err := validateAerospikeConfigUpdate( aslog, aerospikeCluster.Spec.AerospikeConfig, oldObject.Spec.AerospikeConfig, @@ -159,6 +163,23 @@ func (acv *AerospikeClusterCustomValidator) ValidateUpdate(_ context.Context, ol return warnings, validateRackUpdate(aslog, oldObject, aerospikeCluster) } +func validateAccessControlUpdate( + oldSpec *asdbv1.AerospikeClusterSpec, + newSpec *asdbv1.AerospikeClusterSpec, + status *asdbv1.AerospikeClusterStatus, +) error { + // Prevent removal of access control before status is updated + if oldSpec.AerospikeAccessControl != nil && + newSpec.AerospikeAccessControl == nil && + status.AerospikeAccessControl == nil { + return fmt.Errorf( + "cannot remove aerospikeAccessControl: " + + "security enablement is in progress and status has not yet been updated to reflect the current configuration") + } + + return nil +} + func validate(aslog logr.Logger, cluster *asdbv1.AerospikeCluster) (admission.Warnings, error) { aslog.V(1).Info("Validate AerospikeCluster spec", "obj.Spec", cluster.Spec) @@ -926,26 +947,6 @@ func validateNamespaceConfig( return nil } -func validateSecurityConfigUpdateFromStatus(newSpec, currentStatus *asdbv1.AerospikeConfigSpec) error { - if currentStatus != nil { - currentSecurityEnabled, err := asdbv1.IsSecurityEnabled(currentStatus.Value) - if err != nil { - return err - } - - desiredSecurityEnabled, err := asdbv1.IsSecurityEnabled(newSpec.Value) - if err != nil { - return err - } - - if currentSecurityEnabled && !desiredSecurityEnabled { - return fmt.Errorf("cannot disable cluster security in running cluster") - } - } - - return nil -} - func validateAerospikeConfigUpdate( aslog logr.Logger, incomingSpec, outgoingSpec, currentStatus *asdbv1.AerospikeConfigSpec, @@ -959,10 +960,6 @@ func validateAerospikeConfigUpdate( return err } - if err := validateSecurityConfigUpdateFromStatus(incomingSpec, currentStatus); err != nil { - return err - } - return validateNsConfUpdateFromStatus(incomingSpec, currentStatus) } diff --git a/pkg/validation/validate.go b/pkg/validation/validate.go index 7b8ead2e..aca229b5 100644 --- a/pkg/validation/validate.go +++ b/pkg/validation/validate.go @@ -632,28 +632,6 @@ func isValueUpdated(m1, m2 map[string]interface{}, key string) bool { return !reflect.DeepEqual(val1, val2) } -func validateSecurityConfigUpdate(oldConfig, newConfig map[string]interface{}) error { - ovflag, err := asdbv1.IsSecurityEnabled(oldConfig) - if err != nil { - return fmt.Errorf( - "failed to validate Security context of old aerospike conf: %w", err, - ) - } - - ivflag, err := asdbv1.IsSecurityEnabled(newConfig) - if err != nil { - return fmt.Errorf( - "failed to validate Security context of new aerospike conf: %w", err, - ) - } - - if !ivflag && ovflag { - return fmt.Errorf("cannot disable cluster security in running cluster") - } - - return nil -} - // ValidateAerospikeConfigUpdate validates the update of aerospikeConfig. // It validates the schema, security, tls, network and namespace configurations for the newConfig // It also validates the update of security, tls, network and namespace configurations. @@ -673,10 +651,6 @@ func ValidateAerospikeConfigUpdate( // ValidateAerospikeConfigUpdateWithoutSchema validates the update of aerospikeConfig except for the schema. // It validates the update of security, tls, network and namespace configurations. func ValidateAerospikeConfigUpdateWithoutSchema(oldConfig, newConfig map[string]interface{}) error { - if err := validateSecurityConfigUpdate(oldConfig, newConfig); err != nil { - return err - } - if err := validateTLSUpdate(oldConfig, newConfig); err != nil { return err } diff --git a/test/cluster/access_control_test.go b/test/cluster/access_control_test.go index ffef9b84..1337785c 100644 --- a/test/cluster/access_control_test.go +++ b/test/cluster/access_control_test.go @@ -16,6 +16,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/ptr" as "github.com/aerospike/aerospike-client-go/v8" @@ -25,7 +26,7 @@ import ( ) const ( - testClusterSize = 2 + testClusterSize = 4 ) var aerospikeConfigWithSecurity = &asdbv1.AerospikeConfigSpec{ @@ -1274,7 +1275,7 @@ var _ = Describe( ) } - aerospikeConfigSpec.setEnableSecurity(false) + aerospikeConfigSpec.setSecurity(false) aeroCluster := getAerospikeClusterSpecWithAccessControl( clusterNamespacedName, &accessControl, @@ -1358,7 +1359,7 @@ var _ = Describe( ) } - aerospikeConfigSpec.setEnableSecurity(true) + aerospikeConfigSpec.setSecurity(true) aeroCluster := getAerospikeClusterSpecWithAccessControl( clusterNamespacedName, &accessControl, @@ -1528,7 +1529,7 @@ var _ = Describe( ) } - aerospikeConfigSpec.setEnableSecurity(false) + aerospikeConfigSpec.setSecurity(false) // Save cluster variable as well for cleanup. aeroCluster := getAerospikeClusterSpecWithAccessControl( @@ -1575,7 +1576,60 @@ var _ = Describe( }, } - aerospikeConfigSpec, err = NewAerospikeConfSpec(latestImage) + aerospikeConfigSpec.setSecurity(true) + + aeroCluster = getAerospikeClusterSpecWithAccessControl( + clusterNamespacedName, accessControl, + aerospikeConfigSpec, + ) + err = testAccessControlReconcile( + aeroCluster, ctx, + ) + if err != nil { + Fail("Security should have enabled successfully") + } + }, + ) + + It( + "SecurityDisable: should disable security in running cluster", + func() { + accessControl := &asdbv1.AerospikeAccessControlSpec{ + Roles: []asdbv1.AerospikeRoleSpec{ + { + Name: "profiler", + Privileges: []string{ + "read-write-udf.test.users", + "write", + }, + Whitelist: []string{ + "8.8.0.0/16", + }, + }, + }, + Users: []asdbv1.AerospikeUserSpec{ + { + Name: "admin", + SecretName: test.AuthSecretNameForUpdate, + Roles: []string{ + "sys-admin", + "user-admin", + }, + }, + + { + Name: "profileUser", + SecretName: test.AuthSecretNameForUpdate, + Roles: []string{ + "data-admin", + "read-write-udf", + "write", + }, + }, + }, + } + + aerospikeConfigSpec, err := NewAerospikeConfSpec(latestImage) if err != nil { Fail( fmt.Sprintf( @@ -1585,8 +1639,23 @@ var _ = Describe( ) } - aerospikeConfigSpec.setEnableSecurity(true) + aerospikeConfigSpec.setSecurity(true) + + aeroCluster := getAerospikeClusterSpecWithAccessControl( + clusterNamespacedName, accessControl, + aerospikeConfigSpec, + ) + err = testAccessControlReconcile( + aeroCluster, ctx, + ) + if err != nil { + Fail("Security should be enabled") + } + + aerospikeConfigSpec.setSecurity(false) + accessControl = nil + // Save cluster variable as well for cleanup. aeroCluster = getAerospikeClusterSpecWithAccessControl( clusterNamespacedName, accessControl, aerospikeConfigSpec, @@ -1594,9 +1663,104 @@ var _ = Describe( err = testAccessControlReconcile( aeroCluster, ctx, ) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("SECURITY_NOT_ENABLED")) + }, + ) + + It( + "SecurityDisable: should disable security in partially security enabled cluster", + func() { + var accessControl *asdbv1.AerospikeAccessControlSpec + + aerospikeConfigSpec, err := NewAerospikeConfSpec(latestImage) if err != nil { - Fail("Security should have enabled successfully") + Fail( + fmt.Sprintf( + "Invalid Aerospike Config Spec: %v", + err, + ), + ) + } + + aerospikeConfigSpec.setSecurity(false) + + // Save cluster variable as well for cleanup. + aeroCluster := getAerospikeClusterSpecWithAccessControl( + clusterNamespacedName, accessControl, + aerospikeConfigSpec, + ) + err = aerospikeClusterCreateUpdate( + k8sClient, aeroCluster, ctx, + ) + Expect(err).ToNot(HaveOccurred()) + + accessControl = &asdbv1.AerospikeAccessControlSpec{ + Roles: []asdbv1.AerospikeRoleSpec{ + { + Name: "profiler", + Privileges: []string{ + "read-write-udf.test.users", + "write", + }, + Whitelist: []string{ + "8.8.0.0/16", + }, + }, + }, + Users: []asdbv1.AerospikeUserSpec{ + { + Name: "admin", + SecretName: test.AuthSecretNameForUpdate, + Roles: []string{ + "sys-admin", + "user-admin", + }, + }, + + { + Name: "profileUser", + SecretName: test.AuthSecretNameForUpdate, + Roles: []string{ + "profiler", + }, + }, + }, } + + aerospikeConfigSpec.setSecurity(true) + + aeroCluster = getAerospikeClusterSpecWithAccessControl( + clusterNamespacedName, accessControl, + aerospikeConfigSpec, + ) + + err = updateClusterWithNoWait(k8sClient, ctx, aeroCluster) + Expect(err).ToNot(HaveOccurred()) + + aerospikeConfigSpec.setSecurity(false) + accessControl = nil + + // Save cluster variable as well for cleanup. + aeroCluster = getAerospikeClusterSpecWithAccessControl( + clusterNamespacedName, accessControl, + aerospikeConfigSpec, + ) + + err = testAccessControlReconcile( + aeroCluster, ctx, + ) + + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring( + "security enablement is in progress")) + + Eventually(func(g Gomega) { + err := testAccessControlReconcile(aeroCluster, ctx) + g.Expect(err).To(HaveOccurred()) + g.Expect(err.Error()).To(ContainSubstring("SECURITY_NOT_ENABLED")) + }, 5*time.Minute, 20*time.Second).Should(Succeed()) + }, ) @@ -1663,7 +1827,7 @@ var _ = Describe( ) } - aerospikeConfigSpec.setEnableSecurity(true) + aerospikeConfigSpec.setSecurity(true) aeroCluster := getAerospikeClusterSpecWithAccessControl( clusterNamespacedName, &accessControl, @@ -1718,33 +1882,6 @@ var _ = Describe( ) Expect(err).ToNot(HaveOccurred()) - By("SecurityUpdateReject") - aerospikeConfigSpec, err = NewAerospikeConfSpec(latestImage) - if err != nil { - Fail( - fmt.Sprintf( - "Invalid Aerospike Config Spec: %v", - err, - ), - ) - } - - aerospikeConfigSpec.setEnableSecurity(false) - - aeroCluster = getAerospikeClusterSpecWithAccessControl( - clusterNamespacedName, nil, - aerospikeConfigSpec, - ) - err = testAccessControlReconcile( - aeroCluster, ctx, - ) - if err == nil || !strings.Contains( - err.Error(), - "cannot disable cluster security in running cluster", - ) { - Fail("SecurityUpdate should have failed") - } - By("EnableQuota") accessControl = asdbv1.AerospikeAccessControlSpec{ @@ -1800,17 +1937,7 @@ var _ = Describe( }, } - aerospikeConfigSpec, err = NewAerospikeConfSpec(latestImage) - if err != nil { - Fail( - fmt.Sprintf( - "Invalid Aerospike Config Spec: %v", - err, - ), - ) - } - - aerospikeConfigSpec.setEnableSecurity(true) + aerospikeConfigSpec.setSecurity(true) aerospikeConfigSpec.setEnableQuotas(true) aeroCluster = getAerospikeClusterSpecWithAccessControl( @@ -1873,16 +2000,7 @@ var _ = Describe( }, } - aerospikeConfigSpec, err = NewAerospikeConfSpec(latestImage) - if err != nil { - Fail( - fmt.Sprintf( - "Invalid Aerospike Config Spec: %v", - err, - ), - ) - } - aerospikeConfigSpec.setEnableSecurity(true) + aerospikeConfigSpec.setSecurity(true) aerospikeConfigSpec.setEnableQuotas(false) aeroCluster = getAerospikeClusterSpecWithAccessControl( @@ -1947,16 +2065,7 @@ var _ = Describe( }, } - aerospikeConfigSpec, err = NewAerospikeConfSpec(latestImage) - if err != nil { - Fail( - fmt.Sprintf( - "Invalid Aerospike Config Spec: %v", - err, - ), - ) - } - aerospikeConfigSpec.setEnableSecurity(true) + aerospikeConfigSpec.setSecurity(true) aerospikeConfigSpec.setEnableQuotas(false) aeroCluster = getAerospikeClusterSpecWithAccessControl( @@ -2140,6 +2249,14 @@ func getAerospikeClusterSpecWithAccessControl( accessControl *asdbv1.AerospikeAccessControlSpec, aerospikeConfSpec *AerospikeConfSpec, ) *asdbv1.AerospikeCluster { + racks := []asdbv1.Rack{ + { + ID: 1, + }, + { + ID: 2, + }, + } // create Aerospike custom resource return &asdbv1.AerospikeCluster{ ObjectMeta: metav1.ObjectMeta{ @@ -2147,6 +2264,12 @@ func getAerospikeClusterSpecWithAccessControl( Namespace: clusterNamespacedName.Namespace, }, Spec: asdbv1.AerospikeClusterSpec{ + RackConfig: asdbv1.RackConfig{ + Namespaces: []string{"test"}, + Racks: racks, + RollingUpdateBatchSize: &intstr.IntOrString{Type: intstr.Int, + IntVal: int32(2)}, + }, Size: testClusterSize, Image: fmt.Sprintf( "%s:%s", baseImage, aerospikeConfSpec.getVersion(), diff --git a/test/cluster/cluster_helper.go b/test/cluster/cluster_helper.go index 7736c581..f3d0e04b 100644 --- a/test/cluster/cluster_helper.go +++ b/test/cluster/cluster_helper.go @@ -1441,14 +1441,7 @@ func aerospikeClusterCreateUpdateWithTO( current.Spec.AerospikeConfig.Value = desired.Spec.AerospikeConfig.DeepCopy().Value - if err := k8sClient.Update(ctx, current); err != nil { - return err - } - - return waitForAerospikeCluster( - k8sClient, ctx, desired, int(desired.Spec.Size), retryInterval, timeout, - []asdbv1.AerospikeClusterPhase{asdbv1.AerospikeClusterCompleted}, - ) + return updateClusterWithTO(k8sClient, ctx, current, timeout) } func aerospikeClusterCreateUpdate( diff --git a/test/cluster/utils.go b/test/cluster/utils.go index 80e5d0c4..9eb032b8 100644 --- a/test/cluster/utils.go +++ b/test/cluster/utils.go @@ -244,10 +244,12 @@ func (acs *AerospikeConfSpec) getVersion() string { return acs.version } -func (acs *AerospikeConfSpec) setEnableSecurity(enableSecurity bool) { +func (acs *AerospikeConfSpec) setSecurity(enableSecurity bool) { if enableSecurity { security := map[string]interface{}{} acs.security = security + } else { + acs.security = nil } } @@ -342,7 +344,7 @@ func NewAerospikeConfSpec(image string) (*AerospikeConfSpec, error) { namespaces := []interface{}{ map[string]interface{}{ "name": "test", - "replication-factor": 1, + "replication-factor": 2, "storage-engine": map[string]interface{}{ "type": "memory", "data-size": 1073741824,