Skip to content

Commit 6d7094b

Browse files
authored
Merge pull request #1799 from splunk/feature/database-controllers-base-refactor-2
fix(postgres): address PR review — API validation, type cleanup, controller correctness
2 parents 2a80020 + 0936891 commit 6d7094b

11 files changed

Lines changed: 179 additions & 159 deletions

api/v4/postgrescluster_types.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ type ManagedRole struct {
4444
// Validation rules ensure immutability of Class, and that Storage and PostgresVersion can only be set once and cannot be removed or downgraded.
4545
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.postgresVersion) || (has(self.postgresVersion) && int(self.postgresVersion.split('.')[0]) >= int(oldSelf.postgresVersion.split('.')[0]))",messageExpression="!has(self.postgresVersion) ? 'postgresVersion cannot be removed once set (was: ' + oldSelf.postgresVersion + ')' : 'postgresVersion major version cannot be downgraded (from: ' + oldSelf.postgresVersion + ', to: ' + self.postgresVersion + ')'"
4646
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.storage) || (has(self.storage) && quantity(self.storage).compareTo(quantity(oldSelf.storage)) >= 0)",messageExpression="!has(self.storage) ? 'storage cannot be removed once set (was: ' + string(oldSelf.storage) + ')' : 'storage size cannot be decreased (from: ' + string(oldSelf.storage) + ', to: ' + string(self.storage) + ')'"
47-
// +kubebuilder:validation:XValidation:rule="!has(self.connectionPoolerConfig)",message="connectionPoolerConfig cannot be overridden on PostgresCluster"
47+
4848
type PostgresClusterSpec struct {
4949
// This field is IMMUTABLE after creation.
5050
// +kubebuilder:validation:Required
@@ -92,14 +92,9 @@ type PostgresClusterSpec struct {
9292

9393
// ConnectionPoolerEnabled controls whether PgBouncer connection pooling is deployed for this cluster.
9494
// When set, takes precedence over the class-level connectionPoolerEnabled value.
95-
// +kubebuilder:default=false
9695
// +optional
9796
ConnectionPoolerEnabled *bool `json:"connectionPoolerEnabled,omitempty"`
9897

99-
// Only takes effect when connection pooling is enabled.
100-
// +optional
101-
ConnectionPoolerConfig *ConnectionPoolerConfig `json:"connectionPoolerConfig,omitempty"`
102-
10398
// ManagedRoles contains PostgreSQL roles that should be created in the cluster.
10499
// This field supports Server-Side Apply with per-role granularity, allowing
105100
// multiple PostgresDatabase controllers to manage different roles independently.
@@ -185,6 +180,7 @@ type ConnectionPoolerStatus struct {
185180
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
186181

187182
// PostgresCluster is the Schema for the postgresclusters API.
183+
// +kubebuilder:validation:XValidation:rule="size(self.metadata.name) <= 50",message="name must be 50 characters or fewer to accommodate derived resource names"
188184
type PostgresCluster struct {
189185
metav1.TypeMeta `json:",inline"`
190186
metav1.ObjectMeta `json:"metadata,omitempty"`

api/v4/postgresclusterclass_types.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ import (
2424

2525
// +kubebuilder:validation:XValidation:rule="!has(self.cnpg) || self.provisioner == 'postgresql.cnpg.io'",message="cnpg config can only be set when provisioner is postgresql.cnpg.io"
2626
// +kubebuilder:validation:XValidation:rule="!has(self.config) || !has(self.config.connectionPoolerEnabled) || !self.config.connectionPoolerEnabled || (has(self.cnpg) && has(self.cnpg.connectionPooler))",message="cnpg.connectionPooler must be set when config.connectionPoolerEnabled is true"
27+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="PostgresClusterClass is immutable after creation"
2728
// PostgresClusterClassSpec defines the desired state of PostgresClusterClass.
2829
// PostgresClusterClass is immutable after creation - it serves as a template for Cluster CRs.
30+
2931
type PostgresClusterClassSpec struct {
3032
// Provisioner identifies which database provisioner to use.
3133
// Currently supported: "postgresql.cnpg.io" (CloudNativePG)
@@ -174,9 +176,9 @@ type PostgresClusterClassStatus struct {
174176
// +kubebuilder:subresource:status
175177
// +kubebuilder:resource:scope=Cluster
176178
// +kubebuilder:printcolumn:name="Provisioner",type=string,JSONPath=`.spec.provisioner`
177-
// +kubebuilder:printcolumn:name="Instances",type=integer,JSONPath=`.spec.postgresClusterConfig.instances`
178-
// +kubebuilder:printcolumn:name="Storage",type=string,JSONPath=`.spec.postgresClusterConfig.storage`
179-
// +kubebuilder:printcolumn:name="Version",type=string,JSONPath=`.spec.postgresClusterConfig.postgresVersion`
179+
// +kubebuilder:printcolumn:name="Instances",type=integer,JSONPath=`.spec.config.instances`
180+
// +kubebuilder:printcolumn:name="Storage",type=string,JSONPath=`.spec.config.storage`
181+
// +kubebuilder:printcolumn:name="Version",type=string,JSONPath=`.spec.config.postgresVersion`
180182
// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase`
181183
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
182184

api/v4/postgresdatabase_types.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323

2424
// PostgresDatabaseSpec defines the desired state of PostgresDatabase.
2525
// +kubebuilder:validation:XValidation:rule="self.clusterRef == oldSelf.clusterRef",message="clusterRef is immutable"
26+
// +kubebuilder:validation:XValidation:rule="self.clusterRef.name != ''",message="clusterRef.name must not be empty"
2627
type PostgresDatabaseSpec struct {
2728
// Reference to Postgres Cluster managed by postgresCluster controller
2829
// +kubebuilder:validation:Required
@@ -37,7 +38,9 @@ type PostgresDatabaseSpec struct {
3738

3839
type DatabaseDefinition struct {
3940
// +kubebuilder:validation:Required
41+
// +kubebuilder:validation:MinLength=1
4042
// +kubebuilder:validation:MaxLength=30
43+
// +kubebuilder:validation:Pattern=`^[a-z_][a-z0-9_]*$`
4144
Name string `json:"name"`
4245
Extensions []string `json:"extensions,omitempty"`
4346
// +kubebuilder:validation:Enum=Delete;Retain
@@ -51,7 +54,7 @@ type DatabaseInfo struct {
5154
DatabaseRef *corev1.LocalObjectReference `json:"databaseRef,omitempty"`
5255
AdminUserSecretRef *corev1.SecretKeySelector `json:"adminUserSecretRef,omitempty"`
5356
RWUserSecretRef *corev1.SecretKeySelector `json:"rwUserSecretRef,omitempty"`
54-
ConfigMapRef *corev1.LocalObjectReference `json:"configMap,omitempty"`
57+
ConfigMapRef *corev1.LocalObjectReference `json:"configMapRef,omitempty"`
5558
}
5659

5760
// PostgresDatabaseStatus defines the observed state of PostgresDatabase.
@@ -74,6 +77,7 @@ type PostgresDatabaseStatus struct {
7477
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
7578

7679
// PostgresDatabase is the Schema for the postgresdatabases API.
80+
// +kubebuilder:validation:XValidation:rule="size(self.metadata.name) <= 50",message="name must be 50 characters or fewer to accommodate derived resource names"
7781
type PostgresDatabase struct {
7882
metav1.TypeMeta `json:",inline"`
7983
metav1.ObjectMeta `json:"metadata,omitempty"`

api/v4/zz_generated.deepcopy.go

Lines changed: 0 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/enterprise.splunk.com_postgresclusterclasses.yaml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ spec:
1818
- jsonPath: .spec.provisioner
1919
name: Provisioner
2020
type: string
21-
- jsonPath: .spec.postgresClusterConfig.instances
21+
- jsonPath: .spec.config.instances
2222
name: Instances
2323
type: integer
24-
- jsonPath: .spec.postgresClusterConfig.storage
24+
- jsonPath: .spec.config.storage
2525
name: Storage
2626
type: string
27-
- jsonPath: .spec.postgresClusterConfig.postgresVersion
27+
- jsonPath: .spec.config.postgresVersion
2828
name: Version
2929
type: string
3030
- jsonPath: .status.phase
@@ -58,9 +58,6 @@ spec:
5858
metadata:
5959
type: object
6060
spec:
61-
description: |-
62-
PostgresClusterClassSpec defines the desired state of PostgresClusterClass.
63-
PostgresClusterClass is immutable after creation - it serves as a template for Cluster CRs.
6461
properties:
6562
cnpg:
6663
description: |-
@@ -251,6 +248,8 @@ spec:
251248
is true
252249
rule: '!has(self.config) || !has(self.config.connectionPoolerEnabled)
253250
|| !self.config.connectionPoolerEnabled || (has(self.cnpg) && has(self.cnpg.connectionPooler))'
251+
- message: PostgresClusterClass is immutable after creation
252+
rule: self == oldSelf
254253
status:
255254
description: PostgresClusterClassStatus defines the observed state of
256255
PostgresClusterClass.

config/crd/bases/enterprise.splunk.com_postgresclusters.yaml

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,6 @@ spec:
4747
metadata:
4848
type: object
4949
spec:
50-
description: |-
51-
PostgresClusterSpec defines the desired state of PostgresCluster.
52-
Validation rules ensure immutability of Class, and that Storage and PostgresVersion can only be set once and cannot be removed or downgraded.
5350
properties:
5451
class:
5552
description: This field is IMMUTABLE after creation.
@@ -66,37 +63,7 @@ spec:
6663
- Delete
6764
- Retain
6865
type: string
69-
connectionPoolerConfig:
70-
description: Only takes effect when connection pooling is enabled.
71-
properties:
72-
config:
73-
additionalProperties:
74-
type: string
75-
description: |-
76-
Config contains PgBouncer configuration parameters.
77-
Passed directly to CNPG Pooler spec.pgbouncer.parameters.
78-
See: https://cloudnative-pg.io/docs/1.28/connection_pooling/#pgbouncer-configuration-options
79-
type: object
80-
instances:
81-
default: 3
82-
description: |-
83-
Instances is the number of PgBouncer pod replicas.
84-
Higher values provide better availability and load distribution.
85-
format: int32
86-
maximum: 10
87-
minimum: 1
88-
type: integer
89-
mode:
90-
default: transaction
91-
description: Mode defines the connection pooling strategy.
92-
enum:
93-
- session
94-
- transaction
95-
- statement
96-
type: string
97-
type: object
9866
connectionPoolerEnabled:
99-
default: false
10067
description: |-
10168
ConnectionPoolerEnabled controls whether PgBouncer connection pooling is deployed for this cluster.
10269
When set, takes precedence over the class-level connectionPoolerEnabled value.
@@ -270,8 +237,6 @@ spec:
270237
'' + string(self.storage) + '')'''
271238
rule: '!has(oldSelf.storage) || (has(self.storage) && quantity(self.storage).compareTo(quantity(oldSelf.storage))
272239
>= 0)'
273-
- message: connectionPoolerConfig cannot be overridden on PostgresCluster
274-
rule: '!has(self.connectionPoolerConfig)'
275240
status:
276241
description: PostgresClusterStatus defines the observed state of PostgresCluster.
277242
properties:
@@ -463,6 +428,10 @@ spec:
463428
type: object
464429
type: object
465430
type: object
431+
x-kubernetes-validations:
432+
- message: name must be 50 characters or fewer to accommodate derived resource
433+
names
434+
rule: size(self.metadata.name) <= 50
466435
served: true
467436
storage: true
468437
subresources:

config/crd/bases/enterprise.splunk.com_postgresdatabases.yaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ spec:
7979
type: array
8080
name:
8181
maxLength: 30
82+
minLength: 1
83+
pattern: ^[a-z_][a-z0-9_]*$
8284
type: string
8385
required:
8486
- name
@@ -96,6 +98,8 @@ spec:
9698
x-kubernetes-validations:
9799
- message: clusterRef is immutable
98100
rule: self.clusterRef == oldSelf.clusterRef
101+
- message: clusterRef.name must not be empty
102+
rule: self.clusterRef.name != ''
99103
status:
100104
description: PostgresDatabaseStatus defines the observed state of PostgresDatabase.
101105
properties:
@@ -182,7 +186,7 @@ spec:
182186
- key
183187
type: object
184188
x-kubernetes-map-type: atomic
185-
configMap:
189+
configMapRef:
186190
description: |-
187191
LocalObjectReference contains enough information to let you locate the
188192
referenced object inside the same namespace.
@@ -253,6 +257,10 @@ spec:
253257
type: string
254258
type: object
255259
type: object
260+
x-kubernetes-validations:
261+
- message: name must be 50 characters or fewer to accommodate derived resource
262+
names
263+
rule: size(self.metadata.name) <= 50
256264
served: true
257265
storage: true
258266
subresources:

config/crd/patches/patch_preserve_unknown_fields.yaml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,34 @@ metadata:
4747
spec:
4848
preserveUnknownFields: false
4949

50-
---
50+
---
5151
apiVersion: apiextensions.k8s.io/v1
5252
kind: CustomResourceDefinition
5353
metadata:
5454
name: searchheadclusters.enterprise.splunk.com
55+
spec:
56+
preserveUnknownFields: false
57+
58+
---
59+
apiVersion: apiextensions.k8s.io/v1
60+
kind: CustomResourceDefinition
61+
metadata:
62+
name: postgresclusters.enterprise.splunk.com
63+
spec:
64+
preserveUnknownFields: false
65+
66+
---
67+
apiVersion: apiextensions.k8s.io/v1
68+
kind: CustomResourceDefinition
69+
metadata:
70+
name: postgresclusterclasses.enterprise.splunk.com
71+
spec:
72+
preserveUnknownFields: false
73+
74+
---
75+
apiVersion: apiextensions.k8s.io/v1
76+
kind: CustomResourceDefinition
77+
metadata:
78+
name: postgresdatabases.enterprise.splunk.com
5579
spec:
5680
preserveUnknownFields: false

0 commit comments

Comments
 (0)