diff --git a/test/rdp-access/README.md b/test/rdp-access/README.md index f028687..8c1594f 100644 --- a/test/rdp-access/README.md +++ b/test/rdp-access/README.md @@ -54,11 +54,13 @@ is `127.0.0.1:5002`; use a local SSH forward or a browser on the controller. Choose alternate ports with `--http-port` and `--tunnel-port` if either is in use. The VM must already be running. `up` checks the documented VM/snapshot identity but intentionally does not restore, start, stop, or reset the VM. It -starts a small host-side watchdog for the SSH master. The watchdog reconnects -after a transient Helium/SSH failure while preserving the same Docker-gateway -listener, so an already-open Guacamole session can recover without restarting -the containers. Its PID, stop marker, and diagnostic log are kept under the -ignored `.runtime/` directory. +starts a small host-side watchdog for the SSH master. Before printing the URL, +`up` waits until the HTTPS gateway can serve `/guacamole/`; this prevents a +browser login from racing Tomcat's Guacamole WAR deployment. The watchdog +reconnects after a transient Helium/SSH failure while preserving the same +Docker-gateway listener, so an already-open Guacamole session can recover +without restarting the containers. Its PID, stop marker, and diagnostic log +are kept under the ignored `.runtime/` directory. All fixture-specific values have embedded, working defaults: the `helium-remote` SSH alias, Helium's loopback VRDE endpoint (`127.0.0.1:3389`), diff --git a/test/rdp-access/rdp-access b/test/rdp-access/rdp-access index a4ed2b6..3b5b634 100755 --- a/test/rdp-access/rdp-access +++ b/test/rdp-access/rdp-access @@ -76,6 +76,24 @@ compose() { docker compose --project-name "$project" -f "$compose_file" "$@" } +wait_for_gateway() { + command -v curl >/dev/null 2>&1 || fail "curl is required for the Guacamole readiness check" + attempts=0 + while [ "$attempts" -lt 60 ]; do + # The listener is bound on the controller, even when the public + # address is 0.0.0.0. Ignore the self-signed certificate here: this + # check is only proving that nginx can reach the Guacamole servlet. + if curl -kfsS --connect-timeout 1 --max-time 3 \ + "https://127.0.0.1:$RDP_ACCESS_HTTP_PORT/guacamole/" \ + >/dev/null 2>&1; then + return 0 + fi + attempts=$((attempts + 1)) + sleep 1 + done + return 1 +} + socket_path=$runtime_dir/ssh-control.socket session_file=$runtime_dir/session.env cert_name_file=$runtime_dir/cert-name @@ -356,6 +374,7 @@ case $action in else fail "existing Guacamole stack was found but the private VRDE tunnel could not be restored; inspect $tunnel_log_file" fi + wait_for_gateway || fail "Guacamole stack is running but its HTTPS endpoint did not become ready; inspect Compose logs" if [ -f "$session_file" ]; then sed -n '1p' "$session_file"; fi exit 0 fi @@ -377,6 +396,9 @@ case $action in compose down --remove-orphans fail "could not start Guacamole gateway" fi + if ! wait_for_gateway; then + fail "Guacamole gateway started but its HTTPS endpoint did not become ready; inspect Compose logs" + fi printf 'Guacamole is ready at https://%s:%s/guacamole/\n' "$RDP_ACCESS_PUBLIC_HOST" "$RDP_ACCESS_HTTP_PORT" printf 'Accept the self-signed certificate warning, then sign in as %s with the fixture password.\n' "$RDP_ACCESS_WEB_USER" ;;