An action on a name that is no app answers 404, not 'settings cannot be saved' (found walking capability map B2 on 9202)
gates / gates (push) Successful in 27s

Test TestAnActionOnANameThatIsNoAppIsA404 red first. Commit only.
This commit is contained in:
admin committed 2026-10-28 23:56:36 +01:00
1 parent eed23e7594
commit 20c5877056
4 files changed
+44 -1

No files matched your search

+5
View File
@@ -40,6 +40,11 @@ night report (`audits/night-2026-10-28/`).
and said once; no agent (9202) = Docker's flag only, as before. The inspect now reads `{{.Id}}` too. Tests
`TestR528_*` (stacks, cmd/controller), red before the fix (the host-counted kill was not seen) or red-proved by
mutation (the back-off, the wiring).
- **Found walking the capability map's B2 on 9202 (small, fixed in the session):** a Stop/Start of a name that is no
app on the box (the bootstrap-managed `felhom-controller`) answered 500 „…az alkalmazás beállításai nem menthetők." —
the desired-state write's „not found" read as a save failure. `stacks.SetDesiredState` returns the
`ErrStackNotFound` kind with the household's sentence (`err.stacks.alkalmazas_nem_talalhato`); `actionStack` answers
404 before recording any intent. Nothing was ever stopped. Test `TestAnActionOnANameThatIsNoAppIsA404` (red first).
- **H8 — `internal/backup/restore_copy_sweep.go`:** an unused restore copy goes after 14 days. Every 6 hours
(`restore-copy-sweep`) a copy is removed only when the app has no restore hold of any kind, the app-stop marker is
readable and does not name the app, no restore runs, and the copy is older than 14 days. Tests `TestR1256_H8_*`
+6
View File
@@ -771,6 +771,12 @@ func (r *Router) actionStack(w http.ResponseWriter, req *http.Request, action, n
// above, so nothing is recorded for an action that was never going to happen.
if desired, ok := desiredStateForAction(action); ok {
if derr := r.stackMgr.SetDesiredState(name, desired); derr != nil {
if errors.Is(derr, stacks.ErrStackNotFound) {
// no app by that name on this box (e.g. the bootstrap-managed controller): a 404, not a save failure
r.logger.Printf("[WARN] [api] %s for %s refused: no such app", action, name)
writeJSON(w, stackOpStatusFor(derr), apiResponse{OK: false, Error: r.errText(req, derr)})
return
}
r.logger.Printf("[ERROR] [api] %s for %s refused: could not record desired state: %v", action, name, derr)
writeJSON(w, http.StatusInternalServerError, apiResponse{
OK: false,
@@ -0,0 +1,29 @@
package api
import (
"encoding/json"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
// Found walking the capability map's B2 („App lifecycle") on 9202, 2026-10-28 night: a Stop of a name that is no app
// on this box (`felhom-controller` — bootstrap-managed, not a stack) answered 500 „…az alkalmazás beállításai nem
// menthetők." — the desired-state write's „not found" read as a save failure. It is a 404 now, before any intent is
// recorded. RED-PROOF: drop the ErrStackNotFound branch in actionStack → 500 → FAILS.
func TestAnActionOnANameThatIsNoAppIsA404(t *testing.T) {
r, _, _, _ := newSlice4Router(t)
for _, action := range []string{"stop", "start"} {
w := httptest.NewRecorder()
r.actionStack(w, httptest.NewRequest("POST", "/api/stacks/nosuchapp/"+action, nil), action, "nosuchapp")
var resp apiResponse
_ = json.Unmarshal(w.Body.Bytes(), &resp)
if w.Code != http.StatusNotFound {
t.Fatalf("%s of a name that is no app: %d %q — want 404", action, w.Code, resp.Error)
}
if strings.Contains(strings.ToLower(resp.Error), "mentheto") || strings.Contains(resp.Error, "menthetők") {
t.Fatalf("%s: the answer still blames a save: %q", action, resp.Error)
}
}
}
+4 -1
View File
@@ -3,6 +3,8 @@ package stacks
import (
"fmt"
"path/filepath"
"gitea.dooplex.hu/admin/felhom-controller/internal/util"
)
// Desired-state values for AppConfig.DesiredState (R-166, decision D-b).
@@ -57,7 +59,8 @@ func (m *Manager) SetDesiredState(name, desired string) error {
stack, ok := m.GetStack(name)
if !ok {
return fmt.Errorf("stack %q not found", name)
// a KIND (404 at the API) and the household's sentence — not a save failure
return util.MsgErrorf(ErrStackNotFound, "err.stacks.alkalmazas_nem_talalhato", name)
}
stackDir := filepath.Dir(stack.ComposePath)