controller: zero-toggle honesty — a configured+escrowed offbox with no app selected shows 'Nincs távoli mentésre jelölt alkalmazás…' on the toggle list, and a zero-toggle run reports 'Sikeres — nincs mentésre jelölt alkalmazás' instead of bare success
Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
This commit is contained in:
@@ -441,6 +441,12 @@ func (m *Manager) RunOffboxBackup(ctx context.Context) error {
|
||||
o.LastError = ""
|
||||
o.SnapshotCount = snapshots
|
||||
var warns []string
|
||||
// Zero-toggle honesty (take-two obs.): a configured target with NOTHING selected reports
|
||||
// its emptiness instead of a bare success — the customer thinks offsite runs, but nothing
|
||||
// is covered until at least one app is toggled.
|
||||
if len(apps) == 0 {
|
||||
warns = append(warns, "Sikeres — nincs mentésre jelölt alkalmazás")
|
||||
}
|
||||
if len(missing) > 0 {
|
||||
warns = append(warns, fmt.Sprintf("Figyelmeztetés: %d alkalmazásnak nincs elérhető mentése, ezek kimaradtak: %s",
|
||||
len(missing), strings.Join(missing, ", ")))
|
||||
|
||||
@@ -194,6 +194,43 @@ func TestOffbox_RunFailsFastAndAlerts(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Zero-toggle honesty (take-two obs., v0.123.0): a run with a configured+escrowed target but ZERO
|
||||
// toggled apps must stay status=ok yet report "Sikeres — nincs mentésre jelölt alkalmazás" instead
|
||||
// of a bare success. Red-proof: drop the len(apps)==0 warns branch → the LastWarning assertion fails.
|
||||
func TestOffbox_ZeroToggledRunReportsEmptiness(t *testing.T) {
|
||||
m, sett := newOffboxManager(t)
|
||||
m.SetOffboxRunner(func(_ context.Context, _ []string, args ...string) ([]byte, error) {
|
||||
if contains(args, "cat") && contains(args, "config") {
|
||||
return []byte(`{"version":2}`), nil // repo exists
|
||||
}
|
||||
return []byte(`[]`), nil
|
||||
})
|
||||
// No SetAppOffbox call — zero apps toggled.
|
||||
if err := m.RunOffboxBackup(context.Background()); err != nil {
|
||||
t.Fatalf("zero-toggled run must not error: %v", err)
|
||||
}
|
||||
st := sett.GetOffboxTarget()
|
||||
if st.LastStatus != "ok" {
|
||||
t.Fatalf("zero-toggled run status = %q, want ok (emptiness is honesty, not failure)", st.LastStatus)
|
||||
}
|
||||
if !strings.Contains(st.LastWarning, "Sikeres — nincs mentésre jelölt alkalmazás") {
|
||||
t.Fatalf("zero-toggled run must report its emptiness, LastWarning = %q", st.LastWarning)
|
||||
}
|
||||
|
||||
// Companion negative: with one toggled app captured, the emptiness copy must NOT appear.
|
||||
nsRoot := m.AppNamespaceRoot("rallly")
|
||||
if err := os.MkdirAll(filepath.Join(RecoveryUnitPath(nsRoot, "rallly"), "db-dumps"), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_ = sett.SetAppOffbox("rallly", true)
|
||||
if err := m.RunOffboxBackup(context.Background()); err != nil {
|
||||
t.Fatalf("toggled run must not error: %v", err)
|
||||
}
|
||||
if st := sett.GetOffboxTarget(); strings.Contains(st.LastWarning, "nincs mentésre jelölt") {
|
||||
t.Fatalf("a covered run must not carry the emptiness copy, LastWarning = %q", st.LastWarning)
|
||||
}
|
||||
}
|
||||
|
||||
// TestOffbox_RepoIdempotent: when the repo exists (cat config succeeds), ensure must NOT init.
|
||||
func TestOffbox_RepoIdempotent(t *testing.T) {
|
||||
m, sett := newOffboxManager(t)
|
||||
|
||||
@@ -671,7 +671,17 @@ func (s *Server) backupsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
offboxTgt := s.settings.GetOffboxTarget()
|
||||
data["Offbox"] = offboxTgt
|
||||
data["OffboxConfigured"] = s.backupMgr.OffboxConfigured()
|
||||
data["OffboxApps"] = s.buildOffboxApps()
|
||||
offboxApps := s.buildOffboxApps()
|
||||
data["OffboxApps"] = offboxApps
|
||||
// Zero-toggle hint (take-two obs.): configured + escrowed but no app selected — nothing is
|
||||
// actually covered by the offsite leg until the customer toggles at least one.
|
||||
offboxToggled := 0
|
||||
for _, a := range offboxApps {
|
||||
if a.Enabled {
|
||||
offboxToggled++
|
||||
}
|
||||
}
|
||||
data["OffboxToggledCount"] = offboxToggled
|
||||
// SLICE 4 soft-quota usage bar (rendered only when a quota is set — shared model).
|
||||
data["OffboxQuotaPct"] = backup.OffboxQuotaPercent(offboxTgt)
|
||||
} else {
|
||||
|
||||
@@ -169,6 +169,9 @@
|
||||
</form>
|
||||
</div>
|
||||
<h4 style="margin-top:1.25rem">Mely alkalmazások mentődnek a távoli tárolóra?</h4>
|
||||
{{if and .OffboxApps (eq .Offbox.EscrowState "escrowed") (eq .OffboxToggledCount 0)}}
|
||||
<p class="form-hint">Nincs távoli mentésre jelölt alkalmazás — jelölj ki legalább egyet.</p>
|
||||
{{end}}
|
||||
{{if .OffboxApps}}
|
||||
<div class="storage-paths-list">
|
||||
{{range .OffboxApps}}
|
||||
|
||||
Reference in New Issue
Block a user