66 lines
2.4 KiB
Go
66 lines
2.4 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"git.misaka.ren/m1saka/dsh-web/internal/store"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestOrphanReclaimGuards(t *testing.T) {
|
|
for _, kind := range []string{"safe", "running", "foreign-mount", "reference", "upgrade", "confirmation", "nonadmin"} {
|
|
t.Run(kind, func(t *testing.T) {
|
|
t.Setenv("HOST_DATA_ROOT", "/host/data")
|
|
id, inst, owner := strings.Repeat("a", 64), strings.Repeat("b", 32), strings.Repeat("c", 32)
|
|
deleted := false
|
|
a, sid := runtimeTestAPI(t, func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method == "DELETE" {
|
|
if r.URL.Query().Get("force") != "false" || r.URL.Query().Get("v") != "false" {
|
|
t.Fatal("unsafe deletion")
|
|
}
|
|
deleted = true
|
|
w.WriteHeader(204)
|
|
return
|
|
}
|
|
source := "/host/data/workspaces/" + owner + "/instances/" + inst + "/home"
|
|
if kind == "foreign-mount" {
|
|
source = "/unrelated"
|
|
}
|
|
writeJSON(w, map[string]any{"Id": id, "Name": "/dsh-inst-" + inst, "Config": map[string]any{"Labels": map[string]string{"dsh-mgr.role": "dsh", "dsh-mgr.instance": inst, "dsh-mgr.owner": owner}}, "State": map[string]any{"Status": "exited", "Running": kind == "running"}, "Mounts": []map[string]string{{"Type": "bind", "Source": source, "Destination": "/workspace"}}})
|
|
})
|
|
if err := a.s.CreateUser(store.User{ID: owner, Username: "orphan-owner"}, "unused"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if kind != "nonadmin" {
|
|
if _, err := a.s.DB.Exec("UPDATE users SET admin=1 WHERE id='owner'"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if kind == "reference" {
|
|
if err := a.s.AddInstance(store.Instance{ID: inst, UID: owner, ContainerID: id}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if kind == "upgrade" {
|
|
if _, err := a.s.DB.Exec("CREATE TABLE upgrade_journal(instance_id TEXT,old_container TEXT,new_container TEXT); INSERT INTO upgrade_journal VALUES(?,?,'')", inst, id); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if kind == "safe" && a.checkOrphan(context.Background(), id) != nil {
|
|
t.Fatal("safe orphan rejected")
|
|
}
|
|
confirm := id
|
|
if kind == "confirmation" {
|
|
confirm = "wrong"
|
|
}
|
|
w := httptest.NewRecorder()
|
|
a.orphans(w, runtimeRequest("DELETE", "/api/orphans?id="+id+"&confirm="+confirm, "", sid))
|
|
if (w.Code == 200) != (kind == "safe") || deleted != (kind == "safe") {
|
|
t.Fatalf("status=%d deleted=%v body=%s", w.Code, deleted, w.Body.String())
|
|
}
|
|
})
|
|
}
|
|
}
|