package api import ( "io" "log" "net/http" "net/http/httptest" "os" "path/filepath" "strings" "testing" "gitea.dooplex.hu/admin/felhom-controller/internal/config" "gitea.dooplex.hu/admin/felhom-controller/internal/settings" "gitea.dooplex.hu/admin/felhom-controller/internal/stacks" ) // R-839: a deploy whose HDD_PATH names a folder INSIDE a registered drive is refused at the API, so // the boot sweep can never again hold an app for asking a folder whether it is a mountpoint. Through // the real deployStack handler. PATH is emptied so a regression that lets the deploy proceed can // never reach a real docker (tests that reach real docker act on DooPlex). func TestR839_DeployRefusesASubPathOfADrive(t *testing.T) { t.Setenv("PATH", "") lg := log.New(io.Discard, "", 0) root := t.TempDir() sett, err := settings.Load(filepath.Join(root, "settings.json"), lg) if err != nil { t.Fatal(err) } const drive = "/mnt/felhom-drives/scratch_hdd" if err := sett.AddStoragePath(settings.StoragePath{Path: drive, Label: "HDD", Schedulable: true}); err != nil { t.Fatal(err) } cfg := &config.Config{} cfg.Paths.StacksDir = filepath.Join(root, "stacks") cfg.Stacks.ComposeCommand = "docker compose" if err := os.MkdirAll(cfg.Paths.StacksDir, 0o755); err != nil { t.Fatal(err) } m, err := stacks.NewManager(cfg, lg) if err != nil { t.Fatal(err) } r := &Router{stackMgr: m, cfg: cfg, sett: sett, logger: lg} r.classifyFSPath = func(string) string { return "" } deploy := func(hdd string) (int, string) { w := httptest.NewRecorder() body := `{"values":{"HDD_PATH":"` + hdd + `"}}` r.deployStack(w, httptest.NewRequest(http.MethodPost, "/api/stacks/paperless-ngx/deploy", strings.NewReader(body)), "paperless-ngx") return w.Code, w.Body.String() } code, body := deploy(drive + "/userdata/paperless-ngx") if code != http.StatusConflict || !strings.Contains(body, "nem egy mappa") || !strings.Contains(body, drive) { t.Fatalf("R-839: a folder inside a drive must be refused naming the drive; got %d %s", code, body) } // Controls: the drive itself and an unregistered path are not this gate's business. for _, ok := range []string{drive, drive + "/", "/srv/elsewhere"} { if _, b := deploy(ok); strings.Contains(b, "nem egy mappa") { t.Errorf("R-839: %q must not be refused as a folder inside a drive: %s", ok, b) } } if d, in := sett.DriveOfSubPath(drive + "x/userdata"); in { t.Errorf("a sibling path sharing the prefix (%s) is not inside the drive", d) } }