Skip to content

Commit 3a293e1

Browse files
committed
Remove old nodes from cluster status
1 parent 34f9532 commit 3a293e1

File tree

4 files changed

+84
-8
lines changed

4 files changed

+84
-8
lines changed

hack/upgrades-tests/test_upgrade_v0.3.0.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ function cmd_teardown {
208208
function cmd_test {
209209

210210
# operator install
211-
install_operator 0.2.7 presslabs/mysql-operator
211+
install_operator 0.2.10 presslabs/mysql-operator
212212

213213
# install a cluster with 2 replica
214214
CL_NAME=my-cluster

pkg/controller/mysqlcluster/internal/upgrades/upgrades.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ func (u *upgrader) checkNode0Ok(insts []orc.Instance) error {
181181
node0 := u.getNodeFrom(insts, 0)
182182
if node0 == nil {
183183
// continue
184-
log.Info("no node found in orchestraotr")
184+
log.Info("no node found in orchestrator")
185185
return fmt.Errorf("node-0 not found in orchestarotr")
186186
}
187187

pkg/controller/orchestrator/orchestrator_reconcile.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,12 @@ func (ou *orcUpdater) removeNodeConditionNotInOrc(insts InstancesSet) {
436436
// remove nodes status for nodes that are not desired, nodes that are left behind from scale down
437437
validIndex := 0
438438
for _, ns := range ou.cluster.Status.Nodes {
439-
// save only the nodes that are desired [0, 1, ..., replicas-1]
440-
if indexInSts(ns.Name) < *ou.cluster.Spec.Replicas {
439+
// save only the nodes that are desired [0, 1, ..., replicas-1] or if index can't be extracted
440+
index, err := indexInSts(ns.Name)
441+
if err != nil {
442+
log.Info("failed to parse hostname for index - won't be removed", "error", err)
443+
}
444+
if index < *ou.cluster.Spec.Replicas || err != nil {
441445
ou.cluster.Status.Nodes[validIndex] = ns
442446
validIndex++
443447
}
@@ -448,12 +452,15 @@ func (ou *orcUpdater) removeNodeConditionNotInOrc(insts InstancesSet) {
448452
}
449453

450454
// indexInSts is a helper function that returns the index of the pod in statefulset
451-
func indexInSts(name string) int32 {
452-
re := regexp.MustCompile(`^[\w-]+-mysql-(\d*)\.mysql\.[\w-]+$`)
455+
func indexInSts(name string) (int32, error) {
456+
re := regexp.MustCompile(`^[\w-]+-mysql-(\d*)\.[\w-]*mysql(?:-nodes)?\.[\w-]+$`)
453457
values := re.FindStringSubmatch(name)
458+
if len(values) != 2 {
459+
return 0, fmt.Errorf("no match found")
460+
}
454461

455-
i, _ := strconv.Atoi(values[1])
456-
return int32(i)
462+
i, err := strconv.Atoi(values[1])
463+
return int32(i), err
457464
}
458465

459466
// set a host writable just if needed

pkg/controller/orchestrator/orchestrator_reconcile_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,18 @@ var _ = Describe("Orchestrator reconciler", func() {
435435
Expect(insts).To(HaveLen(1))
436436
})
437437

438+
It("should remove nodes from cluster status at scale down", func() {
439+
// scale down the cluster
440+
cluster.Spec.Replicas = &one
441+
cluster.Status.ReadyNodes = 1
442+
443+
// call the function
444+
insts, _ := orcClient.Cluster(cluster.GetClusterAlias())
445+
updater.removeNodeConditionNotInOrc(insts)
446+
447+
Expect(cluster.Status.Nodes).To(ConsistOf(hasNodeWithStatus(cluster.GetPodHostname(0))))
448+
})
449+
438450
When("cluster is not ready", func() {
439451
BeforeEach(func() {
440452
cluster.Spec.Replicas = &two
@@ -488,6 +500,53 @@ var _ = Describe("Orchestrator reconciler", func() {
488500
})
489501

490502
})
503+
504+
// NOTE: this test sute should be deleted in next major version
505+
Describe("status updater unit tests at upgrade", func() {
506+
var (
507+
updater *orcUpdater
508+
)
509+
510+
BeforeEach(func() {
511+
updater = &orcUpdater{
512+
cluster: cluster,
513+
recorder: rec,
514+
orcClient: orcClient,
515+
}
516+
// set cluster on readonly, master should be in read only state
517+
orcClient.AddInstance(orc.Instance{
518+
ClusterName: cluster.GetClusterAlias(),
519+
Key: orc.InstanceKey{Hostname: oldPodHostname(cluster, 0)},
520+
ReadOnly: false, // mark node as master
521+
// mark instance as uptodate
522+
IsUpToDate: true,
523+
IsLastCheckValid: true,
524+
})
525+
orcClient.AddInstance(orc.Instance{
526+
ClusterName: cluster.GetClusterAlias(),
527+
Key: orc.InstanceKey{Hostname: oldPodHostname(cluster, 1)},
528+
MasterKey: orc.InstanceKey{Hostname: oldPodHostname(cluster, 0)},
529+
})
530+
531+
// update cluster nodes status
532+
insts, _ := orcClient.Cluster(cluster.GetClusterAlias())
533+
master, _ := orcClient.Master(cluster.GetClusterAlias())
534+
updater.updateStatusFromOrc(insts, master)
535+
})
536+
537+
It("should not remove nodes from cluster when upgrading", func() {
538+
// scale down the cluster
539+
cluster.Spec.Replicas = &one
540+
cluster.Status.ReadyNodes = 1
541+
542+
// call the function
543+
insts, _ := orcClient.Cluster(cluster.GetClusterAlias())
544+
updater.removeNodeConditionNotInOrc(insts)
545+
546+
// nothing should be remove
547+
Expect(cluster.Status.Nodes).To(ConsistOf(hasNodeWithStatus(oldPodHostname(cluster, 0))))
548+
})
549+
})
491550
})
492551

493552
// haveNodeCondWithStatus is a helper func that returns a matcher to check for an existing condition in a ClusterCondition list.
@@ -510,5 +569,15 @@ func haveCondWithStatus(condType api.ClusterConditionType, status core.Condition
510569
"Reason": Equal(reason),
511570
})),
512571
})
572+
}
573+
574+
func hasNodeWithStatus(host string) gomegatypes.GomegaMatcher {
575+
return MatchFields(IgnoreExtras, Fields{
576+
"Name": Equal(host),
577+
})
578+
}
513579

580+
func oldPodHostname(cluster *mysqlcluster.MysqlCluster, index int) string {
581+
return fmt.Sprintf("%s-mysql-%d.%s.%s", cluster.Name, index, cluster.GetNameForResource(mysqlcluster.OldHeadlessSVC),
582+
cluster.Namespace)
514583
}

0 commit comments

Comments
 (0)