@@ -20,13 +20,14 @@ import (
20
20
"fmt"
21
21
"strings"
22
22
23
- "k8s.io/apimachinery/pkg/api/validation "
23
+ apiequality "k8s.io/apimachinery/pkg/api/equality "
24
24
apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
25
25
"k8s.io/apimachinery/pkg/util/sets"
26
26
"k8s.io/apimachinery/pkg/util/validation/field"
27
27
"k8s.io/apiserver/pkg/util/shufflesharding"
28
28
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
29
29
"k8s.io/kubernetes/pkg/apis/flowcontrol"
30
+ "k8s.io/kubernetes/pkg/apis/flowcontrol/internalbootstrap"
30
31
)
31
32
32
33
// ValidateFlowSchemaName validates name for flow-schema.
@@ -73,7 +74,17 @@ var supportedLimitResponseType = sets.NewString(
73
74
// ValidateFlowSchema validates the content of flow-schema
74
75
func ValidateFlowSchema (fs * flowcontrol.FlowSchema ) field.ErrorList {
75
76
allErrs := apivalidation .ValidateObjectMeta (& fs .ObjectMeta , false , ValidateFlowSchemaName , field .NewPath ("metadata" ))
76
- allErrs = append (allErrs , ValidateFlowSchemaSpec (& fs .Spec , field .NewPath ("spec" ))... )
77
+ specPath := field .NewPath ("spec" )
78
+ allErrs = append (allErrs , ValidateFlowSchemaSpec (fs .Name , & fs .Spec , specPath )... )
79
+ if mand , ok := internalbootstrap .MandatoryFlowSchemas [fs .Name ]; ok {
80
+ // Check for almost exact equality. This is a pretty
81
+ // strict test, and it is OK in this context because both
82
+ // sides of this comparison are intended to ultimately
83
+ // come from the same code.
84
+ if ! apiequality .Semantic .DeepEqual (fs .Spec , mand .Spec ) {
85
+ allErrs = append (allErrs , field .Invalid (specPath , fs .Spec , fmt .Sprintf ("spec of '%s' must equal the fixed value" , fs .Name )))
86
+ }
87
+ }
77
88
allErrs = append (allErrs , ValidateFlowSchemaStatus (& fs .Status , field .NewPath ("status" ))... )
78
89
return allErrs
79
90
}
@@ -84,14 +95,17 @@ func ValidateFlowSchemaUpdate(old, fs *flowcontrol.FlowSchema) field.ErrorList {
84
95
}
85
96
86
97
// ValidateFlowSchemaSpec validates the content of flow-schema's spec
87
- func ValidateFlowSchemaSpec (spec * flowcontrol.FlowSchemaSpec , fldPath * field.Path ) field.ErrorList {
98
+ func ValidateFlowSchemaSpec (fsName string , spec * flowcontrol.FlowSchemaSpec , fldPath * field.Path ) field.ErrorList {
88
99
var allErrs field.ErrorList
89
100
if spec .MatchingPrecedence <= 0 {
90
101
allErrs = append (allErrs , field .Invalid (fldPath .Child ("matchingPrecedence" ), spec .MatchingPrecedence , "must be a positive value" ))
91
102
}
92
103
if spec .MatchingPrecedence > flowcontrol .FlowSchemaMaxMatchingPrecedence {
93
104
allErrs = append (allErrs , field .Invalid (fldPath .Child ("matchingPrecedence" ), spec .MatchingPrecedence , fmt .Sprintf ("must not be greater than %v" , flowcontrol .FlowSchemaMaxMatchingPrecedence )))
94
105
}
106
+ if (spec .MatchingPrecedence == 1 ) && (fsName != flowcontrol .FlowSchemaNameExempt ) {
107
+ allErrs = append (allErrs , field .Invalid (fldPath .Child ("matchingPrecedence" ), spec .MatchingPrecedence , "only the schema named 'exempt' may have matchingPrecedence 1" ))
108
+ }
95
109
if spec .DistinguisherMethod != nil {
96
110
if ! supportedDistinguisherMethods .Has (string (spec .DistinguisherMethod .Type )) {
97
111
allErrs = append (allErrs , field .NotSupported (fldPath .Child ("distinguisherMethod" ).Child ("type" ), spec .DistinguisherMethod , supportedDistinguisherMethods .List ()))
@@ -139,10 +153,28 @@ func ValidateFlowSchemaSubject(subject *flowcontrol.Subject, fldPath *field.Path
139
153
switch subject .Kind {
140
154
case flowcontrol .SubjectKindServiceAccount :
141
155
allErrs = append (allErrs , ValidateServiceAccountSubject (subject .ServiceAccount , fldPath .Child ("serviceAccount" ))... )
156
+ if subject .User != nil {
157
+ allErrs = append (allErrs , field .Forbidden (fldPath .Child ("user" ), "user is forbidden when subject kind is not 'User'" ))
158
+ }
159
+ if subject .Group != nil {
160
+ allErrs = append (allErrs , field .Forbidden (fldPath .Child ("group" ), "group is forbidden when subject kind is not 'Group'" ))
161
+ }
142
162
case flowcontrol .SubjectKindUser :
143
163
allErrs = append (allErrs , ValidateUserSubject (subject .User , fldPath .Child ("user" ))... )
164
+ if subject .ServiceAccount != nil {
165
+ allErrs = append (allErrs , field .Forbidden (fldPath .Child ("serviceAccount" ), "serviceAccount is forbidden when subject kind is not 'ServiceAccount'" ))
166
+ }
167
+ if subject .Group != nil {
168
+ allErrs = append (allErrs , field .Forbidden (fldPath .Child ("group" ), "group is forbidden when subject kind is not 'Group'" ))
169
+ }
144
170
case flowcontrol .SubjectKindGroup :
145
171
allErrs = append (allErrs , ValidateGroupSubject (subject .Group , fldPath .Child ("group" ))... )
172
+ if subject .ServiceAccount != nil {
173
+ allErrs = append (allErrs , field .Forbidden (fldPath .Child ("serviceAccount" ), "serviceAccount is forbidden when subject kind is not 'ServiceAccount'" ))
174
+ }
175
+ if subject .User != nil {
176
+ allErrs = append (allErrs , field .Forbidden (fldPath .Child ("user" ), "user is forbidden when subject kind is not 'User'" ))
177
+ }
146
178
default :
147
179
allErrs = append (allErrs , field .NotSupported (fldPath .Child ("kind" ), subject .Kind , supportedSubjectKinds .List ()))
148
180
}
@@ -152,10 +184,13 @@ func ValidateFlowSchemaSubject(subject *flowcontrol.Subject, fldPath *field.Path
152
184
// ValidateServiceAccountSubject validates subject of "ServiceAccount" kind
153
185
func ValidateServiceAccountSubject (subject * flowcontrol.ServiceAccountSubject , fldPath * field.Path ) field.ErrorList {
154
186
var allErrs field.ErrorList
187
+ if subject == nil {
188
+ return append (allErrs , field .Required (fldPath , "serviceAccount is required when subject kind is 'ServiceAccount'" ))
189
+ }
155
190
if len (subject .Name ) == 0 {
156
191
allErrs = append (allErrs , field .Required (fldPath .Child ("name" ), "" ))
157
192
} else if subject .Name != flowcontrol .NameAll {
158
- for _ , msg := range validation .ValidateServiceAccountName (subject .Name , false ) {
193
+ for _ , msg := range apimachineryvalidation .ValidateServiceAccountName (subject .Name , false ) {
159
194
allErrs = append (allErrs , field .Invalid (fldPath .Child ("name" ), subject .Name , msg ))
160
195
}
161
196
}
@@ -174,6 +209,9 @@ func ValidateServiceAccountSubject(subject *flowcontrol.ServiceAccountSubject, f
174
209
// ValidateUserSubject validates subject of "User" kind
175
210
func ValidateUserSubject (subject * flowcontrol.UserSubject , fldPath * field.Path ) field.ErrorList {
176
211
var allErrs field.ErrorList
212
+ if subject == nil {
213
+ return append (allErrs , field .Required (fldPath , "user is required when subject kind is 'User'" ))
214
+ }
177
215
if len (subject .Name ) == 0 {
178
216
allErrs = append (allErrs , field .Required (fldPath .Child ("name" ), "" ))
179
217
}
@@ -183,6 +221,9 @@ func ValidateUserSubject(subject *flowcontrol.UserSubject, fldPath *field.Path)
183
221
// ValidateGroupSubject validates subject of "Group" kind
184
222
func ValidateGroupSubject (subject * flowcontrol.GroupSubject , fldPath * field.Path ) field.ErrorList {
185
223
var allErrs field.ErrorList
224
+ if subject == nil {
225
+ return append (allErrs , field .Required (fldPath , "group is required when subject kind is 'Group'" ))
226
+ }
186
227
if len (subject .Name ) == 0 {
187
228
allErrs = append (allErrs , field .Required (fldPath .Child ("name" ), "" ))
188
229
}
@@ -298,7 +339,17 @@ func ValidateFlowSchemaCondition(condition *flowcontrol.FlowSchemaCondition, fld
298
339
// ValidatePriorityLevelConfiguration validates priority-level-configuration.
299
340
func ValidatePriorityLevelConfiguration (pl * flowcontrol.PriorityLevelConfiguration ) field.ErrorList {
300
341
allErrs := apivalidation .ValidateObjectMeta (& pl .ObjectMeta , false , ValidatePriorityLevelConfigurationName , field .NewPath ("metadata" ))
301
- allErrs = append (allErrs , ValidatePriorityLevelConfigurationSpec (& pl .Spec , pl .Name , field .NewPath ("spec" ))... )
342
+ specPath := field .NewPath ("spec" )
343
+ allErrs = append (allErrs , ValidatePriorityLevelConfigurationSpec (& pl .Spec , pl .Name , specPath )... )
344
+ if mand , ok := internalbootstrap .MandatoryPriorityLevelConfigurations [pl .Name ]; ok {
345
+ // Check for almost exact equality. This is a pretty
346
+ // strict test, and it is OK in this context because both
347
+ // sides of this comparison are intended to ultimately
348
+ // come from the same code.
349
+ if ! apiequality .Semantic .DeepEqual (pl .Spec , mand .Spec ) {
350
+ allErrs = append (allErrs , field .Invalid (specPath , pl .Spec , fmt .Sprintf ("spec of '%s' must equal the fixed value" , pl .Name )))
351
+ }
352
+ }
302
353
allErrs = append (allErrs , ValidatePriorityLevelConfigurationStatus (& pl .Status , field .NewPath ("status" ))... )
303
354
return allErrs
304
355
}
@@ -311,14 +362,17 @@ func ValidatePriorityLevelConfigurationUpdate(old, pl *flowcontrol.PriorityLevel
311
362
// ValidatePriorityLevelConfigurationSpec validates priority-level-configuration's spec.
312
363
func ValidatePriorityLevelConfigurationSpec (spec * flowcontrol.PriorityLevelConfigurationSpec , name string , fldPath * field.Path ) field.ErrorList {
313
364
var allErrs field.ErrorList
365
+ if (name == flowcontrol .PriorityLevelConfigurationNameExempt ) != (spec .Type == flowcontrol .PriorityLevelEnablementExempt ) {
366
+ allErrs = append (allErrs , field .Invalid (fldPath .Child ("type" ), spec .Type , "type must be 'Exempt' if and only if name is 'exempt'" ))
367
+ }
314
368
switch spec .Type {
315
369
case flowcontrol .PriorityLevelEnablementExempt :
316
370
if spec .Limited != nil {
317
371
allErrs = append (allErrs , field .Forbidden (fldPath .Child ("limited" ), "must be nil if the type is not Limited" ))
318
372
}
319
373
case flowcontrol .PriorityLevelEnablementLimited :
320
374
if spec .Limited == nil {
321
- allErrs = append (allErrs , field .Required (fldPath .Child ("limited" ), "must not be empty" ))
375
+ allErrs = append (allErrs , field .Required (fldPath .Child ("limited" ), "must not be empty when type is Limited " ))
322
376
} else {
323
377
allErrs = append (allErrs , ValidateLimitedPriorityLevelConfiguration (spec .Limited , fldPath .Child ("limited" ))... )
324
378
}
@@ -344,11 +398,11 @@ func ValidateLimitResponse(lr flowcontrol.LimitResponse, fldPath *field.Path) fi
344
398
switch lr .Type {
345
399
case flowcontrol .LimitResponseTypeReject :
346
400
if lr .Queuing != nil {
347
- allErrs = append (allErrs , field .Forbidden (fldPath .Child ("queuing" ), "must be nil if the type is not Limited" ))
401
+ allErrs = append (allErrs , field .Forbidden (fldPath .Child ("queuing" ), "must be nil if limited.limitResponse. type is not Limited" ))
348
402
}
349
403
case flowcontrol .LimitResponseTypeQueue :
350
404
if lr .Queuing == nil {
351
- allErrs = append (allErrs , field .Required (fldPath .Child ("queuing" ), "must not be empty" ))
405
+ allErrs = append (allErrs , field .Required (fldPath .Child ("queuing" ), "must not be empty if limited.limitResponse.type is Limited " ))
352
406
} else {
353
407
allErrs = append (allErrs , ValidatePriorityLevelQueuingConfiguration (lr .Queuing , fldPath .Child ("queuing" ))... )
354
408
}
0 commit comments