v0.41.0: first-boot base-infra bring-up + self-heal (+ Section-G mount fix)
New internal/infra package renders traefik/cloudflared/filebrowser from config (pinned images, single source of truth; web filebrowser path delegates here). stacks.EnsureBaseStack deploys the traefik-public network + the three stacks, single-flight + idempotent + non-fatal; wired to first boot and every health tick. monitor.EffectiveProtected drops cloudflared when no tunnel token. Section-G fix lives in felhom-agent build-golden.sh (same-path stacks bind). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
package stacks
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/config"
|
||||
)
|
||||
|
||||
// TestEnsureBaseStackSingleFlight proves the single-flight guard short-circuits: when infraMu is
|
||||
// already held, EnsureBaseStack returns immediately (nil) WITHOUT touching docker. We hold the lock
|
||||
// in this goroutine and call EnsureBaseStack in the same goroutine — Go mutexes are non-reentrant, so
|
||||
// TryLock fails and the function returns before any docker network/inspect call. If the guard were
|
||||
// missing, the call would shell out to docker (unavailable in unit tests) and not return nil cleanly.
|
||||
func TestEnsureBaseStackSingleFlight(t *testing.T) {
|
||||
m := &Manager{
|
||||
cfg: &config.Config{},
|
||||
logger: log.New(io.Discard, "", 0),
|
||||
}
|
||||
m.infraMu.Lock()
|
||||
defer m.infraMu.Unlock()
|
||||
|
||||
done := make(chan error, 1)
|
||||
go func() { done <- m.EnsureBaseStack() }()
|
||||
|
||||
select {
|
||||
case err := <-done:
|
||||
if err != nil {
|
||||
t.Fatalf("expected nil (single-flight no-op) while lock held, got %v", err)
|
||||
}
|
||||
case <-time.After(3 * time.Second):
|
||||
t.Fatal("EnsureBaseStack did not short-circuit while infraMu was held (single-flight guard missing?)")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user