Skip to content

Commit f7be064

Browse files
committed
markers/OneOf: make order deterministic relative to XValidation
Currently, if both XValidation and AtMostOneOf/ExactlyOneOf constraints are specified, the ordering of CEL rules can change due to both sets of markers have the same apply priority. This change ensures that OneOf markers always run **after** XValidation markers.
1 parent 8d11ce7 commit f7be064

File tree

3 files changed

+13
-0
lines changed

3 files changed

+13
-0
lines changed

pkg/crd/markers/validation.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,11 @@ func (fields AtMostOneOf) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
672672
return xvalidation.ApplyToSchema(schema)
673673
}
674674

675+
func (_ AtMostOneOf) ApplyPriority() ApplyPriority {
676+
// explicitly go after XValidation markers so that the ordering is deterministic
677+
return ApplyPriorityDefault + 1
678+
}
679+
675680
func (fields ExactlyOneOf) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
676681
if len(fields) == 0 {
677682
return nil
@@ -684,6 +689,11 @@ func (fields ExactlyOneOf) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
684689
return xvalidation.ApplyToSchema(schema)
685690
}
686691

692+
func (_ ExactlyOneOf) ApplyPriority() ApplyPriority {
693+
// explicitly go after XValidation markers so that the ordering is deterministic
694+
return ApplyPriorityDefault + 1
695+
}
696+
687697
// fieldsToOneOfCelRuleStr converts a slice of field names to a string representation
688698
// [has(self.field1),has(self.field1),...].filter(x, x == true).size()
689699
func fieldsToOneOfCelRuleStr(fields []string) string {

pkg/crd/testdata/oneof/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type OneofSpec struct {
3434
SecondTypeWithExactOneof *TypeWithMultipleExactOneofs `json:"secondTypeWithExactOneof,omitempty"`
3535
}
3636

37+
// +kubebuilder:validation:XValidation:message="only one of foo|bar may be set",rule="!(has(self.foo) && has(self.bar))"
3738
// +kubebuilder:validation:AtMostOneOf=foo;bar
3839
type TypeWithOneofs struct {
3940
Foo *string `json:"foo,omitempty"`

pkg/crd/testdata/testdata.kubebuilder.io_oneofs.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ spec:
5656
type: string
5757
type: object
5858
x-kubernetes-validations:
59+
- message: only one of foo|bar may be set
60+
rule: '!(has(self.foo) && has(self.bar))'
5961
- message: at most one of the fields in [foo bar] may be set
6062
rule: '[has(self.foo),has(self.bar)].filter(x,x==true).size() <=
6163
1'

0 commit comments

Comments
 (0)