From 5abe6a02cea57c567f35f45358c8277e8422c7a9 Mon Sep 17 00:00:00 2001 From: Binaek Sarkar Date: Mon, 15 Mar 2021 22:54:36 +0530 Subject: [PATCH] Add `install-dir` argument to specify location of the installation folder. Closes #241 --- cmd/root.go | 5 +++++ cmdconfig/viper.go | 12 +++++++----- constants/args.go | 1 + constants/config.go | 18 +++++++++--------- db/start.go | 43 ++++++++++++++++++++++++++++++++++--------- db/stop.go | 13 +++++++++++++ 6 files changed, 69 insertions(+), 23 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 66745046e9..41d5357643 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -4,7 +4,9 @@ import ( "log" "github.com/spf13/cobra" + "github.com/spf13/viper" "github.com/turbot/steampipe/cmdconfig" + "github.com/turbot/steampipe/constants" "github.com/turbot/steampipe/version" ) @@ -47,6 +49,9 @@ func Execute() error { } func init() { + rootCmd.PersistentFlags().String(constants.ArgInstallDir, constants.DefaultInstallDir, "Path to the Config Directory") + viper.BindPFlag(constants.ArgInstallDir, rootCmd.PersistentFlags().Lookup(constants.ArgInstallDir)) + cobra.OnInitialize(initGlobalConfig) } diff --git a/cmdconfig/viper.go b/cmdconfig/viper.go index 4e0213f7a8..14d678a4ea 100644 --- a/cmdconfig/viper.go +++ b/cmdconfig/viper.go @@ -1,7 +1,7 @@ package cmdconfig import ( - "strings" + "os" "github.com/spf13/viper" "github.com/turbot/steampipe/constants" @@ -10,12 +10,14 @@ import ( // InitViper :: initializes and configures an instance of viper func InitViper() { v := viper.GetViper() - v.SetEnvPrefix("STEAMPIPE") - v.AutomaticEnv() - v.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) - // set defaults v.Set(constants.ShowInteractiveOutputConfigKey, true) + + if installDir, isSet := os.LookupEnv("STEAMPIPE_INSTALL_DIR"); isSet { + v.SetDefault(constants.ArgInstallDir, installDir) + } else { + v.SetDefault(constants.ArgInstallDir, "~/.steampipe") + } } // Viper :: fetches the global viper instance diff --git a/constants/args.go b/constants/args.go index 5fabb794c3..ae24a81a9b 100644 --- a/constants/args.go +++ b/constants/args.go @@ -12,6 +12,7 @@ const ( ArgTimer = "timing" ArgOn = "on" ArgOff = "off" + ArgInstallDir = "install-dir" ) /// metaquery mode arguments diff --git a/constants/config.go b/constants/config.go index 9e24c4d35d..2dc85fd4cf 100644 --- a/constants/config.go +++ b/constants/config.go @@ -5,12 +5,14 @@ import ( "os" "path/filepath" + "github.com/spf13/viper" + "github.com/turbot/go-kit/helpers" "github.com/turbot/steampipe/utils" ) // Constants for Config const ( - SteampipeDirName = ".steampipe" + DefaultInstallDir = "~/.steampipe" PluginExtension = ".plugin" ConfigExtension = ".spc" ConnectionsStateFileName = "connection.json" @@ -18,15 +20,13 @@ const ( // SteampipeDir :: returns the top level ~/.steampipe folder (creates if it doesnt exist) func SteampipeDir() string { - homeDir, err := os.UserHomeDir() - utils.FailOnError(err) - ch := filepath.Join(homeDir, SteampipeDirName) - if _, err := os.Stat(ch); os.IsNotExist(err) { - err = os.MkdirAll(ch, 0755) - utils.FailOnErrorWithMessage(err, "could not create .steampipe directory") + installDir, err := helpers.Tildefy(viper.GetString(ArgInstallDir)) + utils.FailOnErrorWithMessage(err, fmt.Sprintf("failed to sanitize install directory")) + if _, err := os.Stat(installDir); os.IsNotExist(err) { + err = os.MkdirAll(installDir, 0755) + utils.FailOnErrorWithMessage(err, fmt.Sprintf("could not create installation directory: %s", installDir)) } - - return ch + return installDir } func steampipeSubDir(dirName string) string { diff --git a/db/start.go b/db/start.go index 6bc69ce0fd..695c90392e 100644 --- a/db/start.go +++ b/db/start.go @@ -6,9 +6,12 @@ import ( "net" "os" "os/exec" + "strings" "syscall" + "github.com/turbot/go-kit/helpers" "github.com/turbot/steampipe/cmdconfig" + "github.com/turbot/steampipe/utils" "github.com/shirou/gopsutil/process" "github.com/turbot/steampipe/constants" @@ -70,7 +73,7 @@ func (slt Invoker) IsValid() error { // StartDB :: start the database is not already running func StartDB(port int, listen StartListenType, invoker Invoker) (StartResult, error) { - info, err := loadRunningInstanceInfo() + info, err := GetStatus() if err != nil { return ServiceFailedToStart, err @@ -104,6 +107,15 @@ func StartDB(port int, listen StartListenType, invoker Invoker) (StartResult, er return ServiceFailedToStart, fmt.Errorf("Cannot listen on %d. Are you sure that the interface is free?", port) } + checkedPreviousInstances := make(chan bool, 1) + s := utils.StartSpinnerAfterDelay("Checking for running instances", constants.SpinnerShowTimeout, checkedPreviousInstances) + previousProcess := findSteampipePostgresInstance() + checkedPreviousInstances <- true + utils.StopSpinner(s) + if previousProcess != nil { + return ServiceFailedToStart, fmt.Errorf("Another Steampipe service is already running. Use %s to kill all running instances before continuing.", constants.Bold("steampipe service stop --force")) + } + postgresCmd := exec.Command( getPostgresBinaryExecutablePath(), // by this time, we are sure that the port if free to listen to @@ -235,19 +247,32 @@ func isPortBindable(port int) bool { // kill all postgres processes that were started as part of steampipe (if any) func killPreviousInstanceIfAny() bool { + p := findSteampipePostgresInstance() + if p != nil { + killProcessTree(p) + return true + } + return false +} + +func findSteampipePostgresInstance() *process.Process { allProcesses, _ := process.Processes() for _, p := range allProcesses { cmdLine, _ := p.CmdlineSlice() - if len(cmdLine) < 1 { - continue + if isSteampipePostgresProcess(cmdLine) { + return p } - executable := cmdLine[0] + } + return nil +} - // this is a steampipe postgres, kill it along with it's children - if executable == getPostgresBinaryExecutablePath() { - killProcessTree(p) - return true - } +func isSteampipePostgresProcess(cmdline []string) bool { + if len(cmdline) < 1 { + return false + } + if strings.Contains(cmdline[0], "postgres") { + // this is a postgres process + return helpers.StringSliceContains(cmdline, fmt.Sprintf("application_name=%s", constants.APPNAME)) } return false } diff --git a/db/stop.go b/db/stop.go index 553433fdd5..fa0c1e2eb6 100644 --- a/db/stop.go +++ b/db/stop.go @@ -46,6 +46,19 @@ func StopDB(force bool) (StopStatus, error) { if info == nil { // we do not have a info file + if force { + // check if we have a process from another install-dir + checkedPreviousInstances := make(chan bool, 1) + s := utils.StartSpinnerAfterDelay("Checking for running instances", constants.SpinnerShowTimeout, checkedPreviousInstances) + previousProcess := findSteampipePostgresInstance() + checkedPreviousInstances <- true + utils.StopSpinner(s) + if previousProcess != nil { + // we have an errant process + killPreviousInstanceIfAny() + return ServiceStopped, nil + } + } return ServiceNotRunning, nil }