Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add FieldPath and Reason to XValidation marker #932

Merged
merged 1 commit into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions pkg/crd/markers/validation.go
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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