v0.44.0: role-aware drive management — protected lockout + customer type-to-confirm wipe + drive-list restyle
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -22,14 +22,21 @@ func diskStub(t *testing.T) (*httptest.Server, string) {
|
||||
_, _ = w.Write([]byte(`{"ok":true,"data":{"ejected":"/mnt/bulk","dependent_guests":[8200]}}`))
|
||||
})
|
||||
mux.HandleFunc("POST /disks/format", func(w http.ResponseWriter, r *http.Request) {
|
||||
var body struct{ Device, FSType string }
|
||||
_ = decodeJSON(r, &body)
|
||||
if strings.Contains(body.Device, "data") {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
_, _ = w.Write([]byte(`{"ok":false,"error":"device is data-bearing — operator authorization (pending_signature)"}`))
|
||||
return
|
||||
var body struct {
|
||||
Device, FSType, DurableID string
|
||||
Confirmed bool
|
||||
}
|
||||
_ = decodeJSON(r, &body)
|
||||
switch {
|
||||
case strings.Contains(body.Device, "protected"): // system/backup → operator signature
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
_, _ = w.Write([]byte(`{"ok":false,"data":{"device":"` + body.Device + `","data_bearing":true,"role":"system","pending_op":{"op":"storage_wipe","host_scope":"h","durable_id":"byid:x","fstype":"ext4"}}}`))
|
||||
case strings.Contains(body.Device, "data") && !body.Confirmed: // user-data, not yet confirmed
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
_, _ = w.Write([]byte(`{"ok":false,"data":{"device":"` + body.Device + `","data_bearing":true,"role":"user-data","needs_confirmation":true,"durable_id":"byid:wwn-1"}}`))
|
||||
default: // blank, or user-data confirmed
|
||||
_, _ = w.Write([]byte(`{"ok":true,"data":{"device":"` + body.Device + `","formatted":true,"role":"user-data"}}`))
|
||||
}
|
||||
_, _ = w.Write([]byte(`{"ok":true,"data":{"device":"` + body.Device + `","formatted":true}}`))
|
||||
})
|
||||
s := httptest.NewTLSServer(mux)
|
||||
return s, strings.TrimPrefix(s.URL, "https://")
|
||||
@@ -65,20 +72,49 @@ func TestFormat_BlankOK(t *testing.T) {
|
||||
s, ep := diskStub(t)
|
||||
defer s.Close()
|
||||
c := clientFor(t, s, ep)
|
||||
res, err := c.FormatDisk(context.Background(), "/dev/sdb", "ext4")
|
||||
res, err := c.FormatDisk(context.Background(), "/dev/sdb", "ext4", false, "")
|
||||
if err != nil || !res.Formatted {
|
||||
t.Fatalf("blank format: %v %+v", err, res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormat_DataBearingRefused(t *testing.T) {
|
||||
// SYSTEM/BACKUP data-bearing → ErrFormatRefused with the operator pending op.
|
||||
func TestFormat_ProtectedRefused(t *testing.T) {
|
||||
s, ep := diskStub(t)
|
||||
defer s.Close()
|
||||
c := clientFor(t, s, ep)
|
||||
_, err := c.FormatDisk(context.Background(), "/dev/data-disk", "ext4")
|
||||
res, err := c.FormatDisk(context.Background(), "/dev/protected-disk", "ext4", false, "")
|
||||
if !errors.Is(err, ErrFormatRefused) {
|
||||
t.Fatalf("expected ErrFormatRefused, got %v", err)
|
||||
}
|
||||
if res.PendingOp == nil {
|
||||
t.Fatal("protected refusal should carry the operator pending op")
|
||||
}
|
||||
}
|
||||
|
||||
// USER-DATA data-bearing, not confirmed → ErrNeedsConfirmation with the durable id to confirm against.
|
||||
func TestFormat_UserDataNeedsConfirmation(t *testing.T) {
|
||||
s, ep := diskStub(t)
|
||||
defer s.Close()
|
||||
c := clientFor(t, s, ep)
|
||||
res, err := c.FormatDisk(context.Background(), "/dev/data-disk", "ext4", false, "")
|
||||
if !errors.Is(err, ErrNeedsConfirmation) {
|
||||
t.Fatalf("expected ErrNeedsConfirmation, got %v", err)
|
||||
}
|
||||
if !res.NeedsConfirmation || res.DurableID != "byid:wwn-1" || res.Role != "user-data" {
|
||||
t.Fatalf("needs-confirmation payload not surfaced: %+v", res)
|
||||
}
|
||||
}
|
||||
|
||||
// USER-DATA data-bearing, confirmed + durable id → formatted.
|
||||
func TestFormat_UserDataConfirmed(t *testing.T) {
|
||||
s, ep := diskStub(t)
|
||||
defer s.Close()
|
||||
c := clientFor(t, s, ep)
|
||||
res, err := c.FormatDisk(context.Background(), "/dev/data-disk", "ext4", true, "byid:wwn-1")
|
||||
if err != nil || !res.Formatted {
|
||||
t.Fatalf("confirmed user-data format: %v %+v", err, res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEject_Dependents(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user