fix(storageclass): ignore vcluster-managed host mirrors - #5
Conversation
|
Independent adversarial review found the managed-host owned-delete path must not use name-only deletion on a stale event. The race-safe helper now lives on PR #6 head Do not merge/deploy this PR standalone before PR #6's helper is included (or this branch is rebased onto it). Independent re-review/test of the combined head is in progress. |
weicao
left a comment
There was a problem hiding this comment.
Focused design-contract review at exact head e829529cb1d62f82c737b64b27488333b222c99e (base apecloud-v0.35.1).
BLOCKER — deletion is not ownership-bound
pkg/controllers/resources/storageclasses/host_syncer.go:98-100 deletes any virtual StorageClass whose name equals a vCluster-managed host StorageClass name. Name equality alone does not prove that the virtual object is the stale mirror created from that host object. A user-owned guest StorageClass can independently have the same long name and no managed marker; reconciling the other vCluster's host object then deletes that user object.
Direct adversarial evidence on the exact head:
TestReviewManagedHostDoesNotDeleteUnownedSameNameVirtualStorageClass
host: name=baseline-x-other-vcluster, managed-by=other-vcluster
virtual: same name, no managed marker, provisioner=user-provisioner
expected: virtual preserved
actual: virtual deleted
result: FAIL
The existing focused tests and their race run pass, but the current "same-name stale mirror" fixtures do not prove mirror ownership: staleVirtualObject / staleVirtual have no marker or other ownership evidence and therefore encode the unsafe behavior as expected.
Please require explicit mirror ownership before DeleteVirtualObject (using the contractually preserved marker/ownership metadata, not name alone), and add both cases:
- owned stale mirror is deleted;
- same-name unowned virtual StorageClass is preserved.
Pre-flight: purpose and two-file scope are coherent; current head verified; no runtime shell/API-version issue. Evidence is source/unit only, not a runtime or product verdict.
Classes 1-8:
- silent fallback: clean; managed host objects fail closed from import.
- non-empty/write contract: blocker equivalent here — destructive ownership precondition is not enforced.
- commit-state continuity: clean in the reviewed path.
4/4a. sentinel/cross-field collision: clean; emptyNamespacedNameis checked by enqueue logic. - conditional cleanup pre-state: blocker at lines 98-100; cleanup is conditioned only on name equality, not revalidated ownership.
- NotFound: clean for this delta.
- terminating vs absent: no release contract in this delta.
- precedence: clean.
Direct commands: existing focused tests rc0; focused race rc0; adversarial ownership-negative case rc1 as above.
Problem
With
sync.fromHost.storageClasses.enabled=trueand an empty selector on a shared host, host StorageClasses created by another vCluster carryvcluster.loft.sh/managed-byandvcluster.loft.sh/object-name. The mirror mapper can map those objects onto a guest name before the host StorageClass syncer evaluates its selector. This can import stale long-name mirrors, overwrite an annotation-mapped guest StorageClass, or make selector-mismatch cleanup delete the wrong guest object.Current-state evidence from the TiDB KB1.2 lane shows one baseline host default StorageClass, one old vCluster-managed translated host collision, the corresponding guest collision, and host-storageclass delete attempts failing on RBAC. This is a syncer contract issue, not a TiDB product failure.
Change
SyncToVirtual.object-nameannotation mapping.Tests
Validated on
aaff9e25ea2650a4429e5d46ae04bb248e6023ca:All pass. Runtime evidence is intentionally not claimed by this PR; the pre-release image is for a separate focused live gate.