P3 wrap: agent auto-creates restore target; tasks.md ticked
1. Agent-side MkdirAll on the new-dir restore target. Restic creates
missing leaves but won't traverse multiple missing levels, and
under the systemd sandbox writes outside ReadWritePaths fail
anyway. Calling os.MkdirAll(target, 0700) before invoking restic
means the operator never has to pre-create the per-job subdir,
and a path the sandbox rejects surfaces as a clean
'restic restore: prepare target ...: read-only file system' error
in the job log instead of a cryptic restic-side stat failure.
2. tasks.md Phase 3 — Restore section refreshed:
- P3-X4 added (job log download dropdown — txt + ndjson)
- P3-X5 added (UK lint locale switch + 73-correction sweep)
- P3-X6 added (SIZE/FILES tooltip when host's restic < 0.17)
- P3-03 entry expanded to cover version-gated --no-ownership,
editable target, $HOME expansion, agent-side MkdirAll
- As-shipped sweep summary mentions custom-target restore +
download dropdown + tooltip in addition to the original walk
Test: TestRunRestoreNewDirAutoCreatesTarget seeds a multi-level
target the operator hasn't created and confirms RunRestore mkdir's
the chain before invoking restic.
This commit is contained in:
@@ -2,6 +2,8 @@ package runner
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -188,6 +190,35 @@ esac
|
||||
}
|
||||
}
|
||||
|
||||
// TestRunRestoreNewDirAutoCreatesTarget: a new-directory restore
|
||||
// should mkdir the requested target chain before invoking restic, so
|
||||
// operators don't have to pre-create the per-job subdir.
|
||||
func TestRunRestoreNewDirAutoCreatesTarget(t *testing.T) {
|
||||
t.Parallel()
|
||||
bin := setupScript(t, `
|
||||
case "$1" in
|
||||
restore)
|
||||
echo '{"message_type":"summary","seconds_elapsed":0,"total_files":0,"files_restored":0,"total_bytes":0,"bytes_restored":0}'
|
||||
;;
|
||||
esac
|
||||
`)
|
||||
tx := &fakeSender{}
|
||||
r := New(Config{ResticBin: bin}, tx, 0)
|
||||
|
||||
// Multi-level path the operator hasn't created yet.
|
||||
target := filepath.Join(t.TempDir(), "deep", "deeper", "deepest")
|
||||
if err := r.RunRestore(context.Background(), "job-rmkdir", "abc",
|
||||
[]string{"/etc/foo"}, false, target); err != nil {
|
||||
t.Fatalf("RunRestore: %v", err)
|
||||
}
|
||||
|
||||
if st, err := os.Stat(target); err != nil {
|
||||
t.Fatalf("expected target dir to exist: %v", err)
|
||||
} else if !st.IsDir() {
|
||||
t.Fatalf("expected directory, got %v", st.Mode())
|
||||
}
|
||||
}
|
||||
|
||||
// TestRunDiffShipsLogLines: diff output is forwarded as log.stream.
|
||||
func TestRunDiffShipsLogLines(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
Reference in New Issue
Block a user