v0.41.2: fix controller-route auto-connect + dead dashboard cross-drive block
containerOnNetwork misread the absent-key '<nil>' as "already attached", so wireController skipped docker network connect -> traefik 502'd felhom.<domain>. Now lists network names and matches exactly. Also removed dashboard.html's dead CrossDrive* block (slice-8C leftover) that 500'd the dashboard via gt <nil> 0, exposed once v0.41.1 made the dashboard reachable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,19 @@
|
|||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### v0.41.2 — fix controller-route auto-connect + dead dashboard cross-drive block (2026-06-11)
|
||||||
|
|
||||||
|
Two fixes found while live-validating v0.41.1 routing on guest 9201:
|
||||||
|
- **`containerOnNetwork` false-positive (v0.41.1 regression):** the membership check used
|
||||||
|
`{{index .NetworkSettings.Networks "traefik-public"}}`, whose output for an absent key is `<nil>`
|
||||||
|
(non-empty) — so `wireController` thought the controller was already attached and **skipped the
|
||||||
|
`docker network connect`**. traefik then matched the route but 502'd (backend unresolvable). Fixed by
|
||||||
|
listing the network names and matching exactly. Live: `felhom.<domain>` now reaches the controller.
|
||||||
|
- **Dead cross-drive dashboard block (pre-existing, slice-8C leftover):** `dashboard.html` still
|
||||||
|
referenced `.CrossDriveTotal/.CrossDriveConfigured/.CrossDriveFailed`, which the de-privileged
|
||||||
|
dashboard handler stopped providing — so `gt <nil> 0` **500'd the entire dashboard**. Only surfaced
|
||||||
|
now because v0.41.1 finally made the dashboard reachable. Removed the dead block (cross-drive backup
|
||||||
|
is the host agent's job since 8C).
|
||||||
|
|
||||||
### v0.41.1 — wire the controller dashboard into traefik (`felhom.<domain>` routing) (2026-06-11)
|
### v0.41.1 — wire the controller dashboard into traefik (`felhom.<domain>` routing) (2026-06-11)
|
||||||
|
|
||||||
Completes v0.41.0: the base-infra bring-up stood up traefik/cloudflared/filebrowser but nothing routed
|
Completes v0.41.0: the base-infra bring-up stood up traefik/cloudflared/filebrowser but nothing routed
|
||||||
|
|||||||
@@ -188,14 +188,20 @@ func (m *Manager) wireController(traefikDir string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// containerOnNetwork reports whether the named container is attached to the given docker network.
|
// containerOnNetwork reports whether the named container is attached to the given docker network.
|
||||||
|
// We list the network names and match exactly — NOT `{{index .Networks "name"}}`, whose output for an
|
||||||
|
// absent key is "<nil>" (a non-empty string), which would falsely read as "already attached".
|
||||||
func containerOnNetwork(name, network string) bool {
|
func containerOnNetwork(name, network string) bool {
|
||||||
out, err := exec.Command("docker", "inspect", "--format",
|
out, err := exec.Command("docker", "inspect", "--format",
|
||||||
fmt.Sprintf("{{index .NetworkSettings.Networks %q}}", network), name).Output()
|
"{{range $k, $_ := .NetworkSettings.Networks}}{{$k}}\n{{end}}", name).Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
s := strings.TrimSpace(string(out))
|
for _, n := range strings.Fields(string(out)) {
|
||||||
return s != "" && s != "<no value>"
|
if n == network {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensureTraefikNetwork creates the external traefik-public docker network if absent (idempotent;
|
// ensureTraefikNetwork creates the external traefik-public docker network if absent (idempotent;
|
||||||
|
|||||||
@@ -127,24 +127,9 @@
|
|||||||
<span class="backup-value">{{len .DBDumpStatus.Results}} mentve</span>
|
<span class="backup-value">{{len .DBDumpStatus.Results}} mentve</span>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if gt .CrossDriveTotal 0}}
|
{{/* Cross-drive ("2. mentés") moved to the host agent in slice 8C — the dashboard handler no
|
||||||
<div class="backup-info-row">
|
longer provides CrossDrive* fields, so the old block was a dead reference that 500'd the
|
||||||
<span class="backup-label">2. mentés:</span>
|
dashboard (gt <nil> 0). Removed in v0.41.2. */}}
|
||||||
<span class="backup-value">
|
|
||||||
{{if eq .CrossDriveConfigured 0}}
|
|
||||||
<span style="color:var(--yellow)">⚠ Nincs beállítva</span>
|
|
||||||
{{else}}
|
|
||||||
<span class="{{if gt .CrossDriveFailed 0}}backup-status-fail{{else}}backup-status-ok{{end}}">{{.CrossDriveConfigured}} / {{.CrossDriveTotal}} alk.</span>
|
|
||||||
{{end}}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
{{if gt .CrossDriveFailed 0}}
|
|
||||||
<div class="backup-info-row">
|
|
||||||
<span class="backup-label" style="color:var(--red)">Figyelmeztetés:</span>
|
|
||||||
<span class="backup-value backup-status-fail">⚠ {{.CrossDriveFailed}} 2. mentés sikertelen</span>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user