feat(samba): lifecycle — ensureSamba/ReconcileSamba/password/disable (R-7 slice 1, Part 2)

ensureSamba joins EnsureBaseStack after filebrowser, gated on SMB.Enabled
(cloudflared conditional precedent); reconcile is idempotent (unchanged config +
running container = ZERO compose calls, asserted via seam). Atomic tmp+fsync+
rename config writes. Password applied via smbpasswd on STDIN (never argv/log/
settings). Disable = compose down, volumes + folders KEPT. samba added to
IsProtectedStack in code (controller.yaml is golden-generated and predates it),
which also makes the app-backup loops correctly skip it.
This commit is contained in:
2026-07-18 11:30:04 +02:00
parent b0c5ef4823
commit 0dcbea90b2
5 changed files with 600 additions and 1 deletions
+7
View File
@@ -111,6 +111,13 @@ type Manager struct {
// isMountPoint reports whether a path is a live mountpoint; defaults to system.IsMountPoint.
// Injectable so the userdata-belt drive-absent gate is testable (a t.TempDir is never a real mount).
isMountPoint func(string) bool
// Samba (R-7) seams — nil in production. sambaUpFn replaces the `compose up -d` call (tests
// assert the idempotent no-op performs ZERO calls); sambaPasswdFn replaces the smbpasswd
// docker-exec so no unit test touches docker or handles a real secret.
sambaUpFn func(dir string) error
sambaPasswdFn func(password string) error
sambaRunFn func() bool // replaces the docker-inspect liveness probe
}
// NewManager creates a new stack manager.