v0.329.0: each app reaches only its own appdata folder; empty allow-list; drive retirement asks the agent first; plain no-durable-id refusal; :latest only for a release
gates / gates (push) Successful in 45s
gates / gates (push) Successful in 45s
R-1142: the HDD_PATH root is appdata/<own folder>, with a compiled-in folder map (paperless-ngx -> paperless). R-981: the allow-list is empty (homepage's socket served no Felhom feature). R-1063: finalizeDecommissionWith asks the agent before it marks the drive or moves the default; the 403/409 come back typed and reach the household as a plain 409. R-1069: the agent's no-durable-id format refusal is ErrNoDurableID and a plain sentence. R-1143: build.sh carries :latest only for x.y.z. Each pinned by a red-proofed test. MinAgent 0.158.1.
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
@@ -35,3 +36,52 @@ func TestR856_CrashGuardDecodesAndAnOlderAgentIs404(t *testing.T) {
|
||||
t.Fatalf("an older agent must answer a typed 404, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// R-1063: the agent's two decommission refusals come back TYPED (403 a protected role, 409 the whole-guest backup
|
||||
// target), with the same text as before; any other failure is not that type.
|
||||
func TestDecommission_PolicyRefusalsAreTyped(t *testing.T) {
|
||||
for _, c := range []struct {
|
||||
code int
|
||||
typed bool
|
||||
}{{http.StatusForbidden, true}, {http.StatusConflict, true}, {http.StatusBadGateway, false}} {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("POST /disks/decommission", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(c.code)
|
||||
_, _ = w.Write([]byte(`{"ok":false,"error":"refused for the test"}`))
|
||||
})
|
||||
s := httptest.NewTLSServer(mux)
|
||||
_, err := clientFor(t, s, strings.TrimPrefix(s.URL, "https://")).Decommission(context.Background(), "/mnt/x")
|
||||
s.Close()
|
||||
var dr *DecommissionRefusedError
|
||||
if got := errors.As(err, &dr); got != c.typed {
|
||||
t.Fatalf("HTTP %d: typed=%v, want %v (err %v)", c.code, got, c.typed, err)
|
||||
}
|
||||
if c.typed && (dr.Status != c.code || !strings.Contains(err.Error(), "HTTP "+strconv.Itoa(c.code)+": refused for the test")) {
|
||||
t.Fatalf("HTTP %d: %+v / %q", c.code, dr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// R-1069: the agent's anti-retarget refusal of a blank format (its exact text, a 409) comes back as ErrNoDurableID;
|
||||
// another 409 does not.
|
||||
func TestFormatDisk_NoDurableIDIsTyped(t *testing.T) {
|
||||
for _, c := range []struct {
|
||||
body string
|
||||
typed bool
|
||||
}{
|
||||
{`{"ok":false,"error":"format refused: device has no durable id to bind the format to (path-only formats are not permitted)","data":{"formatted":false,"data_bearing":false}}`, true},
|
||||
{`{"ok":false,"error":"format refused (device may have changed since inspection): gone","data":{"formatted":false}}`, false},
|
||||
} {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("POST /disks/format", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusConflict)
|
||||
_, _ = w.Write([]byte(c.body))
|
||||
})
|
||||
s := httptest.NewTLSServer(mux)
|
||||
_, err := clientFor(t, s, strings.TrimPrefix(s.URL, "https://")).FormatDisk(context.Background(), "/dev/vdb", "ext4", false, "")
|
||||
s.Close()
|
||||
if got := errors.Is(err, ErrNoDurableID); got != c.typed || err == nil {
|
||||
t.Fatalf("body %s: ErrNoDurableID=%v want %v (err %v)", c.body[:60], got, c.typed, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user