From 5a894b22fc8d48033b0605c6f7f3ff49e9a770bd Mon Sep 17 00:00:00 2001 From: Madhu Rajanna Date: Thu, 21 Sep 2023 15:03:13 +0200 Subject: [PATCH] use CEL for validation use CEL to validate the CR fields as it is having multiple advantages over webhooks and also it already beta in 1.25 onwards and going to be GA in 1.29 More details about it at https://kubernetes.io/blog/2022/09/29/\ enforce-immutability-using-cel/ Signed-off-by: Madhu Rajanna --- .../csiaddons/v1alpha1/csiaddonsnode_types.go | 4 ++ apis/csiaddons/v1alpha1/networkfence_types.go | 7 ++++ .../v1alpha1/reclaimspacejob_types.go | 1 + .../v1alpha1/volumereplication_types.go | 2 + .../v1alpha1/volumereplicationclass_types.go | 2 + ...csiaddons.openshift.io_csiaddonsnodes.yaml | 6 +++ .../csiaddons.openshift.io_networkfences.yaml | 15 +++++++ ...ons.openshift.io_reclaimspacecronjobs.yaml | 3 ++ ...iaddons.openshift.io_reclaimspacejobs.yaml | 3 ++ ...openshift.io_volumereplicationclasses.yaml | 6 +++ ...orage.openshift.io_volumereplications.yaml | 6 +++ deploy/controller/crds.yaml | 39 +++++++++++++++++++ 12 files changed, 94 insertions(+) diff --git a/apis/csiaddons/v1alpha1/csiaddonsnode_types.go b/apis/csiaddons/v1alpha1/csiaddonsnode_types.go index 9fef02d12..9db238ca9 100644 --- a/apis/csiaddons/v1alpha1/csiaddonsnode_types.go +++ b/apis/csiaddons/v1alpha1/csiaddonsnode_types.go @@ -36,6 +36,8 @@ type CSIAddonsNodeDriver struct { // This must be the same name returned by the CSI-Addons GetIdentity() // call for that driver. The name of the driver is in the format: // `example.csi.ceph.com` + // +kubebuilder:validation:Required + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="name is immutable" Name string `json:"name"` // EndPoint is url that contains the ip-address to which the CSI-Addons @@ -44,6 +46,8 @@ type CSIAddonsNodeDriver struct { // NodeID is the ID of the node to identify on which node the side-car // is running. + // +kubebuilder:validation:Required + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="nodeID is immutable" NodeID string `json:"nodeID"` } diff --git a/apis/csiaddons/v1alpha1/networkfence_types.go b/apis/csiaddons/v1alpha1/networkfence_types.go index 04b1d6bda..8c82b692e 100644 --- a/apis/csiaddons/v1alpha1/networkfence_types.go +++ b/apis/csiaddons/v1alpha1/networkfence_types.go @@ -40,13 +40,18 @@ const ( FencingOperationResultFailed FencingOperationResult = "Failed" ) +// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="secret is immutable" // SecretSpec defines the secrets to be used for the network fencing operation. type SecretSpec struct { // Name specifies the name of the secret. + // +kubebuilder:validation:Optional + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="name is immutable" Name string `json:"name,omitempty"` // Namespace specifies the namespace in which the secret // is located. + // +kubebuilder:validation:Optional + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="namespace is immutable" Namespace string `json:"namespace,omitempty"` } @@ -54,6 +59,7 @@ type SecretSpec struct { type NetworkFenceSpec struct { // Driver contains the name of CSI driver. // +kubebuilder:validation:Required + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="driver is immutable" Driver string `json:"driver"` // FenceState contains the desired state for the CIDRs @@ -71,6 +77,7 @@ type NetworkFenceSpec struct { Secret SecretSpec `json:"secret,omitempty"` // Parameters is used to pass additional parameters to the CSI driver. + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="parameters are immutable" Parameters map[string]string `json:"parameters,omitempty"` } diff --git a/apis/csiaddons/v1alpha1/reclaimspacejob_types.go b/apis/csiaddons/v1alpha1/reclaimspacejob_types.go index 892577662..333239b8e 100644 --- a/apis/csiaddons/v1alpha1/reclaimspacejob_types.go +++ b/apis/csiaddons/v1alpha1/reclaimspacejob_types.go @@ -36,6 +36,7 @@ const ( // performed. type TargetSpec struct { // PersistentVolumeClaim specifies the target PersistentVolumeClaim name. + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="persistentVolumeClaim is immutable" PersistentVolumeClaim string `json:"persistentVolumeClaim,omitempty"` } diff --git a/apis/replication.storage/v1alpha1/volumereplication_types.go b/apis/replication.storage/v1alpha1/volumereplication_types.go index 9093b5c32..d9fca40ad 100644 --- a/apis/replication.storage/v1alpha1/volumereplication_types.go +++ b/apis/replication.storage/v1alpha1/volumereplication_types.go @@ -58,6 +58,7 @@ const ( type VolumeReplicationSpec struct { // VolumeReplicationClass is the VolumeReplicationClass name for this VolumeReplication resource // +kubebuilder:validation:Required + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="volumeReplicationClass is immutable" VolumeReplicationClass string `json:"volumeReplicationClass"` // ReplicationState represents the replication operation to be performed on the volume. @@ -67,6 +68,7 @@ type VolumeReplicationSpec struct { // DataSource represents the object associated with the volume // +kubebuilder:validation:Required + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="dataSource is immutable" DataSource corev1.TypedLocalObjectReference `json:"dataSource"` // AutoResync represents the volume to be auto resynced when diff --git a/apis/replication.storage/v1alpha1/volumereplicationclass_types.go b/apis/replication.storage/v1alpha1/volumereplicationclass_types.go index 4808519e0..274650310 100644 --- a/apis/replication.storage/v1alpha1/volumereplicationclass_types.go +++ b/apis/replication.storage/v1alpha1/volumereplicationclass_types.go @@ -26,10 +26,12 @@ import ( type VolumeReplicationClassSpec struct { // Provisioner is the name of storage provisioner // +kubebuilder:validation:Required + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="provisioner is immutable" Provisioner string `json:"provisioner"` // Parameters is a key-value map with storage provisioner specific configurations for // creating volume replicas // +kubebuilder:validation:Optional + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="parameters are immutable" Parameters map[string]string `json:"parameters,omitempty"` } diff --git a/config/crd/bases/csiaddons.openshift.io_csiaddonsnodes.yaml b/config/crd/bases/csiaddons.openshift.io_csiaddonsnodes.yaml index 19b25e58a..e577d22fb 100644 --- a/config/crd/bases/csiaddons.openshift.io_csiaddonsnodes.yaml +++ b/config/crd/bases/csiaddons.openshift.io_csiaddonsnodes.yaml @@ -64,10 +64,16 @@ spec: GetIdentity() call for that driver. The name of the driver is in the format: `example.csi.ceph.com`' type: string + x-kubernetes-validations: + - message: name is immutable + rule: self == oldSelf nodeID: description: NodeID is the ID of the node to identify on which node the side-car is running. type: string + x-kubernetes-validations: + - message: nodeID is immutable + rule: self == oldSelf required: - endpoint - name diff --git a/config/crd/bases/csiaddons.openshift.io_networkfences.yaml b/config/crd/bases/csiaddons.openshift.io_networkfences.yaml index ed416c1ce..3234ca5fd 100644 --- a/config/crd/bases/csiaddons.openshift.io_networkfences.yaml +++ b/config/crd/bases/csiaddons.openshift.io_networkfences.yaml @@ -59,6 +59,9 @@ spec: driver: description: Driver contains the name of CSI driver. type: string + x-kubernetes-validations: + - message: driver is immutable + rule: self == oldSelf fenceState: default: Fenced description: FenceState contains the desired state for the CIDRs mentioned @@ -73,6 +76,9 @@ spec: description: Parameters is used to pass additional parameters to the CSI driver. type: object + x-kubernetes-validations: + - message: parameters are immutable + rule: self == oldSelf secret: description: Secret is a kubernetes secret, which is required to perform the fence/unfence operation. @@ -80,11 +86,20 @@ spec: name: description: Name specifies the name of the secret. type: string + x-kubernetes-validations: + - message: name is immutable + rule: self == oldSelf namespace: description: Namespace specifies the namespace in which the secret is located. type: string + x-kubernetes-validations: + - message: namespace is immutable + rule: self == oldSelf type: object + x-kubernetes-validations: + - message: secret is immutable + rule: self == oldSelf required: - cidrs - driver diff --git a/config/crd/bases/csiaddons.openshift.io_reclaimspacecronjobs.yaml b/config/crd/bases/csiaddons.openshift.io_reclaimspacecronjobs.yaml index 105eb179c..7e5047b91 100644 --- a/config/crd/bases/csiaddons.openshift.io_reclaimspacecronjobs.yaml +++ b/config/crd/bases/csiaddons.openshift.io_reclaimspacecronjobs.yaml @@ -113,6 +113,9 @@ spec: description: PersistentVolumeClaim specifies the target PersistentVolumeClaim name. type: string + x-kubernetes-validations: + - message: persistentVolumeClaim is immutable + rule: self == oldSelf type: object timeout: description: Timeout specifies the timeout in seconds for diff --git a/config/crd/bases/csiaddons.openshift.io_reclaimspacejobs.yaml b/config/crd/bases/csiaddons.openshift.io_reclaimspacejobs.yaml index 6cf218ccf..2a71ca267 100644 --- a/config/crd/bases/csiaddons.openshift.io_reclaimspacejobs.yaml +++ b/config/crd/bases/csiaddons.openshift.io_reclaimspacejobs.yaml @@ -79,6 +79,9 @@ spec: description: PersistentVolumeClaim specifies the target PersistentVolumeClaim name. type: string + x-kubernetes-validations: + - message: persistentVolumeClaim is immutable + rule: self == oldSelf type: object timeout: description: Timeout specifies the timeout in seconds for the grpc diff --git a/config/crd/bases/replication.storage.openshift.io_volumereplicationclasses.yaml b/config/crd/bases/replication.storage.openshift.io_volumereplicationclasses.yaml index 260ec6514..8e22bd26c 100644 --- a/config/crd/bases/replication.storage.openshift.io_volumereplicationclasses.yaml +++ b/config/crd/bases/replication.storage.openshift.io_volumereplicationclasses.yaml @@ -49,9 +49,15 @@ spec: description: Parameters is a key-value map with storage provisioner specific configurations for creating volume replicas type: object + x-kubernetes-validations: + - message: parameters are immutable + rule: self == oldSelf provisioner: description: Provisioner is the name of storage provisioner type: string + x-kubernetes-validations: + - message: provisioner is immutable + rule: self == oldSelf required: - provisioner type: object diff --git a/config/crd/bases/replication.storage.openshift.io_volumereplications.yaml b/config/crd/bases/replication.storage.openshift.io_volumereplications.yaml index 3ca1d96d3..46f07df85 100644 --- a/config/crd/bases/replication.storage.openshift.io_volumereplications.yaml +++ b/config/crd/bases/replication.storage.openshift.io_volumereplications.yaml @@ -78,6 +78,9 @@ spec: - name type: object x-kubernetes-map-type: atomic + x-kubernetes-validations: + - message: dataSource is immutable + rule: self == oldSelf replicationHandle: description: replicationHandle represents an existing (but new) replication id @@ -95,6 +98,9 @@ spec: description: VolumeReplicationClass is the VolumeReplicationClass name for this VolumeReplication resource type: string + x-kubernetes-validations: + - message: volumeReplicationClass is immutable + rule: self == oldSelf required: - autoResync - dataSource diff --git a/deploy/controller/crds.yaml b/deploy/controller/crds.yaml index 67127ce7f..ccfe94de4 100644 --- a/deploy/controller/crds.yaml +++ b/deploy/controller/crds.yaml @@ -63,10 +63,16 @@ spec: GetIdentity() call for that driver. The name of the driver is in the format: `example.csi.ceph.com`' type: string + x-kubernetes-validations: + - message: name is immutable + rule: self == oldSelf nodeID: description: NodeID is the ID of the node to identify on which node the side-car is running. type: string + x-kubernetes-validations: + - message: nodeID is immutable + rule: self == oldSelf required: - endpoint - name @@ -161,6 +167,9 @@ spec: driver: description: Driver contains the name of CSI driver. type: string + x-kubernetes-validations: + - message: driver is immutable + rule: self == oldSelf fenceState: default: Fenced description: FenceState contains the desired state for the CIDRs mentioned @@ -175,6 +184,9 @@ spec: description: Parameters is used to pass additional parameters to the CSI driver. type: object + x-kubernetes-validations: + - message: parameters are immutable + rule: self == oldSelf secret: description: Secret is a kubernetes secret, which is required to perform the fence/unfence operation. @@ -182,11 +194,20 @@ spec: name: description: Name specifies the name of the secret. type: string + x-kubernetes-validations: + - message: name is immutable + rule: self == oldSelf namespace: description: Namespace specifies the namespace in which the secret is located. type: string + x-kubernetes-validations: + - message: namespace is immutable + rule: self == oldSelf type: object + x-kubernetes-validations: + - message: secret is immutable + rule: self == oldSelf required: - cidrs - driver @@ -394,6 +415,9 @@ spec: description: PersistentVolumeClaim specifies the target PersistentVolumeClaim name. type: string + x-kubernetes-validations: + - message: persistentVolumeClaim is immutable + rule: self == oldSelf type: object timeout: description: Timeout specifies the timeout in seconds for @@ -573,6 +597,9 @@ spec: description: PersistentVolumeClaim specifies the target PersistentVolumeClaim name. type: string + x-kubernetes-validations: + - message: persistentVolumeClaim is immutable + rule: self == oldSelf type: object timeout: description: Timeout specifies the timeout in seconds for the grpc @@ -739,9 +766,15 @@ spec: description: Parameters is a key-value map with storage provisioner specific configurations for creating volume replicas type: object + x-kubernetes-validations: + - message: parameters are immutable + rule: self == oldSelf provisioner: description: Provisioner is the name of storage provisioner type: string + x-kubernetes-validations: + - message: provisioner is immutable + rule: self == oldSelf required: - provisioner type: object @@ -836,6 +869,9 @@ spec: - name type: object x-kubernetes-map-type: atomic + x-kubernetes-validations: + - message: dataSource is immutable + rule: self == oldSelf replicationHandle: description: replicationHandle represents an existing (but new) replication id @@ -853,6 +889,9 @@ spec: description: VolumeReplicationClass is the VolumeReplicationClass name for this VolumeReplication resource type: string + x-kubernetes-validations: + - message: volumeReplicationClass is immutable + rule: self == oldSelf required: - autoResync - dataSource