fix: clarify SSH readiness progress

This commit is contained in:
Peter Steinberger 2026-05-05 15:38:51 +01:00
parent 281ac8ec57
commit 6e6caa018b
No known key found for this signature in database
3 changed files with 29 additions and 5 deletions

View File

@ -11,6 +11,7 @@
### Fixed
- Fixed managed Linux desktop bootstrap performance by using a lean Openbox/Xvfb desktop stack instead of the heavier XFCE meta package.
- Fixed SSH readiness progress logs to distinguish open TCP ports, failed SSH authentication, and failed Crabbox ready checks.
- Fixed auto-shell command reconstruction so arguments with spaces stay quoted when shell operators such as `&&` are present.
- Fixed managed Linux bootstrap ordering so SSH is reachable before slow desktop/browser package setup while readiness still waits for the full desktop/browser contract.
- Fixed managed desktop/browser warmups so slow cloud-init bootstraps get a longer readiness window, retry once after SSH timeout, and clean up failed leases instead of leaking unusable VMs.

View File

@ -74,6 +74,7 @@ func waitForSSHReady(ctx context.Context, target *SSHTarget, stderr io.Writer, p
return exit(5, "timed out waiting for SSH on %s during %s", target.Host, phase)
}
reachablePort := ""
transportPort := ""
for _, port := range sshPortCandidates(target.Port, target.FallbackPorts) {
probe := *target
probe.Port = port
@ -85,7 +86,13 @@ func waitForSSHReady(ctx context.Context, target *SSHTarget, stderr io.Writer, p
if reachablePort == "" {
reachablePort = probe.Port
}
if runSSHQuiet(ctx, probe, sshReadyCommand(probe)) == nil {
if runSSHQuietWithOptions(ctx, probe, sshTransportProbeCommand(probe), "5", "1") != nil {
continue
}
if transportPort == "" {
transportPort = probe.Port
}
if runSSHQuietWithOptions(ctx, probe, sshReadyCommand(probe), "5", "1") == nil {
if target.Port != probe.Port {
fmt.Fprintf(stderr, "using ssh port %s for %s (configured %s not ready)\n", probe.Port, target.Host, target.Port)
target.Port = probe.Port
@ -93,19 +100,22 @@ func waitForSSHReady(ctx context.Context, target *SSHTarget, stderr io.Writer, p
return nil
}
}
fmt.Fprintln(stderr, sshWaitProgressMessage(target, phase, reachablePort, time.Since(start), time.Until(deadline)))
fmt.Fprintln(stderr, sshWaitProgressMessage(target, phase, reachablePort, transportPort, time.Since(start), time.Until(deadline)))
time.Sleep(10 * time.Second)
}
}
func sshWaitProgressMessage(target *SSHTarget, phase, reachablePort string, elapsed, remaining time.Duration) string {
func sshWaitProgressMessage(target *SSHTarget, phase, reachablePort, transportPort string, elapsed, remaining time.Duration) string {
if remaining < 0 {
remaining = 0
}
elapsed = elapsed.Round(time.Second)
remaining = remaining.Round(time.Second)
if transportPort != "" {
return fmt.Sprintf("waiting for %s:%s %s ready-check... elapsed=%s remaining=%s", target.Host, transportPort, phase, elapsed, remaining)
}
if reachablePort != "" {
return fmt.Sprintf("waiting for %s:%s %s toolchain... elapsed=%s remaining=%s", target.Host, reachablePort, phase, elapsed, remaining)
return fmt.Sprintf("waiting for %s:%s %s ssh-auth... elapsed=%s remaining=%s", target.Host, reachablePort, phase, elapsed, remaining)
}
return fmt.Sprintf("waiting for %s:%s %s... elapsed=%s remaining=%s", target.Host, target.Port, phase, elapsed, remaining)
}

View File

@ -262,11 +262,12 @@ func TestSSHWaitProgressIncludesElapsedAndRemaining(t *testing.T) {
&SSHTarget{Host: "203.0.113.10", Port: "2222"},
"bootstrap",
"2222",
"2222",
95*time.Second,
10*time.Minute,
)
for _, want := range []string{
"waiting for 203.0.113.10:2222 bootstrap toolchain...",
"waiting for 203.0.113.10:2222 bootstrap ready-check...",
"elapsed=1m35s",
"remaining=10m0s",
} {
@ -276,6 +277,18 @@ func TestSSHWaitProgressIncludesElapsedAndRemaining(t *testing.T) {
}
}
func TestSSHWaitProgressDistinguishesAuthFromReadiness(t *testing.T) {
target := &SSHTarget{Host: "203.0.113.10", Port: "2222"}
got := sshWaitProgressMessage(target, "bootstrap", "2222", "", 5*time.Second, time.Minute)
if !strings.Contains(got, "bootstrap ssh-auth") {
t.Fatalf("TCP-only progress should report ssh-auth stage: %q", got)
}
got = sshWaitProgressMessage(target, "bootstrap", "2222", "2222", 5*time.Second, time.Minute)
if !strings.Contains(got, "bootstrap ready-check") {
t.Fatalf("SSH transport progress should report ready-check stage: %q", got)
}
}
func TestSSHPortCandidatesPreferConfiguredPortWithFallback(t *testing.T) {
tests := map[string][]string{
"": {"22"},