Skip to content

Commit a16409e

Browse files
fix CEL validation error message format introduced by Kubernetes v1.35
Kubernetes v1.35 changed CEL validation error message format to include the actual validated value instead of just the type ("string" or "object"). This provides more helpful error messages for debugging validation failures. Changes: - Update test expectations to include actual values in error messages - Change from "Invalid value: \"string\"" to "Invalid value: \"actual-value\"" - Change from "Invalid value: \"object\"" to "Invalid value:" for object validations - Update 20+ test cases in TestImageSourceCELValidationRules and related tests Assisted-by: Cursor/Claude
1 parent 87a45d4 commit a16409e

3 files changed

Lines changed: 37 additions & 23 deletions

File tree

api/v1/clustercatalog_types_test.go

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func TestImageSourceCELValidationRules(t *testing.T) {
3838
PollIntervalMinutes: ptr.To(1),
3939
},
4040
wantErrs: []string{
41-
"openAPIV3Schema.properties.spec.properties.source.properties.image: Invalid value: \"object\": cannot specify pollIntervalMinutes while using digest-based image",
41+
"openAPIV3Schema.properties.spec.properties.source.properties.image: Invalid value: cannot specify pollIntervalMinutes while using digest-based image",
4242
},
4343
},
4444
"valid digest based image ref, poll interval not allowed, poll interval not specified": {
@@ -52,63 +52,63 @@ func TestImageSourceCELValidationRules(t *testing.T) {
5252
Ref: "-quay+docker/foo/bar@sha256:abcdef123456789abcdef123456789abc",
5353
},
5454
wantErrs: []string{
55-
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": must start with a valid domain. valid domains must be alphanumeric characters (lowercase and uppercase) separated by the \".\" character.",
55+
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"-quay+docker/foo/bar@sha256:abcdef123456789abcdef123456789abc\": must start with a valid domain. valid domains must be alphanumeric characters (lowercase and uppercase) separated by the \".\" character.",
5656
},
5757
},
5858
"invalid digest based image ref, invalid name": {
5959
spec: ImageSource{
6060
Ref: "docker.io/FOO/BAR@sha256:abcdef123456789abcdef123456789abc",
6161
},
6262
wantErrs: []string{
63-
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": a valid name is required. valid names must contain lowercase alphanumeric characters separated only by the \".\", \"_\", \"__\", \"-\" characters.",
63+
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"docker.io/FOO/BAR@sha256:abcdef123456789abcdef123456789abc\": a valid name is required. valid names must contain lowercase alphanumeric characters separated only by the \".\", \"_\", \"__\", \"-\" characters.",
6464
},
6565
},
6666
"invalid digest based image ref, invalid digest algorithm": {
6767
spec: ImageSource{
6868
Ref: "docker.io/foo/bar@99-problems:abcdef123456789abcdef123456789abc",
6969
},
7070
wantErrs: []string{
71-
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": digest algorithm is not valid. valid algorithms must start with an uppercase or lowercase alpha character followed by alphanumeric characters and may contain the \"-\", \"_\", \"+\", and \".\" characters.",
71+
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"docker.io/foo/bar@99-problems:abcdef123456789abcdef123456789abc\": digest algorithm is not valid. valid algorithms must start with an uppercase or lowercase alpha character followed by alphanumeric characters and may contain the \"-\", \"_\", \"+\", and \".\" characters.",
7272
},
7373
},
7474
"invalid digest based image ref, too short digest encoding": {
7575
spec: ImageSource{
7676
Ref: "docker.io/foo/bar@sha256:abcdef123456789",
7777
},
7878
wantErrs: []string{
79-
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": digest is not valid. the encoded string must be at least 32 characters",
79+
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"docker.io/foo/bar@sha256:abcdef123456789\": digest is not valid. the encoded string must be at least 32 characters",
8080
},
8181
},
8282
"invalid digest based image ref, invalid characters in digest encoding": {
8383
spec: ImageSource{
8484
Ref: "docker.io/foo/bar@sha256:XYZxy123456789abcdef123456789abc",
8585
},
8686
wantErrs: []string{
87-
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": digest is not valid. the encoded string must only contain hex characters (A-F, a-f, 0-9)",
87+
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"docker.io/foo/bar@sha256:XYZxy123456789abcdef123456789abc\": digest is not valid. the encoded string must only contain hex characters (A-F, a-f, 0-9)",
8888
},
8989
},
9090
"invalid image ref, no tag or digest": {
9191
spec: ImageSource{
9292
Ref: "docker.io/foo/bar",
9393
},
9494
wantErrs: []string{
95-
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": must end with a digest or a tag",
95+
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"docker.io/foo/bar\": must end with a digest or a tag",
9696
},
9797
},
9898
"invalid tag based image ref, tag too long": {
9999
spec: ImageSource{
100100
Ref: fmt.Sprintf("docker.io/foo/bar:%s", strings.Repeat("x", 128)),
101101
},
102102
wantErrs: []string{
103-
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": tag is invalid. the tag must not be more than 127 characters",
103+
fmt.Sprintf("openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"docker.io/foo/bar:%s\": tag is invalid. the tag must not be more than 127 characters", strings.Repeat("x", 128)),
104104
},
105105
},
106106
"invalid tag based image ref, tag contains invalid characters": {
107107
spec: ImageSource{
108108
Ref: "docker.io/foo/bar:-foo_bar-",
109109
},
110110
wantErrs: []string{
111-
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": tag is invalid. valid tags must begin with a word character (alphanumeric + \"_\") followed by word characters or \".\", and \"-\" characters",
111+
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"docker.io/foo/bar:-foo_bar-\": tag is invalid. valid tags must begin with a word character (alphanumeric + \"_\") followed by word characters or \".\", and \"-\" characters",
112112
},
113113
},
114114
"valid tag based image ref": {
@@ -129,7 +129,7 @@ func TestImageSourceCELValidationRules(t *testing.T) {
129129
Ref: "docker.io:8080",
130130
},
131131
wantErrs: []string{
132-
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"string\": a valid name is required. valid names must contain lowercase alphanumeric characters separated only by the \".\", \"_\", \"__\", \"-\" characters.",
132+
"openAPIV3Schema.properties.spec.properties.source.properties.image.ref: Invalid value: \"docker.io:8080\": a valid name is required. valid names must contain lowercase alphanumeric characters separated only by the \".\", \"_\", \"__\", \"-\" characters.",
133133
},
134134
},
135135
"valid image ref, domain with port": {
@@ -179,64 +179,64 @@ func TestResolvedImageSourceCELValidation(t *testing.T) {
179179
Ref: "-quay+docker/foo/bar@sha256:abcdef123456789abcdef123456789abc",
180180
},
181181
wantErrs: []string{
182-
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": must start with a valid domain. valid domains must be alphanumeric characters (lowercase and uppercase) separated by the \".\" character.",
182+
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"-quay+docker/foo/bar@sha256:abcdef123456789abcdef123456789abc\": must start with a valid domain. valid domains must be alphanumeric characters (lowercase and uppercase) separated by the \".\" character.",
183183
},
184184
},
185185
"invalid digest based image ref, invalid name": {
186186
spec: ImageSource{
187187
Ref: "docker.io/FOO/BAR@sha256:abcdef123456789abcdef123456789abc",
188188
},
189189
wantErrs: []string{
190-
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": a valid name is required. valid names must contain lowercase alphanumeric characters separated only by the \".\", \"_\", \"__\", \"-\" characters.",
190+
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"docker.io/FOO/BAR@sha256:abcdef123456789abcdef123456789abc\": a valid name is required. valid names must contain lowercase alphanumeric characters separated only by the \".\", \"_\", \"__\", \"-\" characters.",
191191
},
192192
},
193193
"invalid digest based image ref, invalid digest algorithm": {
194194
spec: ImageSource{
195195
Ref: "docker.io/foo/bar@99-problems:abcdef123456789abcdef123456789abc",
196196
},
197197
wantErrs: []string{
198-
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": digest algorithm is not valid. valid algorithms must start with an uppercase or lowercase alpha character followed by alphanumeric characters and may contain the \"-\", \"_\", \"+\", and \".\" characters.",
198+
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"docker.io/foo/bar@99-problems:abcdef123456789abcdef123456789abc\": digest algorithm is not valid. valid algorithms must start with an uppercase or lowercase alpha character followed by alphanumeric characters and may contain the \"-\", \"_\", \"+\", and \".\" characters.",
199199
},
200200
},
201201
"invalid digest based image ref, too short digest encoding": {
202202
spec: ImageSource{
203203
Ref: "docker.io/foo/bar@sha256:abcdef123456789",
204204
},
205205
wantErrs: []string{
206-
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": digest is not valid. the encoded string must be at least 32 characters",
206+
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"docker.io/foo/bar@sha256:abcdef123456789\": digest is not valid. the encoded string must be at least 32 characters",
207207
},
208208
},
209209
"invalid digest based image ref, invalid characters in digest encoding": {
210210
spec: ImageSource{
211211
Ref: "docker.io/foo/bar@sha256:XYZxy123456789abcdef123456789abc",
212212
},
213213
wantErrs: []string{
214-
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": digest is not valid. the encoded string must only contain hex characters (A-F, a-f, 0-9)",
214+
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"docker.io/foo/bar@sha256:XYZxy123456789abcdef123456789abc\": digest is not valid. the encoded string must only contain hex characters (A-F, a-f, 0-9)",
215215
},
216216
},
217217
"invalid image ref, no digest": {
218218
spec: ImageSource{
219219
Ref: "docker.io/foo/bar",
220220
},
221221
wantErrs: []string{
222-
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": must end with a digest",
222+
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"docker.io/foo/bar\": must end with a digest",
223223
},
224224
},
225225
"invalid image ref, only domain with port": {
226226
spec: ImageSource{
227227
Ref: "docker.io:8080",
228228
},
229229
wantErrs: []string{
230-
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": a valid name is required. valid names must contain lowercase alphanumeric characters separated only by the \".\", \"_\", \"__\", \"-\" characters.",
231-
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": must end with a digest",
230+
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"docker.io:8080\": a valid name is required. valid names must contain lowercase alphanumeric characters separated only by the \".\", \"_\", \"__\", \"-\" characters.",
231+
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"docker.io:8080\": must end with a digest",
232232
},
233233
},
234234
"invalid image ref, tag-based ref": {
235235
spec: ImageSource{
236236
Ref: "docker.io/foo/bar:latest",
237237
},
238238
wantErrs: []string{
239-
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"string\": must end with a digest",
239+
"openAPIV3Schema.properties.status.properties.resolvedSource.properties.image.properties.ref: Invalid value: \"docker.io/foo/bar:latest\": must end with a digest",
240240
},
241241
},
242242
} {
@@ -271,15 +271,15 @@ func TestClusterCatalogURLsCELValidation(t *testing.T) {
271271
Base: "file://somefilepath",
272272
},
273273
wantErrs: []string{
274-
fmt.Sprintf("%s: Invalid value: \"string\": scheme must be either http or https", pth),
274+
fmt.Sprintf("%s: Invalid value: \"file://somefilepath\": scheme must be either http or https", pth),
275275
},
276276
},
277277
"base is invalid": {
278278
urls: ClusterCatalogURLs{
279279
Base: "notevenarealURL",
280280
},
281281
wantErrs: []string{
282-
fmt.Sprintf("%s: Invalid value: \"string\": must be a valid URL", pth),
282+
fmt.Sprintf("%s: Invalid value: \"notevenarealURL\": must be a valid URL", pth),
283283
},
284284
},
285285
} {
@@ -309,7 +309,7 @@ func TestSourceCELValidation(t *testing.T) {
309309
Type: SourceTypeImage,
310310
},
311311
wantErrs: []string{
312-
fmt.Sprintf("%s: Invalid value: \"object\": image is required when source type is %s, and forbidden otherwise", pth, SourceTypeImage),
312+
fmt.Sprintf("%s: Invalid value: image is required when source type is %s, and forbidden otherwise", pth, SourceTypeImage),
313313
},
314314
},
315315
"image source with required image field": {
@@ -351,7 +351,7 @@ func TestResolvedSourceCELValidation(t *testing.T) {
351351
Type: SourceTypeImage,
352352
},
353353
wantErrs: []string{
354-
fmt.Sprintf("%s: Invalid value: \"object\": image is required when source type is %s, and forbidden otherwise", pth, SourceTypeImage),
354+
fmt.Sprintf("%s: Invalid value: image is required when source type is %s, and forbidden otherwise", pth, SourceTypeImage),
355355
},
356356
},
357357
"image source with required image field": {

api/v1/suite_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,18 @@ func TestMain(m *testing.M) {
6767
// stopWithRetry wraps testEnv.Stop() with retry logic for graceful shutdown
6868
func stopWithRetry(env interface{ Stop() error }, timeout, interval time.Duration) error {
6969
deadline := time.Now().Add(timeout)
70+
var lastErr error
7071
for time.Now().Before(deadline) {
7172
if err := env.Stop(); err == nil {
7273
return nil
74+
} else {
75+
lastErr = err
76+
log.Printf("stopWithRetry: env.Stop() failed during teardown, retrying in %s: %v", interval, err)
7377
}
7478
time.Sleep(interval)
7579
}
80+
if lastErr != nil {
81+
log.Printf("stopWithRetry: timeout reached before successful teardown; last error: %v", lastErr)
82+
}
7683
return env.Stop() // Final attempt
7784
}

internal/operator-controller/controllers/suite_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,18 @@ func TestMain(m *testing.M) {
142142
// stopWithRetry wraps testEnv.Stop() with retry logic for graceful shutdown
143143
func stopWithRetry(env interface{ Stop() error }, timeout, interval time.Duration) error {
144144
deadline := time.Now().Add(timeout)
145+
var lastErr error
145146
for time.Now().Before(deadline) {
146147
if err := env.Stop(); err == nil {
147148
return nil
149+
} else {
150+
lastErr = err
151+
log.Printf("stopWithRetry: env.Stop() failed during teardown, retrying in %s: %v", interval, err)
148152
}
149153
time.Sleep(interval)
150154
}
155+
if lastErr != nil {
156+
log.Printf("stopWithRetry: timeout reached before successful teardown; last error: %v", lastErr)
157+
}
151158
return env.Stop() // Final attempt
152159
}

0 commit comments

Comments
 (0)