a43d0423d5
gates / gates (push) Successful in 46s
felhom.eu architecture/16 §4-§6 (build B). MinAgent 0.157.0 — the internal place and the partitions appear only when agent >= 0.158.0 reports them. Tests red-proved; four parity fixtures refreshed (only the new lines). Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
104 lines
4.1 KiB
Go
104 lines
4.1 KiB
Go
package web
|
|
|
|
import (
|
|
"context"
|
|
"net/http/httptest"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"gitea.dooplex.hu/admin/felhom-controller/internal/agentapi"
|
|
"gitea.dooplex.hu/admin/felhom-controller/internal/settings"
|
|
)
|
|
|
|
// The internal data place (felhom.eu architecture/16 §5, v0.318.0): bound and registered with no press, the default
|
|
// drive when there is no other, never ejected, retired or formatted.
|
|
|
|
func internalRow(gp string, bound bool) agentapi.DiskInfo {
|
|
return agentapi.DiskInfo{Name: "belso", Kind: agentapi.PlaceKindInternal, MountPath: "/mnt/belso", GuestPath: gp,
|
|
BoundUnderParent: bound, Role: "user-data"}
|
|
}
|
|
|
|
func TestInternalPlace_UnboundIsBoundNotYetRegistered(t *testing.T) {
|
|
s := testServer(t)
|
|
gp := filepath.Join(t.TempDir(), "belso")
|
|
ag := &mockAgent{}
|
|
s.ensureInternalPlace(context.Background(), ag, []agentapi.DiskInfo{internalRow(gp, false)})
|
|
if len(ag.guestAttachCalls) != 1 || ag.guestAttachCalls[0] != "/mnt/belso" {
|
|
t.Fatalf("want one guest bind of /mnt/belso, got %v", ag.guestAttachCalls)
|
|
}
|
|
if n := len(s.settings.GetStoragePaths()); n != 0 {
|
|
t.Fatalf("an unbound place must not be registered yet, got %d path(s)", n)
|
|
}
|
|
}
|
|
|
|
func TestInternalPlace_BoundIsRegisteredAsTheDefaultDrive(t *testing.T) {
|
|
s := testServer(t)
|
|
gp := filepath.Join(t.TempDir(), "belso")
|
|
ag := &mockAgent{}
|
|
s.ensureInternalPlace(context.Background(), ag, []agentapi.DiskInfo{internalRow(gp, true)})
|
|
paths := s.settings.GetStoragePaths()
|
|
if len(paths) != 1 {
|
|
t.Fatalf("want the internal place registered once, got %+v", paths)
|
|
}
|
|
sp := paths[0]
|
|
if sp.Path != gp || !sp.IsInternal() || !sp.IsDefault || !sp.Schedulable || sp.Label == "" || strings.Contains(sp.Label, ".") {
|
|
t.Fatalf("registered as: %+v", sp)
|
|
}
|
|
if len(ag.guestAttachCalls) != 0 {
|
|
t.Fatalf("a bound place needs no new bind, got %v", ag.guestAttachCalls)
|
|
}
|
|
// Idempotent: the next tick changes nothing.
|
|
s.ensureInternalPlace(context.Background(), ag, []agentapi.DiskInfo{internalRow(gp, true)})
|
|
if n := len(s.settings.GetStoragePaths()); n != 1 {
|
|
t.Fatalf("a second tick must not register it again, got %d", n)
|
|
}
|
|
}
|
|
|
|
func TestInternalPlace_HouseholdDefaultStaysDefault(t *testing.T) {
|
|
s := testServer(t)
|
|
usb := filepath.Join(t.TempDir(), "hdd_1")
|
|
if err := s.settings.AddStoragePath(settings.StoragePath{Path: usb, IsDefault: true, Schedulable: true}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
gp := filepath.Join(t.TempDir(), "belso")
|
|
s.ensureInternalPlace(context.Background(), &mockAgent{}, []agentapi.DiskInfo{internalRow(gp, true)})
|
|
for _, sp := range s.settings.GetStoragePaths() {
|
|
if sp.Path == gp && sp.IsDefault {
|
|
t.Fatalf("the household's own default drive must stay the default")
|
|
}
|
|
if sp.Path == usb && !sp.IsDefault {
|
|
t.Fatalf("the USB default was taken away")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestInternalPlace_OtherKindsAreNotTouched(t *testing.T) {
|
|
s := testServer(t)
|
|
ag := &mockAgent{}
|
|
usb := agentapi.DiskInfo{Name: "hdd_1", Kind: "disk", MountPath: "/mnt/hdd_1", GuestPath: filepath.Join(t.TempDir(), "hdd_1"), BoundUnderParent: false}
|
|
s.ensureInternalPlace(context.Background(), ag, []agentapi.DiskInfo{usb})
|
|
if len(ag.guestAttachCalls) != 0 || len(s.settings.GetStoragePaths()) != 0 {
|
|
t.Fatalf("a household drive is enrolled only by the household: attach=%v paths=%v", ag.guestAttachCalls, s.settings.GetStoragePaths())
|
|
}
|
|
}
|
|
|
|
// Eject, decommission and wipe of the internal place are refused in words. Positive control: a normal drive path is
|
|
// not refused by this gate.
|
|
func TestInternalPlace_LifecycleRefused(t *testing.T) {
|
|
s := testServer(t)
|
|
gp := filepath.Join(t.TempDir(), "belso")
|
|
s.ensureInternalPlace(context.Background(), &mockAgent{}, []agentapi.DiskInfo{internalRow(gp, true)})
|
|
r := httptest.NewRequest("POST", "/api/storage/eject", nil)
|
|
w := httptest.NewRecorder()
|
|
if !s.refuseInternalLifecycle(w, r, gp+"/") {
|
|
t.Fatalf("the internal place must be refused")
|
|
}
|
|
if w.Code != 400 || !strings.Contains(w.Body.String(), "lemez") {
|
|
t.Fatalf("refusal: %d %s", w.Code, w.Body.String())
|
|
}
|
|
if s.refuseInternalLifecycle(httptest.NewRecorder(), r, "/mnt/felhom-drives/hdd_1") {
|
|
t.Fatalf("positive control: a household drive is not refused by this gate")
|
|
}
|
|
}
|