Parent: #208
Summary
Make the Go ensure path tolerate a nil control room target so that workloads with empty control_room_* fields in ptd.yaml can run ptd ensure without panicking. This is the foundational refactoring that enables severance — once the code handles "no control room" as a valid state, eject can simply strip the config and re-run ensure.
Context
Today, persistent.go:141 calls updateControlRoomMimirPassword(ctx, s.SrcTarget, ...) with no nil guard — if SrcTarget is nil, this panics. All 11 step implementations assign controlRoomTarget to SrcTarget via Set(), but only persistent.go actually uses it.
Additionally, cmd/ensure.go:132-139 calls ControlRoomTargetFromName() which errors if the control room config is not found. This needs a "no control room configured" path that passes nil instead of erroring.
Requirements
lib/steps/persistent.go: Guard the updateControlRoomMimirPassword call — skip if s.SrcTarget == nil
lib/steps/persistent.go:148-164: The workload secret write only runs for AWS (types.AWS check) — verify this path also handles nil control room safely
lib/steps/steps.go: Verify Set() handles nil gracefully (line 193-195 has a nil check for logging — confirm nothing else needs guarding)
cmd/ensure.go: When control_room_* fields are empty, pass nil as controlRoomTarget instead of erroring. Must work for both AWS and Azure workload targets.
- Tests: persistent step with nil SrcTarget for both AWS and Azure workload types, ensure command with empty control room config
Acceptance Criteria
ptd ensure <target> --only-steps persistent succeeds when ptd.yaml has empty control_room_* fields, for both AWS and Azure workloads
- Mimir password sync is skipped, workload-local operations proceed normally
- No panics when any ensure step receives a nil control room target
Parent: #208
Summary
Make the Go ensure path tolerate a nil control room target so that workloads with empty
control_room_*fields in ptd.yaml can runptd ensurewithout panicking. This is the foundational refactoring that enables severance — once the code handles "no control room" as a valid state, eject can simply strip the config and re-run ensure.Context
Today,
persistent.go:141callsupdateControlRoomMimirPassword(ctx, s.SrcTarget, ...)with no nil guard — ifSrcTargetis nil, this panics. All 11 step implementations assigncontrolRoomTargettoSrcTargetviaSet(), but onlypersistent.goactually uses it.Additionally,
cmd/ensure.go:132-139callsControlRoomTargetFromName()which errors if the control room config is not found. This needs a "no control room configured" path that passes nil instead of erroring.Requirements
lib/steps/persistent.go: Guard theupdateControlRoomMimirPasswordcall — skip ifs.SrcTarget == nillib/steps/persistent.go:148-164: The workload secret write only runs for AWS (types.AWScheck) — verify this path also handles nil control room safelylib/steps/steps.go: VerifySet()handles nil gracefully (line 193-195 has a nil check for logging — confirm nothing else needs guarding)cmd/ensure.go: Whencontrol_room_*fields are empty, passnilascontrolRoomTargetinstead of erroring. Must work for both AWS and Azure workload targets.Acceptance Criteria
ptd ensure <target> --only-steps persistentsucceeds when ptd.yaml has emptycontrol_room_*fields, for both AWS and Azure workloads