diff --git a/cmd/connect.go b/cmd/connect.go index 6a4988e..b0e8f5e 100644 --- a/cmd/connect.go +++ b/cmd/connect.go @@ -8,6 +8,9 @@ import ( "os/exec" "strconv" "strings" + "time" + + "github.com/briandowns/spinner" "github.com/fatih/color" "github.com/manifoldco/promptui" @@ -23,20 +26,35 @@ const ( GreenColor = "\033[32m" ) -func setProject(env string) string { - // TODO: get project list with gcloud sdk - switch env { - case "dev": - project = "beecash-staging" - case "staging": - project = "beecash-staging" - case "prod": - project = "tokko-production" - default: - fmt.Print("Invalid Environment\n Please enter a valid environment: dev, staging, prod\n") +func getProject() string { + var proj_id []string + getprojectcommand := fmt.Sprintf("gcloud projects list --format='value(project_id)'") + getproject := exec.Command("bash", "-c", getprojectcommand) + getprojectout, err := getproject.Output() + if err != nil { + log.Fatal(err) + } else { + proj := strings.TrimSuffix(string(getprojectout), "\n") + proj_id = strings.Split(proj, "\n") + } + + prompt := promptui.Select{ + Label: "Select GCP Project", + Items: proj_id, + } + + _, result, err := prompt.Run() + + if err != nil { + fmt.Printf("Prompt failed %v\n", err) os.Exit(1) + return "" } - return project + + fmt.Printf("Project ID: %q\n", result) + promptresult := strings.Split(result, ":") + project_id := promptresult[len(promptresult)-1] + return project_id } func listInstances(project string) []string { @@ -65,11 +83,11 @@ func listInstances(project string) []string { return list } -func getInstance(env string) string { - project := setProject(env) +func getInstance() string { + project := getProject() instancelist := listInstances(project) prompt := promptui.Select{ - Label: "Select Project" + project, + Label: "Select instance to connect", Items: instancelist, } @@ -83,13 +101,12 @@ func getInstance(env string) string { blue := color.New(color.FgBlue) boldBlue := blue.Add(color.Bold) boldBlue.Printf("You choose: %q\n", result) - // fmt.Printf("You choose %q\n", result) return result } -func connectInstance(env string, port int) { +func connectInstance(port int) { var userName string - sqlConnectionName := getInstance(env) + sqlConnectionName := getInstance() fmt.Println("Connecting Instance") cmd := exec.Command("cloud_sql_proxy", "-enable_iam_login", "-instances="+sqlConnectionName+"=tcp:"+strconv.Itoa(port)) cmd.Stdout = os.Stdout @@ -97,6 +114,13 @@ func connectInstance(env string, port int) { if err != nil { log.Fatal(err) } + + // Loading spinner + s := spinner.New(spinner.CharSets[39], 100*time.Millisecond) + s.Start() + time.Sleep(2 * time.Second) + s.Stop() + log.Printf("Cloudsql proxy process is running in background, process_id: %d\n", cmd.Process.Pid) command := fmt.Sprintf("gcloud auth list --filter=status:ACTIVE --format='value(account)'") diff --git a/cmd/doctor.go b/cmd/doctor.go new file mode 100644 index 0000000..854b5b7 --- /dev/null +++ b/cmd/doctor.go @@ -0,0 +1,46 @@ +package cmd + +import ( + "fmt" + "log" + "os/exec" + + "github.com/fatih/color" +) + +func doctor() { + + // Check if gcloud sdk is available + gcloudversioncommand := fmt.Sprintf("gcloud version | head -n 1") + gcloudversion := exec.Command("bash", "-c", gcloudversioncommand) + gcloudversionout, err := gcloudversion.Output() + if err != nil { + fmt.Println("Please reinstall gcloud sdk") + log.Fatal(err) + } + fmt.Printf("gcloud version: %s", gcloudversionout) + + // Check if user is authenticated in gcloud + gcloudusercommand := fmt.Sprintf("gcloud auth list --filter=status:ACTIVE --format='value(account)'") + gclouduser := exec.Command("bash", "-c", gcloudusercommand) + gclouduserout, err := gclouduser.Output() + if err != nil { + fmt.Println("User not authenticated\nRun: gcloud auth application-default login") + log.Fatal(err) + } + fmt.Printf("Authenticated user account: %s", gclouduserout) + + // Check if cloud_sql_proxy is installed + cloudsqlproxyversion := exec.Command("cloud_sql_proxy", "--version") + cloudsqlproxyversionout, err := cloudsqlproxyversion.Output() + if err != nil { + fmt.Println("Please reinstall cloud_sql_proxy") + log.Fatal(err) + } + fmt.Printf("cloud_sql_proxy version: %s", cloudsqlproxyversionout) + + //Print eveything is ok + green := color.New(color.FgGreen) + boldGreen := green.Add(color.Bold) + boldGreen.Printf("Your system is ready to connect CloudSQL instances") +} diff --git a/cmd/root.go b/cmd/root.go index 85414d0..b284626 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,7 +1,3 @@ -/* -Copyright © 2022 NAME HERE - -*/ package cmd import ( @@ -25,16 +21,13 @@ var connectCmd = &cobra.Command{ Short: "connect to cloudsql instance", Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { - env, _ := cmd.Flags().GetString("env") port, _ := cmd.Flags().GetInt("port") - fmt.Printf("Environment: %v\n", env) _, err := net.Listen("tcp", ":"+strconv.Itoa(port)) if err != nil { - // Log or report the error here fmt.Printf("Port already in use\n") os.Exit(1) } - connectInstance(env, port) + connectInstance(port) }, } @@ -47,6 +40,14 @@ var disconnectCmd = &cobra.Command{ }, } +var doctorCmd = &cobra.Command{ + Use: "doctor", + Short: "for troubleshooting", + Args: cobra.NoArgs, + Run: func(cmd *cobra.Command, args []string) { + doctor() + }, +} func Execute() { err := connectCmd.Execute() @@ -56,7 +57,6 @@ func Execute() { } func init() { - rootCmd.AddCommand(disconnectCmd, connectCmd) - connectCmd.PersistentFlags().StringP("env", "e", "dev", "environment\nSupported environments: dev, staging, prod\n") + rootCmd.AddCommand(disconnectCmd, connectCmd, doctorCmd) connectCmd.PersistentFlags().IntP("port", "p", 5432, "port") } diff --git a/go.mod b/go.mod index cf19ffb..85dc2ee 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,8 @@ module bukukasio/lummo-sqlproxy go 1.18 require ( + github.com/briandowns/spinner v1.19.0 + github.com/fatih/color v1.13.0 github.com/manifoldco/promptui v0.9.0 github.com/spf13/cobra v1.5.0 golang.org/x/oauth2 v0.0.0-20220808172628-8227340efae7 @@ -12,7 +14,6 @@ require ( require ( cloud.google.com/go/compute v1.7.0 // indirect github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect - github.com/fatih/color v1.13.0 // indirect github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/uuid v1.3.0 // indirect diff --git a/go.sum b/go.sum index cb9daa4..3168f03 100644 --- a/go.sum +++ b/go.sum @@ -59,6 +59,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/briandowns/spinner v1.19.0 h1:s8aq38H+Qju89yhp89b4iIiMzMm8YN3p6vGpwyh/a8E= +github.com/briandowns/spinner v1.19.0/go.mod h1:mQak9GHqbspjC/5iUx3qMlIho8xBS/ppAL/hX5SmPJU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -90,6 +92,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -195,8 +198,10 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= @@ -350,6 +355,7 @@ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=