From 6eee4fd0f80737fb3bb26ef61ad98e188c6900ae Mon Sep 17 00:00:00 2001 From: Chris Bandy Date: Wed, 19 Mar 2025 11:13:36 -0500 Subject: [PATCH 1/2] Document how "schemaless" interacts with CEL rules --- .../v1beta1/shared_types.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go index 281370a40..f2e15e66f 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go @@ -139,12 +139,18 @@ func (spec *VolumeClaimSpec) AsPersistentVolumeClaimSpec() corev1.PersistentVolu return out } +// --- // SchemalessObject is a map compatible with JSON object. // // Use with the following markers: -// - kubebuilder:pruning:PreserveUnknownFields -// - kubebuilder:validation:Schemaless -// - kubebuilder:validation:Type=object +// - kubebuilder:pruning:PreserveUnknownFields +// - kubebuilder:validation:Schemaless +// - kubebuilder:validation:Type=object +// +// NOTE: PreserveUnknownFields allows arbitrary values within fields of this +// type but also prevents any validation rules from reaching inside; its CEL +// type is "object" or "message" with zero fields: +// https://kubernetes.io/docs/reference/using-api/cel/#type-system-integration type SchemalessObject map[string]any // DeepCopy creates a new SchemalessObject by copying the receiver. From 7587678316ded2a484617564f80d542c60c70228 Mon Sep 17 00:00:00 2001 From: Chris Bandy Date: Wed, 19 Mar 2025 11:14:31 -0500 Subject: [PATCH 2/2] Ensure Duration.AsDuration returns a copy --- .../v1beta1/shared_types.go | 2 +- .../v1beta1/shared_types_test.go | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go index f2e15e66f..c185cd4b2 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types.go @@ -81,7 +81,7 @@ func NewDuration(s string) (*Duration, error) { return &Duration{metav1.Duration(umd), s}, err } -// AsDuration returns d as a [metav1.Duration]. +// AsDuration returns a copy of d as a [metav1.Duration]. func (d *Duration) AsDuration() metav1.Duration { return d.parsed } diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types_test.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types_test.go index e4101b672..c4c2fe65f 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types_test.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/shared_types_test.go @@ -16,6 +16,23 @@ import ( "sigs.k8s.io/yaml" ) +func TestDurationAsDuration(t *testing.T) { + t.Parallel() + + v, err := NewDuration("2s") + assert.NilError(t, err) + + // get the value + other := v.AsDuration() + assert.Equal(t, other.Duration, 2*time.Second, + "expected the same value as the original") + + // change the copy + other.Duration = time.Hour + assert.Equal(t, v.AsDuration().Duration, 2*time.Second, + "expected no effect on the original value") +} + func TestDurationYAML(t *testing.T) { t.Parallel()