From 321b1f94ad78d7607ece6a5eb9d33c718d13a138 Mon Sep 17 00:00:00 2001 From: alessandroargentieri Date: Thu, 9 Jan 2025 13:15:50 +0100 Subject: [PATCH] Addition of waits and retries to have the instance vnc URL ready --- cmd/instance/instance_vnc.go | 47 +++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/cmd/instance/instance_vnc.go b/cmd/instance/instance_vnc.go index ba7da01..0c4d032 100644 --- a/cmd/instance/instance_vnc.go +++ b/cmd/instance/instance_vnc.go @@ -1,14 +1,21 @@ package instance import ( + "fmt" + "net/http" + "os" + "time" + "github.com/civo/cli/common" "github.com/civo/cli/config" "github.com/civo/cli/pkg/browser" "github.com/civo/cli/utility" "github.com/spf13/cobra" - "os" ) +// maxAttempts represents the max number of attempts (each one every 7s) to connect to the vnc URL +const maxAttempts = 5 + var instanceVncCmd = &cobra.Command{ Use: "vnc", Example: "civo instance vnc INSTANCE-ID/NAME", @@ -46,7 +53,16 @@ var instanceVncCmd = &cobra.Command{ // Display VNC details utility.Info("VNC has been successfully enabled for instance: %s", instance.Hostname) utility.Info("VNC URL: %s", vnc.URI) + utility.Info("We're preparing the VNC Console Access. This may take a while...") + + err = waitEndpointReady(vnc.URI) + if err != nil { + utility.Error("VNC Console URL is not reachable: %s", err) + os.Exit(1) + } + utility.Info("Opening VNC in your default browser...") + time.Sleep(3 * time.Second) // Open VNC in the browser err = browser.OpenInBrowser(vnc.URI) @@ -57,3 +73,32 @@ var instanceVncCmd = &cobra.Command{ } }, } + +// endpointReady checks if the given URL endpoint is ready by sending a GET request +// and returning true if the HTTP status code is not 503 or 40x +func endpointReady(url string) bool { + utility.Info("New attempt to reach the VNC Console URI...") + resp, err := http.Get(url) + if err != nil { + return false + } + defer resp.Body.Close() + + return resp.StatusCode != http.StatusServiceUnavailable +} + +// waitEndpointReady continuously checks the given URL endpoint every 5 seconds +// until it becomes ready (i.e., it does not return an HTTP 503 status). +func waitEndpointReady(url string) error { + var attempt int + for { + attempt++ + if endpointReady(url) { + return nil + } + if attempt == maxAttempts { + return fmt.Errorf("max num of attempts reached: VNC endpoint not ready - please contact the support") + } + time.Sleep(7 * time.Second) // Wait for 7 seconds before the next attempt + } +}