Skip to content

Commit

Permalink
Add FieldPath and Reason to XValidation marker
Browse files Browse the repository at this point in the history
  • Loading branch information
JoelSpeed committed Apr 23, 2024
1 parent 473c028 commit 6fca3f8
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 3 deletions.
14 changes: 14 additions & 0 deletions pkg/crd/markers/validation.go
Expand Up @@ -312,6 +312,8 @@ type XValidation struct {
Rule string
Message string `marker:",optional"`
MessageExpression string `marker:"messageExpression,optional"`
Reason string `marker:"reason,optional"`
FieldPath string `marker:"fieldPath,optional"`
}

func (m Maximum) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
Expand Down Expand Up @@ -534,10 +536,22 @@ func (m XIntOrString) ApplyPriority() ApplyPriority {
}

func (m XValidation) ApplyToSchema(schema *apiext.JSONSchemaProps) error {
var reason *apiext.FieldValueErrorReason
if m.Reason != "" {
switch m.Reason {
case string(apiext.FieldValueRequired), string(apiext.FieldValueInvalid), string(apiext.FieldValueForbidden), string(apiext.FieldValueDuplicate):
reason = (*apiext.FieldValueErrorReason)(&m.Reason)
default:
return fmt.Errorf("invalid reason %s, valid values are %s, %s, %s and %s", m.Reason, apiext.FieldValueRequired, apiext.FieldValueInvalid, apiext.FieldValueForbidden, apiext.FieldValueDuplicate)
}
}

schema.XValidations = append(schema.XValidations, apiext.ValidationRule{
Rule: m.Rule,
Message: m.Message,
MessageExpression: m.MessageExpression,
Reason: reason,
FieldPath: m.FieldPath,
})
return nil
}
8 changes: 8 additions & 0 deletions pkg/crd/markers/zz_generated.markerhelp.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions pkg/crd/testdata/cronjob_types.go
Expand Up @@ -39,6 +39,7 @@ import (
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

// CronJobSpec defines the desired state of CronJob
// +kubebuilder:validation:XValidation:rule="has(oldSelf.forbiddenInt) || !has(self.forbiddenInt)",message="forbiddenInt is not allowed",fieldPath=".forbiddenInt",reason="FieldValueForbidden"
type CronJobSpec struct {
// The schedule in Cron format, see https://en.wikipedia.org/wiki/Cron.
Schedule string `json:"schedule"`
Expand Down Expand Up @@ -251,6 +252,10 @@ type CronJobSpec struct {
// +kubebuilder:validation:XValidation:rule="self.size() % 2 == 0",messageExpression="'Length has to be even but is ' + len(self.stringWithEvenLengthAndMessageExpression) + ' instead'"
StringWithEvenLengthAndMessageExpression string `json:"stringWithEvenLengthAndMessageExpression,omitempty"`

// Test that we can add a forbidden field using XValidation Reason and FieldPath.
// The validation is applied to the spec struct itself and not the field.
ForbiddenInt int `json:"forbiddenInt,omitempty"`

// Checks that fixed-length arrays work
Array [3]int `json:"array,omitempty"`

Expand Down
17 changes: 14 additions & 3 deletions pkg/crd/testdata/testdata.kubebuilder.io_cronjobs.yaml
Expand Up @@ -196,6 +196,11 @@ spec:
description: This tests that exported fields are not skipped in the
schema generation
type: string
forbiddenInt:
description: |-
Test that we can add a forbidden field using XValidation Reason and FieldPath.
The validation is applied to the spec struct itself and not the field.
type: integer
hosts:
description: This tests string slice item validation.
items:
Expand Down Expand Up @@ -6806,11 +6811,12 @@ spec:
rule: self.size() % 2 == 0
- rule: "true"
stringWithEvenLengthAndMessageExpression:
description: Test of the expression-based validation with
messageExpression marker.
description: Test of the expression-based validation with messageExpression
marker.
type: string
x-kubernetes-validations:
- messageExpression: "'Length has to be even but is ' + len(self.stringWithEvenLengthAndMessageExpression) + ' instead'"
- messageExpression: '''Length has to be even but is '' + len(self.stringWithEvenLengthAndMessageExpression)
+ '' instead'''
rule: self.size() % 2 == 0
structWithSeveralFields:
description: A struct that can only be entirely replaced
Expand Down Expand Up @@ -6903,6 +6909,11 @@ spec:
- unprunedFomTypeAndField
- unprunedJSON
type: object
x-kubernetes-validations:
- fieldPath: .forbiddenInt
message: forbiddenInt is not allowed
reason: FieldValueForbidden
rule: has(oldSelf.forbiddenInt) || !has(self.forbiddenInt)
status:
description: CronJobStatus defines the observed state of CronJob
properties:
Expand Down

0 comments on commit 6fca3f8

Please sign in to comment.