Skip to content

Commit 876df11

Browse files
cici37k8s-publishing-bot
authored andcommitted
Hot fix for panic on schema conversion. (#126167)
Kubernetes-commit: 5420b2fe9a84af57cc24793c8f8ac8821b65f42f
1 parent 21fdbb3 commit 876df11

File tree

6 files changed

+84
-19
lines changed

6 files changed

+84
-19
lines changed

go.mod

+6-6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ require (
1212
github.com/google/go-cmp v0.6.0
1313
github.com/google/gofuzz v1.2.0
1414
github.com/google/uuid v1.6.0
15+
github.com/pkg/errors v0.9.1
1516
github.com/spf13/cobra v1.8.1
1617
github.com/spf13/pflag v1.0.5
1718
github.com/stretchr/testify v1.9.0
@@ -24,12 +25,12 @@ require (
2425
google.golang.org/protobuf v1.34.2
2526
gopkg.in/evanphx/json-patch.v4 v4.12.0
2627
gopkg.in/yaml.v2 v2.4.0
27-
k8s.io/api v0.0.0-20240720022854-7d5e5eaf3aef
28-
k8s.io/apimachinery v0.0.0-20240719223001-62791ecbc514
29-
k8s.io/apiserver v0.0.0-20240720104541-d681845e4f6a
30-
k8s.io/client-go v0.0.0-20240719063343-5130bd9e7862
28+
k8s.io/api v0.0.0-20240722223049-b689d905290f
29+
k8s.io/apimachinery v0.0.0-20240720202316-95b78024e3fe
30+
k8s.io/apiserver v0.0.0-20240723030233-2b2a4b0fa8e4
31+
k8s.io/client-go v0.0.0-20240723023642-bad8f77ca6ef
3132
k8s.io/code-generator v0.0.0-20240720023521-ec3cc888df4c
32-
k8s.io/component-base v0.0.0-20240715183844-6f32dbe8ef25
33+
k8s.io/component-base v0.0.0-20240722183709-6cc953a9d440
3334
k8s.io/klog/v2 v2.130.1
3435
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340
3536
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8
@@ -78,7 +79,6 @@ require (
7879
github.com/modern-go/reflect2 v1.0.2 // indirect
7980
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
8081
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
81-
github.com/pkg/errors v0.9.1 // indirect
8282
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
8383
github.com/prometheus/client_golang v1.19.1 // indirect
8484
github.com/prometheus/client_model v0.6.1 // indirect

go.sum

+10-10
Original file line numberDiff line numberDiff line change
@@ -365,18 +365,18 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
365365
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
366366
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
367367
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
368-
k8s.io/api v0.0.0-20240720022854-7d5e5eaf3aef h1:srEy4lds3ddDhT+cxFy68Uvt3GVRTo3fwnw+Us/Nqqs=
369-
k8s.io/api v0.0.0-20240720022854-7d5e5eaf3aef/go.mod h1:SvpyE6bmVBf1ly5BaD4y6yym4ZpHrV2pa8tTRjcglaA=
370-
k8s.io/apimachinery v0.0.0-20240719223001-62791ecbc514 h1:r9/8IzTbEU+H8bAZ4DtiN8A4Lr7UXnfPoPsnbe50zZ8=
371-
k8s.io/apimachinery v0.0.0-20240719223001-62791ecbc514/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
372-
k8s.io/apiserver v0.0.0-20240720104541-d681845e4f6a h1:Hcn+rrkkCCMuRxtWTpGdVZhrkfKiQkZI+peIJIRuqnM=
373-
k8s.io/apiserver v0.0.0-20240720104541-d681845e4f6a/go.mod h1:UFdCOgZ0UgBzrSbF5rc3eVHS4OhIdbnIFYEITre8ZT8=
374-
k8s.io/client-go v0.0.0-20240719063343-5130bd9e7862 h1:7pxBn9PlLxKT4L7sh5YE3nUt6dBajHFY6MitAvQ0K4E=
375-
k8s.io/client-go v0.0.0-20240719063343-5130bd9e7862/go.mod h1:Ku8rB5ecknMAlxaO9IDX/HkHUBKk6ku4yWmXJ3o4Uaw=
368+
k8s.io/api v0.0.0-20240722223049-b689d905290f h1:wtqzslJEcheiQ7hXjw1yGfqUyMCb7G4j72aL64Bzpbo=
369+
k8s.io/api v0.0.0-20240722223049-b689d905290f/go.mod h1:ytlEzqC2wOTwYET71W7+J+k7O2V7vrDuzmNLBSpgT+k=
370+
k8s.io/apimachinery v0.0.0-20240720202316-95b78024e3fe h1:V9MwpYUwbKlfLKVrhpVuKWiat/LBIhm1pGB9/xdHm5Q=
371+
k8s.io/apimachinery v0.0.0-20240720202316-95b78024e3fe/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
372+
k8s.io/apiserver v0.0.0-20240723030233-2b2a4b0fa8e4 h1:7nrffLiDUbMAXLKzBvyU8rwLHw5WpCw2AjhDO5IZYRs=
373+
k8s.io/apiserver v0.0.0-20240723030233-2b2a4b0fa8e4/go.mod h1:R1HYbPCD+ClvTmzeLBYaS4aktC3entK1o4hyD+WemtA=
374+
k8s.io/client-go v0.0.0-20240723023642-bad8f77ca6ef h1:+munBmXPvgGM5AFzdZh7Xe7S2LJ9udXYRfBDfm+0Eac=
375+
k8s.io/client-go v0.0.0-20240723023642-bad8f77ca6ef/go.mod h1:L1rDFyPUkmS0j6WXGYh5v/iWsfIFYH+LWnFOT1LCsf4=
376376
k8s.io/code-generator v0.0.0-20240720023521-ec3cc888df4c h1:oiNPH9Y/YrQfxo8eTW/w71aBrSyr9MX/wGBKTwDSZsc=
377377
k8s.io/code-generator v0.0.0-20240720023521-ec3cc888df4c/go.mod h1:TVAwbna2B36D+IsWJ5oHqKZKSU8ZBtxeiMTb7uKM6Z0=
378-
k8s.io/component-base v0.0.0-20240715183844-6f32dbe8ef25 h1:9SIVS17h6glmGM2G4ILkpQRUYc/zZ7y15gD2uaby0rM=
379-
k8s.io/component-base v0.0.0-20240715183844-6f32dbe8ef25/go.mod h1:YYWVx/ele54LQcShCdQpmsIqiHgZ+KjWY7WGMzTjKGk=
378+
k8s.io/component-base v0.0.0-20240722183709-6cc953a9d440 h1:14X+5sRQRsul6tLxIKTP0/DotvWlMd9DFCgMqHP1hZY=
379+
k8s.io/component-base v0.0.0-20240722183709-6cc953a9d440/go.mod h1:dj2Pl05aLcVMZi2NXcwv+M/WdUVPEkisFPjDze7rbSk=
380380
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 h1:NGrVE502P0s0/1hudf8zjgwki1X/TByhmAoILTarmzo=
381381
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8=
382382
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=

pkg/apiserver/schema/cel/compilation.go

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/google/cel-go/cel"
2525
"github.com/google/cel-go/checker"
2626
"github.com/google/cel-go/common/types"
27+
"github.com/pkg/errors"
2728

2829
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2930
"k8s.io/apiextensions-apiserver/pkg/apiserver/schema"
@@ -125,6 +126,9 @@ func Compile(s *schema.Structural, declType *apiservercel.DeclType, perCallLimit
125126
if len(s.XValidations) == 0 {
126127
return nil, nil
127128
}
129+
if declType == nil {
130+
return nil, errors.New("Failed to convert to declType for CEL validation rules")
131+
}
128132
celRules := s.XValidations
129133

130134
oldSelfEnvSet, optionalOldSelfEnvSet, err := prepareEnvSet(baseEnvSet, declType)

pkg/apiserver/schema/cel/model/adaptor.go

+3
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ func (s *Structural) Pattern() string {
6262
}
6363

6464
func (s *Structural) Items() common.Schema {
65+
if s.Structural.Items == nil {
66+
return nil
67+
}
6568
return &Structural{Structural: s.Structural.Items}
6669
}
6770

pkg/apiserver/schema/cel/model/schemas_test.go

+50-1
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ func TestEstimateMaxLengthJSON(t *testing.T) {
274274
Name string
275275
InputSchema *schema.Structural
276276
ExpectedMaxElements int64
277+
ExpectNilType bool
277278
}
278279
tests := []maxLengthTest{
279280
{
@@ -499,13 +500,61 @@ func TestEstimateMaxLengthJSON(t *testing.T) {
499500
// so we expect the max length to be exactly equal to the user-supplied one
500501
ExpectedMaxElements: 20,
501502
},
503+
{
504+
Name: "Property under array",
505+
InputSchema: &schema.Structural{
506+
Generic: schema.Generic{
507+
Type: "array",
508+
},
509+
Properties: map[string]schema.Structural{
510+
"field": {
511+
Generic: schema.Generic{
512+
Type: "string",
513+
Default: schema.JSON{Object: "default"},
514+
},
515+
},
516+
},
517+
},
518+
// Got nil for delType
519+
ExpectedMaxElements: 0,
520+
ExpectNilType: true,
521+
},
522+
{
523+
Name: "Items under object",
524+
InputSchema: &schema.Structural{
525+
Generic: schema.Generic{
526+
Type: "object",
527+
},
528+
Items: &schema.Structural{
529+
Generic: schema.Generic{
530+
Type: "array",
531+
},
532+
Properties: map[string]schema.Structural{
533+
"field": {
534+
Generic: schema.Generic{
535+
Type: "string",
536+
Default: schema.JSON{Object: "default"},
537+
},
538+
},
539+
},
540+
ValueValidation: &schema.ValueValidation{
541+
Required: []string{"field"},
542+
},
543+
},
544+
},
545+
// Skip items under object for schema conversion.
546+
ExpectedMaxElements: 0,
547+
},
502548
}
503549
for _, testCase := range tests {
504550
t.Run(testCase.Name, func(t *testing.T) {
505551
decl := SchemaDeclType(testCase.InputSchema, false)
506-
if decl.MaxElements != testCase.ExpectedMaxElements {
552+
if decl != nil && decl.MaxElements != testCase.ExpectedMaxElements {
507553
t.Errorf("wrong maxElements (got %d, expected %d)", decl.MaxElements, testCase.ExpectedMaxElements)
508554
}
555+
if testCase.ExpectNilType && decl != nil {
556+
t.Errorf("expected nil type, got %v", decl)
557+
}
509558
})
510559
}
511560
}

pkg/apiserver/schema/cel/validation.go

+11-2
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,15 @@ func validator(validationSchema, nodeSchema *schema.Structural, isResourceRoot b
100100
var itemsValidator, additionalPropertiesValidator *Validator
101101
var propertiesValidators map[string]Validator
102102
var allOfValidators []*Validator
103+
var elemType *cel.DeclType
104+
if declType != nil {
105+
elemType = declType.ElemType
106+
} else {
107+
elemType = declType
108+
}
103109

104110
if validationSchema.Items != nil && nodeSchema.Items != nil {
105-
itemsValidator = validator(validationSchema.Items, nodeSchema.Items, nodeSchema.Items.XEmbeddedResource, declType.ElemType, perCallLimit)
111+
itemsValidator = validator(validationSchema.Items, nodeSchema.Items, nodeSchema.Items.XEmbeddedResource, elemType, perCallLimit)
106112
}
107113

108114
if len(validationSchema.Properties) > 0 {
@@ -117,6 +123,9 @@ func validator(validationSchema, nodeSchema *schema.Structural, isResourceRoot b
117123

118124
var fieldType *cel.DeclType
119125
if escapedPropName, ok := cel.Escape(k); ok {
126+
if declType == nil {
127+
continue
128+
}
120129
if f, ok := declType.Fields[escapedPropName]; ok {
121130
fieldType = f.Type
122131
} else {
@@ -138,7 +147,7 @@ func validator(validationSchema, nodeSchema *schema.Structural, isResourceRoot b
138147
}
139148
if validationSchema.AdditionalProperties != nil && validationSchema.AdditionalProperties.Structural != nil &&
140149
nodeSchema.AdditionalProperties != nil && nodeSchema.AdditionalProperties.Structural != nil {
141-
additionalPropertiesValidator = validator(validationSchema.AdditionalProperties.Structural, nodeSchema.AdditionalProperties.Structural, nodeSchema.AdditionalProperties.Structural.XEmbeddedResource, declType.ElemType, perCallLimit)
150+
additionalPropertiesValidator = validator(validationSchema.AdditionalProperties.Structural, nodeSchema.AdditionalProperties.Structural, nodeSchema.AdditionalProperties.Structural.XEmbeddedResource, elemType, perCallLimit)
142151
}
143152

144153
if validationSchema.ValueValidation != nil && len(validationSchema.ValueValidation.AllOf) > 0 {

0 commit comments

Comments
 (0)