mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-09 22:13:18 +09:00
Editing a VMDisk's storageClass or source after its DataVolume already
exists was silently ignored: dv.yaml reused the existing DataVolume.spec
verbatim (DataVolume.spec is immutable in CDI), so the edit rendered as a
no-op while the HelmRelease reported success and the CR diverged from the
cluster.
When a DataVolume already exists, fail with a clear message if the
requested storageClass or source differs from what the disk was created
with. Both compare the operator's input recorded in an annotation at
creation (vm-disk.cozystack.io/storage-class and .../source), written only
at creation and preserved verbatim afterwards — never overwritten with an
unapplied edit. Recording the input rather than reading the live object
matters on both axes: the image-clone PVC name carries a chart-version
prefix (vm-image- was renamed to vm-default-images-, commit bec35e3a) that
drifts across upgrades with no edit, and the live PVC storageClassName of an
adopted or foreign DataVolume may legitimately differ from the CR default
without being a change. The annotation key presence (not its value) marks a recorded class, so a disk
created with the cluster default "" is recorded and still caught if later
changed to a concrete class.
Disks with no annotation (created earlier, or out-of-band) are handled
conservatively so a working release never deadlocks: source is compared
against the stored spec.source only when that stored source is a shape the
chart itself produces, so an adopted DataVolume using spec.sourceRef or a
non-chart source (registry, snapshot, http+secretRef, ...) is left alone
rather than deadlocked. The image-clone exemption fires only when the stored
source is a cozy-public pvc AND the request is itself an image, so a change
away from an image source to another type is still caught. storageClass has
no safe live fallback, so an un-annotated disk is not guarded here (apiserver
CEL, #2657, is the eventual guard). An unrecognized source type
now fails explicitly. Storage growth is unaffected and still handled by
pvc-resize-hook.yaml.
Mark source as immutable in values.yaml so the generated schema carries
the same x-kubernetes-validations rule already present on storageClass,
and document the contract, the exemption, and the source-annotation schema
coupling in docs/storage-immutability.md and the chart README.
Add helm-unittest coverage for the immutability guard (rejection incl.
clearing storageClass to empty and changing a non-image disk to image,
no-op reuse with annotations preserved, legacy image-disk drift, annotation
non-poisoning, un-annotated storageClass skip, adopted default-class disk,
unknown source) and initial-creation source rendering.
Fixes #2985
Signed-off-by: Alexey Artamonov <aleksei.artamonov@aenix.io>
Virtual Machine Disk
A Virtual Machine Disk
storageClassandsourceare annotated as immutable in the chart schema — seedocs/storage-immutability.mdfor the contract and which consumers enforce it.DataVolume.specis immutable in CDI, so the chart also fails the release on an attemptedstorageClass/sourceedit of an existing disk rather than silently reusing the old spec; delete and recreate the disk to change either field.
Parameters
Common parameters
| Name | Description | Type | Value |
|---|---|---|---|
source |
The source image location used to create a disk. | object |
{} |
source.image |
Use image by name from default collection. | *object |
null |
source.image.name |
Name of the image to use. | string |
"" |
source.upload |
Upload local image. | *object |
null |
source.http |
Download image from an HTTP source. | *object |
null |
source.http.url |
URL to download the image. | string |
"" |
source.disk |
Clone an existing vm-disk. | *object |
null |
source.disk.name |
Name of the vm-disk to clone. | string |
"" |
optical |
Defines if disk should be considered optical. | bool |
false |
storage |
The size of the disk allocated for the virtual machine. | quantity |
5Gi |
storageClass |
StorageClass used to store the data. | string |
replicated |