Skip to content

Commit e4ad00d

Browse files
fix: enable MultiOrch placement defaulting
Implements logic in `reconcileDatabases` to automatically populate `MultiOrch.Cells` if it is empty. It defaults to the set of all unique cells defined in the Shard's pools, ensuring the orchestration layer is deployed alongside data nodes as per the design specification. Adds regression test "Create: MultiOrch Placement Defaulting".
1 parent e69a2ce commit e4ad00d

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

pkg/cluster-handler/controller/multigrescluster/multigrescluster_controller.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package multigrescluster
33
import (
44
"context"
55
"fmt"
6+
"sort"
67
"time"
78

89
appsv1 "k8s.io/api/apps/v1"
@@ -202,6 +203,7 @@ func (r *MultigresClusterReconciler) reconcileGlobalComponents(ctx context.Conte
202203
Labels: map[string]string{"app": "multiadmin", "multigres.com/cluster": cluster.Name},
203204
},
204205
Spec: corev1.PodSpec{
206+
ImagePullSecrets: cluster.Spec.Images.ImagePullSecrets,
205207
Containers: []corev1.Container{
206208
{
207209
Name: "multiadmin",
@@ -325,6 +327,24 @@ func (r *MultigresClusterReconciler) reconcileDatabases(ctx context.Context, clu
325327

326328
orch, pools := MergeShardConfig(tpl, shard.Overrides, shard.Spec)
327329

330+
// Default MultiOrch Cells if empty (Consensus safety)
331+
// If 'cells' is empty, it defaults to all cells where pools are defined.
332+
if len(orch.Cells) == 0 {
333+
uniqueCells := make(map[string]bool)
334+
for _, pool := range pools {
335+
for _, cell := range pool.Cells {
336+
uniqueCells[string(cell)] = true
337+
}
338+
}
339+
for c := range uniqueCells {
340+
orch.Cells = append(orch.Cells, multigresv1alpha1.CellName(c))
341+
}
342+
// Sort for deterministic output
343+
sort.Slice(orch.Cells, func(i, j int) bool {
344+
return string(orch.Cells[i]) < string(orch.Cells[j])
345+
})
346+
}
347+
328348
resolvedShards = append(resolvedShards, multigresv1alpha1.ShardResolvedSpec{
329349
Name: shard.Name,
330350
MultiOrch: orch,

pkg/cluster-handler/controller/multigrescluster/multigrescluster_controller_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,65 @@ func TestMultigresClusterReconciler_Reconcile(t *testing.T) {
258258
}
259259
},
260260
},
261+
{
262+
name: "Create: MultiOrch Placement Defaulting",
263+
cluster: func() *multigresv1alpha1.MultigresCluster {
264+
c := baseCluster.DeepCopy()
265+
c.Spec.TemplateDefaults.ShardTemplate = "" // Ensure no default template interferes
266+
// Define a database with explicit pools containing cells
267+
c.Spec.Databases = []multigresv1alpha1.DatabaseConfig{
268+
{
269+
Name: "db-defaulting",
270+
TableGroups: []multigresv1alpha1.TableGroupConfig{
271+
{
272+
Name: "tg1",
273+
Shards: []multigresv1alpha1.ShardConfig{
274+
{
275+
Name: "0",
276+
Spec: &multigresv1alpha1.ShardInlineSpec{
277+
// MultiOrch Cells explicitly EMPTY
278+
MultiOrch: multigresv1alpha1.MultiOrchSpec{
279+
StatelessSpec: multigresv1alpha1.StatelessSpec{Replicas: ptr.To(int32(1))},
280+
},
281+
Pools: map[string]multigresv1alpha1.PoolSpec{
282+
"pool-a": {Cells: []multigresv1alpha1.CellName{"zone-a"}},
283+
"pool-b": {Cells: []multigresv1alpha1.CellName{"zone-b"}},
284+
},
285+
},
286+
},
287+
},
288+
},
289+
},
290+
},
291+
}
292+
return c
293+
}(),
294+
existingObjects: []client.Object{coreTpl, cellTpl},
295+
expectError: false,
296+
validate: func(t *testing.T, c client.Client) {
297+
ctx := context.Background()
298+
// Fetch the child TableGroup (which holds the resolved shard spec)
299+
tgName := clusterName + "-db-defaulting-tg1"
300+
tg := &multigresv1alpha1.TableGroup{}
301+
if err := c.Get(ctx, types.NamespacedName{Name: tgName, Namespace: namespace}, tg); err != nil {
302+
t.Fatal(err)
303+
}
304+
305+
if len(tg.Spec.Shards) != 1 {
306+
t.Fatalf("Expected 1 shard, got %d", len(tg.Spec.Shards))
307+
}
308+
309+
orchCells := tg.Spec.Shards[0].MultiOrch.Cells
310+
if len(orchCells) != 2 {
311+
t.Errorf("MultiOrch should default to 2 cells, got %d: %v", len(orchCells), orchCells)
312+
}
313+
314+
// Check content (order is sorted by controller)
315+
if string(orchCells[0]) != "zone-a" || string(orchCells[1]) != "zone-b" {
316+
t.Errorf("MultiOrch cells mismatch. Got %v, Want [zone-a zone-b]", orchCells)
317+
}
318+
},
319+
},
261320
{
262321
name: "Create: Inline Etcd",
263322
cluster: func() *multigresv1alpha1.MultigresCluster {

0 commit comments

Comments
 (0)