CRD Validations for etcd ​
- The validations for the fields within the
etcdresource are done via kubebuilder markers for CRD validation. - The validations for clusters with kubernetes versions
>= 1.29are written using a combination of CEL expressions via thex-validationtag which provides a straightforward syntax to write validation rules for the fields, and pattern matching with the use of thevalidationtag. - The validations for clusters with kubernetes versions
< 1.29will not contain validations viaCELexpressions since this is GA for kubernetes version 1.29 or higher. - Upon any changes to the validation rules to the etcd resource, the
yamlfiles for the same can be generated by running themake generatecommand.
Validation rules: ​
Type Validation rules: ​
The validations for fields of types Duration(metav1.Duration) and cron expressions are done via regex matching. These use the validation:Pattern marker.(The checking for the Quantity(resource.Quantity) fields are done by default, hence, no explicit validation is needed for the fields of this type):
Duration fields:
'^([0-9]+([.][0-9]+)?h)?([0-9]+([.][0-9]+)?m)?([0-9]+([.][0-9]+)?s)?([0-9]+([.][0-9]+)?d)?$')Cron expression:
^(\*|[1-5]?[0-9]|[1-5]?[0-9]-[1-5]?[0-9]|(?:[1-9]|[1-4][0-9]|5[0-9])\/(?:[1-9]|[1-4][0-9]|5[0-9]|60)|\*\/(?:[1-9]|[1-4][0-9]|5[0-9]|60))\s+(\*|[0-9]|1[0-9]|2[0-3]|[0-9]-(?:[0-9]|1[0-9]|2[0-3])|1[0-9]-(?:1[0-9]|2[0-3])|2[0-3]-2[0-3]|(?:[1-9]|1[0-9]|2[0-3])\/(?:[1-9]|1[0-9]|2[0-4])|\*\/(?:[1-9]|1[0-9]|2[0-4]))\s+(\*|[1-9]|[12][0-9]|3[01]|[1-9]-(?:[1-9]|[12][0-9]|3[01])|[12][0-9]-(?:[12][0-9]|3[01])|3[01]-3[01]|(?:[1-9]|[12][0-9]|30)\/(?:[1-9]|[12][0-9]|3[01])|\*\/(?:[1-9]|[12][0-9]|3[01]))\s+(\*|[1-9]|1[0-2]|[1-9]-(?:[1-9]|1[0-2])|1[0-2]-1[0-2]|(?:[1-9]|1[0-2])\/(?:[1-9]|1[0-2])|\*\/(?:[1-9]|1[0-2]))\s+(\*|[1-7]|[1-6]-[1-7]|[1-6]\/[1-7]|\*\/[1-7])$- NOTE: The provided regex does not account for
special stringssuch as@yearlyor@monthly. Additionally, it fails to invalidate cases involving thestep operator (x/y)and therange operator (x-y), where the cron expression is considered valid even ifx > y. Please ensure these values are validated before passing the expression.
- NOTE: The provided regex does not account for
Update validations ​
These validations are triggered when an update operation is done on the etcd resource.
Immutable fields: The fields
etcd.spec.StorageClass,etcd.spec.StorageCapacityandetcd.spec.VolumeClaimTemplateare immutable. The immutability is enforced by the CEL expression :self == oldSelf.The value set for the field
etcd.spec.replicascan either be decreased to0or increased. This is enforced by the CEL expression:self==0 ? true : self < oldSelf ? false : true
Field validations ​
- The fields which expect only a particular set of values are checked by using the kubebuilder marker:
+kubebuilder:validation:Enum=<value1>;<value2>- The
etcd.spec.etcd.metricscan only be set as eitherbasicorextensive. - The
etcd.spec.backup.garbageCollectionPolicycan only be set asExponentialorLimitBased - The
etcd.spec.backup.compression.policycan only be set as eithergziporlzworzlib. - The
etcd.spec.sharedConfig.autoCompactionModecan only be set as eitherperiodicorrevision.
- The
The value of
etcd.spec.backup.garbageCollectionPeriodmust be greater thanetcd.spec.backup.deltaSnapshotPeriod. This is enforced by the CEL expression!(has(self.deltaSnapshotPeriod) && has(self.garbageCollectionPeriod)) || duration(self.deltaSnapshotPeriod).getSeconds() < duration(self.garbageCollectionPeriod).getSeconds(). The first part of the expression ensures that both the fields are present and then compares the values of the garbageCollectionPeriod and deltaSnapshotPeriod fields, if not, skips the check.The value of
etcd.spec.StorageCapacitymust be more than 3 times that of theetcd.spec.etcd.quotaif backups are enabled. If not, the value must be greater than that of theetcd.spec.etcd.quotafield. This is enforced by using the CEL expression:has(self.storageCapacity) && has(self.etcd.quota) ? (has(self.backup.store) ? quantity(self.storageCapacity).compareTo(quantity(self.etcd.quota).add(quantity(self.etcd.quota)).add(quantity(self.etcd.quota))) > 0 : quantity(self.storageCapacity).compareTo(quantity(self.etcd.quota)) > 0 ): trueThe check for whether backups are enabled or not is done by checking if the fieldetcd.spec.backup.storeexists.