mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-07-04 03:48:58 +00:00
parent
d2d4ed5aee
commit
9c98a4c2b1
@ -1,123 +0,0 @@
|
|||||||
package auth
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/up9inc/mizu/cli/logger"
|
|
||||||
"github.com/up9inc/mizu/cli/uiUtils"
|
|
||||||
"golang.org/x/oauth2"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const loginTimeoutInMin = 2
|
|
||||||
|
|
||||||
// Ports are configured in keycloak "cli" client as valid redirect URIs. A change here must be reflected there as well.
|
|
||||||
var listenPorts = []int{3141, 4001, 5002, 6003, 7004, 8005, 9006, 10007}
|
|
||||||
|
|
||||||
func LoginInteractively(envName string) (*oauth2.Token, error) {
|
|
||||||
tokenChannel := make(chan *oauth2.Token)
|
|
||||||
errorChannel := make(chan error)
|
|
||||||
|
|
||||||
server := http.Server{}
|
|
||||||
go startLoginServer(tokenChannel, errorChannel, envName, &server)
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if err := server.Shutdown(context.Background()); err != nil {
|
|
||||||
logger.Log.Debugf("Error shutting down server, err: %v", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-time.After(loginTimeoutInMin * time.Minute):
|
|
||||||
return nil, errors.New("auth timed out")
|
|
||||||
case err := <-errorChannel:
|
|
||||||
return nil, err
|
|
||||||
case token := <-tokenChannel:
|
|
||||||
return token, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func startLoginServer(tokenChannel chan *oauth2.Token, errorChannel chan error, envName string, server *http.Server) {
|
|
||||||
for _, port := range listenPorts {
|
|
||||||
var config = &oauth2.Config{
|
|
||||||
ClientID: "cli",
|
|
||||||
RedirectURL: fmt.Sprintf("http://localhost:%v/callback", port),
|
|
||||||
Endpoint: oauth2.Endpoint{
|
|
||||||
AuthURL: fmt.Sprintf("https://auth.%s/auth/realms/testr/protocol/openid-connect/auth", envName),
|
|
||||||
TokenURL: fmt.Sprintf("https://auth.%s/auth/realms/testr/protocol/openid-connect/token", envName),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
state := uuid.New()
|
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
|
||||||
server.Handler = mux
|
|
||||||
mux.Handle("/callback", loginCallbackHandler(tokenChannel, errorChannel, config, envName, state))
|
|
||||||
|
|
||||||
listener, listenErr := net.Listen("tcp", fmt.Sprintf("%s:%d", "127.0.0.1", port))
|
|
||||||
if listenErr != nil {
|
|
||||||
logger.Log.Debugf("failed to start listening on port %v, err: %v", port, listenErr)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
authorizationUrl := config.AuthCodeURL(state.String())
|
|
||||||
uiUtils.OpenBrowser(authorizationUrl)
|
|
||||||
|
|
||||||
serveErr := server.Serve(listener)
|
|
||||||
if serveErr == http.ErrServerClosed {
|
|
||||||
logger.Log.Debugf("received server shutdown, server on port %v is closed", port)
|
|
||||||
return
|
|
||||||
} else if serveErr != nil {
|
|
||||||
logger.Log.Debugf("failed to start serving on port %v, err: %v", port, serveErr)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Log.Debugf("didn't receive server closed on port %v", port)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
errorChannel <- fmt.Errorf("failed to start serving on all listen ports, ports: %v", listenPorts)
|
|
||||||
}
|
|
||||||
|
|
||||||
func loginCallbackHandler(tokenChannel chan *oauth2.Token, errorChannel chan error, config *oauth2.Config, envName string, state uuid.UUID) http.Handler {
|
|
||||||
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
|
||||||
if err := request.ParseForm(); err != nil {
|
|
||||||
errorMsg := fmt.Sprintf("failed to parse form, err: %v", err)
|
|
||||||
http.Error(writer, errorMsg, http.StatusBadRequest)
|
|
||||||
errorChannel <- fmt.Errorf(errorMsg)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
requestState := request.Form.Get("state")
|
|
||||||
if requestState != state.String() {
|
|
||||||
errorMsg := fmt.Sprintf("state invalid, requestState: %v, authState:%v", requestState, state.String())
|
|
||||||
http.Error(writer, errorMsg, http.StatusBadRequest)
|
|
||||||
errorChannel <- fmt.Errorf(errorMsg)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
code := request.Form.Get("code")
|
|
||||||
if code == "" {
|
|
||||||
errorMsg := "code not found"
|
|
||||||
http.Error(writer, errorMsg, http.StatusBadRequest)
|
|
||||||
errorChannel <- fmt.Errorf(errorMsg)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
token, err := config.Exchange(context.Background(), code)
|
|
||||||
if err != nil {
|
|
||||||
errorMsg := fmt.Sprintf("failed to create token, err: %v", err)
|
|
||||||
http.Error(writer, errorMsg, http.StatusInternalServerError)
|
|
||||||
errorChannel <- fmt.Errorf(errorMsg)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tokenChannel <- token
|
|
||||||
|
|
||||||
http.Redirect(writer, request, fmt.Sprintf("https://%s/CliLogin", envName), http.StatusFound)
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var authCmd = &cobra.Command{
|
|
||||||
Use: "auth",
|
|
||||||
Short: "Authenticate to up9 application",
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootCmd.AddCommand(authCmd)
|
|
||||||
}
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/up9inc/mizu/cli/auth"
|
|
||||||
"github.com/up9inc/mizu/cli/config"
|
|
||||||
"github.com/up9inc/mizu/cli/config/configStructs"
|
|
||||||
"github.com/up9inc/mizu/cli/logger"
|
|
||||||
"github.com/up9inc/mizu/cli/telemetry"
|
|
||||||
)
|
|
||||||
|
|
||||||
var authLoginCmd = &cobra.Command{
|
|
||||||
Use: "login",
|
|
||||||
Short: "Login to up9 application",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
go telemetry.ReportRun("authLogin", config.Config.Auth)
|
|
||||||
|
|
||||||
token, err := auth.LoginInteractively(config.Config.Auth.EnvName)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Errorf("Failed login interactively, err: %v", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
authConfig := configStructs.AuthConfig{
|
|
||||||
EnvName: config.Config.Auth.EnvName,
|
|
||||||
Token: token.AccessToken,
|
|
||||||
}
|
|
||||||
|
|
||||||
config.Config.Auth = authConfig
|
|
||||||
|
|
||||||
if err := config.WriteConfig(&config.Config); err != nil {
|
|
||||||
logger.Log.Errorf("Failed writing config with auth, err: %v", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Log.Infof("Login successfully, token stored in config")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
authCmd.AddCommand(authLoginCmd)
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/up9inc/mizu/cli/config"
|
|
||||||
"github.com/up9inc/mizu/cli/logger"
|
|
||||||
"github.com/up9inc/mizu/cli/telemetry"
|
|
||||||
)
|
|
||||||
|
|
||||||
var authLogoutCmd = &cobra.Command{
|
|
||||||
Use: "logout",
|
|
||||||
Short: "Logout from up9 application",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
go telemetry.ReportRun("authLogout", config.Config.Auth)
|
|
||||||
|
|
||||||
config.Config.Auth.Token = ""
|
|
||||||
|
|
||||||
if err := config.WriteConfig(&config.Config); err != nil {
|
|
||||||
logger.Log.Errorf("Failed writing config with default auth, err: %v", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Log.Infof("Logout successfully, token removed from config")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
authCmd.AddCommand(authLogoutCmd)
|
|
||||||
}
|
|
@ -4,7 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/up9inc/mizu/cli/config"
|
"github.com/up9inc/mizu/cli/config"
|
||||||
@ -47,3 +49,21 @@ func waitForFinish(ctx context.Context, cancel context.CancelFunc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func openBrowser(url string) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "linux":
|
||||||
|
err = exec.Command("xdg-open", url).Start()
|
||||||
|
case "windows":
|
||||||
|
err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
|
||||||
|
case "darwin":
|
||||||
|
err = exec.Command("open", url).Start()
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("unsupported platform")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logger.Log.Errorf("error while opening browser, %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/up9inc/mizu/cli/logger"
|
"github.com/up9inc/mizu/cli/logger"
|
||||||
"github.com/up9inc/mizu/cli/telemetry"
|
"github.com/up9inc/mizu/cli/telemetry"
|
||||||
"github.com/up9inc/mizu/cli/uiUtils"
|
"github.com/up9inc/mizu/cli/uiUtils"
|
||||||
|
"io/ioutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
var configCmd = &cobra.Command{
|
var configCmd = &cobra.Command{
|
||||||
@ -17,30 +18,22 @@ var configCmd = &cobra.Command{
|
|||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
go telemetry.ReportRun("config", config.Config.Config)
|
go telemetry.ReportRun("config", config.Config.Config)
|
||||||
|
|
||||||
configWithDefaults, err := config.GetConfigWithDefaults()
|
template, err := config.GetConfigWithDefaults()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log.Errorf("Failed generating config with defaults, err: %v", err)
|
logger.Log.Errorf("Failed generating config with defaults %v", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Config.Config.Regenerate {
|
if config.Config.Config.Regenerate {
|
||||||
if err := config.WriteConfig(configWithDefaults); err != nil {
|
data := []byte(template)
|
||||||
logger.Log.Errorf("Failed writing config with defaults, err: %v", err)
|
if err := ioutil.WriteFile(config.Config.ConfigFilePath, data, 0644); err != nil {
|
||||||
|
logger.Log.Errorf("Failed writing config %v", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Log.Infof(fmt.Sprintf("Template File written to %s", fmt.Sprintf(uiUtils.Purple, config.Config.ConfigFilePath)))
|
logger.Log.Infof(fmt.Sprintf("Template File written to %s", fmt.Sprintf(uiUtils.Purple, config.Config.ConfigFilePath)))
|
||||||
} else {
|
} else {
|
||||||
template, err := uiUtils.PrettyYaml(configWithDefaults)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Errorf("Failed converting config with defaults to yaml, err: %v", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Log.Debugf("Writing template config.\n%v", template)
|
logger.Log.Debugf("Writing template config.\n%v", template)
|
||||||
fmt.Printf("%v", template)
|
fmt.Printf("%v", template)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -585,7 +585,7 @@ func watchApiServerPod(ctx context.Context, kubernetesProvider *kubernetes.Provi
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.Log.Infof("Mizu is available at %s\n", url)
|
logger.Log.Infof("Mizu is available at %s\n", url)
|
||||||
uiUtils.OpenBrowser(url)
|
openBrowser(url)
|
||||||
requestForAnalysisIfNeeded()
|
requestForAnalysisIfNeeded()
|
||||||
if err := apiserver.Provider.ReportTappedPods(state.currentlyTappedPods); err != nil {
|
if err := apiserver.Provider.ReportTappedPods(state.currentlyTappedPods); err != nil {
|
||||||
logger.Log.Debugf("[Error] failed update tapped pods %v", err)
|
logger.Log.Debugf("[Error] failed update tapped pods %v", err)
|
||||||
|
@ -57,8 +57,7 @@ func runMizuView() {
|
|||||||
|
|
||||||
logger.Log.Infof("Mizu is available at %s\n", url)
|
logger.Log.Infof("Mizu is available at %s\n", url)
|
||||||
|
|
||||||
uiUtils.OpenBrowser(url)
|
openBrowser(url)
|
||||||
|
|
||||||
if isCompatible, err := version.CheckVersionCompatibility(); err != nil {
|
if isCompatible, err := version.CheckVersionCompatibility(); err != nil {
|
||||||
logger.Log.Errorf("Failed to check versions compatibility %v", err)
|
logger.Log.Errorf("Failed to check versions compatibility %v", err)
|
||||||
cancel()
|
cancel()
|
||||||
|
@ -54,30 +54,16 @@ func InitConfig(cmd *cobra.Command) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetConfigWithDefaults() (*ConfigStruct, error) {
|
func GetConfigWithDefaults() (string, error) {
|
||||||
defaultConf := ConfigStruct{}
|
defaultConf := ConfigStruct{}
|
||||||
if err := defaults.Set(&defaultConf); err != nil {
|
if err := defaults.Set(&defaultConf); err != nil {
|
||||||
return nil, err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
configElem := reflect.ValueOf(&defaultConf).Elem()
|
configElem := reflect.ValueOf(&defaultConf).Elem()
|
||||||
setZeroForReadonlyFields(configElem)
|
setZeroForReadonlyFields(configElem)
|
||||||
|
|
||||||
return &defaultConf, nil
|
return uiUtils.PrettyYaml(defaultConf)
|
||||||
}
|
|
||||||
|
|
||||||
func WriteConfig(config *ConfigStruct) error {
|
|
||||||
template, err := uiUtils.PrettyYaml(config)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed converting config to yaml, err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
data := []byte(template)
|
|
||||||
if err := ioutil.WriteFile(Config.ConfigFilePath, data, 0644); err != nil {
|
|
||||||
return fmt.Errorf("failed writing config, err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func mergeConfigFile(configFilePath string) error {
|
func mergeConfigFile(configFilePath string) error {
|
||||||
|
@ -21,7 +21,6 @@ type ConfigStruct struct {
|
|||||||
Version configStructs.VersionConfig `yaml:"version"`
|
Version configStructs.VersionConfig `yaml:"version"`
|
||||||
View configStructs.ViewConfig `yaml:"view"`
|
View configStructs.ViewConfig `yaml:"view"`
|
||||||
Logs configStructs.LogsConfig `yaml:"logs"`
|
Logs configStructs.LogsConfig `yaml:"logs"`
|
||||||
Auth configStructs.AuthConfig `yaml:"auth"`
|
|
||||||
Config configStructs.ConfigConfig `yaml:"config,omitempty"`
|
Config configStructs.ConfigConfig `yaml:"config,omitempty"`
|
||||||
AgentImage string `yaml:"agent-image,omitempty" readonly:""`
|
AgentImage string `yaml:"agent-image,omitempty" readonly:""`
|
||||||
ImagePullPolicyStr string `yaml:"image-pull-policy" default:"Always"`
|
ImagePullPolicyStr string `yaml:"image-pull-policy" default:"Always"`
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
package configStructs
|
|
||||||
|
|
||||||
type AuthConfig struct {
|
|
||||||
EnvName string `yaml:"env-name" default:"up9.app"`
|
|
||||||
Token string `yaml:"token"`
|
|
||||||
}
|
|
@ -3,7 +3,6 @@ package config_test
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/up9inc/mizu/cli/config"
|
"github.com/up9inc/mizu/cli/config"
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@ -16,11 +15,10 @@ func TestConfigWriteIgnoresReadonlyFields(t *testing.T) {
|
|||||||
getFieldsWithReadonlyTag(configElem, &readonlyFields)
|
getFieldsWithReadonlyTag(configElem, &readonlyFields)
|
||||||
|
|
||||||
configWithDefaults, _ := config.GetConfigWithDefaults()
|
configWithDefaults, _ := config.GetConfigWithDefaults()
|
||||||
configWithDefaultsBytes, _ := yaml.Marshal(configWithDefaults)
|
|
||||||
for _, readonlyField := range readonlyFields {
|
for _, readonlyField := range readonlyFields {
|
||||||
t.Run(readonlyField, func(t *testing.T) {
|
t.Run(readonlyField, func(t *testing.T) {
|
||||||
readonlyFieldToCheck := fmt.Sprintf(" %s:", readonlyField)
|
readonlyFieldToCheck := fmt.Sprintf("\n%s:", readonlyField)
|
||||||
if strings.Contains(string(configWithDefaultsBytes), readonlyFieldToCheck) {
|
if strings.Contains(configWithDefaults, readonlyFieldToCheck) {
|
||||||
t.Errorf("unexpected result - readonly field: %v, config: %v", readonlyField, configWithDefaults)
|
t.Errorf("unexpected result - readonly field: %v, config: %v", readonlyField, configWithDefaults)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -6,13 +6,12 @@ require (
|
|||||||
github.com/creasty/defaults v1.5.1
|
github.com/creasty/defaults v1.5.1
|
||||||
github.com/denisbrodbeck/machineid v1.0.1
|
github.com/denisbrodbeck/machineid v1.0.1
|
||||||
github.com/google/go-github/v37 v37.0.0
|
github.com/google/go-github/v37 v37.0.0
|
||||||
github.com/google/uuid v1.1.2
|
github.com/gorilla/websocket v1.4.2
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||||
github.com/spf13/cobra v1.1.3
|
github.com/spf13/cobra v1.1.3
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/up9inc/mizu/shared v0.0.0
|
github.com/up9inc/mizu/shared v0.0.0
|
||||||
github.com/up9inc/mizu/tap/api v0.0.0
|
github.com/up9inc/mizu/tap/api v0.0.0
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||||
k8s.io/api v0.21.2
|
k8s.io/api v0.21.2
|
||||||
k8s.io/apimachinery v0.21.2
|
k8s.io/apimachinery v0.21.2
|
||||||
|
@ -237,6 +237,7 @@ github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyyc
|
|||||||
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
|
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
package uiUtils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/up9inc/mizu/cli/logger"
|
|
||||||
"os/exec"
|
|
||||||
"runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
func OpenBrowser(url string) {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "linux":
|
|
||||||
err = exec.Command("xdg-open", url).Start()
|
|
||||||
case "windows":
|
|
||||||
err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
|
|
||||||
case "darwin":
|
|
||||||
err = exec.Command("open", url).Start()
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("unsupported platform")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Errorf("error while opening browser, %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user