ui: snapshots SIZE/FILES tooltip when host's restic is < 0.17

Per-snapshot size + file-count come from the embedded summary block
restic added to 'snapshots --json' in 0.17 (the source comment in
internal/restic/snapshots.go incorrectly said 0.16+). Hosts running
0.16.x leave those columns blank.

- Fix the snapshots.go doc comment: '0.16+' -> '0.17+'.
- hostDetailPage carries a LegacyRestic bool computed from the host's
  reported ResticVersion via Env.AtLeastVersion(0, 17). Empty version
  also counts as legacy (conservative default).
- Template attaches title='Needs restic 0.17+ on the agent host. This
  host runs <ver>.' + cursor:help on the SIZE / FILES headers when
  the flag is true. Hosts already on 0.17+ get no tooltip and no
  extra styling.

A host upgrading restic to 0.17+ gets the columns populated on the
next backup automatically — no further code change needed.
This commit is contained in:
2026-05-04 17:45:32 +01:00
parent 8e06bc7924
commit 02250670c1
4 changed files with 18 additions and 6 deletions
+5 -3
View File
@@ -13,9 +13,11 @@ import (
// decode only the fields we project to the server; restic's full
// shape has more (parent, tree, program version) that we don't need.
//
// Summary is only populated by restic 0.16+ (which embeds the backup
// summary inside each snapshot). Older clients leave it nil and the
// agent reports zero size/file-count — the UI degrades to "—".
// Summary is only populated by restic 0.17+ (which embeds the backup
// summary inside each snapshot record). Older clients leave it nil
// and the agent reports zero size/file-count — the UI degrades to
// "—" and the column headers carry a tooltip explaining the version
// requirement (see web/templates/pages/host_detail.html).
type Snapshot struct {
ID string `json:"id"`
ShortID string `json:"short_id"`
+8
View File
@@ -16,6 +16,7 @@ import (
"gitea.dcglab.co.uk/steve/restic-manager/internal/api"
"gitea.dcglab.co.uk/steve/restic-manager/internal/auth"
"gitea.dcglab.co.uk/steve/restic-manager/internal/restic"
"gitea.dcglab.co.uk/steve/restic-manager/internal/server/ui"
"gitea.dcglab.co.uk/steve/restic-manager/internal/server/ws"
"gitea.dcglab.co.uk/steve/restic-manager/internal/store"
@@ -569,6 +570,12 @@ type hostDetailPage struct {
// SnapshotsShown is the number rendered (we cap at ~50 for the
// first slice; pagination lands when it matters).
SnapshotsShown int
// LegacyRestic is true when the host's restic version predates
// 0.17, in which case `restic snapshots --json` doesn't embed the
// per-snapshot summary block and the Size/Files columns render
// blank. The template uses this to attach a tooltip to those
// column headers explaining the version requirement.
LegacyRestic bool
}
// handleUIHostDetail is the host detail page (snapshots tab by default).
@@ -611,6 +618,7 @@ func (s *Server) handleUIHostDetail(w stdhttp.ResponseWriter, r *stdhttp.Request
hostChromeData: s.loadHostChrome(r, *host, "snapshots", "snapshots"),
Snapshots: shown,
SnapshotsShown: len(shown),
LegacyRestic: !restic.Env{Version: host.ResticVersion}.AtLeastVersion(0, 17),
}
if err := s.deps.UI.Render(w, "host_detail", view); err != nil {
slog.Error("ui: render host_detail", "err", err)
File diff suppressed because one or more lines are too long
+4 -2
View File
@@ -35,8 +35,10 @@
<div>Snapshot id</div>
<div>Time</div>
<div>Paths</div>
<div class="text-right">Size</div>
<div class="text-right">Files</div>
<div class="text-right{{if $page.LegacyRestic}} cursor-help{{end}}"
{{if $page.LegacyRestic}}title="Needs restic 0.17+ on the agent host. This host runs {{$host.ResticVersion}}."{{end}}>Size</div>
<div class="text-right{{if $page.LegacyRestic}} cursor-help{{end}}"
{{if $page.LegacyRestic}}title="Needs restic 0.17+ on the agent host. This host runs {{$host.ResticVersion}}."{{end}}>Files</div>
<div></div>
</div>