diff --git a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml index 594b73af5..2d67c385c 100644 --- a/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml +++ b/build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml @@ -28778,6 +28778,8 @@ spec: and is true rule: '!has(self.users) || self.postgresVersion >= 15 || self.users.all(u, !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)' + - message: CRVersion must be a valid semantic version + rule: '!has(self.crVersion) || self.crVersion == "" || self.crVersion.matches(''^[0-9]+\\.[0-9]+\\.[0-9]+(-[a-zA-Z0-9.+-]+)?$'')' status: properties: conditions: diff --git a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml index 195fd6a63..6cabac1c9 100644 --- a/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml +++ b/config/crd/bases/pgv2.percona.com_perconapgclusters.yaml @@ -29473,6 +29473,8 @@ spec: and is true rule: '!has(self.users) || self.postgresVersion >= 15 || self.users.all(u, !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)' + - message: CRVersion must be a valid semantic version + rule: '!has(self.crVersion) || self.crVersion == "" || self.crVersion.matches(''^[0-9]+\\.[0-9]+\\.[0-9]+(-[a-zA-Z0-9.+-]+)?$'')' status: properties: conditions: diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index aa9ffe309..06dd13fc6 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -29770,6 +29770,8 @@ spec: and is true rule: '!has(self.users) || self.postgresVersion >= 15 || self.users.all(u, !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)' + - message: CRVersion must be a valid semantic version + rule: '!has(self.crVersion) || self.crVersion == "" || self.crVersion.matches(''^[0-9]+\\.[0-9]+\\.[0-9]+(-[a-zA-Z0-9.+-]+)?$'')' status: properties: conditions: diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 505329580..cca53bb00 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -29770,6 +29770,8 @@ spec: and is true rule: '!has(self.users) || self.postgresVersion >= 15 || self.users.all(u, !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)' + - message: CRVersion must be a valid semantic version + rule: '!has(self.crVersion) || self.crVersion == "" || self.crVersion.matches(''^[0-9]+\\.[0-9]+\\.[0-9]+(-[a-zA-Z0-9.+-]+)?$'')' status: properties: conditions: diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 0216f2dda..3b992f318 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -29770,6 +29770,8 @@ spec: and is true rule: '!has(self.users) || self.postgresVersion >= 15 || self.users.all(u, !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)' + - message: CRVersion must be a valid semantic version + rule: '!has(self.crVersion) || self.crVersion == "" || self.crVersion.matches(''^[0-9]+\\.[0-9]+\\.[0-9]+(-[a-zA-Z0-9.+-]+)?$'')' status: properties: conditions: diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go index 7231fc176..e7164469f 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go @@ -52,6 +52,7 @@ type PerconaPGCluster struct { } // +kubebuilder:validation:XValidation:rule="!has(self.users) || self.postgresVersion >= 15 || self.users.all(u, !has(u.grantPublicSchemaAccess) || !u.grantPublicSchemaAccess)",message="PostgresVersion must be >= 15 if grantPublicSchemaAccess exists and is true" +// +kubebuilder:validation:XValidation:rule="!has(self.crVersion) || self.crVersion == \"\" || self.crVersion.matches('^[0-9]+\\\\.[0-9]+\\\\.[0-9]+(-[a-zA-Z0-9.+-]+)?$')",message="CRVersion must be a valid semantic version" type PerconaPGClusterSpec struct { // +optional Metadata *crunchyv1beta1.Metadata `json:"metadata,omitempty"` @@ -505,7 +506,11 @@ func (cr *PerconaPGCluster) ToCrunchy(ctx context.Context, postgresCluster *crun } func (cr *PerconaPGCluster) Version() *gover.Version { - return gover.Must(gover.NewVersion(cr.Spec.CRVersion)) + crVersion := cr.Spec.CRVersion + if crVersion == "" { + crVersion = version.Version() + } + return gover.Must(gover.NewVersion(crVersion)) } func (cr *PerconaPGCluster) CompareVersion(ver string) int { diff --git a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go index 693640fb2..32bc035e5 100644 --- a/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go +++ b/pkg/apis/pgv2.percona.com/v2/perconapgcluster_types_test.go @@ -65,6 +65,25 @@ func TestPerconaPGCluster_Validate(t *testing.T) { }) } +func TestPerconaPGCluster_Version(t *testing.T) { + t.Run("empty CRVersion does not crash", func(t *testing.T) { + cr := new(PerconaPGCluster) + // cr.Version() should not panic when CRVersion is empty + ver := cr.Version() + require.NotNil(t, ver) + // Should return the default operator version + assert.Equal(t, version.Version(), ver.String()) + }) + + t.Run("valid CRVersion is parsed correctly", func(t *testing.T) { + cr := new(PerconaPGCluster) + cr.Spec.CRVersion = "2.5.0" + ver := cr.Version() + require.NotNil(t, ver) + assert.Equal(t, "2.5.0", ver.String()) + }) +} + func TestPerconaPGCluster_Proxy(t *testing.T) { t.Run("Proxy is nil, CRVersion < 2.9.0", func(t *testing.T) { cr := new(PerconaPGCluster)