diff --git a/pkg/crd/markers/validation.go b/pkg/crd/markers/validation.go index e1cad593c..96f4e9a87 100644 --- a/pkg/crd/markers/validation.go +++ b/pkg/crd/markers/validation.go @@ -106,6 +106,9 @@ var FieldOnlyMarkers = []*definitionWithHelp{ must(markers.MakeAnyTypeDefinition("kubebuilder:title", markers.DescribesField, Title{})). WithHelp(Title{}.Help()), + + must(markers.MakeDefinition("k8s:immutable", markers.DescribesField, Immutable{})). + WithHelp(Immutable{}.Help()), } // ValidationIshMarkers are field-and-type markers that don't fall under the @@ -325,6 +328,19 @@ type XIntOrString struct{} // to be used only as a last resort. type Schemaless struct{} +// +controllertools:marker:generateHelp:category="CRD validation" +// Immutable marks a field as immutable. +// The value of an immutable field may not be changed after creation. +type Immutable struct{} + +func (Immutable) ApplyToSchema(schema *apiext.JSONSchemaProps) error { + schema.XValidations = append(schema.XValidations, apiext.ValidationRule{ + Message: "Value is immutable", + Rule: "self == oldSelf", + }) + return nil +} + func hasNumericType(schema *apiext.JSONSchemaProps) bool { return schema.Type == string(Integer) || schema.Type == string(Number) } diff --git a/pkg/crd/markers/zz_generated.markerhelp.go b/pkg/crd/markers/zz_generated.markerhelp.go index 7d8282cfc..1612cf8b8 100644 --- a/pkg/crd/markers/zz_generated.markerhelp.go +++ b/pkg/crd/markers/zz_generated.markerhelp.go @@ -116,6 +116,17 @@ func (Format) Help() *markers.DefinitionHelp { } } +func (Immutable) Help() *markers.DefinitionHelp { + return &markers.DefinitionHelp{ + Category: "CRD validation", + DetailedHelp: markers.DetailedHelp{ + Summary: "marks a field as immutable.", + Details: "The value of an immutable field may not be changed after creation.", + }, + FieldHelp: map[string]markers.DetailedHelp{}, + } +} + func (KubernetesDefault) Help() *markers.DefinitionHelp { return &markers.DefinitionHelp{ Category: "CRD validation",