From 495db95169538b4a34774783bfa86524915e88da Mon Sep 17 00:00:00 2001 From: Tanmay Jain Date: Mon, 11 Dec 2023 15:03:31 +0530 Subject: [PATCH] Adding support for dynamic config change. --- api/v1/access_control_validate.go | 7 +- api/v1/aerospikecluster_mutating_webhook.go | 48 +--- api/v1/aerospikecluster_types.go | 144 +++++----- api/v1/aerospikecluster_validating_webhook.go | 13 +- api/v1/aerospikeconfig.go | 2 +- api/v1/utils.go | 4 +- api/v1beta1/aerospikeconfig.go | 7 +- controllers/aero_info_calls.go | 36 +++ controllers/configmap.go | 7 +- controllers/pod.go | 257 ++++++++++++++++-- controllers/rack.go | 115 ++++++-- controllers/reconciler.go | 13 +- controllers/statefulset.go | 17 +- go.mod | 7 +- go.sum | 9 +- test/cluster_helper.go | 14 +- test/services_test.go | 5 +- 17 files changed, 491 insertions(+), 214 deletions(-) diff --git a/api/v1/access_control_validate.go b/api/v1/access_control_validate.go index 1ef0531a1..cb7358db6 100644 --- a/api/v1/access_control_validate.go +++ b/api/v1/access_control_validate.go @@ -33,6 +33,9 @@ const ( // DefaultAdminPassword si default admin user password. DefaultAdminPassword = "admin" + + // Version6 server version 6 tag + Version6 = "6.0.0.0" ) // roleNameForbiddenChars are characters forbidden in role name. @@ -213,7 +216,7 @@ func isRoleSpecValid( _, ok := PredefinedRoles[roleSpec.Name] if ok { - cmp, err := asconfig.CompareVersions(version, "6.0.0.0") + cmp, err := asconfig.CompareVersions(version, Version6) if err != nil { return false, err } @@ -319,7 +322,7 @@ func isPrivilegeValid( } // Check if new privileges are used in an older version. - cmp, err := asconfig.CompareVersions(version, "6.0.0.0") + cmp, err := asconfig.CompareVersions(version, Version6) if err != nil { return false, err } diff --git a/api/v1/aerospikecluster_mutating_webhook.go b/api/v1/aerospikecluster_mutating_webhook.go index 4dc2f371c..552d6409d 100644 --- a/api/v1/aerospikecluster_mutating_webhook.go +++ b/api/v1/aerospikecluster_mutating_webhook.go @@ -1,5 +1,5 @@ /* -Copyright 2021. +Copyright 2023. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "github.com/aerospike/aerospike-kubernetes-operator/pkg/merge" + lib "github.com/aerospike/aerospike-management-lib" ) //nolint:lll // for readability @@ -88,9 +89,7 @@ func (c *AerospikeCluster) setDefaults(asLog logr.Logger) error { // Set common aerospikeConfig defaults // Update configMap - if err := c.setDefaultAerospikeConfigs( - asLog, *c.Spec.AerospikeConfig, - ); err != nil { + if err := c.setDefaultAerospikeConfigs(asLog, *c.Spec.AerospikeConfig, DefaultRackID); err != nil { return err } @@ -254,18 +253,18 @@ func (c *AerospikeCluster) updateRacksAerospikeConfigFromGlobal(asLog logr.Logge c.Spec.AerospikeConfig.Value, rack.InputAerospikeConfig.Value, ) + if err != nil { + return err + } + asLog.V(1).Info( "Merged rack config from global aerospikeConfig", "rack id", rack.ID, "rackAerospikeConfig", m, "globalAerospikeConfig", c.Spec.AerospikeConfig, ) - - if err != nil { - return err - } } else { // Use the global config. - m = c.Spec.AerospikeConfig.Value + m = lib.DeepCopy(c.Spec.AerospikeConfig.Value).(map[string]interface{}) } asLog.V(1).Info( @@ -275,9 +274,7 @@ func (c *AerospikeCluster) updateRacksAerospikeConfigFromGlobal(asLog logr.Logge // Set defaults in updated rack config // Above merge function may have overwritten defaults. - if err := c.setDefaultAerospikeConfigs( - asLog, AerospikeConfigSpec{Value: m}, - ); err != nil { + if err := c.setDefaultAerospikeConfigs(asLog, AerospikeConfigSpec{Value: m}, rack.ID); err != nil { return err } @@ -287,15 +284,12 @@ func (c *AerospikeCluster) updateRacksAerospikeConfigFromGlobal(asLog logr.Logge return nil } -func (c *AerospikeCluster) setDefaultAerospikeConfigs( - asLog logr.Logger, configSpec AerospikeConfigSpec, -) error { +func (c *AerospikeCluster) setDefaultAerospikeConfigs(asLog logr.Logger, + configSpec AerospikeConfigSpec, rackID int) error { config := configSpec.Value // namespace conf - if err := setDefaultNsConf( - asLog, configSpec, c.Spec.RackConfig.Namespaces, - ); err != nil { + if err := setDefaultNsConf(asLog, configSpec, c.Spec.RackConfig.Namespaces, rackID); err != nil { return err } @@ -362,10 +356,7 @@ func (n *AerospikeNetworkPolicy) setNetworkNamespace(namespace string) { // Helper // ***************************************************************************** -func setDefaultNsConf( - asLog logr.Logger, configSpec AerospikeConfigSpec, - rackEnabledNsList []string, -) error { +func setDefaultNsConf(asLog logr.Logger, configSpec AerospikeConfigSpec, rackEnabledNsList []string, rackID int) error { config := configSpec.Value // namespace conf nsConf, ok := config["namespaces"] @@ -399,21 +390,10 @@ func setDefaultNsConf( ) } - // Add dummy rack-id only for rackEnabled namespaces - defaultConfs := map[string]interface{}{"rack-id": DefaultRackID} - if nsName, ok := nsMap["name"]; ok { if _, ok := nsName.(string); ok { if isNameExist(rackEnabledNsList, nsName.(string)) { - // Add dummy rack-id, should be replaced with actual rack-id by init-container script - if err := setDefaultsInConfigMap( - asLog, nsMap, defaultConfs, - ); err != nil { - return fmt.Errorf( - "failed to set default aerospikeConfig.namespaces rack config: %v", - err, - ) - } + nsMap["rack-id"] = rackID } else { // User may have added this key or may have patched object with new smaller rackEnabledNamespace list // but left namespace defaults. This key should be removed then only controller will detect diff --git a/api/v1/aerospikecluster_types.go b/api/v1/aerospikecluster_types.go index 9346610f5..f496a5ea7 100644 --- a/api/v1/aerospikecluster_types.go +++ b/api/v1/aerospikecluster_types.go @@ -1,5 +1,5 @@ /* -Copyright 2021. +Copyright 2023. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -864,87 +864,78 @@ func init() { } // CopySpecToStatus copy spec in status. Spec to Status DeepCopy doesn't work. It fails in reflect lib. -func CopySpecToStatus(spec *AerospikeClusterSpec) (*AerospikeClusterStatusSpec, error) { //nolint:dupl // not duplicate +func CopySpecToStatus(spec *AerospikeClusterSpec) (*AerospikeClusterStatusSpec, error) { status := AerospikeClusterStatusSpec{} status.Size = spec.Size status.Image = spec.Image // Storage - statusStorage := AerospikeStorageSpec{} - lib.DeepCopy(&statusStorage, &spec.Storage) + statusStorage := lib.DeepCopy(spec.Storage).(AerospikeStorageSpec) status.Storage = statusStorage if spec.AerospikeAccessControl != nil { // AerospikeAccessControl - statusAerospikeAccessControl := &AerospikeAccessControlSpec{} - lib.DeepCopy( - statusAerospikeAccessControl, spec.AerospikeAccessControl, - ) + statusAerospikeAccessControl := lib.DeepCopy( + *spec.AerospikeAccessControl, + ).(AerospikeAccessControlSpec) - status.AerospikeAccessControl = statusAerospikeAccessControl + status.AerospikeAccessControl = &statusAerospikeAccessControl } - // AerospikeConfig - statusAerospikeConfig := &AerospikeConfigSpec{} - lib.DeepCopy( - statusAerospikeConfig, spec.AerospikeConfig, - ) + if spec.AerospikeConfig != nil { + // AerospikeConfig + statusAerospikeConfig := lib.DeepCopy( + *spec.AerospikeConfig, + ).(AerospikeConfigSpec) - status.AerospikeConfig = statusAerospikeConfig + status.AerospikeConfig = &statusAerospikeConfig + } if spec.ValidationPolicy != nil { // ValidationPolicy - statusValidationPolicy := &ValidationPolicySpec{} - lib.DeepCopy( - statusValidationPolicy, spec.ValidationPolicy, - ) + statusValidationPolicy := lib.DeepCopy( + *spec.ValidationPolicy, + ).(ValidationPolicySpec) - status.ValidationPolicy = statusValidationPolicy + status.ValidationPolicy = &statusValidationPolicy } // RackConfig - statusRackConfig := RackConfig{} - lib.DeepCopy(&statusRackConfig, &spec.RackConfig) + statusRackConfig := lib.DeepCopy(spec.RackConfig).(RackConfig) status.RackConfig = statusRackConfig // AerospikeNetworkPolicy - statusAerospikeNetworkPolicy := AerospikeNetworkPolicy{} - lib.DeepCopy( - &statusAerospikeNetworkPolicy, &spec.AerospikeNetworkPolicy, - ) + statusAerospikeNetworkPolicy := lib.DeepCopy( + spec.AerospikeNetworkPolicy, + ).(AerospikeNetworkPolicy) status.AerospikeNetworkPolicy = statusAerospikeNetworkPolicy if spec.OperatorClientCertSpec != nil { - clientCertSpec := &AerospikeOperatorClientCertSpec{} - lib.DeepCopy( - clientCertSpec, spec.OperatorClientCertSpec, - ) + clientCertSpec := lib.DeepCopy( + *spec.OperatorClientCertSpec, + ).(AerospikeOperatorClientCertSpec) - status.OperatorClientCertSpec = clientCertSpec + status.OperatorClientCertSpec = &clientCertSpec } // Storage - statusPodSpec := AerospikePodSpec{} - lib.DeepCopy(&statusPodSpec, &spec.PodSpec) + statusPodSpec := lib.DeepCopy(spec.PodSpec).(AerospikePodSpec) status.PodSpec = statusPodSpec - seedsFinderServices := SeedsFinderServices{} - lib.DeepCopy( - &seedsFinderServices, &spec.SeedsFinderServices, - ) + seedsFinderServices := lib.DeepCopy( + spec.SeedsFinderServices, + ).(SeedsFinderServices) status.SeedsFinderServices = seedsFinderServices // RosterNodeBlockList if len(spec.RosterNodeBlockList) != 0 { - var rosterNodeBlockList []string - - lib.DeepCopy( - &rosterNodeBlockList, &spec.RosterNodeBlockList, - ) + rosterNodeBlockList := lib.DeepCopy( + spec.RosterNodeBlockList, + ).([]string) status.RosterNodeBlockList = rosterNodeBlockList } @@ -953,88 +944,79 @@ func CopySpecToStatus(spec *AerospikeClusterSpec) (*AerospikeClusterStatusSpec, } // CopyStatusToSpec copy status in spec. Status to Spec DeepCopy doesn't work. It fails in reflect lib. -func CopyStatusToSpec(status *AerospikeClusterStatusSpec) (*AerospikeClusterSpec, error) { //nolint:dupl // no need +func CopyStatusToSpec(status *AerospikeClusterStatusSpec) (*AerospikeClusterSpec, error) { spec := AerospikeClusterSpec{} spec.Size = status.Size spec.Image = status.Image // Storage - specStorage := AerospikeStorageSpec{} - lib.DeepCopy(&specStorage, &status.Storage) + specStorage := lib.DeepCopy(status.Storage).(AerospikeStorageSpec) spec.Storage = specStorage if status.AerospikeAccessControl != nil { // AerospikeAccessControl - specAerospikeAccessControl := &AerospikeAccessControlSpec{} - lib.DeepCopy( - specAerospikeAccessControl, status.AerospikeAccessControl, - ) + specAerospikeAccessControl := lib.DeepCopy( + status.AerospikeAccessControl, + ).(*AerospikeAccessControlSpec) spec.AerospikeAccessControl = specAerospikeAccessControl } // AerospikeConfig - specAerospikeConfig := &AerospikeConfigSpec{} - lib.DeepCopy( - specAerospikeConfig, status.AerospikeConfig, - ) + if status.AerospikeConfig != nil { + specAerospikeConfig := lib.DeepCopy( + status.AerospikeConfig, + ).(*AerospikeConfigSpec) - spec.AerospikeConfig = specAerospikeConfig + spec.AerospikeConfig = specAerospikeConfig + } if status.ValidationPolicy != nil { // ValidationPolicy - specValidationPolicy := &ValidationPolicySpec{} - lib.DeepCopy( - specValidationPolicy, status.ValidationPolicy, - ) + specValidationPolicy := lib.DeepCopy( + *status.ValidationPolicy, + ).(ValidationPolicySpec) - spec.ValidationPolicy = specValidationPolicy + spec.ValidationPolicy = &specValidationPolicy } // RackConfig - specRackConfig := RackConfig{} - lib.DeepCopy(&specRackConfig, &status.RackConfig) + specRackConfig := lib.DeepCopy(status.RackConfig).(RackConfig) spec.RackConfig = specRackConfig // AerospikeNetworkPolicy - specAerospikeNetworkPolicy := AerospikeNetworkPolicy{} - lib.DeepCopy( - &specAerospikeNetworkPolicy, &status.AerospikeNetworkPolicy, - ) + specAerospikeNetworkPolicy := lib.DeepCopy( + status.AerospikeNetworkPolicy, + ).(AerospikeNetworkPolicy) spec.AerospikeNetworkPolicy = specAerospikeNetworkPolicy if status.OperatorClientCertSpec != nil { - clientCertSpec := &AerospikeOperatorClientCertSpec{} - lib.DeepCopy( - clientCertSpec, status.OperatorClientCertSpec, - ) + clientCertSpec := lib.DeepCopy( + *status.OperatorClientCertSpec, + ).(AerospikeOperatorClientCertSpec) - spec.OperatorClientCertSpec = clientCertSpec + spec.OperatorClientCertSpec = &clientCertSpec } // Storage - specPodSpec := AerospikePodSpec{} - lib.DeepCopy(&specPodSpec, &status.PodSpec) + specPodSpec := lib.DeepCopy(status.PodSpec).(AerospikePodSpec) spec.PodSpec = specPodSpec - seedsFinderServices := SeedsFinderServices{} - lib.DeepCopy( - &seedsFinderServices, &status.SeedsFinderServices, - ) + seedsFinderServices := lib.DeepCopy( + status.SeedsFinderServices, + ).(SeedsFinderServices) spec.SeedsFinderServices = seedsFinderServices // RosterNodeBlockList if len(status.RosterNodeBlockList) != 0 { - var rosterNodeBlockList []string - - lib.DeepCopy( - &rosterNodeBlockList, &status.RosterNodeBlockList, - ) + rosterNodeBlockList := lib.DeepCopy( + status.RosterNodeBlockList, + ).([]string) spec.RosterNodeBlockList = rosterNodeBlockList } diff --git a/api/v1/aerospikecluster_validating_webhook.go b/api/v1/aerospikecluster_validating_webhook.go index 96d8e9454..021d7c074 100644 --- a/api/v1/aerospikecluster_validating_webhook.go +++ b/api/v1/aerospikecluster_validating_webhook.go @@ -1,5 +1,5 @@ /* -Copyright 2021. +Copyright 2023. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -1384,7 +1384,7 @@ func validateAerospikeConfigUpdate( } } - return validateNsConfUpdate(incomingSpec, outgoingSpec, currentStatus) + return validateNsConfUpdate(incomingSpec, outgoingSpec, currentStatus, incomingVersion) } func validateTLSUpdate(oldConf, newConf map[string]interface{}) error { @@ -1542,7 +1542,7 @@ func validateNetworkPolicyUpdate(oldPolicy, newPolicy *AerospikeNetworkPolicy) e return nil } -func validateNsConfUpdate(newConfSpec, oldConfSpec, currentStatus *AerospikeConfigSpec) error { +func validateNsConfUpdate(newConfSpec, oldConfSpec, currentStatus *AerospikeConfigSpec, incomingVersion string) error { newConf := newConfSpec.Value oldConf := oldConfSpec.Value @@ -1577,7 +1577,12 @@ func validateNsConfUpdate(newConfSpec, oldConfSpec, currentStatus *AerospikeConf if singleConf["name"] == oldSingleConf["name"] { // replication-factor update not allowed - if isValueUpdated( + val, err := asconfig.CompareVersions(incomingVersion, Version6) + if err != nil { + return fmt.Errorf("failed to check image version: %v", err) + } + + if (IsNSSCEnabled(singleConf) || val < 0) && isValueUpdated( oldSingleConf, singleConf, "replication-factor", ) { return fmt.Errorf( diff --git a/api/v1/aerospikeconfig.go b/api/v1/aerospikeconfig.go index 824b75a40..d2e37db70 100644 --- a/api/v1/aerospikeconfig.go +++ b/api/v1/aerospikeconfig.go @@ -27,7 +27,7 @@ func (c *AerospikeConfigSpec) DeepCopy() *AerospikeConfigSpec { dst := &AerospikeConfigSpec{ Value: map[string]interface{}{}, } - lib.DeepCopy(dst, c) + dst.Value = lib.DeepCopy(c.Value).(map[string]interface{}) return dst } diff --git a/api/v1/utils.go b/api/v1/utils.go index fe1a28e3a..d613db5d4 100644 --- a/api/v1/utils.go +++ b/api/v1/utils.go @@ -61,8 +61,8 @@ const ( AerospikeInitContainerName = "aerospike-init" AerospikeInitContainerRegistryEnvVar = "AEROSPIKE_KUBERNETES_INIT_REGISTRY" AerospikeInitContainerDefaultRegistry = "docker.io" - AerospikeInitContainerDefaultRegistryNamespace = "aerospike" - AerospikeInitContainerDefaultRepoAndTag = "aerospike-kubernetes-init:2.1.0" + AerospikeInitContainerDefaultRegistryNamespace = "tanmayj10" + AerospikeInitContainerDefaultRepoAndTag = "aerospike-kubernetes-init:2.1.0-dev" AerospikeAppLabel = "app" AerospikeCustomResourceLabel = "aerospike.com/cr" AerospikeRackIDLabel = "aerospike.com/rack-id" diff --git a/api/v1beta1/aerospikeconfig.go b/api/v1beta1/aerospikeconfig.go index 7d7ae431c..5b94577ed 100644 --- a/api/v1beta1/aerospikeconfig.go +++ b/api/v1beta1/aerospikeconfig.go @@ -24,11 +24,10 @@ func (c *AerospikeConfigSpec) UnmarshalJSON(b []byte) error { } func (c *AerospikeConfigSpec) DeepCopy() *AerospikeConfigSpec { - src := *c - dst := AerospikeConfigSpec{ + dst := &AerospikeConfigSpec{ Value: map[string]interface{}{}, } - lib.DeepCopy(dst.Value, src.Value) + dst.Value = lib.DeepCopy(c.Value).(map[string]interface{}) - return &dst + return dst } diff --git a/controllers/aero_info_calls.go b/controllers/aero_info_calls.go index 093da495b..818378076 100644 --- a/controllers/aero_info_calls.go +++ b/controllers/aero_info_calls.go @@ -296,3 +296,39 @@ func (r *SingleClusterReconciler) setMigrateFillDelay( return reconcileSuccess() } + +func (r *SingleClusterReconciler) setDynamicConfig( + policy *as.ClientPolicy, + cmds []string, pods []*corev1.Pod, ignorablePodNames sets.Set[string], +) reconcileResult { + // This doesn't make actual connection, only objects having connection info are created + allHostConns, err := r.newAllHostConnWithOption(ignorablePodNames) + if err != nil { + return reconcileError( + fmt.Errorf( + "failed to get hostConn for aerospike cluster nodes: %v", err, + ), + ) + } + + podList := make([]corev1.Pod, 0, len(pods)) + + for idx := range pods { + podList = append(podList, *pods[idx]) + } + + selectedHostConns, err := r.newPodsHostConnWithOption(podList, ignorablePodNames) + if err != nil { + return reconcileError( + fmt.Errorf( + "failed to get hostConn for aerospike cluster nodes: %v", err, + ), + ) + } + + if err := deployment.SetConfigCommandsOnHosts(r.Log, policy, allHostConns, selectedHostConns, cmds); err != nil { + return reconcileError(err) + } + + return reconcileSuccess() +} diff --git a/controllers/configmap.go b/controllers/configmap.go index 102ef5911..a94bbd78e 100644 --- a/controllers/configmap.go +++ b/controllers/configmap.go @@ -167,10 +167,9 @@ func (r *SingleClusterReconciler) createConfigMapData(rack *asdbv1.Rack) ( func createPodSpecForRack( aeroCluster *asdbv1.AerospikeCluster, rack *asdbv1.Rack, ) *asdbv1.AerospikePodSpec { - rackFullPodSpec := asdbv1.AerospikePodSpec{} - lib.DeepCopy( - &rackFullPodSpec, &aeroCluster.Spec.PodSpec, - ) + rackFullPodSpec := lib.DeepCopy( + aeroCluster.Spec.PodSpec, + ).(asdbv1.AerospikePodSpec) rackFullPodSpec.Affinity = rack.PodSpec.Affinity rackFullPodSpec.Tolerations = rack.PodSpec.Tolerations diff --git a/controllers/pod.go b/controllers/pod.go index 1244e6f3e..9bf04c06c 100644 --- a/controllers/pod.go +++ b/controllers/pod.go @@ -20,6 +20,7 @@ import ( asdbv1 "github.com/aerospike/aerospike-kubernetes-operator/api/v1" "github.com/aerospike/aerospike-kubernetes-operator/pkg/jsonpatch" "github.com/aerospike/aerospike-kubernetes-operator/pkg/utils" + "github.com/aerospike/aerospike-management-lib/asconfig" ) // RestartType is the type of pod restart to use. @@ -29,6 +30,9 @@ const ( // noRestart needed. noRestart RestartType = iota + // noRestartUpdateConf indicates that restart is not needed but conf file has to be updated. + noRestartUpdateConf + // podRestart indicates that restart requires a restart of the pod. podRestart @@ -37,7 +41,7 @@ const ( ) // mergeRestartType generates the updated restart type based on precedence. -// podRestart > quickRestart > noRestart +// podRestart > quickRestart > noRestartUpdateConf > noRestart func mergeRestartType(current, incoming RestartType) RestartType { if current == podRestart || incoming == podRestart { return podRestart @@ -47,20 +51,31 @@ func mergeRestartType(current, incoming RestartType) RestartType { return quickRestart } + if current == noRestartUpdateConf || incoming == noRestartUpdateConf { + return noRestartUpdateConf + } + return noRestart } // Fetching RestartType of all pods, based on the operation being performed. -func (r *SingleClusterReconciler) getRollingRestartTypeMap( - rackState *RackState, pods []*corev1.Pod, ignorablePodNames sets.Set[string], -) (map[string]RestartType, error) { - var addedNSDevices []string +func (r *SingleClusterReconciler) getRollingRestartTypeMap(rackState *RackState, ignorablePodNames sets.Set[string]) ( + restartTypeMap map[string]RestartType, dynamicCmds []string, err error) { + var ( + addedNSDevices []string + onlyDynamicConfigChange bool + ) - restartTypeMap := make(map[string]RestartType) + restartTypeMap = make(map[string]RestartType) + + pods, err := r.getOrderedRackPodList(rackState.Rack.ID) + if err != nil { + return nil, nil, fmt.Errorf("failed to list pods: %v", err) + } confMap, err := r.getConfigMap(rackState.Rack.ID) if err != nil { - return nil, err + return nil, nil, err } requiredConfHash := confMap.Data[aerospikeConfHashFileName] @@ -71,24 +86,39 @@ func (r *SingleClusterReconciler) getRollingRestartTypeMap( } podStatus := r.aeroCluster.Status.Pods[pods[idx].Name] - if addedNSDevices == nil && podStatus.AerospikeConfigHash != requiredConfHash { - // Fetching all block devices that have been added in namespaces. - addedNSDevices, err = r.getNSAddedDevices(rackState) - if err != nil { - return nil, err + if podStatus.AerospikeConfigHash != requiredConfHash { + if addedNSDevices == nil { + // Fetching all block devices that have been added in namespaces. + addedNSDevices, err = r.getNSAddedDevices(rackState) + if err != nil { + return nil, nil, err + } + } + + if dynamicCmds == nil { + // Fetching all dynamic config commands. + dynamicCmds, err = r.handleDynamicConfigChange(rackState) + if err != nil { + return nil, nil, err + } } } - restartType := r.getRollingRestartTypePod(rackState, pods[idx], confMap, addedNSDevices) + if len(dynamicCmds) > 0 { + onlyDynamicConfigChange = true + } + + restartType := r.getRollingRestartTypePod(rackState, pods[idx], confMap, addedNSDevices, onlyDynamicConfigChange) restartTypeMap[pods[idx].Name] = restartType } - return restartTypeMap, nil + return restartTypeMap, dynamicCmds, nil } func (r *SingleClusterReconciler) getRollingRestartTypePod( - rackState *RackState, pod *corev1.Pod, confMap *corev1.ConfigMap, addedNSDevices []string, + rackState *RackState, pod *corev1.Pod, confMap *corev1.ConfigMap, + addedNSDevices []string, onlyDynamicConfigChange bool, ) RestartType { restartType := noRestart @@ -105,9 +135,14 @@ func (r *SingleClusterReconciler) getRollingRestartTypePod( // Check if aerospikeConfig is updated if podStatus.AerospikeConfigHash != requiredConfHash { + podRestartType := quickRestart // checking if volumes added in namespace is part of dirtyVolumes. // if yes, then podRestart is needed. - podRestartType := r.handleNSOrDeviceAddition(addedNSDevices, pod.Name) + if len(addedNSDevices) > 0 { + podRestartType = r.handleNSOrDeviceAddition(addedNSDevices, pod.Name) + } else if onlyDynamicConfigChange { + podRestartType = noRestartUpdateConf + } restartType = mergeRestartType(restartType, podRestartType) @@ -180,14 +215,25 @@ func (r *SingleClusterReconciler) rollingRestartPods( return reconcileSuccess() } -func (r *SingleClusterReconciler) restartASDInPod( - rackState *RackState, pod *corev1.Pod, -) error { +func (r *SingleClusterReconciler) restartOrUpdateAerospikeServer(rackState *RackState, + pod *corev1.Pod, operation RestartType) error { cmName := getNamespacedNameForSTSConfigMap(r.aeroCluster, rackState.Rack.ID) initBinary := "/etc/aerospike/akoinit" + + var subCommand string + + switch operation { + case noRestart, podRestart: + return fmt.Errorf("invalid operation for akoinit") + case quickRestart: + subCommand = "quick-restart" + case noRestartUpdateConf: + subCommand = "update-conf" + } + cmd := []string{ initBinary, - "quick-restart", + subCommand, "--cm-name", cmName.Name, "--cm-namespace", @@ -226,7 +272,7 @@ func (r *SingleClusterReconciler) restartASDInPod( } } else { r.Log.V(1).Info( - "Failed warm restart", "err", err, "podName", pod.Name, "stdout", + "Failed to perform", "operation", subCommand, "err", err, "podName", pod.Name, "stdout", stdout, "stderr", stderr, ) @@ -234,11 +280,19 @@ func (r *SingleClusterReconciler) restartASDInPod( } } - r.Recorder.Eventf( - r.aeroCluster, corev1.EventTypeNormal, "PodWarmRestarted", - "[rack-%d] Restarted Pod %s", rackState.Rack.ID, pod.Name, - ) - r.Log.V(1).Info("Pod warm restarted", "podName", pod.Name) + if subCommand == "quick-restart" { + r.Recorder.Eventf( + r.aeroCluster, corev1.EventTypeNormal, "PodWarmRestarted", + "[rack-%d] Restarted Pod %s", rackState.Rack.ID, pod.Name, + ) + r.Log.V(1).Info("Pod warm restarted", "podName", pod.Name) + } else { + r.Recorder.Eventf( + r.aeroCluster, corev1.EventTypeNormal, "PodConfUpdated", + "[rack-%d] Updated Pod %s", rackState.Rack.ID, pod.Name, + ) + r.Log.V(1).Info("Pod conf updated", "podName", pod.Name) + } return nil } @@ -261,7 +315,7 @@ func (r *SingleClusterReconciler) restartPods( if restartType == quickRestart { // If ASD restart fails then go ahead and restart the pod - if err := r.restartASDInPod(rackState, pod); err == nil { + if err := r.restartOrUpdateAerospikeServer(rackState, pod, quickRestart); err == nil { continue } } @@ -283,6 +337,44 @@ func (r *SingleClusterReconciler) restartPods( return reconcileSuccess() } +func (r *SingleClusterReconciler) updatePods( + rackState *RackState, podsToUpdate []*corev1.Pod, +) reconcileResult { + restartedPods := make([]*corev1.Pod, 0, len(podsToUpdate)) + + for idx := range podsToUpdate { + pod := podsToUpdate[idx] + + r.Log.Info("updating pod", "pod", pod.Name) + // If update Conf fails then go ahead and restart the asd + var err error + if err = r.restartOrUpdateAerospikeServer(rackState, pod, noRestartUpdateConf); err == nil { + continue + } + + r.Log.Info("Restarting pod as updating failed", "pod", pod.Name, "err", err) + // If ASD restart fails then go ahead and restart the pod + if err := r.restartOrUpdateAerospikeServer(rackState, pod, quickRestart); err == nil { + continue + } + + if err := r.Client.Delete(context.TODO(), pod); err != nil { + r.Log.Error(err, "Failed to delete pod") + return reconcileError(err) + } + + restartedPods = append(restartedPods, pod) + + r.Log.V(1).Info("Pod deleted", "podName", pod.Name) + } + + if len(restartedPods) > 0 { + return r.ensurePodsRunningAndReady(restartedPods) + } + + return reconcileSuccess() +} + func (r *SingleClusterReconciler) ensurePodsRunningAndReady(podsToCheck []*corev1.Pod) reconcileResult { podNames := getPodNames(podsToCheck) readyPods := map[string]bool{} @@ -641,8 +733,10 @@ func (r *SingleClusterReconciler) cleanupDanglingPodsRack(sts *appsv1.StatefulSe } } - if err := r.cleanupPods(danglingPods, rackState); err != nil { - return fmt.Errorf("failed dangling pod cleanup: %v", err) + if len(danglingPods) > 0 { + if err := r.cleanupPods(danglingPods, rackState); err != nil { + return fmt.Errorf("failed dangling pod cleanup: %v", err) + } } return nil @@ -1012,7 +1106,7 @@ func (r *SingleClusterReconciler) handleNSOrDeviceRemoval(rackState *RackState, } func (r *SingleClusterReconciler) handleNSOrDeviceRemovalPerPod( - removedDevices []string, removedFiles []string, pod *corev1.Pod, + removedDevices, removedFiles []string, pod *corev1.Pod, ) error { podStatus := r.aeroCluster.Status.Pods[pod.Name] @@ -1212,3 +1306,106 @@ func (r *SingleClusterReconciler) getConfigMap(rackID int) (*corev1.ConfigMap, e return confMap, nil } + +func (r *SingleClusterReconciler) handleDynamicConfigChange(rackState *RackState) ([]string, error) { + var rackStatus asdbv1.Rack + + asConfCmds := make([]string, 0) + + for idx := range r.aeroCluster.Status.RackConfig.Racks { + if r.aeroCluster.Status.RackConfig.Racks[idx].ID == rackState.Rack.ID { + rackStatus = r.aeroCluster.Status.RackConfig.Racks[idx] + } + } + + version := strings.Split(r.aeroCluster.Spec.Image, ":") + + asConfStatus, err := asconfig.NewMapAsConfig(r.Log, version[1], rackStatus.AerospikeConfig.Value) + if err != nil { + return asConfCmds, fmt.Errorf("failed to load config map by lib: %v", err) + } + + asConfSpec, err := asconfig.NewMapAsConfig(r.Log, version[1], rackState.Rack.AerospikeConfig.Value) + if err != nil { + return asConfCmds, fmt.Errorf("failed to load config map by lib: %v", err) + } + + flatStatusConf := *asConfStatus.GetFlatMap() + flatSpecConf := *asConfSpec.GetFlatMap() + + specToStatusDiffs := asconfig.ConfDiff(r.Log, flatSpecConf, flatStatusConf, true, false, true, version[1]) + r.Log.Info("print diff", "difference", fmt.Sprintf("%v", specToStatusDiffs)) + + if len(specToStatusDiffs) > 1 { + r.Log.V(1).Info("Multiple config change in single go is not supported,"+ + "falling back to rolling restart if needed", "diff", fmt.Sprintf("%v", specToStatusDiffs)) + + return asConfCmds, nil + } + + dynamic, _ := asconfig.GetDynamic("6.4.0") + r.Log.Info("printing dynamic values", "dynamic", dynamic) + + for diff, value := range specToStatusDiffs { + isDynamic := isFieldDynamic(dynamic, diff) + r.Log.Info("isDynamic", "isDynamic", isDynamic) + + if !isDynamic { + r.Log.Info("Static field has been changed, cannot change config dynamically", "key", diff) + return asConfCmds, nil + } + + if fmt.Sprintf("%T", value) == "[]string" { + if statusValue, ok := flatStatusConf[diff]; ok { + statusSet := sets.NewString(statusValue.([]string)...) + diffSet := sets.NewString(value.([]string)...) + + if len(statusSet.Difference(diffSet)) > 0 { + r.Log.Info("Can not remove value from list dynamically", "key", diff, + "statusset", fmt.Sprint(statusSet.List()), "diffSet", fmt.Sprint(diffSet.List())) + return asConfCmds, nil + } + } + } + } + + for diff, value := range specToStatusDiffs { + r.Log.Info("creating command", "diff", diff, "value", value) + + cmds, err := asconfig.CreateASConfCommand(diff, value) + if err != nil { + return asConfCmds, fmt.Errorf("failed to create asconfig command: %v", err) + } + + asConfCmds = append(asConfCmds, cmds...) + } + + r.Log.Info("printing commands", "asConfCmds", fmt.Sprintf("%v", asConfCmds)) + // run asinfo command list in server + + return asConfCmds, nil +} + +func isFieldDynamic(dynamic map[string]bool, diff string) bool { + var key string + + tokens := strings.Split(diff, ".") + for _, token := range tokens { + if token[0] == '{' && token[len(token)-1] == '}' { + key += "_." + } else { + key = key + token + "." + } + } + + key = strings.TrimSuffix(key, ".") + if strings.Contains(key, "replication-factor") { + return true + } + + if strings.Contains(key, "rack-id") { + return false + } + + return dynamic[key] +} diff --git a/controllers/rack.go b/controllers/rack.go index 66e269349..df9cc9c22 100644 --- a/controllers/rack.go +++ b/controllers/rack.go @@ -392,7 +392,8 @@ func (r *SingleClusterReconciler) upgradeOrRollingRestartRack(found *appsv1.Stat return found, res } } else { - var needRollingRestartRack, restartTypeMap, nErr = r.needRollingRestartRack(rackState, ignorablePodNames) + var needRollingRestartRack, needDynamicUpdateRack, restartTypeMap, + dynamicCmds, nErr = r.needRollingRestartRack(rackState, ignorablePodNames) if nErr != nil { return found, reconcileError(nErr) } @@ -417,6 +418,27 @@ func (r *SingleClusterReconciler) upgradeOrRollingRestartRack(found *appsv1.Stat return found, res } } + + if needDynamicUpdateRack { + res = r.updateDynamicConfig(rackState, ignorablePodNames, restartTypeMap, failedPods, dynamicCmds) + if !res.isSuccess { + if res.err != nil { + r.Log.Error( + res.err, "Failed to do dynamic update", "stsName", + found.Name, + ) + + r.Recorder.Eventf( + r.aeroCluster, corev1.EventTypeWarning, + "RackRollingRestartFailed", + "[rack-%d] Failed to do rolling restart {STS: %s/%s}", + rackState.Rack.ID, found.Namespace, found.Name, + ) + } + + return found, res + } + } } if r.aeroCluster.Spec.RackConfig.MaxIgnorablePods != nil { @@ -428,6 +450,69 @@ func (r *SingleClusterReconciler) upgradeOrRollingRestartRack(found *appsv1.Stat return found, reconcileSuccess() } +func (r *SingleClusterReconciler) updateDynamicConfig(rackState *RackState, + ignorablePodNames sets.Set[string], restartTypeMap map[string]RestartType, + failedPods []*corev1.Pod, dynamicCmds []string) reconcileResult { + r.Log.Info("Update dynamic config in Aerospike pods") + + r.Recorder.Eventf( + r.aeroCluster, corev1.EventTypeNormal, "RackDynamicUpdate", + "[rack-%d] Started Dynamic update", rackState.Rack.ID, + ) + + var ( + err error + podList []*corev1.Pod + ) + + failedPodNames := sets.Set[string]{} + + for idx := range failedPods { + sets.Insert(failedPodNames, failedPods[idx].Name) + } + + // List the pods for this aeroCluster's statefulset + podList, err = r.getOrderedRackPodList(rackState.Rack.ID) + if err != nil { + return reconcileError(fmt.Errorf("failed to list pods: %v", err)) + } + + // Find pods which needs restart + podsToUpdate := make([]*corev1.Pod, 0, len(podList)) + + for idx := range podList { + pod := podList[idx] + + restartType := restartTypeMap[pod.Name] + if restartType != noRestartUpdateConf || failedPodNames.Has(pod.Name) { + r.Log.Info("This Pod doesn't need any update, Skip this", "pod", pod.Name) + continue + } + + podsToUpdate = append(podsToUpdate, pod) + } + + podNames := getPodNames(podsToUpdate) + if err = r.createOrUpdatePodServiceIfNeeded(podNames); err != nil { + return reconcileError(err) + } + + if res := r.setDynamicConfig(r.getClientPolicy(), dynamicCmds, podsToUpdate, ignorablePodNames); !res.isSuccess { + return res + } + + if res := r.updatePods(rackState, podsToUpdate); !res.isSuccess { + return res + } + + r.Recorder.Eventf( + r.aeroCluster, corev1.EventTypeNormal, "RackDynamicUpdate", + "[rack-%d] Finished Dynamic update", rackState.Rack.ID, + ) + + return reconcileSuccess() +} + func (r *SingleClusterReconciler) handleNSOrDeviceRemovalForIgnorablePods( rackState *RackState, ignorablePodNames sets.Set[string], ) reconcileResult { @@ -997,7 +1082,7 @@ func (r *SingleClusterReconciler) rollingRestartRack(found *appsv1.StatefulSet, } restartType := restartTypeMap[pod.Name] - if restartType == noRestart { + if restartType == noRestart || restartType == noRestartUpdateConf { r.Log.Info("This Pod doesn't need rolling restart, Skip this", "pod", pod.Name) continue } @@ -1062,25 +1147,25 @@ func (r *SingleClusterReconciler) rollingRestartRack(found *appsv1.StatefulSet, } func (r *SingleClusterReconciler) needRollingRestartRack(rackState *RackState, ignorablePodNames sets.Set[string]) ( - needRestart bool, restartTypeMap map[string]RestartType, err error, + needRestart, needUpdateConf bool, restartTypeMap map[string]RestartType, dynamicCmds []string, err error, ) { - podList, err := r.getOrderedRackPodList(rackState.Rack.ID) + restartTypeMap, dynamicCmds, err = r.getRollingRestartTypeMap(rackState, ignorablePodNames) if err != nil { - return false, nil, fmt.Errorf("failed to list pods: %v", err) - } - - restartTypeMap, err = r.getRollingRestartTypeMap(rackState, podList, ignorablePodNames) - if err != nil { - return false, nil, err + return needRestart, needUpdateConf, nil, nil, err } for _, restartType := range restartTypeMap { - if restartType != noRestart { - return true, restartTypeMap, nil + switch restartType { + case noRestart: + // Do nothing + case noRestartUpdateConf: + needUpdateConf = true + case podRestart, quickRestart: + needRestart = true } } - return false, nil, nil + return needRestart, needUpdateConf, restartTypeMap, dynamicCmds, nil } func (r *SingleClusterReconciler) isRackUpgradeNeeded(rackID int, ignorablePodNames sets.Set[string]) ( @@ -1213,9 +1298,7 @@ func (r *SingleClusterReconciler) isStorageVolumeSourceUpdated(volume *asdbv1.Vo return true } - var volumeCopy asdbv1.VolumeSpec - - lib.DeepCopy(&volumeCopy, volume) + volumeCopy := lib.DeepCopy(*volume).(asdbv1.VolumeSpec) if volumeCopy.Source.Secret != nil { setDefaultsSecretVolumeSource(volumeCopy.Source.Secret) diff --git a/controllers/reconciler.go b/controllers/reconciler.go index 58b4417bb..d6fcb915a 100644 --- a/controllers/reconciler.go +++ b/controllers/reconciler.go @@ -384,18 +384,17 @@ func (r *SingleClusterReconciler) updateAccessControlStatus() error { } // AerospikeAccessControl - statusAerospikeAccessControl := &asdbv1.AerospikeAccessControlSpec{} - lib.DeepCopy( - statusAerospikeAccessControl, r.aeroCluster.Spec.AerospikeAccessControl, - ) + statusAerospikeAccessControl := lib.DeepCopy( + *r.aeroCluster.Spec.AerospikeAccessControl, + ).(asdbv1.AerospikeAccessControlSpec) - newAeroCluster.Status.AerospikeClusterStatusSpec.AerospikeAccessControl = statusAerospikeAccessControl + newAeroCluster.Status.AerospikeClusterStatusSpec.AerospikeAccessControl = &statusAerospikeAccessControl if err := r.patchStatus(newAeroCluster); err != nil { return fmt.Errorf("error updating status: %w", err) } - r.aeroCluster.Status.AerospikeClusterStatusSpec.AerospikeAccessControl = statusAerospikeAccessControl + r.aeroCluster.Status.AerospikeClusterStatusSpec.AerospikeAccessControl = &statusAerospikeAccessControl r.Log.Info("Updated access control status", "status", newAeroCluster.Status) @@ -539,7 +538,7 @@ func (r *SingleClusterReconciler) patchStatus(newAeroCluster *asdbv1.AerospikeCl // Seems like a bug in encoding/json/Unmarshall. // // Workaround by force copying new object's status to old object's status. - lib.DeepCopy(&oldAeroCluster.Status, &newAeroCluster.Status) + oldAeroCluster.Status = lib.DeepCopy(newAeroCluster.Status).(asdbv1.AerospikeClusterStatus) return nil } diff --git a/controllers/statefulset.go b/controllers/statefulset.go index 1d36c7596..26412718a 100644 --- a/controllers/statefulset.go +++ b/controllers/statefulset.go @@ -133,7 +133,7 @@ func (r *SingleClusterReconciler) createSTS( { Name: asdbv1.AerospikeInitContainerName, Image: asdbv1.GetAerospikeInitContainerImage(r.aeroCluster), - ImagePullPolicy: corev1.PullIfNotPresent, + ImagePullPolicy: corev1.PullAlways, VolumeMounts: getDefaultAerospikeInitContainerVolumeMounts(), Env: append( envVarList, []corev1.EnvVar{ @@ -790,13 +790,13 @@ func (r *SingleClusterReconciler) updateSTSNonPVStorage( func (r *SingleClusterReconciler) updateSTSSchedulingPolicy( st *appsv1.StatefulSet, rackState *RackState, ) { - affinity := &corev1.Affinity{} + var affinity corev1.Affinity // Use rack affinity, if given if rackState.Rack.PodSpec.Affinity != nil { - lib.DeepCopy(affinity, rackState.Rack.PodSpec.Affinity) + affinity = lib.DeepCopy(*rackState.Rack.PodSpec.Affinity).(corev1.Affinity) } else if r.aeroCluster.Spec.PodSpec.Affinity != nil { - lib.DeepCopy(affinity, r.aeroCluster.Spec.PodSpec.Affinity) + affinity = lib.DeepCopy(*r.aeroCluster.Spec.PodSpec.Affinity).(corev1.Affinity) } // Set our rules in PodAntiAffinity @@ -896,7 +896,7 @@ func (r *SingleClusterReconciler) updateSTSSchedulingPolicy( } } - st.Spec.Template.Spec.Affinity = affinity + st.Spec.Template.Spec.Affinity = &affinity // Use rack nodeSelector, if given if len(rackState.Rack.PodSpec.NodeSelector) != 0 { @@ -961,8 +961,7 @@ func updateSTSContainers( // Create a copy because updating stateful sets defaults // on the sidecar container object which mutates original aeroCluster object. - specContainerCopy := &corev1.Container{} - lib.DeepCopy(specContainerCopy, specContainer) + specContainerCopy := lib.DeepCopy(*specContainer).(corev1.Container) for stsIdx := range stsContainers { if specContainer.Name != stsContainers[stsIdx].Name { @@ -972,7 +971,7 @@ func updateSTSContainers( // Retain volume mounts and devices to make sure external storage will not lose. specContainerCopy.VolumeMounts = stsContainers[stsIdx].VolumeMounts specContainerCopy.VolumeDevices = stsContainers[stsIdx].VolumeDevices - stsContainers[stsIdx] = *specContainerCopy + stsContainers[stsIdx] = specContainerCopy found = true break @@ -980,7 +979,7 @@ func updateSTSContainers( if !found { // Add to stateful set containers. - stsContainers = append(stsContainers, *specContainerCopy) + stsContainers = append(stsContainers, specContainerCopy) } } diff --git a/go.mod b/go.mod index 87eff97ac..10e7d55c7 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( github.com/aerospike/aerospike-client-go/v6 v6.14.0 - github.com/aerospike/aerospike-management-lib v0.0.0-20231129055344-b6aff63f1dbb + github.com/aerospike/aerospike-management-lib v0.0.0-20231208095128-a898bdce6a13 github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d github.com/evanphx/json-patch v4.12.0+incompatible github.com/go-logr/logr v1.2.4 @@ -68,7 +68,6 @@ require ( github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect - github.com/qdm12/reprint v0.0.0-20200326205758-722754a53494 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect @@ -78,7 +77,7 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/net v0.10.0 // indirect + golang.org/x/net v0.17.0 // indirect golang.org/x/sync v0.2.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect @@ -87,7 +86,7 @@ require ( google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/grpc v1.54.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index abd92dab8..a222b152f 100644 --- a/go.sum +++ b/go.sum @@ -598,8 +598,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/aerospike/aerospike-client-go/v6 v6.14.0 h1:Z3FcGWJda1sagzdc6Akz4EJ13Pq55Uyn6qtFLrVUDd0= github.com/aerospike/aerospike-client-go/v6 v6.14.0/go.mod h1:/0Wm81GhMqem+9flWcpazPKoRfjFeG6WrQdXGiMNi0A= -github.com/aerospike/aerospike-management-lib v0.0.0-20231129055344-b6aff63f1dbb h1:ykX3ElBNT/VOUhw/+5+jiFnWw3LSbPfl6eRrhQzBBFk= -github.com/aerospike/aerospike-management-lib v0.0.0-20231129055344-b6aff63f1dbb/go.mod h1:LPOsGG8okRSH4hN9Y8VXFzsfIpBDj2WKEsI/f6wxwaw= +github.com/aerospike/aerospike-management-lib v0.0.0-20231208095128-a898bdce6a13 h1:T8KB2wrwTEPfiyeWzQMXmUI/cm6HmVAdI1QZx952ed8= +github.com/aerospike/aerospike-management-lib v0.0.0-20231208095128-a898bdce6a13/go.mod h1:qoBjUWFlcE7s7PBSyeEXeEJVypgr0/w5lXGKy7MvKVo= github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= @@ -878,8 +878,6 @@ github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= -github.com/qdm12/reprint v0.0.0-20200326205758-722754a53494 h1:wSmWgpuccqS2IOfmYrbRiUgv+g37W5suLLLxwwniTSc= -github.com/qdm12/reprint v0.0.0-20200326205758-722754a53494/go.mod h1:yipyliwI08eQ6XwDm1fEwKPdF/xdbkiHtrU+1Hg+vc4= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1457,8 +1455,9 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/test/cluster_helper.go b/test/cluster_helper.go index b1263a8c7..f165f4abd 100644 --- a/test/cluster_helper.go +++ b/test/cluster_helper.go @@ -298,7 +298,7 @@ func rollingRestartClusterTest( aeroCluster.Spec.AerospikeConfig.Value["service"] = map[string]interface{}{} } - aeroCluster.Spec.AerospikeConfig.Value["service"].(map[string]interface{})["proto-fd-max"] = defaultProtofdmax + 1 + aeroCluster.Spec.AerospikeConfig.Value["service"].(map[string]interface{})["indent-allocations"] = true err = updateCluster(k8sClient, ctx, aeroCluster) if err != nil { @@ -307,7 +307,7 @@ func rollingRestartClusterTest( // Verify that the change has been applied on the cluster. return validateAerospikeConfigServiceClusterUpdate( - log, k8sClient, ctx, clusterNamespacedName, []string{"proto-fd-max"}, + log, k8sClient, ctx, clusterNamespacedName, []string{"indent-allocations"}, ) } @@ -1363,16 +1363,14 @@ func aerospikeClusterCreateUpdateWithTO( // Apply the update. if desired.Spec.AerospikeAccessControl != nil { - current.Spec.AerospikeAccessControl = &asdbv1.AerospikeAccessControlSpec{} - lib.DeepCopy(¤t.Spec, &desired.Spec) + current.Spec = lib.DeepCopy(desired.Spec).(asdbv1.AerospikeClusterSpec) } else { current.Spec.AerospikeAccessControl = nil } - lib.DeepCopy( - ¤t.Spec.AerospikeConfig.Value, - &desired.Spec.AerospikeConfig.Value, - ) + current.Spec.AerospikeConfig.Value = lib.DeepCopy( + desired.Spec.AerospikeConfig.Value, + ).(map[string]interface{}) if err := k8sClient.Update(ctx, current); err != nil { return err diff --git a/test/services_test.go b/test/services_test.go index b7e49e8d8..8ea26485d 100644 --- a/test/services_test.go +++ b/test/services_test.go @@ -129,10 +129,9 @@ func createLoadBalancer() *asdbv1.LoadBalancerSpec { ), ) - result := &asdbv1.LoadBalancerSpec{} - lib.DeepCopy(result, lb) + result := lib.DeepCopy(lb).(asdbv1.LoadBalancerSpec) - return result + return &result } func loadBalancerName(aeroCluster *asdbv1.AerospikeCluster) types.NamespacedName {