Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
8da7761
Correct resource CLI arguments
rytswd Jan 5, 2026
260d579
Update pgctld copy to use different image
rytswd Jan 5, 2026
600c0ec
Ensure watch-targets is passed down
rytswd Jan 5, 2026
ba328fc
Correct image handling for multigateway
rytswd Jan 5, 2026
ca4c7e5
Correct CRD installation
rytswd Jan 5, 2026
b6f0b71
Correct caching logic for coverage CI
rytswd Jan 5, 2026
2de2e5e
Merge remote-tracking branch 'origin/main' into correct-cmd-args
rytswd Jan 5, 2026
9d6dd13
Use server side apply for large CRD def
rytswd Jan 5, 2026
07fbb17
Merge remote-tracking branch 'origin/main' into correct-cmd-args
rytswd Jan 5, 2026
7194674
Update database and tablegroup to be default
rytswd Jan 5, 2026
cd64f48
Add note about MVP implementation
rytswd Jan 5, 2026
2c8af2b
Correct topo server reference
rytswd Jan 5, 2026
a44f32c
Add note about MVP demo specific env
rytswd Jan 5, 2026
d197ae0
Add e2e helper script for data-handler logic
rytswd Jan 5, 2026
7cb9830
Correct target namespace
rytswd Jan 5, 2026
ba775cd
Add temp env variable POSTGRES_HOST_AUTH_METHOD
rytswd Jan 6, 2026
a56ec95
Update pgctld image reference
rytswd Jan 6, 2026
3579585
Merge remote-tracking branch 'origin/main' into correct-cmd-args
rytswd Jan 6, 2026
1cfeb4f
Rename pools in sample
rytswd Jan 6, 2026
9c913d7
Update replica count for pools
rytswd Jan 6, 2026
269070c
Add job setup for topo registration
rytswd Jan 6, 2026
a0608d6
Ensure to use postgres 17
rytswd Jan 6, 2026
0e652cb
Add security context for non-root requirement
rytswd Jan 6, 2026
6b1aaa1
Correct kubeconfig handling
rytswd Jan 6, 2026
a3137ca
Add more const for pooler and pgctld
rytswd Jan 6, 2026
4747d6e
Correct pgctld setup
rytswd Jan 6, 2026
0510044
Correct comment and test spec
rytswd Jan 6, 2026
e74ed1b
Remove unused code
rytswd Jan 7, 2026
40dc20d
Correct service-map and service-id handling
rytswd Jan 7, 2026
0e2c2ba
Use simple image name for pgctld
rytswd Jan 7, 2026
fb282c3
Temporarily remove the second pool from config
rytswd Jan 7, 2026
34b86ae
Ensure to add backup volume
rytswd Jan 7, 2026
084d508
Use pgctld image directly rather than copying
rytswd Jan 8, 2026
31e5d60
Correct socket, add pvc handling
rytswd Jan 8, 2026
72f2f1e
Merge commit 'f0cdef4' into correct-cmd-args
rytswd Jan 8, 2026
6fd0b8e
Update kustomization version
rytswd Jan 8, 2026
2d04650
Add pvc handling
rytswd Jan 8, 2026
219dc9b
Remove unused env variable
rytswd Jan 8, 2026
50b595f
Add pb_hba.conf handling
rytswd Jan 8, 2026
3c2eca1
Add pb_hba handling to container setup
rytswd Jan 8, 2026
2a196ee
Add pg_hba setup and backup volume
rytswd Jan 8, 2026
f7c38a8
Correct with PVC binding and update comments
rytswd Jan 8, 2026
76d27e3
Add test and correct comment reference
rytswd Jan 9, 2026
7f48a65
Update kustomization tag
rytswd Jan 9, 2026
1cd7f5a
Merge remote-tracking branch 'origin/main' into correct-cmd-args
rytswd Jan 9, 2026
461fdd0
Merge remote-tracking branch 'origin/main' into correct-cmd-args
rytswd Jan 9, 2026
721950a
Update api reference
rytswd Jan 9, 2026
5cc1f8f
Add explicit access modes
rytswd Jan 9, 2026
6bfa5f0
Add access mode handling for PVCs
rytswd Jan 9, 2026
c8a032d
Correct pgctld mount path
rytswd Jan 9, 2026
8074979
Correct socket path
rytswd Jan 9, 2026
56764f8
Correct zone
rytswd Jan 9, 2026
dc21184
Correct socket dir input
rytswd Jan 9, 2026
8fd7add
Correct pg_hba template
rytswd Jan 9, 2026
aa5e2fc
Correct zone in multiorch testing
rytswd Jan 9, 2026
18c96b6
Add access mode testing
rytswd Jan 9, 2026
2f1a6da
Add backup volume
rytswd Jan 9, 2026
55306c1
Adjust test spec for postgres container
rytswd Jan 9, 2026
eae66ea
Add all flags in integration test results
rytswd Jan 9, 2026
b8040f2
Add backup PVC related test cases
rytswd Jan 10, 2026
e3e20b2
Fix lint
rytswd Jan 10, 2026
f3d7bb0
Correct copy logic and comment
rytswd Jan 10, 2026
7c81547
Match test cases with updated impl
rytswd Jan 10, 2026
e686f25
Remove old files
rytswd Jan 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -404,12 +404,12 @@ kind-up: ## Create a kind cluster for local development
}
@if $(KIND) get clusters | grep -q "^$(KIND_CLUSTER)$$"; then \
echo "Kind cluster '$(KIND_CLUSTER)' already exists."; \
echo "==> Exporting kubeconfig to $(KIND_KUBECONFIG)"; \
$(KIND) get kubeconfig --name $(KIND_CLUSTER) > $(KIND_KUBECONFIG); \
else \
echo "Creating kind cluster '$(KIND_CLUSTER)'..."; \
$(KIND) create cluster --name $(KIND_CLUSTER); \
$(KIND) create cluster --name $(KIND_CLUSTER) --kubeconfig $(KIND_KUBECONFIG); \
fi
@echo "==> Exporting kubeconfig to $(KIND_KUBECONFIG)"
@$(KIND) get kubeconfig --name $(KIND_CLUSTER) > $(KIND_KUBECONFIG)
@echo "==> Cluster ready. Use: export KUBECONFIG=$(KIND_KUBECONFIG)"

.PHONY: kind-load
Expand All @@ -430,7 +430,7 @@ kind-deploy: kind-up manifests kustomize kind-load ## Deploy operator to kind cl
.PHONY: kind-redeploy
kind-redeploy: kind-load ## Rebuild image, reload to kind, and restart pods
@echo "==> Restarting operator pods..."
KUBECONFIG=$(KIND_KUBECONFIG) $(KUBECTL) rollout restart deployment -n multigres-operator-system
KUBECONFIG=$(KIND_KUBECONFIG) $(KUBECTL) rollout restart deployment -n multigres-operator

.PHONY: kind-down
kind-down: ## Delete the kind cluster
Expand Down
2 changes: 1 addition & 1 deletion config/manager/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ kind: Kustomization
images:
- name: controller
newName: ghcr.io/numtide/multigres-operator
newTag: e2b8632-dirty
newTag: a96d950
4 changes: 0 additions & 4 deletions pkg/resource-handler/controller/cell/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ func TestCellReconciliation(t *testing.T) {
"--pg-port", "15432",
"--topo-global-server-addresses", "global-topo:2379",
"--topo-global-root", "/multigres/global",
"--topo-implementation", "etcd2",
"--cell", "zone1",
},
Ports: []corev1.ContainerPort{
Expand Down Expand Up @@ -201,7 +200,6 @@ func TestCellReconciliation(t *testing.T) {
"--pg-port", "15432",
"--topo-global-server-addresses", "global-topo:2379",
"--topo-global-root", "/multigres/global",
"--topo-implementation", "etcd2",
"--cell", "zone2",
},
Ports: []corev1.ContainerPort{
Expand Down Expand Up @@ -288,7 +286,6 @@ func TestCellReconciliation(t *testing.T) {
"--pg-port", "15432",
"--topo-global-server-addresses", "global-topo:2379",
"--topo-global-root", "/multigres/global",
"--topo-implementation", "etcd2",
"--cell", "zone3",
},
Ports: []corev1.ContainerPort{
Expand Down Expand Up @@ -392,7 +389,6 @@ func TestCellReconciliation(t *testing.T) {
"--pg-port", "15432",
"--topo-global-server-addresses", "global-topo:2379",
"--topo-global-root", "/multigres/global",
"--topo-implementation", "etcd2",
"--cell", "zone4",
},
Ports: []corev1.ContainerPort{
Expand Down
1 change: 0 additions & 1 deletion pkg/resource-handler/controller/cell/multigateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ func BuildMultiGatewayDeployment(
"--pg-port", fmt.Sprintf("%d", MultiGatewayPostgresPort),
"--topo-global-server-addresses", cell.Spec.GlobalTopoServer.Address,
"--topo-global-root", cell.Spec.GlobalTopoServer.RootPath,
"--topo-implementation", cell.Spec.GlobalTopoServer.Implementation,
"--cell", cell.Spec.Name,
},
Resources: cell.Spec.MultiGateway.Resources,
Expand Down
5 changes: 0 additions & 5 deletions pkg/resource-handler/controller/cell/multigateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ func TestBuildMultiGatewayDeployment(t *testing.T) {
"--pg-port", "15432",
"--topo-global-server-addresses", "global-topo:2379",
"--topo-global-root", "/multigres/global",
"--topo-implementation", "etcd2",
"--cell", "zone1",
},
Resources: corev1.ResourceRequirements{},
Expand Down Expand Up @@ -200,7 +199,6 @@ func TestBuildMultiGatewayDeployment(t *testing.T) {
"--pg-port", "15432",
"--topo-global-server-addresses", "global-topo:2379",
"--topo-global-root", "/multigres/global",
"--topo-implementation", "etcd2",
"--cell", "zone2",
},
Resources: corev1.ResourceRequirements{},
Expand Down Expand Up @@ -303,7 +301,6 @@ func TestBuildMultiGatewayDeployment(t *testing.T) {
"--pg-port", "15432",
"--topo-global-server-addresses", "global-topo:2379",
"--topo-global-root", "/multigres/global",
"--topo-implementation", "etcd2",
"--cell", "zone3",
},
Resources: corev1.ResourceRequirements{},
Expand Down Expand Up @@ -422,7 +419,6 @@ func TestBuildMultiGatewayDeployment(t *testing.T) {
"--pg-port", "15432",
"--topo-global-server-addresses", "global-topo:2379",
"--topo-global-root", "/multigres/global",
"--topo-implementation", "etcd2",
"--cell", "zone4",
},
Resources: corev1.ResourceRequirements{},
Expand Down Expand Up @@ -551,7 +547,6 @@ func TestBuildMultiGatewayDeployment(t *testing.T) {
"--pg-port", "15432",
"--topo-global-server-addresses", "global-topo:2379",
"--topo-global-root", "/multigres/global",
"--topo-implementation", "etcd2",
"--cell", "zone5",
},
Resources: corev1.ResourceRequirements{
Expand Down
55 changes: 55 additions & 0 deletions pkg/resource-handler/controller/shard/configmap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package shard

import (
_ "embed"
"fmt"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"

multigresv1alpha1 "github.com/numtide/multigres-operator/api/v1alpha1"
)

// DefaultPgHbaTemplate is the default pg_hba.conf template for pooler instances.
// Uses trust authentication for testing/development. Production deployments should
// override this with proper authentication (scram-sha-256, SSL certificates, etc.).
//
//go:embed templates/pg_hba_template.conf
var DefaultPgHbaTemplate string

// BuildPgHbaConfigMap creates a ConfigMap containing the pg_hba.conf template.
// This ConfigMap is shared across all pools in a shard and mounted into postgres containers.
func BuildPgHbaConfigMap(
shard *multigresv1alpha1.Shard,
scheme *runtime.Scheme,
) (*corev1.ConfigMap, error) {
// TODO: Add Shard.Spec.PgHbaTemplate field to allow custom templates
template := DefaultPgHbaTemplate

labels := map[string]string{
"app.kubernetes.io/name": "multigres",
"app.kubernetes.io/instance": shard.Name,
"app.kubernetes.io/component": "pg-hba-config",
"app.kubernetes.io/part-of": "multigres",
"app.kubernetes.io/managed-by": "multigres-operator",
}

cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: PgHbaConfigMapName,
Namespace: shard.Namespace,
Labels: labels,
},
Data: map[string]string{
"pg_hba_template.conf": template,
},
}

if err := ctrl.SetControllerReference(shard, cm, scheme); err != nil {
return nil, fmt.Errorf("failed to set controller reference: %w", err)
}

return cm, nil
}
172 changes: 172 additions & 0 deletions pkg/resource-handler/controller/shard/configmap_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package shard

import (
"strings"
"testing"

"github.com/google/go-cmp/cmp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/ptr"

multigresv1alpha1 "github.com/numtide/multigres-operator/api/v1alpha1"
)

func TestBuildPgHbaConfigMap(t *testing.T) {
defaultScheme := runtime.NewScheme()
_ = multigresv1alpha1.AddToScheme(defaultScheme)

tests := map[string]struct {
shard *multigresv1alpha1.Shard
scheme *runtime.Scheme
wantErr bool
}{
"creates configmap with default template": {
shard: &multigresv1alpha1.Shard{
ObjectMeta: metav1.ObjectMeta{
Name: "test-shard",
Namespace: "default",
UID: "test-uid",
},
},
wantErr: false,
},
"creates configmap with correct embedded template": {
shard: &multigresv1alpha1.Shard{
ObjectMeta: metav1.ObjectMeta{
Name: "production-shard",
Namespace: "prod",
UID: "prod-uid",
},
},
wantErr: false,
},
"returns error when scheme is invalid (missing Shard kind)": {
shard: &multigresv1alpha1.Shard{
ObjectMeta: metav1.ObjectMeta{
Name: "error-shard",
Namespace: "default",
UID: "error-uid",
},
},
scheme: runtime.NewScheme(), // Empty scheme
wantErr: true,
},
}

for name, tc := range tests {
t.Run(name, func(t *testing.T) {
scheme := tc.scheme
if scheme == nil {
scheme = defaultScheme
}

cm, err := BuildPgHbaConfigMap(tc.shard, scheme)
if (err != nil) != tc.wantErr {
t.Fatalf("BuildPgHbaConfigMap() error = %v, wantErr %v", err, tc.wantErr)
}

if tc.wantErr {
return
}

if cm.Name != PgHbaConfigMapName {
t.Errorf("ConfigMap name = %v, want %v", cm.Name, PgHbaConfigMapName)
}
if cm.Namespace != tc.shard.Namespace {
t.Errorf("ConfigMap namespace = %v, want %v", cm.Namespace, tc.shard.Namespace)
}

// Verify owner reference
if len(cm.OwnerReferences) != 1 {
t.Fatalf("Expected 1 owner reference, got %d", len(cm.OwnerReferences))
}
ownerRef := cm.OwnerReferences[0]
if ownerRef.Name != tc.shard.Name || ownerRef.Kind != "Shard" {
t.Errorf("Owner reference = %+v, want Shard/%s", ownerRef, tc.shard.Name)
}
if !ptr.Deref(ownerRef.Controller, false) {
t.Error("Expected owner reference to be controller")
}

// Verify labels
expectedLabels := map[string]string{
"app.kubernetes.io/name": "multigres",
"app.kubernetes.io/instance": tc.shard.Name,
"app.kubernetes.io/component": "pg-hba-config",
"app.kubernetes.io/part-of": "multigres",
"app.kubernetes.io/managed-by": "multigres-operator",
}
if diff := cmp.Diff(expectedLabels, cm.Labels); diff != "" {
t.Errorf("Labels mismatch (-want +got):\n%s", diff)
}

// Verify template content exists
template, ok := cm.Data["pg_hba_template.conf"]
if !ok {
t.Fatal("ConfigMap missing pg_hba_template.conf key")
}

// Verify the template matches what's embedded (source of truth)
if template != DefaultPgHbaTemplate {
t.Error("Template content doesn't match DefaultPgHbaTemplate")
}
})
}
}

func TestDefaultPgHbaTemplateEmbedded(t *testing.T) {
// Verify the embedded template is not empty
if DefaultPgHbaTemplate == "" {
t.Error("DefaultPgHbaTemplate is empty - go:embed may have failed")
}

// Verify critical configuration lines exist
// We check for the presence of rules, ignoring multiple spaces
checks := []struct {
desc string
mustContain []string
}{
{
desc: "header",
mustContain: []string{"# PostgreSQL Client Authentication"},
},
{
desc: "local trust rule",
mustContain: []string{"local", "all", "{{.User}}", "trust"},
},
{
desc: "replication trust rule",
mustContain: []string{"host", "replication", "all", "0.0.0.0/0", "trust"},
},
{
desc: "production warning",
mustContain: []string{"PRODUCTION:", "scram-sha-256"},
},
}

for _, check := range checks {
found := false
lines := strings.Split(DefaultPgHbaTemplate, "\n")
for _, line := range lines {
allMatch := true
for _, part := range check.mustContain {
if !strings.Contains(line, part) {
allMatch = false
break
}
}
if allMatch {
found = true
break
}
}
if !found {
t.Errorf(
"DefaultPgHbaTemplate missing %s (expected line containing all of: %v)",
check.desc,
check.mustContain,
)
}
}
}
Loading