agent+server: apply host bandwidth caps to restic invocations

P2R-13a. restic.Env gains LimitUploadKBps/LimitDownloadKBps which are
emitted as global --limit-upload/--limit-download flags before the
subcommand on every invocation. Agent dispatcher tracks host-wide
caps received via config.update; server pushes them on hello and
after PUT /api/hosts/{id}/bandwidth.

Also extends api.CommandRunPayload with optional per-job overrides
(BandwidthUpKBps/Down + PreHook/PostHook); the override consumers
land in T2/T6.
This commit is contained in:
2026-05-04 10:38:34 +01:00
parent 95ab3f4d16
commit cdf88c6dc3
8 changed files with 246 additions and 35 deletions
+37
View File
@@ -174,6 +174,43 @@ func TestRunStatsErrorsWithoutJSON(t *testing.T) {
}
}
func TestBandwidthLimitFlagsInjected(t *testing.T) {
// Script echoes its argv to stdout. Each variant should produce
// the right --limit-* flags before the subcommand.
cases := []struct {
name string
env Env
want []string
}{
{"both caps", Env{LimitUploadKBps: 1024, LimitDownloadKBps: 512}, []string{"--limit-upload 1024", "--limit-download 512"}},
{"only upload", Env{LimitUploadKBps: 256}, []string{"--limit-upload 256"}},
{"zero means omit", Env{LimitUploadKBps: 0, LimitDownloadKBps: 0}, nil},
{"negative means omit", Env{LimitUploadKBps: -1}, nil},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
bin := setupScriptBin(t, `echo "$@"`)
env := c.env
env.Bin = bin
lines, h := captureLines()
if err := env.RunUnlock(context.Background(), h); err != nil {
t.Fatalf("RunUnlock: %v", err)
}
joined := strings.Join(*lines, "\n")
for _, want := range c.want {
if !strings.Contains(joined, want) {
t.Fatalf("want %q in argv; got: %s", want, joined)
}
}
if len(c.want) == 0 {
if strings.Contains(joined, "--limit-upload") || strings.Contains(joined, "--limit-download") {
t.Fatalf("expected no limit flags; got: %s", joined)
}
}
})
}
}
func TestRunStatsZeroSnapshots(t *testing.T) {
// Confirms RunStats succeeds and returns a valid *RepoStats when the
// repo has no snapshots (snapshots_count=0). A regression that