You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: PLAN.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -533,7 +533,7 @@ and per-object configuration lives in typed Spec / Status fields.
533
533
534
534
### 10.2 — Status is the only home for observed state
535
535
536
-
-[] Audit every site where observed state currently writes to `Spec.Props`. Today `pkg/satellitecontroller/server.applyObserved`lands `DrbdState`into Resource Spec via `SetState`'s `drbdProps`; that's a Spec write triggered by an observation stream — race with desired-state writers. Move `DrbdState` to the existing `Resource.Status.Volumes[i].DiskState` (typed) and drop the Spec side-write entirely.
536
+
-[x] Audit every site where observed state currently writes to `Spec.Props` (2026-05-10). `applyObserved`now sets `state.DrbdState`directly on the typed `apiv1.ResourceState`; the k8s store routes the whole write through `.Status().Update()` to `Resource.Status.DrbdState`. SetState's legacy `drbdProps map[string]string` parameter is gone. No production Spec.Props side-writes remain on the observation path.
537
537
-[ ] Add `ResourceVolumeStatus.CurrentGi string` (also covered by Phase 8.1 follow-up) and `ResourceVolumeStatus.HistoryGi []string` if split-brain visibility matters for the UI.
538
538
-[ ] Document the Spec/Status split rule in `docs/architecture.md`: anything observed by the satellite from the kernel goes to Status, never Spec; anything the operator or controller asks the satellite to do goes to Spec, never Status.
539
539
-[ ] Use Kubernetes server-side-apply field managers when both controller (writes parts of Status — e.g. allocator outputs `DRBDPort`) and satellite (writes other parts of Status — `DiskState`, `CurrentGi`) touch the same Status, so neither clobbers the other. Today the controller uses regular `Update` which can clobber Status writes that landed between Get and Update.
@@ -547,10 +547,10 @@ LINSTOR boundary.
547
547
548
548
-[x]`ResourceDefinition.Spec.DRBDOptions { Net, Disk, PeerDevice, Resource, Handlers }` typed structs (2026-05-10). Embedded on RG/RD/Resource alongside the existing Props map; `pkg/drbd.ResolveDRBDOptions` walks the same controller→RG→RD→Resource hierarchy with nil-vs-set discipline so an explicit `*bool=false` survives lower-scope inheritance and an empty-string handler key DELETES the inherited entry.
549
549
-[x]`ResourceDefinition.Spec.Encryption.PassphraseSecretRef LocalObjectReference` (2026-05-10). The CRD now carries `EncryptionConfig.PassphraseSecretRef`; the satellite already reads the passphrase via the apiserver on reconcile (Phase 6) — this just typifies the slot that previously lived in `Props["DrbdOptions/Encryption/passphrase"]`.
550
-
-[]`Node.Spec.SatelliteEndpoint string`— replaces `Props["SatelliteEndpoint"]`. (Or removed entirely once 10.6 lands and the endpoint is no longer dialled.)
550
+
-[x]`Node.Spec.SatelliteEndpoint string`(2026-05-10). Dispatcher reads typed first with Props fallback; k8s store transcodes both ways so golinstor still sees `Props["SatelliteEndpoint"]` on GET.
551
551
-[ ]`Node.Spec.DRBDPortRange / DRBDMinorRange { Min, Max int32 }` — replaces `Props["DrbdOptions/TcpPortRange"]` / `"DrbdOptions/MinorNrRange"`. Defaults baked in via kubebuilder.
-[]`Resource.Spec.StoragePool string`— replaces `Props["StorPoolName"]`. Already half-typed via dispatcher's `buildVolumes`; finish the migration.
553
+
-[x]`Resource.Spec.StoragePool string`(2026-05-10). Typed field on Resource; dispatcher's buildVolumes + autoplacer dispatch read typed first; auto-diskful promotion stamps both typed + legacy Props key; k8s store transcodes both ways.
554
554
-[ ] Topology: drop `Props["Aux/zone"]` / `"Aux/rack"`. Use Kubernetes-native `metadata.labels["topology.blockstor.io/zone"]` etc. Autoplacer reads labels via `client.MatchingLabels`. This is also the upgrade path to label-aware features like `topologySpreadConstraints` later.
555
555
-[x] REST shim transcoder (2026-05-10). `pkg/store/k8s/drbd_transcode.go` splits the wire `props` bag into `Spec.DRBDOptions` (recognised keys) + `Spec.ExtraProps` (unknown DrbdOptions/* + non-DRBD residual keys); inverse re-emits typed back to `props` on GET. Pinned by 7 unit tests (per-section recognition, unknown-key fallthrough, parse-error fallback, round-trip losslessness, bool spelling tolerance). Controller's `resolveEffectiveProps` now walks typed via `ResolveDRBDOptions` and flattens via `drbd.TypedDRBDOptionsToProps` for the dispatcher → satellite renders the same .res file from typed CRD fields rather than string-keyed Props.
556
556
-[x] Validation via kubebuilder enums (2026-05-10). `Net.Protocol`, `Disk.OnIOError`, `Resource.Quorum`, `Resource.OnNoQuorum`, `Net.AfterSb0Pri/1Pri/2Pri` all carry `+kubebuilder:validation:Enum=...` markers; CRD manifests regenerated. Pinned via `internal/controller/drbd_admission_test.go` — 8 ginkgo specs that submit garbage values against a live envtest apiserver and assert it rejects at admission.
0 commit comments