diff --git a/cmd/setup.go b/cmd/setup.go index 73bedab..3a62664 100644 --- a/cmd/setup.go +++ b/cmd/setup.go @@ -5,6 +5,7 @@ import ( "github.com/dpastoor/wbi/internal/authentication" "github.com/dpastoor/wbi/internal/config" + "github.com/dpastoor/wbi/internal/connect" "github.com/dpastoor/wbi/internal/jupyter" "github.com/dpastoor/wbi/internal/languages" "github.com/dpastoor/wbi/internal/license" @@ -149,6 +150,22 @@ func newSetup(setupOpts setupOpts) error { return fmt.Errorf("issue handling authentication: %w", AuthErr) } + // Connect URL + connectChoice, err := connect.PromptConnectChoice() + if err != nil { + return fmt.Errorf("issue in prompt for Connect URL choice: %w", err) + } + if connectChoice { + rawConnectURL, err := connect.PromptConnectURL() + if err != nil { + return fmt.Errorf("issue entering Connect URL: %w", err) + } + WBConfig.ConnectURL, err = connect.VerifyConnectURL(rawConnectURL) + if err != nil { + return fmt.Errorf("issue with checking the Connect URL: %w", err) + } + } + // Write config to console WBConfig.ConfigStructToText() diff --git a/internal/config/config.go b/internal/config/config.go index 69e3a09..92f5edd 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -31,6 +31,7 @@ type WBConfig struct { RConfig RConfig PythonConfig PythonConfig AuthConfig AuthConfig + ConnectURL string } type AuthConfig struct { diff --git a/internal/config/print.go b/internal/config/print.go index 8d9b26d..ffea16e 100644 --- a/internal/config/print.go +++ b/internal/config/print.go @@ -7,6 +7,7 @@ func (WBConfig *WBConfig) ConfigStructToText() { WBConfig.PythonConfig.PythonStructToText() WBConfig.SSLConfig.SSLStructToText() WBConfig.AuthConfig.AuthStructToText() + WBConfig.ConnectStringToText() fmt.Println("\n=== Please restart Workbench after making these changes") } @@ -55,3 +56,9 @@ func (OIDCConfig *OIDCConfig) AuthOIDCStructToText() { fmt.Println("client-id=" + OIDCConfig.ClientID) fmt.Println("client-secret=" + OIDCConfig.ClientSecret) } + +// Prints the ConnectURL configuration string information to the console +func (WBConfig *WBConfig) ConnectStringToText() { + fmt.Println("\n=== Add to config file: /etc/rstudio/rsession.conf:") + fmt.Println("default-rsconnect-server=" + WBConfig.ConnectURL) +} diff --git a/internal/connect/prompt.go b/internal/connect/prompt.go new file mode 100644 index 0000000..315de81 --- /dev/null +++ b/internal/connect/prompt.go @@ -0,0 +1,34 @@ +package connect + +import ( + "errors" + "fmt" + + "github.com/AlecAivazis/survey/v2" +) + +// Prompt users if they wish to add a default Connect URL to Workbench +func PromptConnectChoice() (bool, error) { + name := true + prompt := &survey.Confirm{ + Message: "Would you like to provide a default Connect URL for Workbench?", + } + err := survey.AskOne(prompt, &name) + if err != nil { + return false, errors.New("there was an issue with the Connect URL prompt") + } + return name, nil +} + +// Prompt users for a default Connect URL +func PromptConnectURL() (string, error) { + target := "" + prompt := &survey.Input{ + Message: "Connect URL:", + } + err := survey.AskOne(prompt, &target) + if err != nil { + return "", fmt.Errorf("issue prompting for a Connect URL: %w", err) + } + return target, nil +} diff --git a/internal/connect/verify.go b/internal/connect/verify.go new file mode 100644 index 0000000..322d588 --- /dev/null +++ b/internal/connect/verify.go @@ -0,0 +1,44 @@ +package connect + +import ( + "context" + "errors" + "fmt" + "net/http" + "time" +) + +func cleanConnectURL(connectURL string) string { + // remove trailing slash if present + if connectURL[len(connectURL)-1] == '/' { + connectURL = connectURL[:len(connectURL)-1] + } + return connectURL +} + +// VerifyConnectURL checks if the Connect URL is valid +func VerifyConnectURL(connectURL string) (string, error) { + + cleanConnectURL := cleanConnectURL(connectURL) + fullTestURL := cleanConnectURL + "/__ping__" + + client := &http.Client{ + Timeout: 30 * time.Second, + } + req, err := http.NewRequestWithContext(context.Background(), + http.MethodGet, fullTestURL, nil) + if err != nil { + return "", errors.New("error creating request") + } + res, err := client.Do(req) + if err != nil { + return "", errors.New("error retrieving JSON data") + } + defer res.Body.Close() + if res.StatusCode != http.StatusOK { + return "", errors.New("error in HTTP status code") + } + + fmt.Println("\nConnect URL has been successfull validated.\n") + return cleanConnectURL, nil +}