Skip to content

Commit

Permalink
Adding support for active-rack
Browse files Browse the repository at this point in the history
  • Loading branch information
tanmayja committed Sep 5, 2024
1 parent fbd9d18 commit 0c6a705
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ spec:
path: resources
- description: SecretMounts is the list of secret to be mounted in the backup
service.
displayName: Backup Service Volume
displayName: Backup Service SecretMounts
path: secrets
- description: Service defines the Kubernetes service configuration for the
backup service. It is used to expose the backup service deployment. By default,
the service type is ClusterIP.
displayName: Backup Service
displayName: K8s Service
path: service
version: v1beta1
- description: AerospikeCluster is the schema for the AerospikeCluster API
Expand Down Expand Up @@ -235,7 +235,8 @@ spec:
displayName: Restore Service Polling Period
path: pollingPeriod
- description: Type is the type of restore. It can of type Full, Incremental,
and Timestamp. Based on the restore type, relevant restore config is given.
and Timestamp. Based on the restore type, the relevant restore config should
be given.
displayName: Restore Type
path: type
version: v1beta1
Expand Down
55 changes: 55 additions & 0 deletions controllers/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,16 @@ func (r *SingleClusterReconciler) Reconcile() (result ctrl.Result, recErr error)
}
}

if r.IsReclusterNeeded() {
if err = deployment.InfoRecluster(
r.Log,
r.getClientPolicy(), allHostConns,
); err != nil {
r.Log.Error(err, "Failed to do recluster")
return reconcile.Result{}, err
}
}

// Update the AerospikeCluster status.
if err = r.updateStatus(); err != nil {
r.Log.Error(err, "Failed to update AerospikeCluster status")
Expand Down Expand Up @@ -1023,3 +1033,48 @@ func (r *SingleClusterReconciler) AddAPIVersionLabel(ctx context.Context) error

return r.Client.Update(ctx, aeroCluster, common.UpdateOption)
}

func (r *SingleClusterReconciler) IsReclusterNeeded() bool {
// Return false if dynamic configuration updates are disabled
if !asdbv1.GetBool(r.aeroCluster.Spec.EnableDynamicConfigUpdate) {
return false
}

for specIdx := range r.aeroCluster.Spec.RackConfig.Racks {
for statusIdx := range r.aeroCluster.Status.RackConfig.Racks {
if r.aeroCluster.Spec.RackConfig.Racks[specIdx].ID == r.aeroCluster.Status.RackConfig.Racks[statusIdx].ID &&
r.IsReclusterNeededForRack(&r.aeroCluster.Spec.RackConfig.Racks[specIdx],
&r.aeroCluster.Status.RackConfig.Racks[statusIdx]) {
return true
}
}
}

return false
}

func (r *SingleClusterReconciler) IsReclusterNeededForRack(specRack, statusRack *asdbv1.Rack) bool {
specNamespaces, ok := specRack.AerospikeConfig.Value["namespaces"].([]interface{})
if !ok {
return false
}

statusNamespaces, ok := statusRack.AerospikeConfig.Value["namespaces"].([]interface{})
if !ok {
return false
}

for _, specNamespace := range specNamespaces {
for _, statusNamespace := range statusNamespaces {
if specNamespace.(map[string]interface{})["name"] != statusNamespace.(map[string]interface{})["name"] {
continue
}

if specNamespace.(map[string]interface{})["active-rack"] != statusNamespace.(map[string]interface{})["active-rack"] {
return true
}
}
}

return false
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.21
toolchain go1.21.8

require (
github.com/aerospike/aerospike-management-lib v1.4.0
github.com/aerospike/aerospike-management-lib v1.4.1-0.20240905074352-532f7cf2e66b
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
github.com/evanphx/json-patch v4.12.0+incompatible
github.com/go-logr/logr v1.4.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ github.com/abhishekdwivedi3060/aerospike-backup-service v0.0.0-20240709182036-38
github.com/abhishekdwivedi3060/aerospike-backup-service v0.0.0-20240709182036-38038c5c38c7/go.mod h1:CMA+bHRLvL/Kj/aLlbu95iNnlPnvP67q62X81b5e2G4=
github.com/aerospike/aerospike-client-go/v7 v7.4.0 h1:g8/7v8RHhQhTArhW3C7Au7o+u8j8x5eySZL6MXfpHKU=
github.com/aerospike/aerospike-client-go/v7 v7.4.0/go.mod h1:pPKnWiS8VDJcH4IeB1b8SA2TWnkjcVLHwAAJ+BHfGK8=
github.com/aerospike/aerospike-management-lib v1.4.0 h1:wT0l3kwzXv5DV5Cd+hD0BQq3hjSIyaPX1HaUb1304TI=
github.com/aerospike/aerospike-management-lib v1.4.0/go.mod h1:3JKrmC/mLSV8SygbrPQPNV8T7bFaTMjB8wfnX25gB+4=
github.com/aerospike/aerospike-management-lib v1.4.1-0.20240905074352-532f7cf2e66b h1:x7zrG9VzAdGU4MUOVBhB8OZ8VWUgko1qqfA5ikyocWw=
github.com/aerospike/aerospike-management-lib v1.4.1-0.20240905074352-532f7cf2e66b/go.mod h1:3JKrmC/mLSV8SygbrPQPNV8T7bFaTMjB8wfnX25gB+4=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=
Expand Down
81 changes: 81 additions & 0 deletions test/cluster/dynamic_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,87 @@ var _ = Describe(
)
},
)

Context(
"When changing fields those need recluster", func() {
BeforeEach(
func() {
// Create a 4 node cluster
aeroCluster := createNonSCDummyAerospikeCluster(
clusterNamespacedName, 4,
)
aeroCluster.Spec.EnableDynamicConfigUpdate = ptr.To(true)
aeroCluster.Spec.Image = "aerospike.jfrog.io/docker/aerospike/aerospike-server-enterprise-rc:7.2.0.0-rc1"
aeroCluster.Spec.PodSpec.ImagePullSecrets = []v1.LocalObjectReference{
{
Name: "regcred",
},
}
aeroCluster.Spec.RackConfig.Racks = append(aeroCluster.Spec.RackConfig.Racks,
asdbv1.Rack{
ID: 1,
},
asdbv1.Rack{
ID: 2,
})
aeroCluster.Spec.RackConfig.Namespaces = []string{
"test",
}
err := deployCluster(k8sClient, ctx, aeroCluster)
Expect(err).ToNot(HaveOccurred())
},
)

AfterEach(
func() {
aeroCluster, err := getCluster(k8sClient, ctx, clusterNamespacedName)
Expect(err).ToNot(HaveOccurred())

_ = deleteCluster(k8sClient, ctx, aeroCluster)
},
)

It(
"Should update active-rack dynamically", func() {

By("Modify dynamic config by adding fields")

aeroCluster, err := getCluster(
k8sClient, ctx, clusterNamespacedName,
)
Expect(err).ToNot(HaveOccurred())

podPIDMap, err := getPodIDs(ctx, aeroCluster)
Expect(err).ToNot(HaveOccurred())

nsList := aeroCluster.Spec.AerospikeConfig.Value["namespaces"].([]interface{})
nsList[0].(map[string]interface{})["active-rack"] = 1

err = updateCluster(k8sClient, ctx, aeroCluster)
Expect(err).ToNot(HaveOccurred())

By("Fetch and verify dynamic configs")

pod := aeroCluster.Status.Pods["dynamic-config-test-1-0"]

info, err := requestInfoFromNode(logger, k8sClient, ctx, clusterNamespacedName, "namespace/test", &pod)
Expect(err).ToNot(HaveOccurred())

confs := strings.Split(info["namespace/test"], ";")
for _, conf := range confs {
if strings.Contains(conf, "effective_active_rack") {
keyValue := strings.Split(conf, "=")
Expect(keyValue[1]).To(Equal("1"))
}
}

By("Verify no warm/cold restarts in Pods")

validateServerRestart(ctx, aeroCluster, podPIDMap, false)
},
)
},
)
},
)

Expand Down
24 changes: 24 additions & 0 deletions test/cluster/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,30 @@ func getAerospikeConfigFromNode(log logr.Logger, k8sClient client.Client, ctx go
return confs[configContext].(lib.Stats), nil
}

func requestInfoFromNode(log logr.Logger, k8sClient client.Client, ctx goctx.Context,
clusterNamespacedName types.NamespacedName, cmd string, pod *asdbv1.AerospikePodStatus) (map[string]string, error) {
aeroCluster, err := getCluster(k8sClient, ctx, clusterNamespacedName)
if err != nil {
return nil, err
}

host, err := createHost(pod)
if err != nil {
return nil, err
}

asinfo := info.NewAsInfo(
log, host, getClientPolicy(aeroCluster, k8sClient),
)

confs, err := asinfo.RequestInfo(cmd)
if err != nil {
return nil, err
}

return confs, nil
}

func getPasswordFromSecret(k8sClient client.Client,
secretNamespcedName types.NamespacedName, passFileName string,
) (string, error) {
Expand Down

0 comments on commit 0c6a705

Please sign in to comment.