--- # platform-config-cdi — the SECOND-ORDER config wave: custom resources whose CRD is created at # RUNTIME by a controller that a `platform-config` custom resource switches on. # # ── THE BUG THIS DIRECTORY EXISTS TO FIX (observed on PROD, 2026-09-05) ─────────────────────────── # The repo already splits CONTROLLERS (`platform`) from CONFIGS (`platform-config`) because a CR # cannot be dry-run before its CRD is registered. That split assumes a CRD is registered by the # controller INSTALL. CDI breaks the assumption: `cdi-operator.yaml` registers exactly ONE CRD # (`cdis.cdi.kubevirt.io`). Every OTHER CDI CRD — `storageprofiles`, `datavolumes`, `datasources`, # `dataimportcrons`, … — is created by cdi-operator only AFTER it has reconciled the `CDI` CR. # # So `cdi-cr.yaml` is a FIRST-order CR (its CRD comes from the install) and belongs in # platform-config, while `cdi-storageprofiles.yaml` is a SECOND-order CR (its CRD comes from # reconciling the first-order CR). Having both in ONE Flux Kustomization is a true DEADLOCK, not a # race: kustomize-controller server-side dry-runs EVERY object before applying ANY of them, so the # unknown `StorageProfile` kind aborts the whole pass → the `CDI` CR is never applied → the # StorageProfile CRD is never created → platform-config can NEVER converge, and every tier that # dependsOn it stays blocked forever. On prod, cdi-operator sat Available for 12h with no CR: # # StorageProfile/longhorn dry-run failed: no matches for kind "StorageProfile" # in version "cdi.kubevirt.io/v1beta1" # # Invisible on dev (whose CDI CRDs have existed for months) and fatal on any COLD cluster. # # ── THE RULE, so this is not rediscovered a third time ──────────────────────────────────────────── # A CR belongs HERE (not in platform-config) when the CRD it needs is created by a CONTROLLER AT # RUNTIME rather than by a manifest in git. Grep test: if `grep -rn "kind: CustomResourceDefinition"` # over ./platform (following remote bases) does not produce the CRD, and no chart installs it, then # some operator creates it after being switched on — and this is the tier for it. # # Files are referenced IN PLACE via ../platform/... (Flux builds with LoadRestrictionsNone, and the # manifests stay beside the component they configure). Build/verify locally with: # kubectl kustomize --load-restrictor LoadRestrictionsNone platform-config-cdi apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: # CDI StorageProfiles — snapshot smart-clone for `longhorn`, and RWX/Block + snapshot clone for the # `longhorn-vm` virt-default class (clears CDIDefaultStorageClassDegraded). `StorageProfile`'s CRD # is created by cdi-operator only once the `CDI` CR (applied by platform-config) is reconciled, # which is exactly why these cannot live in the same pass as that CR. - ../platform/kubevirt/cdi-storageprofiles.yaml