From f8a2a44df936cbad8fb8b7d73f640662d4788fe2 Mon Sep 17 00:00:00 2001 From: Chris Hayes Date: Thu, 17 Oct 2024 12:28:57 -0600 Subject: [PATCH] REC-57: open browser automatically When calling `engflow_auth login $cluster`, the browser will now automatically open to the correct url with the necessary query params appended. --- README.md | 2 +- cmd/engflow_auth/main.go | 2 +- internal/browser/browser.go | 31 +++++++++++++++++++++++++++++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3fdc654..4051f4d 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ This repository provides `engflow_auth`, a [Bazel credential helper](https://blo ## Use -1. Run `engflow_auth login [CLUSTER URL]` to obtain a credential. This prints a URL to visit in your browser. +1. Run `engflow_auth login [CLUSTER URL]` to obtain a credential. This opens a URL in your browser. 1. Visit the URL to complete the process, logging in if necessary. `engflow_auth` will download and store a credential in on your system's encrypted keyring. This process needs to be repeated after the credential expires, typically every 90 days. diff --git a/cmd/engflow_auth/main.go b/cmd/engflow_auth/main.go index 2fcb4a9..88d5c95 100644 --- a/cmd/engflow_auth/main.go +++ b/cmd/engflow_auth/main.go @@ -47,7 +47,7 @@ const ( ) type appState struct { - // These vars are initialized by `build()` iff they are not pre-populated; + // These vars are initialized by `build()` if they are not pre-populated; // they should be pre-populated in tests and left nil otherwise. userConfigDir string browserOpener browser.Opener diff --git a/internal/browser/browser.go b/internal/browser/browser.go index 6f59e00..12d9f85 100644 --- a/internal/browser/browser.go +++ b/internal/browser/browser.go @@ -18,6 +18,8 @@ import ( "fmt" "net/url" "os" + "os/exec" + "runtime" ) type Opener interface { @@ -26,11 +28,36 @@ type Opener interface { type StderrPrint struct{} +func openURL(url string) error { + var err error + switch runtime.GOOS { + case "darwin": // macOS + err = exec.Command("open", url).Start() + case "linux": + providers := []string{"xdg-open", "x-www-browser", "www-browser"} + + // There are multiple possible providers to open a browser on linux + // One of them is xdg-open, another is x-www-browser, then there's www-browser, etc. + // Look for one that exists and run it + for _, provider := range providers { + if _, err := exec.LookPath(provider); err == nil { + err = exec.Command(provider, url).Start() + } + } + case "windows": + err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start() + default: + err = fmt.Errorf("unsupported platform") + } + return err +} + func (p *StderrPrint) Open(u *url.URL) error { fmt.Fprintf( - os.Stderr, - "Please open the following URL in your web browser to authenticate:\n\n\t%s\n\n", + os.Stdout, + "Opening the following URL in your web browser to authenticate:\n\n\t%s\n\n", u, ) + openURL(u.String()) return nil }