Fix guest session cwd preflight scripts

Guest session cwd and command preflight helpers were emitting literal
`\\n` separators, so the guest shell saw malformed one-line scripts and
could fail `preflight_cwd` even when `/root/repo` already existed.

Replace those builders with real newlines, and fix the nearby attach
helper commands that were making the same mistake.

Add a small daemon guest-SSH seam so workspace preparation and session
start can share a fake backend in tests, then cover the regression with
an end-to-end daemon test for `PrepareVMWorkspace` followed by
`StartGuestSession` on `/root/repo`.

Validation: `GOCACHE=/tmp/banger-gocache go test ./internal/daemon` and
`GOCACHE=/tmp/banger-gocache go test ./...`.
This commit is contained in:
Thales Maciel 2026-04-13 18:26:19 -03:00
parent 37c4c091ec
commit 5e26fd7544
No known key found for this signature in database
GPG key ID: 33112E6833C34679
4 changed files with 296 additions and 49 deletions

View file

@ -27,33 +27,36 @@ import (
)
type Daemon struct {
layout paths.Layout
config model.DaemonConfig
store *store.Store
runner system.CommandRunner
logger *slog.Logger
mu sync.Mutex
createOpsMu sync.Mutex
createOps map[string]*vmCreateOperationState
imageBuildOpsMu sync.Mutex
imageBuildOps map[string]*imageBuildOperationState
vmLocksMu sync.Mutex
vmLocks map[string]*sync.Mutex
sessionControllers map[string]*guestSessionController
tapPoolMu sync.Mutex
tapPool []string
tapPoolNext int
closing chan struct{}
once sync.Once
pid int
listener net.Listener
webListener net.Listener
webServer *http.Server
webURL string
vmDNS *vmdns.Server
vmCaps []vmCapability
imageBuild func(context.Context, imageBuildSpec) error
requestHandler func(context.Context, rpc.Request) rpc.Response
layout paths.Layout
config model.DaemonConfig
store *store.Store
runner system.CommandRunner
logger *slog.Logger
mu sync.Mutex
createOpsMu sync.Mutex
createOps map[string]*vmCreateOperationState
imageBuildOpsMu sync.Mutex
imageBuildOps map[string]*imageBuildOperationState
vmLocksMu sync.Mutex
vmLocks map[string]*sync.Mutex
sessionControllers map[string]*guestSessionController
tapPoolMu sync.Mutex
tapPool []string
tapPoolNext int
closing chan struct{}
once sync.Once
pid int
listener net.Listener
webListener net.Listener
webServer *http.Server
webURL string
vmDNS *vmdns.Server
vmCaps []vmCapability
imageBuild func(context.Context, imageBuildSpec) error
requestHandler func(context.Context, rpc.Request) rpc.Response
guestWaitForSSH func(context.Context, string, string, time.Duration) error
guestDial func(context.Context, string, string) (guestSSHClient, error)
waitForGuestSessionReady func(context.Context, model.VMRecord, model.GuestSession) (model.GuestSession, error)
}
func Open(ctx context.Context) (d *Daemon, err error) {