F20-BUG1: surface swallowed format error in agentapi.FormatDisk
A failed agent format (e.g. 502 'device is mounted', ok:false, data:null) fell through FormatDisk's trailing 'return out, nil', so the web layer reported a zero-value FormatResult as ok:true — a failed DESTRUCTIVE format read as success. postWithStatus now returns the full envelope; FormatDisk returns a non-nil error on any non-2xx/ok:false that is not a recognized refusal (403/needs-confirmation). Test TestFormat_MountedFailureSurfacesError (502 → non-nil err) fails on old code.
This commit is contained in:
@@ -34,6 +34,9 @@ func diskStub(t *testing.T) (*httptest.Server, string) {
|
||||
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"}}`))
|
||||
case strings.Contains(body.Device, "mounted"): // mkfs failed (e.g. device mounted) → agent 502, data:null
|
||||
w.WriteHeader(http.StatusBadGateway)
|
||||
_, _ = w.Write([]byte(`{"ok":false,"error":"format failed: /dev/sdb1 is mounted; will not make a filesystem here!","data":null}`))
|
||||
default: // blank, or user-data confirmed
|
||||
_, _ = w.Write([]byte(`{"ok":true,"data":{"device":"` + body.Device + `","formatted":true,"role":"user-data"}}`))
|
||||
}
|
||||
@@ -117,6 +120,28 @@ func TestFormat_UserDataConfirmed(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// F20-BUG1: a real mkfs failure (agent 502, ok:false, data:null) must surface as a non-nil error —
|
||||
// NOT a zero-value FormatResult with nil err (which read as a silent SUCCESS in the web layer).
|
||||
func TestFormat_MountedFailureSurfacesError(t *testing.T) {
|
||||
s, ep := diskStub(t)
|
||||
defer s.Close()
|
||||
c := clientFor(t, s, ep)
|
||||
res, err := c.FormatDisk(context.Background(), "/dev/sdb1-mounted", "ext4", true, "byid:wwn-1")
|
||||
if err == nil {
|
||||
t.Fatalf("expected a non-nil error for a failed format, got (res=%+v, err=nil) — silent success regression", res)
|
||||
}
|
||||
if res.Formatted {
|
||||
t.Fatalf("Formatted must be false on a failed format: %+v", res)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "502") || !strings.Contains(err.Error(), "mounted") {
|
||||
t.Fatalf("error should carry the HTTP status + agent message, got: %v", err)
|
||||
}
|
||||
// Must not be misclassified as one of the gated refusals.
|
||||
if errors.Is(err, ErrNeedsConfirmation) || errors.Is(err, ErrFormatRefused) {
|
||||
t.Fatalf("a 502 mkfs failure must not be reported as a refusal: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEject_Dependents(t *testing.T) {
|
||||
s, ep := diskStub(t)
|
||||
defer s.Close()
|
||||
|
||||
Reference in New Issue
Block a user