Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 9b7ac1b

Browse files
committed
Make ImageVolumeSource.Reference required via OpenAPI
OpenAPI validation does not count toward the CRD XValidation CEL budget.
1 parent da69a57 commit 9b7ac1b

File tree

12 files changed

+233
-115
lines changed

12 files changed

+233
-115
lines changed

‎config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2620,7 +2620,9 @@ spec:
26202620
type: array
26212621
x-kubernetes-list-type: set
26222622
image:
2623-
description: Details for adding an image volume
2623+
description: |-
2624+
Reference to an image or OCI artifact.
2625+
More info: https://kubernetes.io/docs/concepts/storage/volumes#image
26242626
properties:
26252627
pullPolicy:
26262628
description: |-
@@ -2629,6 +2631,11 @@ spec:
26292631
Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present.
26302632
IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails.
26312633
Defaults to Always if :latest tag is specified, or IfNotPresent otherwise.
2634+
enum:
2635+
- Always
2636+
- Never
2637+
- IfNotPresent
2638+
maxLength: 12
26322639
type: string
26332640
reference:
26342641
description: |-
@@ -2638,7 +2645,10 @@ spec:
26382645
More info: https://kubernetes.io/docs/concepts/containers/images
26392646
This field is optional to allow higher level config management to default or override
26402647
container images in workload controllers like Deployments and StatefulSets.
2648+
minLength: 1
26412649
type: string
2650+
required:
2651+
- reference
26422652
type: object
26432653
name:
26442654
description: |-
@@ -2659,11 +2669,8 @@ spec:
26592669
x-kubernetes-validations:
26602670
- message: you must set only one of image or claimName
26612671
rule: has(self.claimName) != has(self.image)
2662-
- message: readOnly cannot be set false when using an ImageVolumeSource
2672+
- message: image volumes must be readOnly
26632673
rule: '!has(self.image) || !has(self.readOnly) || self.readOnly'
2664-
- message: if using an ImageVolumeSource, you must set a reference
2665-
rule: '!has(self.image) || (self.?image.reference.hasValue()
2666-
&& self.image.reference.size() > 0)'
26672674
maxItems: 10
26682675
type: array
26692676
x-kubernetes-list-map-keys:

‎config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml‎

Lines changed: 168 additions & 98 deletions
Large diffs are not rendered by default.

‎internal/crd/post-process.jq‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,26 @@
33
# SPDX-License-Identifier: Apache-2.0
44
#
55
# This [jq] filter modifies a Kubernetes CustomResourceDefinition.
6+
# Use the controller-gen "+kubebuilder:title" marker to identify schemas that need special manipulation.
67
#
78
# [jq]: https://jqlang.org
89

910
# merge recursively combines a stream of objects.
1011
# https://jqlang.org/manual#multiplication-division-modulo
1112
def merge(stream): reduce stream as $i ({}; . * $i);
1213

14+
# https://pkg.go.dev/k8s.io/api/core/v1#ImageVolumeSource
15+
reduce paths(try .title == "$corev1.ImageVolumeSource") as $path (.;
16+
getpath($path) as $schema |
17+
setpath($path; $schema * {
18+
required: (["reference"] + ($schema.required // []) | sort),
19+
properties: {
20+
pullPolicy: { enum: ["Always", "Never", "IfNotPresent"] },
21+
reference: { minLength: 1 }
22+
}
23+
} | del(.title))
24+
) |
25+
1326
# Kubernetes assumes the evaluation cost of an enum value is very large: https://issue.k8s.io/119511
1427
# Look at every schema that has a populated "enum" property.
1528
reduce paths(try .enum | length > 0) as $path (.;
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

‎internal/testing/validation/postgrescluster_test.go‎ renamed to ‎internal/crd/validation/postgrescluster_test.go‎

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"sigs.k8s.io/controller-runtime/pkg/client"
1515
"sigs.k8s.io/yaml"
1616

17+
"github.com/crunchydata/postgres-operator/internal/testing/cmp"
1718
"github.com/crunchydata/postgres-operator/internal/testing/require"
1819
v1 "github.com/crunchydata/postgres-operator/pkg/apis/postgres-operator.crunchydata.com/v1"
1920
"github.com/crunchydata/postgres-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1"
@@ -110,6 +111,7 @@ func TestPostgresUserInterfaceAcrossVersions(t *testing.T) {
110111
func TestAdditionalVolumes(t *testing.T) {
111112
ctx := context.Background()
112113
cc := require.KubernetesAtLeast(t, "1.30")
114+
dryrun := client.NewDryRunClient(cc)
113115
t.Parallel()
114116

115117
namespace := require.Namespace(t, cc)
@@ -154,8 +156,13 @@ func TestAdditionalVolumes(t *testing.T) {
154156
}]
155157
}
156158
}]`, "spec", "instances")
157-
err := cc.Create(ctx, tmp.DeepCopy(), client.DryRunAll)
159+
160+
err := dryrun.Create(ctx, tmp.DeepCopy())
158161
assert.Assert(t, apierrors.IsInvalid(err))
162+
163+
details := require.StatusErrorDetails(t, err)
164+
assert.Assert(t, cmp.Len(details.Causes, 1))
165+
assert.Equal(t, details.Causes[0].Field, "spec.instances[0].volumes.additional[0]")
159166
assert.ErrorContains(t, err, "you must set only one of image or claimName")
160167
})
161168

@@ -178,9 +185,14 @@ func TestAdditionalVolumes(t *testing.T) {
178185
}]
179186
}
180187
}]`, "spec", "instances")
181-
err := cc.Create(ctx, tmp.DeepCopy(), client.DryRunAll)
188+
189+
err := dryrun.Create(ctx, tmp.DeepCopy())
182190
assert.Assert(t, apierrors.IsInvalid(err))
183-
assert.ErrorContains(t, err, "readOnly cannot be set false when using an ImageVolumeSource")
191+
192+
details := require.StatusErrorDetails(t, err)
193+
assert.Assert(t, cmp.Len(details.Causes, 1))
194+
assert.Equal(t, details.Causes[0].Field, "spec.instances[0].volumes.additional[0]")
195+
assert.ErrorContains(t, err, "image volumes must be readOnly")
184196
})
185197

186198
t.Run("Reference must be set when using image volume", func(t *testing.T) {
@@ -201,9 +213,15 @@ func TestAdditionalVolumes(t *testing.T) {
201213
}]
202214
}
203215
}]`, "spec", "instances")
204-
err := cc.Create(ctx, tmp.DeepCopy(), client.DryRunAll)
216+
217+
err := dryrun.Create(ctx, tmp.DeepCopy())
205218
assert.Assert(t, apierrors.IsInvalid(err))
206-
assert.ErrorContains(t, err, "if using an ImageVolumeSource, you must set a reference")
219+
220+
details := require.StatusErrorDetails(t, err)
221+
assert.Assert(t, cmp.Len(details.Causes, 2))
222+
assert.Assert(t, cmp.Equal(details.Causes[0].Field, "spec.instances[0].volumes.additional[0].image.reference"))
223+
assert.Assert(t, cmp.Equal(details.Causes[0].Type, "FieldValueRequired"))
224+
assert.ErrorContains(t, err, "Required")
207225
})
208226

209227
t.Run("Reference cannot be an empty string when using image volume", func(t *testing.T) {
@@ -225,9 +243,15 @@ func TestAdditionalVolumes(t *testing.T) {
225243
}]
226244
}
227245
}]`, "spec", "instances")
228-
err := cc.Create(ctx, tmp.DeepCopy(), client.DryRunAll)
246+
247+
err := dryrun.Create(ctx, tmp.DeepCopy())
229248
assert.Assert(t, apierrors.IsInvalid(err))
230-
assert.ErrorContains(t, err, "if using an ImageVolumeSource, you must set a reference")
249+
250+
details := require.StatusErrorDetails(t, err)
251+
assert.Assert(t, cmp.Len(details.Causes, 1))
252+
assert.Assert(t, cmp.Equal(details.Causes[0].Field, "spec.instances[0].volumes.additional[0].image.reference"))
253+
assert.Assert(t, cmp.Equal(details.Causes[0].Type, "FieldValueInvalid"))
254+
assert.ErrorContains(t, err, "at least 1 chars long")
231255
})
232256

233257
t.Run("ReadOnly can be omitted or set true when using image volume", func(t *testing.T) {
@@ -265,6 +289,6 @@ func TestAdditionalVolumes(t *testing.T) {
265289
}]
266290
}
267291
}]`, "spec", "instances")
268-
assert.NilError(t, cc.Create(ctx, tmp.DeepCopy(), client.DryRunAll))
292+
assert.NilError(t, dryrun.Create(ctx, tmp.DeepCopy()))
269293
})
270294
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /