Skip to content

Commit 0f8c992

Browse files
Merge pull request #103 from numtide/feature/resolver-smart-defaulting
feat(resolver): implement system catalog smart defaulting
2 parents 057738b + 9bbb9d3 commit 0f8c992

File tree

5 files changed

+136
-2
lines changed

5 files changed

+136
-2
lines changed

pkg/resolver/cluster.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,29 @@ func (r *Resolver) PopulateClusterDefaults(cluster *multigresv1alpha1.MultigresC
4747
cluster.Spec.TemplateDefaults.ShardTemplate = FallbackShardTemplate
4848
}
4949

50-
// 3. Default Inline Configs (Deep Defaulting)
50+
// 3. Smart Defaulting: System Catalog
51+
// If no databases are defined, inject the mandatory system database "postgres".
52+
if len(cluster.Spec.Databases) == 0 {
53+
cluster.Spec.Databases = append(cluster.Spec.Databases, multigresv1alpha1.DatabaseConfig{
54+
Name: DefaultSystemDatabaseName,
55+
Default: true,
56+
})
57+
}
58+
59+
// If any database has no tablegroups, inject the mandatory default tablegroup "default".
60+
for i := range cluster.Spec.Databases {
61+
if len(cluster.Spec.Databases[i].TableGroups) == 0 {
62+
cluster.Spec.Databases[i].TableGroups = append(
63+
cluster.Spec.Databases[i].TableGroups,
64+
multigresv1alpha1.TableGroupConfig{
65+
Name: DefaultSystemTableGroupName,
66+
Default: true,
67+
},
68+
)
69+
}
70+
}
71+
72+
// 4. Default Inline Configs (Deep Defaulting)
5173
// We ONLY default these if the user explicitly provided the block (Inline).
5274
// We DO NOT fetch templates here, adhering to the "Non-Goal" of the design doc.
5375

pkg/resolver/cluster_test.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,19 @@ func TestResolver_PopulateClusterDefaults(t *testing.T) {
4646
CellTemplate: FallbackCellTemplate,
4747
ShardTemplate: FallbackShardTemplate,
4848
},
49+
// Expect Smart Defaulting: System Catalog
50+
Databases: []multigresv1alpha1.DatabaseConfig{
51+
{
52+
Name: DefaultSystemDatabaseName,
53+
Default: true,
54+
TableGroups: []multigresv1alpha1.TableGroupConfig{
55+
{
56+
Name: DefaultSystemTableGroupName,
57+
Default: true,
58+
},
59+
},
60+
},
61+
},
4962
},
5063
},
5164
},
@@ -65,6 +78,13 @@ func TestResolver_PopulateClusterDefaults(t *testing.T) {
6578
CellTemplate: "custom-cell",
6679
ShardTemplate: "custom-shard",
6780
},
81+
Databases: []multigresv1alpha1.DatabaseConfig{
82+
{
83+
Name: "existing-db",
84+
Default: true,
85+
TableGroups: []multigresv1alpha1.TableGroupConfig{{Name: "tg1"}},
86+
},
87+
},
6888
},
6989
},
7090
want: &multigresv1alpha1.MultigresCluster{
@@ -82,6 +102,13 @@ func TestResolver_PopulateClusterDefaults(t *testing.T) {
82102
CellTemplate: "custom-cell",
83103
ShardTemplate: "custom-shard",
84104
},
105+
Databases: []multigresv1alpha1.DatabaseConfig{
106+
{
107+
Name: "existing-db",
108+
Default: true,
109+
TableGroups: []multigresv1alpha1.TableGroupConfig{{Name: "tg1"}},
110+
},
111+
},
85112
},
86113
},
87114
},
@@ -111,6 +138,19 @@ func TestResolver_PopulateClusterDefaults(t *testing.T) {
111138
CellTemplate: FallbackCellTemplate,
112139
ShardTemplate: FallbackShardTemplate,
113140
},
141+
// Expect Smart Defaulting for DBs
142+
Databases: []multigresv1alpha1.DatabaseConfig{
143+
{
144+
Name: DefaultSystemDatabaseName,
145+
Default: true,
146+
TableGroups: []multigresv1alpha1.TableGroupConfig{
147+
{
148+
Name: DefaultSystemTableGroupName,
149+
Default: true,
150+
},
151+
},
152+
},
153+
},
114154
GlobalTopoServer: multigresv1alpha1.GlobalTopoServerSpec{
115155
Etcd: &multigresv1alpha1.EtcdSpec{
116156
Image: DefaultEtcdImage,
@@ -156,6 +196,19 @@ func TestResolver_PopulateClusterDefaults(t *testing.T) {
156196
CellTemplate: FallbackCellTemplate,
157197
ShardTemplate: FallbackShardTemplate,
158198
},
199+
// Expect Smart Defaulting for DBs
200+
Databases: []multigresv1alpha1.DatabaseConfig{
201+
{
202+
Name: DefaultSystemDatabaseName,
203+
Default: true,
204+
TableGroups: []multigresv1alpha1.TableGroupConfig{
205+
{
206+
Name: DefaultSystemTableGroupName,
207+
Default: true,
208+
},
209+
},
210+
},
211+
},
159212
Cells: []multigresv1alpha1.CellConfig{
160213
{
161214
Name: "cell-1",
@@ -195,6 +248,19 @@ func TestResolver_PopulateClusterDefaults(t *testing.T) {
195248
CellTemplate: FallbackCellTemplate,
196249
ShardTemplate: FallbackShardTemplate,
197250
},
251+
// Expect Smart Defaulting for DBs
252+
Databases: []multigresv1alpha1.DatabaseConfig{
253+
{
254+
Name: DefaultSystemDatabaseName,
255+
Default: true,
256+
TableGroups: []multigresv1alpha1.TableGroupConfig{
257+
{
258+
Name: DefaultSystemTableGroupName,
259+
Default: true,
260+
},
261+
},
262+
},
263+
},
198264
GlobalTopoServer: multigresv1alpha1.GlobalTopoServerSpec{
199265
Etcd: &multigresv1alpha1.EtcdSpec{
200266
Image: "custom-etcd",
@@ -206,6 +272,44 @@ func TestResolver_PopulateClusterDefaults(t *testing.T) {
206272
},
207273
},
208274
},
275+
"Smart Defaulting: Inject TableGroup when DB exists": {
276+
input: &multigresv1alpha1.MultigresCluster{
277+
Spec: multigresv1alpha1.MultigresClusterSpec{
278+
Databases: []multigresv1alpha1.DatabaseConfig{
279+
{Name: "postgres", Default: true}, // No TableGroups
280+
},
281+
},
282+
},
283+
want: &multigresv1alpha1.MultigresCluster{
284+
Spec: multigresv1alpha1.MultigresClusterSpec{
285+
Images: multigresv1alpha1.ClusterImages{
286+
Postgres: DefaultPostgresImage,
287+
MultiAdmin: DefaultMultiAdminImage,
288+
MultiOrch: DefaultMultiOrchImage,
289+
MultiPooler: DefaultMultiPoolerImage,
290+
MultiGateway: DefaultMultiGatewayImage,
291+
ImagePullPolicy: DefaultImagePullPolicy,
292+
},
293+
TemplateDefaults: multigresv1alpha1.TemplateDefaults{
294+
CoreTemplate: FallbackCoreTemplate,
295+
CellTemplate: FallbackCellTemplate,
296+
ShardTemplate: FallbackShardTemplate,
297+
},
298+
Databases: []multigresv1alpha1.DatabaseConfig{
299+
{
300+
Name: "postgres",
301+
Default: true,
302+
TableGroups: []multigresv1alpha1.TableGroupConfig{
303+
{
304+
Name: DefaultSystemTableGroupName,
305+
Default: true,
306+
},
307+
},
308+
},
309+
},
310+
},
311+
},
312+
},
209313
}
210314

211315
for name, tc := range tests {

pkg/resolver/defaults.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ const (
2121
// FallbackShardTemplate is the name of the template to look for if no specific ShardTemplate is referenced.
2222
FallbackShardTemplate = "default"
2323

24+
// DefaultSystemDatabaseName is the name of the mandatory system database.
25+
DefaultSystemDatabaseName = "postgres"
26+
27+
// DefaultSystemTableGroupName is the name of the mandatory default table group.
28+
DefaultSystemTableGroupName = "default"
29+
2430
// DefaultPostgresImage is the default container image used for PostgreSQL instances.
2531
DefaultPostgresImage = "postgres:15-alpine"
2632

pkg/resolver/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.25.0
44

55
require (
66
github.com/google/go-cmp v0.7.0
7-
github.com/numtide/multigres-operator/api v0.0.0-20251224124005-355869230728
7+
github.com/numtide/multigres-operator/api v0.0.0-20260103121224-057738b43b3b
88
k8s.io/api v0.34.3
99
k8s.io/apimachinery v0.34.3
1010
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4

pkg/resolver/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
8282
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
8383
github.com/numtide/multigres-operator/api v0.0.0-20251224124005-355869230728 h1:a+iM4L0nC7kUgcAD1P+wuNJg4x0rjcy6rVZ3+vF52Cc=
8484
github.com/numtide/multigres-operator/api v0.0.0-20251224124005-355869230728/go.mod h1:A1bBmTxHr+362dGZ5G6u2S4xsP6enbgdUS/UJUOmKbc=
85+
github.com/numtide/multigres-operator/api v0.0.0-20260103121224-057738b43b3b h1:twErev/AdyVQvlYa5vbo5wqq+NlexZJmIm0pwEQd5qI=
86+
github.com/numtide/multigres-operator/api v0.0.0-20260103121224-057738b43b3b/go.mod h1:A1bBmTxHr+362dGZ5G6u2S4xsP6enbgdUS/UJUOmKbc=
8587
github.com/onsi/ginkgo/v2 v2.25.3 h1:Ty8+Yi/ayDAGtk4XxmmfUy4GabvM+MegeB4cDLRi6nw=
8688
github.com/onsi/ginkgo/v2 v2.25.3/go.mod h1:43uiyQC4Ed2tkOzLsEYm7hnrb7UJTWHYNsuy3bG/snE=
8789
github.com/onsi/gomega v1.38.3 h1:eTX+W6dobAYfFeGC2PV6RwXRu/MyT+cQguijutvkpSM=

0 commit comments

Comments
 (0)