mirror of
https://github.com/turbot/steampipe.git
synced 2025-12-19 18:12:43 -05:00
Update package naming to be consistent and follow Go standards. Closes #1282
General code spring cleaning: * move file paths from `consts` package to `filepaths` * move InitData and ExportData to query and control packages
This commit is contained in:
2
cloud/doc.go
Normal file
2
cloud/doc.go
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// Package cloud contains logic to support connecting to a steampipe cloud database
|
||||||
|
package cloud
|
||||||
152
cmd/check.go
152
cmd/check.go
@@ -10,45 +10,24 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/turbot/steampipe/mod_installer"
|
|
||||||
|
|
||||||
"github.com/briandowns/spinner"
|
"github.com/briandowns/spinner"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/turbot/go-kit/helpers"
|
"github.com/turbot/go-kit/helpers"
|
||||||
"github.com/turbot/steampipe/cmdconfig"
|
"github.com/turbot/steampipe/cmdconfig"
|
||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
|
"github.com/turbot/steampipe/control"
|
||||||
"github.com/turbot/steampipe/control/controldisplay"
|
"github.com/turbot/steampipe/control/controldisplay"
|
||||||
"github.com/turbot/steampipe/control/controlexecute"
|
"github.com/turbot/steampipe/control/controlexecute"
|
||||||
"github.com/turbot/steampipe/db/db_client"
|
"github.com/turbot/steampipe/db/db_client"
|
||||||
"github.com/turbot/steampipe/db/db_common"
|
"github.com/turbot/steampipe/db/db_common"
|
||||||
"github.com/turbot/steampipe/db/db_local"
|
"github.com/turbot/steampipe/db/db_local"
|
||||||
"github.com/turbot/steampipe/display"
|
"github.com/turbot/steampipe/display"
|
||||||
|
"github.com/turbot/steampipe/modinstaller"
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
"github.com/turbot/steampipe/workspace"
|
"github.com/turbot/steampipe/workspace"
|
||||||
)
|
)
|
||||||
|
|
||||||
type checkInitData struct {
|
|
||||||
ctx context.Context
|
|
||||||
workspace *workspace.Workspace
|
|
||||||
client db_common.Client
|
|
||||||
result *db_common.InitResult
|
|
||||||
}
|
|
||||||
|
|
||||||
type exportData struct {
|
|
||||||
executionTree *controlexecute.ExecutionTree
|
|
||||||
exportFormats []controldisplay.CheckExportTarget
|
|
||||||
errorsLock *sync.Mutex
|
|
||||||
errors []error
|
|
||||||
waitGroup *sync.WaitGroup
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *exportData) addErrors(err []error) {
|
|
||||||
e.errorsLock.Lock()
|
|
||||||
e.errors = append(e.errors, err...)
|
|
||||||
e.errorsLock.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkCmd() *cobra.Command {
|
func checkCmd() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "check [flags] [mod/benchmark/control/\"all\"]",
|
Use: "check [flags] [mod/benchmark/control/\"all\"]",
|
||||||
@@ -108,7 +87,7 @@ You may specify one or more benchmarks or controls to run (separated by a space)
|
|||||||
|
|
||||||
func runCheckCmd(cmd *cobra.Command, args []string) {
|
func runCheckCmd(cmd *cobra.Command, args []string) {
|
||||||
utils.LogTime("runCheckCmd start")
|
utils.LogTime("runCheckCmd start")
|
||||||
initData := &checkInitData{}
|
initData := &control.InitData{}
|
||||||
defer func() {
|
defer func() {
|
||||||
utils.LogTime("runCheckCmd end")
|
utils.LogTime("runCheckCmd end")
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@@ -116,12 +95,12 @@ func runCheckCmd(cmd *cobra.Command, args []string) {
|
|||||||
exitCode = 1
|
exitCode = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if initData.client != nil {
|
if initData.Client != nil {
|
||||||
log.Printf("[TRACE] close client")
|
log.Printf("[TRACE] close client")
|
||||||
initData.client.Close()
|
initData.Client.Close()
|
||||||
}
|
}
|
||||||
if initData.workspace != nil {
|
if initData.Workspace != nil {
|
||||||
initData.workspace.Close()
|
initData.Workspace.Close()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -143,9 +122,9 @@ func runCheckCmd(cmd *cobra.Command, args []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// pull out useful properties
|
// pull out useful properties
|
||||||
ctx := initData.ctx
|
ctx := initData.Ctx
|
||||||
workspace := initData.workspace
|
workspace := initData.Workspace
|
||||||
client := initData.client
|
client := initData.Client
|
||||||
failures := 0
|
failures := 0
|
||||||
var exportErrors []error
|
var exportErrors []error
|
||||||
exportErrorsLock := sync.Mutex{}
|
exportErrorsLock := sync.Mutex{}
|
||||||
@@ -175,7 +154,7 @@ func runCheckCmd(cmd *cobra.Command, args []string) {
|
|||||||
utils.FailOnError(err)
|
utils.FailOnError(err)
|
||||||
|
|
||||||
if len(exportFormats) > 0 {
|
if len(exportFormats) > 0 {
|
||||||
d := exportData{executionTree: executionTree, exportFormats: exportFormats, errorsLock: &exportErrorsLock, errors: exportErrors, waitGroup: &exportWaitGroup}
|
d := control.ExportData{ExecutionTree: executionTree, ExportFormats: exportFormats, ErrorsLock: &exportErrorsLock, Errors: exportErrors, WaitGroup: &exportWaitGroup}
|
||||||
exportCheckResult(ctx, &d)
|
exportCheckResult(ctx, &d)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,16 +176,29 @@ func runCheckCmd(cmd *cobra.Command, args []string) {
|
|||||||
exitCode = failures
|
exitCode = failures
|
||||||
}
|
}
|
||||||
|
|
||||||
func initialiseCheck(ctx context.Context, spinner *spinner.Spinner) *checkInitData {
|
func validateArgs(cmd *cobra.Command, args []string) bool {
|
||||||
initData := &checkInitData{
|
if len(args) == 0 {
|
||||||
result: &db_common.InitResult{},
|
fmt.Println()
|
||||||
|
utils.ShowError(fmt.Errorf("you must provide at least one argument"))
|
||||||
|
fmt.Println()
|
||||||
|
cmd.Help()
|
||||||
|
fmt.Println()
|
||||||
|
exitCode = 2
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func initialiseCheck(ctx context.Context, spinner *spinner.Spinner) *control.InitData {
|
||||||
|
initData := &control.InitData{
|
||||||
|
Result: &db_common.InitResult{},
|
||||||
}
|
}
|
||||||
|
|
||||||
if viper.GetBool(constants.ArgModInstall) {
|
if viper.GetBool(constants.ArgModInstall) {
|
||||||
opts := &mod_installer.InstallOpts{WorkspacePath: viper.GetString(constants.ArgWorkspaceChDir)}
|
opts := &modinstaller.InstallOpts{WorkspacePath: viper.GetString(constants.ArgWorkspaceChDir)}
|
||||||
_, err := mod_installer.InstallWorkspaceDependencies(opts)
|
_, err := modinstaller.InstallWorkspaceDependencies(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
initData.result.Error = err
|
initData.Result.Error = err
|
||||||
return initData
|
return initData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,45 +207,45 @@ func initialiseCheck(ctx context.Context, spinner *spinner.Spinner) *checkInitDa
|
|||||||
|
|
||||||
err := validateOutputFormat()
|
err := validateOutputFormat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
initData.result.Error = err
|
initData.Result.Error = err
|
||||||
return initData
|
return initData
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cmdconfig.ValidateConnectionStringArgs()
|
err = cmdconfig.ValidateConnectionStringArgs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
initData.result.Error = err
|
initData.Result.Error = err
|
||||||
return initData
|
return initData
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
startCancelHandler(cancel)
|
startCancelHandler(cancel)
|
||||||
initData.ctx = ctx
|
initData.Ctx = ctx
|
||||||
|
|
||||||
// set color schema
|
// set color schema
|
||||||
err = initialiseColorScheme()
|
err = initialiseColorScheme()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
initData.result.Error = err
|
initData.Result.Error = err
|
||||||
return initData
|
return initData
|
||||||
}
|
}
|
||||||
// load workspace
|
// load workspace
|
||||||
initData.workspace, err = loadWorkspacePromptingForVariables(ctx, spinner)
|
initData.Workspace, err = loadWorkspacePromptingForVariables(ctx, spinner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !utils.IsCancelledError(err) {
|
if !utils.IsCancelledError(err) {
|
||||||
err = utils.PrefixError(err, "failed to load workspace")
|
err = utils.PrefixError(err, "failed to load workspace")
|
||||||
}
|
}
|
||||||
initData.result.Error = err
|
initData.Result.Error = err
|
||||||
return initData
|
return initData
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the required plugins are installed
|
// check if the required plugins are installed
|
||||||
err = initData.workspace.CheckRequiredPluginsInstalled()
|
err = initData.Workspace.CheckRequiredPluginsInstalled()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
initData.result.Error = err
|
initData.Result.Error = err
|
||||||
return initData
|
return initData
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(initData.workspace.Controls) == 0 {
|
if len(initData.Workspace.Controls) == 0 {
|
||||||
initData.result.AddWarnings("no controls found in current workspace")
|
initData.Result.AddWarnings("no controls found in current workspace")
|
||||||
}
|
}
|
||||||
|
|
||||||
display.UpdateSpinnerMessage(spinner, "Connecting to service...")
|
display.UpdateSpinnerMessage(spinner, "Connecting to service...")
|
||||||
@@ -271,45 +263,45 @@ func initialiseCheck(ctx context.Context, spinner *spinner.Spinner) *checkInitDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
initData.result.Error = err
|
initData.Result.Error = err
|
||||||
return initData
|
return initData
|
||||||
}
|
}
|
||||||
initData.client = client
|
initData.Client = client
|
||||||
|
|
||||||
refreshResult := initData.client.RefreshConnectionAndSearchPaths(ctx)
|
refreshResult := initData.Client.RefreshConnectionAndSearchPaths(ctx)
|
||||||
if refreshResult.Error != nil {
|
if refreshResult.Error != nil {
|
||||||
initData.result.Error = refreshResult.Error
|
initData.Result.Error = refreshResult.Error
|
||||||
return initData
|
return initData
|
||||||
}
|
}
|
||||||
initData.result.AddWarnings(refreshResult.Warnings...)
|
initData.Result.AddWarnings(refreshResult.Warnings...)
|
||||||
|
|
||||||
// setup the session data - prepared statements and introspection tables
|
// setup the session data - prepared statements and introspection tables
|
||||||
sessionDataSource := workspace.NewSessionDataSource(initData.workspace, nil)
|
sessionDataSource := workspace.NewSessionDataSource(initData.Workspace, nil)
|
||||||
|
|
||||||
// register EnsureSessionData as a callback on the client.
|
// register EnsureSessionData as a callback on the client.
|
||||||
// if the underlying SQL client has certain errors (for example context expiry) it will reset the session
|
// if the underlying SQL client has certain errors (for example context expiry) it will reset the session
|
||||||
// so our client object calls this callback to restore the session data
|
// so our client object calls this callback to restore the session data
|
||||||
initData.client.SetEnsureSessionDataFunc(func(localCtx context.Context, conn *db_common.DatabaseSession) (error, []string) {
|
initData.Client.SetEnsureSessionDataFunc(func(localCtx context.Context, conn *db_common.DatabaseSession) (error, []string) {
|
||||||
return workspace.EnsureSessionData(localCtx, sessionDataSource, conn)
|
return workspace.EnsureSessionData(localCtx, sessionDataSource, conn)
|
||||||
})
|
})
|
||||||
|
|
||||||
return initData
|
return initData
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleCheckInitResult(initData *checkInitData) bool {
|
func handleCheckInitResult(initData *control.InitData) bool {
|
||||||
// if there is an error or cancellation we bomb out
|
// if there is an error or cancellation we bomb out
|
||||||
// check for the various kinds of failures
|
// check for the various kinds of failures
|
||||||
utils.FailOnError(initData.result.Error)
|
utils.FailOnError(initData.Result.Error)
|
||||||
// cancelled?
|
// cancelled?
|
||||||
if initData.ctx != nil {
|
if initData.Ctx != nil {
|
||||||
utils.FailOnError(initData.ctx.Err())
|
utils.FailOnError(initData.Ctx.Err())
|
||||||
}
|
}
|
||||||
|
|
||||||
// if there is a usage warning we display it
|
// if there is a usage warning we display it
|
||||||
initData.result.DisplayMessages()
|
initData.Result.DisplayMessages()
|
||||||
|
|
||||||
// if there is are any warnings, exit politely
|
// if there is are any warnings, exit politely
|
||||||
shouldExit := len(initData.result.Warnings) > 0
|
shouldExit := len(initData.Result.Warnings) > 0
|
||||||
|
|
||||||
// alternative approach - only stop the control run if there are no controls
|
// alternative approach - only stop the control run if there are no controls
|
||||||
//shouldExit := initData.workspace == nil || len(initData.workspace.Controls) == 0
|
//shouldExit := initData.workspace == nil || len(initData.workspace.Controls) == 0
|
||||||
@@ -317,20 +309,6 @@ func handleCheckInitResult(initData *checkInitData) bool {
|
|||||||
return shouldExit
|
return shouldExit
|
||||||
}
|
}
|
||||||
|
|
||||||
func exportCheckResult(ctx context.Context, d *exportData) {
|
|
||||||
if utils.IsContextCancelled(ctx) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
d.waitGroup.Add(1)
|
|
||||||
go func() {
|
|
||||||
err := exportControlResults(ctx, d.executionTree, d.exportFormats)
|
|
||||||
if len(err) > 0 {
|
|
||||||
d.addErrors(err)
|
|
||||||
}
|
|
||||||
d.waitGroup.Done()
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func printTiming(args []string, durations []time.Duration) {
|
func printTiming(args []string, durations []time.Duration) {
|
||||||
headers := []string{"", "Duration"}
|
headers := []string{"", "Duration"}
|
||||||
var rows [][]string
|
var rows [][]string
|
||||||
@@ -343,19 +321,6 @@ func printTiming(args []string, durations []time.Duration) {
|
|||||||
display.ShowWrappedTable(headers, rows, false)
|
display.ShowWrappedTable(headers, rows, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateArgs(cmd *cobra.Command, args []string) bool {
|
|
||||||
if len(args) == 0 {
|
|
||||||
fmt.Println()
|
|
||||||
utils.ShowError(fmt.Errorf("you must provide at least one argument"))
|
|
||||||
fmt.Println()
|
|
||||||
cmd.Help()
|
|
||||||
fmt.Println()
|
|
||||||
exitCode = 2
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func shouldPrintTiming() bool {
|
func shouldPrintTiming() bool {
|
||||||
outputFormat := viper.GetString(constants.ArgOutput)
|
outputFormat := viper.GetString(constants.ArgOutput)
|
||||||
|
|
||||||
@@ -413,6 +378,17 @@ func initialiseColorScheme() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func exportCheckResult(ctx context.Context, d *control.ExportData) {
|
||||||
|
d.WaitGroup.Add(1)
|
||||||
|
go func() {
|
||||||
|
err := exportControlResults(ctx, d.ExecutionTree, d.ExportFormats)
|
||||||
|
if len(err) > 0 {
|
||||||
|
d.AddErrors(err)
|
||||||
|
}
|
||||||
|
d.WaitGroup.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
func displayControlResults(ctx context.Context, executionTree *controlexecute.ExecutionTree) error {
|
func displayControlResults(ctx context.Context, executionTree *controlexecute.ExecutionTree) error {
|
||||||
outputFormat := viper.GetString(constants.ArgOutput)
|
outputFormat := viper.GetString(constants.ArgOutput)
|
||||||
formatter, _ := controldisplay.GetOutputFormatter(outputFormat)
|
formatter, _ := controldisplay.GetOutputFormatter(outputFormat)
|
||||||
|
|||||||
2
cmd/doc.go
Normal file
2
cmd/doc.go
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// Package cmd contains Cobra command definitions for all Steampipe commands
|
||||||
|
package cmd
|
||||||
24
cmd/mod.go
24
cmd/mod.go
@@ -9,7 +9,8 @@ import (
|
|||||||
"github.com/turbot/go-kit/helpers"
|
"github.com/turbot/go-kit/helpers"
|
||||||
"github.com/turbot/steampipe/cmdconfig"
|
"github.com/turbot/steampipe/cmdconfig"
|
||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
"github.com/turbot/steampipe/mod_installer"
|
"github.com/turbot/steampipe/filepaths"
|
||||||
|
"github.com/turbot/steampipe/modinstaller"
|
||||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||||
"github.com/turbot/steampipe/steampipeconfig/parse"
|
"github.com/turbot/steampipe/steampipeconfig/parse"
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
@@ -17,7 +18,6 @@ import (
|
|||||||
|
|
||||||
// mod management commands
|
// mod management commands
|
||||||
func modCmd() *cobra.Command {
|
func modCmd() *cobra.Command {
|
||||||
|
|
||||||
var cmd = &cobra.Command{
|
var cmd = &cobra.Command{
|
||||||
Use: "mod [command]",
|
Use: "mod [command]",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
@@ -64,10 +64,10 @@ func runModInstallCmd(cmd *cobra.Command, args []string) {
|
|||||||
|
|
||||||
// if any mod names were passed as args, convert into formed mod names
|
// if any mod names were passed as args, convert into formed mod names
|
||||||
opts := newInstallOpts(cmd, args...)
|
opts := newInstallOpts(cmd, args...)
|
||||||
installData, err := mod_installer.InstallWorkspaceDependencies(opts)
|
installData, err := modinstaller.InstallWorkspaceDependencies(opts)
|
||||||
utils.FailOnError(err)
|
utils.FailOnError(err)
|
||||||
|
|
||||||
fmt.Println(mod_installer.BuildInstallSummary(installData))
|
fmt.Println(modinstaller.BuildInstallSummary(installData))
|
||||||
}
|
}
|
||||||
|
|
||||||
// uninstall
|
// uninstall
|
||||||
@@ -98,10 +98,10 @@ func runModUninstallCmd(cmd *cobra.Command, args []string) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
opts := newInstallOpts(cmd, args...)
|
opts := newInstallOpts(cmd, args...)
|
||||||
installData, err := mod_installer.UninstallWorkspaceDependencies(opts)
|
installData, err := modinstaller.UninstallWorkspaceDependencies(opts)
|
||||||
utils.FailOnError(err)
|
utils.FailOnError(err)
|
||||||
|
|
||||||
fmt.Println(mod_installer.BuildUninstallSummary(installData))
|
fmt.Println(modinstaller.BuildUninstallSummary(installData))
|
||||||
}
|
}
|
||||||
|
|
||||||
// update
|
// update
|
||||||
@@ -133,10 +133,10 @@ func runModUpdateCmd(cmd *cobra.Command, args []string) {
|
|||||||
|
|
||||||
opts := newInstallOpts(cmd, args...)
|
opts := newInstallOpts(cmd, args...)
|
||||||
|
|
||||||
installData, err := mod_installer.InstallWorkspaceDependencies(opts)
|
installData, err := modinstaller.InstallWorkspaceDependencies(opts)
|
||||||
utils.FailOnError(err)
|
utils.FailOnError(err)
|
||||||
|
|
||||||
fmt.Println(mod_installer.BuildInstallSummary(installData))
|
fmt.Println(modinstaller.BuildInstallSummary(installData))
|
||||||
}
|
}
|
||||||
|
|
||||||
// list
|
// list
|
||||||
@@ -162,7 +162,7 @@ func runModListCmd(cmd *cobra.Command, _ []string) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
opts := newInstallOpts(cmd)
|
opts := newInstallOpts(cmd)
|
||||||
installer, err := mod_installer.NewModInstaller(opts)
|
installer, err := modinstaller.NewModInstaller(opts)
|
||||||
utils.FailOnError(err)
|
utils.FailOnError(err)
|
||||||
|
|
||||||
treeString := installer.GetModList()
|
treeString := installer.GetModList()
|
||||||
@@ -201,13 +201,13 @@ func runModInitCmd(cmd *cobra.Command, args []string) {
|
|||||||
}
|
}
|
||||||
mod := modconfig.CreateDefaultMod(workspacePath)
|
mod := modconfig.CreateDefaultMod(workspacePath)
|
||||||
utils.FailOnError(mod.Save())
|
utils.FailOnError(mod.Save())
|
||||||
fmt.Printf("Created mod definition file '%s'\n", constants.ModFilePath(workspacePath))
|
fmt.Printf("Created mod definition file '%s'\n", filepaths.ModFilePath(workspacePath))
|
||||||
}
|
}
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
|
|
||||||
func newInstallOpts(cmd *cobra.Command, args ...string) *mod_installer.InstallOpts {
|
func newInstallOpts(cmd *cobra.Command, args ...string) *modinstaller.InstallOpts {
|
||||||
opts := &mod_installer.InstallOpts{
|
opts := &modinstaller.InstallOpts{
|
||||||
WorkspacePath: viper.GetString(constants.ArgWorkspaceChDir),
|
WorkspacePath: viper.GetString(constants.ArgWorkspaceChDir),
|
||||||
DryRun: viper.GetBool(constants.ArgDryRun),
|
DryRun: viper.GetBool(constants.ArgDryRun),
|
||||||
ModArgs: args,
|
ModArgs: args,
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import (
|
|||||||
|
|
||||||
// Plugin management commands
|
// Plugin management commands
|
||||||
func pluginCmd() *cobra.Command {
|
func pluginCmd() *cobra.Command {
|
||||||
|
|
||||||
var cmd = &cobra.Command{
|
var cmd = &cobra.Command{
|
||||||
Use: "plugin [command]",
|
Use: "plugin [command]",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
@@ -88,7 +87,6 @@ Examples:
|
|||||||
|
|
||||||
// Update plugins
|
// Update plugins
|
||||||
func pluginUpdateCmd() *cobra.Command {
|
func pluginUpdateCmd() *cobra.Command {
|
||||||
|
|
||||||
var cmd = &cobra.Command{
|
var cmd = &cobra.Command{
|
||||||
Use: "update [flags] [registry/org/]name[@version]",
|
Use: "update [flags] [registry/org/]name[@version]",
|
||||||
Args: cobra.ArbitraryArgs,
|
Args: cobra.ArbitraryArgs,
|
||||||
@@ -120,7 +118,6 @@ Examples:
|
|||||||
|
|
||||||
// List plugins
|
// List plugins
|
||||||
func pluginListCmd() *cobra.Command {
|
func pluginListCmd() *cobra.Command {
|
||||||
|
|
||||||
var cmd = &cobra.Command{
|
var cmd = &cobra.Command{
|
||||||
Use: "list",
|
Use: "list",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
@@ -176,10 +173,8 @@ Example:
|
|||||||
|
|
||||||
// exitCode=1 For unknown errors resulting in panics
|
// exitCode=1 For unknown errors resulting in panics
|
||||||
// exitCode=2 For insufficient/wrong arguments passed in the command
|
// exitCode=2 For insufficient/wrong arguments passed in the command
|
||||||
// exitCode=3 For errors related to loading state, loading version data or an issue contacting
|
// exitCode=3 For errors related to loading state, loading version data or an issue contacting the update server.
|
||||||
// the update server.
|
|
||||||
// exitCode=4 For plugin listing failures
|
// exitCode=4 For plugin listing failures
|
||||||
|
|
||||||
func runPluginInstallCmd(cmd *cobra.Command, args []string) {
|
func runPluginInstallCmd(cmd *cobra.Command, args []string) {
|
||||||
utils.LogTime("runPluginInstallCmd install")
|
utils.LogTime("runPluginInstallCmd install")
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -217,7 +212,7 @@ func runPluginInstallCmd(cmd *cobra.Command, args []string) {
|
|||||||
installReports = append(installReports, display.InstallReport{
|
installReports = append(installReports, display.InstallReport{
|
||||||
Plugin: p,
|
Plugin: p,
|
||||||
Skipped: true,
|
Skipped: true,
|
||||||
SkipReason: display.ALREADY_INSTALLED,
|
SkipReason: constants.PluginAlreadyInstalled,
|
||||||
IsUpdateReport: false,
|
IsUpdateReport: false,
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
@@ -329,7 +324,7 @@ func runPluginUpdateCmd(cmd *cobra.Command, args []string) {
|
|||||||
updateReports = append(updateReports, display.InstallReport{
|
updateReports = append(updateReports, display.InstallReport{
|
||||||
Skipped: true,
|
Skipped: true,
|
||||||
Plugin: p,
|
Plugin: p,
|
||||||
SkipReason: display.NOT_INSTALLED,
|
SkipReason: constants.PluginNotInstalled,
|
||||||
IsUpdateReport: true,
|
IsUpdateReport: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -362,7 +357,7 @@ func runPluginUpdateCmd(cmd *cobra.Command, args []string) {
|
|||||||
updateReports = append(updateReports, display.InstallReport{
|
updateReports = append(updateReports, display.InstallReport{
|
||||||
Plugin: fmt.Sprintf("%s@%s", report.CheckResponse.Name, report.CheckResponse.Stream),
|
Plugin: fmt.Sprintf("%s@%s", report.CheckResponse.Name, report.CheckResponse.Stream),
|
||||||
Skipped: true,
|
Skipped: true,
|
||||||
SkipReason: display.LATEST_ALREADY_INSTALLED,
|
SkipReason: constants.PluginLatestAlreadyInstalled,
|
||||||
IsUpdateReport: true,
|
IsUpdateReport: true,
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -13,9 +13,10 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/turbot/steampipe-plugin-sdk/logging"
|
"github.com/turbot/steampipe-plugin-sdk/logging"
|
||||||
"github.com/turbot/steampipe/cmdconfig"
|
"github.com/turbot/steampipe/cmdconfig"
|
||||||
"github.com/turbot/steampipe/connection_watcher"
|
"github.com/turbot/steampipe/connectionwatcher"
|
||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
"github.com/turbot/steampipe/plugin_manager"
|
"github.com/turbot/steampipe/filepaths"
|
||||||
|
"github.com/turbot/steampipe/pluginmanager"
|
||||||
"github.com/turbot/steampipe/steampipeconfig"
|
"github.com/turbot/steampipe/steampipeconfig"
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
)
|
)
|
||||||
@@ -41,13 +42,13 @@ func runPluginManagerCmd(cmd *cobra.Command, args []string) {
|
|||||||
log.Printf("[WARN] failed to load connection config: %s", err.Error())
|
log.Printf("[WARN] failed to load connection config: %s", err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
configMap := connection_watcher.NewConnectionConfigMap(steampipeConfig.Connections)
|
configMap := connectionwatcher.NewConnectionConfigMap(steampipeConfig.Connections)
|
||||||
log.Printf("[TRACE] loaded config map")
|
log.Printf("[TRACE] loaded config map")
|
||||||
|
|
||||||
pluginManager := plugin_manager.NewPluginManager(configMap, logger)
|
pluginManager := pluginmanager.NewPluginManager(configMap, logger)
|
||||||
|
|
||||||
if shouldRunConnectionWatcher() {
|
if shouldRunConnectionWatcher() {
|
||||||
connectionWatcher, err := connection_watcher.NewConnectionWatcher(pluginManager.SetConnectionConfigMap)
|
connectionWatcher, err := connectionwatcher.NewConnectionWatcher(pluginManager.SetConnectionConfigMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[WARN] failed to create connection watcher: %s", err.Error())
|
log.Printf("[WARN] failed to create connection watcher: %s", err.Error())
|
||||||
utils.ShowError(err)
|
utils.ShowError(err)
|
||||||
@@ -74,7 +75,7 @@ func shouldRunConnectionWatcher() bool {
|
|||||||
|
|
||||||
func createPluginManagerLog() hclog.Logger {
|
func createPluginManagerLog() hclog.Logger {
|
||||||
logName := fmt.Sprintf("plugin-%s.log", time.Now().Format("2006-01-02"))
|
logName := fmt.Sprintf("plugin-%s.log", time.Now().Format("2006-01-02"))
|
||||||
logPath := filepath.Join(constants.LogDir(), logName)
|
logPath := filepath.Join(filepaths.LogDir(), logName)
|
||||||
f, err := os.OpenFile(logPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
f, err := os.OpenFile(logPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("failed to open plugin manager log file: %s\n", err.Error())
|
fmt.Printf("failed to open plugin manager log file: %s\n", err.Error())
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/turbot/steampipe/db/db_common"
|
"github.com/turbot/steampipe/db/db_common"
|
||||||
"github.com/turbot/steampipe/db/db_local"
|
"github.com/turbot/steampipe/db/db_local"
|
||||||
"github.com/turbot/steampipe/interactive"
|
"github.com/turbot/steampipe/interactive"
|
||||||
|
"github.com/turbot/steampipe/query"
|
||||||
"github.com/turbot/steampipe/query/queryexecute"
|
"github.com/turbot/steampipe/query/queryexecute"
|
||||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
@@ -119,7 +120,7 @@ func runQueryCmd(cmd *cobra.Command, args []string) {
|
|||||||
defer w.Close()
|
defer w.Close()
|
||||||
|
|
||||||
// perform rest of initialisation async
|
// perform rest of initialisation async
|
||||||
initDataChan := make(chan *db_common.QueryInitData, 1)
|
initDataChan := make(chan *query.InitData, 1)
|
||||||
getQueryInitDataAsync(ctx, w, initDataChan, args)
|
getQueryInitDataAsync(ctx, w, initDataChan, args)
|
||||||
|
|
||||||
if interactiveMode {
|
if interactiveMode {
|
||||||
@@ -175,11 +176,11 @@ func loadWorkspacePromptingForVariables(ctx context.Context, spinner *spinner.Sp
|
|||||||
return workspace.Load(workspacePath)
|
return workspace.Load(workspacePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getQueryInitDataAsync(ctx context.Context, w *workspace.Workspace, initDataChan chan *db_common.QueryInitData, args []string) {
|
func getQueryInitDataAsync(ctx context.Context, w *workspace.Workspace, initDataChan chan *query.InitData, args []string) {
|
||||||
go func() {
|
go func() {
|
||||||
utils.LogTime("cmd.getQueryInitDataAsync start")
|
utils.LogTime("cmd.getQueryInitDataAsync start")
|
||||||
defer utils.LogTime("cmd.getQueryInitDataAsync end")
|
defer utils.LogTime("cmd.getQueryInitDataAsync end")
|
||||||
initData := db_common.NewQueryInitData()
|
initData := query.NewInitData()
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
initData.Result.Error = helpers.ToError(r)
|
initData.Result.Error = helpers.ToError(r)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/turbot/steampipe-plugin-sdk/logging"
|
"github.com/turbot/steampipe-plugin-sdk/logging"
|
||||||
"github.com/turbot/steampipe/cmdconfig"
|
"github.com/turbot/steampipe/cmdconfig"
|
||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
|
"github.com/turbot/steampipe/filepaths"
|
||||||
"github.com/turbot/steampipe/steampipeconfig"
|
"github.com/turbot/steampipe/steampipeconfig"
|
||||||
"github.com/turbot/steampipe/task"
|
"github.com/turbot/steampipe/task"
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
@@ -68,7 +69,7 @@ func InitCmd() {
|
|||||||
utils.LogTime("cmd.root.InitCmd start")
|
utils.LogTime("cmd.root.InitCmd start")
|
||||||
defer utils.LogTime("cmd.root.InitCmd end")
|
defer utils.LogTime("cmd.root.InitCmd end")
|
||||||
|
|
||||||
rootCmd.PersistentFlags().String(constants.ArgInstallDir, constants.DefaultInstallDir, fmt.Sprintf("Path to the Config Directory (defaults to %s)", constants.DefaultInstallDir))
|
rootCmd.PersistentFlags().String(constants.ArgInstallDir, filepaths.DefaultInstallDir, fmt.Sprintf("Path to the Config Directory (defaults to %s)", filepaths.DefaultInstallDir))
|
||||||
rootCmd.PersistentFlags().String(constants.ArgWorkspace, "", "Path to the workspace working directory")
|
rootCmd.PersistentFlags().String(constants.ArgWorkspace, "", "Path to the workspace working directory")
|
||||||
rootCmd.PersistentFlags().String(constants.ArgWorkspaceChDir, "", "Path to the workspace working directory")
|
rootCmd.PersistentFlags().String(constants.ArgWorkspaceChDir, "", "Path to the workspace working directory")
|
||||||
rootCmd.PersistentFlags().String(constants.ArgCloudHost, "cloud.steampipe.io", "Steampipe Cloud host")
|
rootCmd.PersistentFlags().String(constants.ArgCloudHost, "cloud.steampipe.io", "Steampipe Cloud host")
|
||||||
@@ -137,7 +138,7 @@ func setWorkspaceChDir() string {
|
|||||||
return workspaceChdir
|
return workspaceChdir
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateLogger :: create a hclog logger with the level specified by the SP_LOG env var
|
// create a hclog logger with the level specified by the SP_LOG env var
|
||||||
func createLogger() {
|
func createLogger() {
|
||||||
level := logging.LogLevel()
|
level := logging.LogLevel()
|
||||||
|
|
||||||
@@ -151,7 +152,7 @@ func createLogger() {
|
|||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SteampipeDir :: set the top level ~/.steampipe folder (creates if it doesnt exist)
|
// set the top level ~/.steampipe folder (creates if it doesnt exist)
|
||||||
func setInstallDir() {
|
func setInstallDir() {
|
||||||
utils.LogTime("cmd.root.setInstallDir start")
|
utils.LogTime("cmd.root.setInstallDir start")
|
||||||
defer utils.LogTime("cmd.root.setInstallDir end")
|
defer utils.LogTime("cmd.root.setInstallDir end")
|
||||||
@@ -162,7 +163,7 @@ func setInstallDir() {
|
|||||||
err = os.MkdirAll(installDir, 0755)
|
err = os.MkdirAll(installDir, 0755)
|
||||||
utils.FailOnErrorWithMessage(err, fmt.Sprintf("could not create installation directory: %s", installDir))
|
utils.FailOnErrorWithMessage(err, fmt.Sprintf("could not create installation directory: %s", installDir))
|
||||||
}
|
}
|
||||||
constants.SteampipeDir = installDir
|
filepaths.SteampipeDir = installDir
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddCommands() {
|
func AddCommands() {
|
||||||
|
|||||||
@@ -18,11 +18,10 @@ import (
|
|||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
"github.com/turbot/steampipe/db/db_local"
|
"github.com/turbot/steampipe/db/db_local"
|
||||||
"github.com/turbot/steampipe/display"
|
"github.com/turbot/steampipe/display"
|
||||||
"github.com/turbot/steampipe/plugin_manager"
|
"github.com/turbot/steampipe/pluginmanager"
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// serviceCmd :: Service management commands
|
|
||||||
func serviceCmd() *cobra.Command {
|
func serviceCmd() *cobra.Command {
|
||||||
var cmd = &cobra.Command{
|
var cmd = &cobra.Command{
|
||||||
Use: "service [command]",
|
Use: "service [command]",
|
||||||
@@ -43,7 +42,7 @@ connection from any Postgres compatible database client.`,
|
|||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// serviceStartCmd :: handler for service start
|
// handler for service start
|
||||||
func serviceStartCmd() *cobra.Command {
|
func serviceStartCmd() *cobra.Command {
|
||||||
var cmd = &cobra.Command{
|
var cmd = &cobra.Command{
|
||||||
Use: "start",
|
Use: "start",
|
||||||
@@ -91,7 +90,7 @@ Report current status of the Steampipe database service.`,
|
|||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// serviceStopCmd :: handler for service stop
|
// handler for service stop
|
||||||
func serviceStopCmd() *cobra.Command {
|
func serviceStopCmd() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "stop",
|
Use: "stop",
|
||||||
@@ -109,7 +108,7 @@ func serviceStopCmd() *cobra.Command {
|
|||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// serviceRestartCmd :: restarts the database service
|
// restarts the database service
|
||||||
func serviceRestartCmd() *cobra.Command {
|
func serviceRestartCmd() *cobra.Command {
|
||||||
var cmd = &cobra.Command{
|
var cmd = &cobra.Command{
|
||||||
Use: "restart",
|
Use: "restart",
|
||||||
@@ -147,7 +146,7 @@ func runServiceStartCmd(cmd *cobra.Command, args []string) {
|
|||||||
|
|
||||||
port := viper.GetInt(constants.ArgPort)
|
port := viper.GetInt(constants.ArgPort)
|
||||||
if port < 1 || port > 65535 {
|
if port < 1 || port > 65535 {
|
||||||
panic("Invalid Port :: MUST be within range (1:65535)")
|
panic("Invalid port - must be within range (1:65535)")
|
||||||
}
|
}
|
||||||
|
|
||||||
listen := db_local.StartListenType(viper.GetString(constants.ArgListenAddress))
|
listen := db_local.StartListenType(viper.GetString(constants.ArgListenAddress))
|
||||||
@@ -329,7 +328,7 @@ func runServiceStatusCmd(cmd *cobra.Command, args []string) {
|
|||||||
showAllStatus(cmd.Context())
|
showAllStatus(cmd.Context())
|
||||||
} else {
|
} else {
|
||||||
dbState, dbStateErr := db_local.GetState()
|
dbState, dbStateErr := db_local.GetState()
|
||||||
pmState, pmStateErr := plugin_manager.LoadPluginManagerState()
|
pmState, pmStateErr := pluginmanager.LoadPluginManagerState()
|
||||||
|
|
||||||
if dbStateErr != nil || pmStateErr != nil {
|
if dbStateErr != nil || pmStateErr != nil {
|
||||||
utils.ShowError(composeStateError(dbStateErr, pmStateErr))
|
utils.ShowError(composeStateError(dbStateErr, pmStateErr))
|
||||||
@@ -502,7 +501,7 @@ func getServiceProcessDetails(process *psutils.Process) (string, string, string,
|
|||||||
return fmt.Sprintf("%d", process.Pid), installDir, port, listenType
|
return fmt.Sprintf("%d", process.Pid), installDir, port, listenType
|
||||||
}
|
}
|
||||||
|
|
||||||
func printStatus(dbState *db_local.RunningDBInstanceInfo, pmState *plugin_manager.PluginManagerState) {
|
func printStatus(dbState *db_local.RunningDBInstanceInfo, pmState *pluginmanager.PluginManagerState) {
|
||||||
if dbState == nil && !pmState.Running {
|
if dbState == nil && !pmState.Running {
|
||||||
fmt.Println("Service is not running")
|
fmt.Println("Service is not running")
|
||||||
return
|
return
|
||||||
|
|||||||
3
cmdconfig/doc.go
Normal file
3
cmdconfig/doc.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Package cmd_config contains helper functions to support constructing Cobra commands, validating arguments
|
||||||
|
// and populating Viper config management
|
||||||
|
package cmdconfig
|
||||||
@@ -7,21 +7,9 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/turbot/go-kit/types"
|
"github.com/turbot/go-kit/types"
|
||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
|
"github.com/turbot/steampipe/filepaths"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitViper initializes and configures an instance of viper
|
|
||||||
func InitViper() {
|
|
||||||
v := viper.GetViper()
|
|
||||||
// set defaults
|
|
||||||
v.Set(constants.ConfigKeyShowInteractiveOutput, 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
|
// Viper fetches the global viper instance
|
||||||
func Viper() *viper.Viper {
|
func Viper() *viper.Viper {
|
||||||
return viper.GetViper()
|
return viper.GetViper()
|
||||||
@@ -39,7 +27,7 @@ func SetViperDefaults(configMap map[string]interface{}) {
|
|||||||
func setBaseDefaults() {
|
func setBaseDefaults() {
|
||||||
defaults := map[string]interface{}{
|
defaults := map[string]interface{}{
|
||||||
constants.ArgUpdateCheck: true,
|
constants.ArgUpdateCheck: true,
|
||||||
constants.ArgInstallDir: constants.DefaultInstallDir,
|
constants.ArgInstallDir: filepaths.DefaultInstallDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range defaults {
|
for k, v := range defaults {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package connection_watcher
|
package connectionwatcher
|
||||||
|
|
||||||
import (
|
import (
|
||||||
pb "github.com/turbot/steampipe/plugin_manager/grpc/proto"
|
pb "github.com/turbot/steampipe/pluginmanager/grpc/proto"
|
||||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package connection_watcher
|
package connectionwatcher
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -10,7 +10,8 @@ import (
|
|||||||
"github.com/turbot/steampipe/cmdconfig"
|
"github.com/turbot/steampipe/cmdconfig"
|
||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
"github.com/turbot/steampipe/db/db_local"
|
"github.com/turbot/steampipe/db/db_local"
|
||||||
pb "github.com/turbot/steampipe/plugin_manager/grpc/proto"
|
"github.com/turbot/steampipe/filepaths"
|
||||||
|
pb "github.com/turbot/steampipe/pluginmanager/grpc/proto"
|
||||||
"github.com/turbot/steampipe/steampipeconfig"
|
"github.com/turbot/steampipe/steampipeconfig"
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
)
|
)
|
||||||
@@ -29,7 +30,7 @@ func NewConnectionWatcher(onConnectionChanged func(configMap map[string]*pb.Conn
|
|||||||
}
|
}
|
||||||
|
|
||||||
watcherOptions := &utils.WatcherOptions{
|
watcherOptions := &utils.WatcherOptions{
|
||||||
Directories: []string{constants.ConfigDir()},
|
Directories: []string{filepaths.ConfigDir()},
|
||||||
Include: filehelpers.InclusionsFromExtensions([]string{constants.ConfigExtension}),
|
Include: filehelpers.InclusionsFromExtensions([]string{constants.ConfigExtension}),
|
||||||
ListFlag: filehelpers.FilesRecursive,
|
ListFlag: filehelpers.FilesRecursive,
|
||||||
|
|
||||||
2
connectionwatcher/doc.go
Normal file
2
connectionwatcher/doc.go
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// Package connection_watcher contains logic and types to support file-watching Steampipe connection config
|
||||||
|
package connectionwatcher
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package constants
|
package constants
|
||||||
|
|
||||||
// Application constants
|
// Application constants
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AppName = "steampipe"
|
AppName = "steampipe"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package constants
|
package constants
|
||||||
|
|
||||||
// ParallelControlMultiplier is used to determine the nbumber of goroutines to start for the control run
|
const (
|
||||||
// this is a multiplier for the max db connections which are configred
|
// ControlQueryCancellationTimeoutSecs is maximum number of seconds to wait for control queries to finish cancelling
|
||||||
const ParallelControlMultiplier = 1
|
ControlQueryCancellationTimeoutSecs = 30
|
||||||
|
// MaxControlRunAttempts determines how many time should a cotnrol run should be retried
|
||||||
// The maximum number of seconds to wait for control queries to finish cancelling
|
// in the case of a GRPC connectivity error
|
||||||
const QueryCancellationTimeout = 30
|
MaxControlRunAttempts = 2
|
||||||
|
)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
// dbClient constants
|
// dbClient constants
|
||||||
const (
|
const (
|
||||||
// the number of clients to initialize in parallel
|
// MaxParallelClientInits is the number of clients to initialize in parallel
|
||||||
// if we start initializing all clients together, it leads to bad performance on all
|
// if we start initializing all clients together, it leads to bad performance on all
|
||||||
MaxParallelClientInits = 3
|
MaxParallelClientInits = 3
|
||||||
)
|
)
|
||||||
@@ -41,7 +41,7 @@ const (
|
|||||||
|
|
||||||
// schema names
|
// schema names
|
||||||
const (
|
const (
|
||||||
// FunctionSchema :: schema container for all steampipe helper functions
|
// FunctionSchema is the schema container for all steampipe helper functions
|
||||||
FunctionSchema = "internal"
|
FunctionSchema = "internal"
|
||||||
|
|
||||||
// CommandSchema is the schema which is used to send commands to the FDW
|
// CommandSchema is the schema which is used to send commands to the FDW
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package constants
|
package constants
|
||||||
|
|
||||||
const DefaultSPCContent = `
|
// DefaultConnectionConfigContent is the content of the default connection config file, default.spc,
|
||||||
|
// that is created if it does not exist
|
||||||
|
const DefaultConnectionConfigContent = `
|
||||||
#
|
#
|
||||||
# For detailed descriptions, see the reference documentation
|
# For detailed descriptions, see the reference documentation
|
||||||
# at https://steampipe.io/docs/reference/cli-args
|
# at https://steampipe.io/docs/reference/cli-args
|
||||||
@@ -4,12 +4,11 @@ import "time"
|
|||||||
|
|
||||||
// Display constants
|
// Display constants
|
||||||
const (
|
const (
|
||||||
// SpinnerShowTimeout :: duration after which spinner should be shown
|
// SpinnerShowTimeout is the duration after which spinner should be shown
|
||||||
SpinnerShowTimeout = 1 * time.Second
|
SpinnerShowTimeout = 1 * time.Second
|
||||||
|
|
||||||
// Max Column Width
|
|
||||||
MaxColumnWidth = 1024
|
MaxColumnWidth = 1024
|
||||||
|
|
||||||
// what do we display for null column values
|
// NullString is the string which is displayed for null column values
|
||||||
NullString = "<null>"
|
NullString = "<null>"
|
||||||
)
|
)
|
||||||
|
|||||||
2
constants/doc.go
Normal file
2
constants/doc.go
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// Package constants contains constant values that are used throughout Steampipe
|
||||||
|
package constants
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package constants
|
package constants
|
||||||
|
|
||||||
// Known Environment Variables
|
// Environment Variables
|
||||||
const (
|
const (
|
||||||
EnvUpdateCheck = "STEAMPIPE_UPDATE_CHECK"
|
EnvUpdateCheck = "STEAMPIPE_UPDATE_CHECK"
|
||||||
EnvInstallDir = "STEAMPIPE_INSTALL_DIR"
|
EnvInstallDir = "STEAMPIPE_INSTALL_DIR"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package constants
|
package constants
|
||||||
|
|
||||||
// EEXISTS :: universal error string to denote that a resource already exists
|
// EEXISTS is the universal error string to denote that a resource already exists
|
||||||
const EEXISTS = "EEXISTS"
|
const EEXISTS = "EEXISTS"
|
||||||
|
|
||||||
// ENOTEXISTS :: universal error string to denote that a resource does not exists
|
// ENOTEXISTS is the universal error string to denote that a resource does not exists
|
||||||
const ENOTEXISTS = "ENOTEXISTS"
|
const ENOTEXISTS = "ENOTEXISTS"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package constants
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
// Metaquery commands
|
// Metaquery commands
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CmdTableList = ".tables" // List all tables
|
CmdTableList = ".tables" // List all tables
|
||||||
CmdOutput = ".output" // Set output mode
|
CmdOutput = ".output" // Set output mode
|
||||||
7
constants/plugin.go
Normal file
7
constants/plugin.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
const (
|
||||||
|
PluginAlreadyInstalled = "Already installed"
|
||||||
|
PluginLatestAlreadyInstalled = "Latest already installed"
|
||||||
|
PluginNotInstalled = "Not installed"
|
||||||
|
)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package runtime_constants
|
package runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// The runtime_constants package contains values which
|
// The runtime package contains values which
|
||||||
// are not constants during compilation, but should remain
|
// are not constants during compilation, but should remain
|
||||||
// constant during the duration of an execution of the binary
|
// constant during the duration of an execution of the binary
|
||||||
|
|
||||||
package runtime_constants
|
package runtime
|
||||||
@@ -89,9 +89,7 @@ func (e *ExecutionTree) Execute(ctx context.Context, client db_common.Client) in
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// the number of goroutines parallel to start
|
// the number of goroutines parallel to start
|
||||||
// - we start goroutines as a multiplier of the number of parallel database connections
|
maxParallelGoRoutines := viper.GetInt64(constants.ArgMaxParallel)
|
||||||
// so that go routines receive connections as soon as they are available
|
|
||||||
maxParallelGoRoutines := viper.GetInt64(constants.ArgMaxParallel) * constants.ParallelControlMultiplier
|
|
||||||
|
|
||||||
// to limit the number of parallel controls go routines started
|
// to limit the number of parallel controls go routines started
|
||||||
parallelismLock := semaphore.NewWeighted(maxParallelGoRoutines)
|
parallelismLock := semaphore.NewWeighted(maxParallelGoRoutines)
|
||||||
@@ -103,7 +101,7 @@ func (e *ExecutionTree) Execute(ctx context.Context, client db_common.Client) in
|
|||||||
if ctx.Err() != nil {
|
if ctx.Err() != nil {
|
||||||
// use a Background context - since the original context has been cancelled
|
// use a Background context - since the original context has been cancelled
|
||||||
// this lets us wait for the active control queries to cancel
|
// this lets us wait for the active control queries to cancel
|
||||||
c, cancel := context.WithTimeout(context.Background(), constants.QueryCancellationTimeout*time.Second)
|
c, cancel := context.WithTimeout(context.Background(), constants.ControlQueryCancellationTimeoutSecs*time.Second)
|
||||||
executeFinishWaitCtx = c
|
executeFinishWaitCtx = c
|
||||||
defer cancel()
|
defer cancel()
|
||||||
}
|
}
|
||||||
|
|||||||
22
control/export_data.go
Normal file
22
control/export_data.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package control
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/turbot/steampipe/control/controldisplay"
|
||||||
|
"github.com/turbot/steampipe/control/controlexecute"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ExportData struct {
|
||||||
|
ExecutionTree *controlexecute.ExecutionTree
|
||||||
|
ExportFormats []controldisplay.CheckExportTarget
|
||||||
|
ErrorsLock *sync.Mutex
|
||||||
|
Errors []error
|
||||||
|
WaitGroup *sync.WaitGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *ExportData) AddErrors(err []error) {
|
||||||
|
e.ErrorsLock.Lock()
|
||||||
|
e.Errors = append(e.Errors, err...)
|
||||||
|
e.ErrorsLock.Unlock()
|
||||||
|
}
|
||||||
15
control/init_data.go
Normal file
15
control/init_data.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package control
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/turbot/steampipe/db/db_common"
|
||||||
|
"github.com/turbot/steampipe/workspace"
|
||||||
|
)
|
||||||
|
|
||||||
|
type InitData struct {
|
||||||
|
Ctx context.Context
|
||||||
|
Workspace *workspace.Workspace
|
||||||
|
Client db_common.Client
|
||||||
|
Result *db_common.InitResult
|
||||||
|
}
|
||||||
@@ -11,8 +11,8 @@ import (
|
|||||||
"github.com/jackc/pgx/v4"
|
"github.com/jackc/pgx/v4"
|
||||||
"github.com/jackc/pgx/v4/stdlib"
|
"github.com/jackc/pgx/v4/stdlib"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
"github.com/turbot/steampipe/constants/runtime"
|
||||||
"github.com/turbot/steampipe/db/db_common"
|
"github.com/turbot/steampipe/db/db_common"
|
||||||
"github.com/turbot/steampipe/runtime_constants"
|
|
||||||
"github.com/turbot/steampipe/schema"
|
"github.com/turbot/steampipe/schema"
|
||||||
"github.com/turbot/steampipe/steampipeconfig"
|
"github.com/turbot/steampipe/steampipeconfig"
|
||||||
"golang.org/x/sync/semaphore"
|
"golang.org/x/sync/semaphore"
|
||||||
@@ -81,7 +81,7 @@ func establishConnection(ctx context.Context, connStr string) (*sql.DB, error) {
|
|||||||
connConfig, _ := pgx.ParseConfig(connStr)
|
connConfig, _ := pgx.ParseConfig(connStr)
|
||||||
connConfig.RuntimeParams = map[string]string{
|
connConfig.RuntimeParams = map[string]string{
|
||||||
// set an app name so that we can track connections from this execution
|
// set an app name so that we can track connections from this execution
|
||||||
"application_name": runtime_constants.PgClientAppName,
|
"application_name": runtime.PgClientAppName,
|
||||||
}
|
}
|
||||||
connStr = stdlib.RegisterConnConfig(connConfig)
|
connStr = stdlib.RegisterConnConfig(connConfig)
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
package db_common
|
|
||||||
|
|
||||||
type QueryInitData struct {
|
|
||||||
Queries []string
|
|
||||||
Workspace WorkspaceResourceProvider
|
|
||||||
Client Client
|
|
||||||
Result *InitResult
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewQueryInitData() *QueryInitData {
|
|
||||||
return &QueryInitData{Result: &InitResult{}}
|
|
||||||
}
|
|
||||||
@@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
"github.com/turbot/steampipe/db/db_common"
|
"github.com/turbot/steampipe/db/db_common"
|
||||||
"github.com/turbot/steampipe/display"
|
"github.com/turbot/steampipe/display"
|
||||||
|
"github.com/turbot/steampipe/filepaths"
|
||||||
"github.com/turbot/steampipe/ociinstaller"
|
"github.com/turbot/steampipe/ociinstaller"
|
||||||
"github.com/turbot/steampipe/ociinstaller/versionfile"
|
"github.com/turbot/steampipe/ociinstaller/versionfile"
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
@@ -44,7 +45,7 @@ func EnsureDBInstalled(ctx context.Context) (err error) {
|
|||||||
|
|
||||||
if IsInstalled() {
|
if IsInstalled() {
|
||||||
// check if the FDW need updating, and init the db id required
|
// check if the FDW need updating, and init the db id required
|
||||||
err := PrepareDb(ctx, spinner)
|
err := prepareDb(ctx, spinner)
|
||||||
display.StopSpinner(spinner)
|
display.StopSpinner(spinner)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -103,33 +104,6 @@ func EnsureDBInstalled(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrepareDb updates the FDW if needed, and inits the database if required
|
|
||||||
func PrepareDb(ctx context.Context, spinner *spinner.Spinner) error {
|
|
||||||
// check if FDW needs to be updated
|
|
||||||
if fdwNeedsUpdate() {
|
|
||||||
_, err := installFDW(ctx, false, spinner)
|
|
||||||
spinner.Stop()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("[TRACE] installFDW failed: %v", err)
|
|
||||||
return fmt.Errorf("Update steampipe-postgres-fdw... FAILED!")
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("%s was updated to %s. ", constants.Bold("steampipe-postgres-fdw"), constants.Bold(constants.FdwVersion))
|
|
||||||
fmt.Println()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if needsInit() {
|
|
||||||
spinner.Start()
|
|
||||||
display.UpdateSpinnerMessage(spinner, "Cleanup any Steampipe processes...")
|
|
||||||
killInstanceIfAny(ctx)
|
|
||||||
if err := runInstall(ctx, false, spinner); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsInstalled checks and reports whether the embedded database is installed and setup
|
// IsInstalled checks and reports whether the embedded database is installed and setup
|
||||||
func IsInstalled() bool {
|
func IsInstalled() bool {
|
||||||
utils.LogTime("db_local.IsInstalled start")
|
utils.LogTime("db_local.IsInstalled start")
|
||||||
@@ -162,6 +136,33 @@ func IsInstalled() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepareDb updates the FDW if needed, and inits the database if required
|
||||||
|
func prepareDb(ctx context.Context, spinner *spinner.Spinner) error {
|
||||||
|
// check if FDW needs to be updated
|
||||||
|
if fdwNeedsUpdate() {
|
||||||
|
_, err := installFDW(ctx, false, spinner)
|
||||||
|
spinner.Stop()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[TRACE] installFDW failed: %v", err)
|
||||||
|
return fmt.Errorf("Update steampipe-postgres-fdw... FAILED!")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%s was updated to %s. ", constants.Bold("steampipe-postgres-fdw"), constants.Bold(constants.FdwVersion))
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if needsInit() {
|
||||||
|
spinner.Start()
|
||||||
|
display.UpdateSpinnerMessage(spinner, "Cleanup any Steampipe processes...")
|
||||||
|
killInstanceIfAny(ctx)
|
||||||
|
if err := runInstall(ctx, false, spinner); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func fdwNeedsUpdate() bool {
|
func fdwNeedsUpdate() bool {
|
||||||
utils.LogTime("db_local.fdwNeedsUpdate start")
|
utils.LogTime("db_local.fdwNeedsUpdate start")
|
||||||
defer utils.LogTime("db_local.fdwNeedsUpdate end")
|
defer utils.LogTime("db_local.fdwNeedsUpdate end")
|
||||||
@@ -339,7 +340,7 @@ func startServiceForInstall(port int) (*psutils.Process, error) {
|
|||||||
"-c", fmt.Sprintf("cluster_name=%s", constants.AppName),
|
"-c", fmt.Sprintf("cluster_name=%s", constants.AppName),
|
||||||
|
|
||||||
// log directory
|
// log directory
|
||||||
"-c", fmt.Sprintf("log_directory=%s", constants.LogDir()),
|
"-c", fmt.Sprintf("log_directory=%s", filepaths.LogDir()),
|
||||||
|
|
||||||
// Data Directory
|
// Data Directory
|
||||||
"-D", getDataLocation())
|
"-D", getDataLocation())
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
|
|
||||||
"github.com/turbot/steampipe/db/db_common"
|
"github.com/turbot/steampipe/db/db_common"
|
||||||
"github.com/turbot/steampipe/plugin_manager"
|
"github.com/turbot/steampipe/pluginmanager"
|
||||||
"github.com/turbot/steampipe/steampipeconfig"
|
"github.com/turbot/steampipe/steampipeconfig"
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
)
|
)
|
||||||
@@ -125,7 +125,7 @@ func (c *LocalDbClient) updateConnectionMap() error {
|
|||||||
func getSchemaQueries(updates steampipeconfig.ConnectionDataMap, failures []*steampipeconfig.ValidationFailure) []string {
|
func getSchemaQueries(updates steampipeconfig.ConnectionDataMap, failures []*steampipeconfig.ValidationFailure) []string {
|
||||||
var schemaQueries []string
|
var schemaQueries []string
|
||||||
for connectionName, connectionData := range updates {
|
for connectionName, connectionData := range updates {
|
||||||
remoteSchema := plugin_manager.PluginFQNToSchemaName(connectionData.Plugin)
|
remoteSchema := pluginmanager.PluginFQNToSchemaName(connectionData.Plugin)
|
||||||
log.Printf("[TRACE] update connection %s, plugin Name %s, schema %s, schemaQueries %v\n ", connectionName, connectionData.Plugin, remoteSchema, schemaQueries)
|
log.Printf("[TRACE] update connection %s, plugin Name %s, schema %s, schemaQueries %v\n ", connectionName, connectionData.Plugin, remoteSchema, schemaQueries)
|
||||||
queries := updateConnectionQuery(connectionName, remoteSchema)
|
queries := updateConnectionQuery(connectionName, remoteSchema)
|
||||||
schemaQueries = append(schemaQueries, queries...)
|
schemaQueries = append(schemaQueries, queries...)
|
||||||
|
|||||||
@@ -6,13 +6,14 @@ import (
|
|||||||
|
|
||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
"github.com/turbot/steampipe/db/platform"
|
"github.com/turbot/steampipe/db/platform"
|
||||||
|
"github.com/turbot/steampipe/filepaths"
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ServiceExecutableRelativeLocation = "/db/12.1.0/postgres/bin/postgres"
|
const ServiceExecutableRelativeLocation = "/db/12.1.0/postgres/bin/postgres"
|
||||||
|
|
||||||
func databaseInstanceDir() string {
|
func databaseInstanceDir() string {
|
||||||
loc := filepath.Join(constants.DatabaseDir(), constants.DatabaseVersion)
|
loc := filepath.Join(filepaths.DatabaseDir(), constants.DatabaseVersion)
|
||||||
if _, err := os.Stat(loc); os.IsNotExist(err) {
|
if _, err := os.Stat(loc); os.IsNotExist(err) {
|
||||||
err = os.MkdirAll(loc, 0755)
|
err = os.MkdirAll(loc, 0755)
|
||||||
utils.FailOnErrorWithMessage(err, "could not create db version directory")
|
utils.FailOnErrorWithMessage(err, "could not create db version directory")
|
||||||
@@ -30,7 +31,7 @@ func getDatabaseLocation() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getDatabaseLogDirectory() string {
|
func getDatabaseLogDirectory() string {
|
||||||
loc := constants.LogDir()
|
loc := filepaths.LogDir()
|
||||||
if _, err := os.Stat(loc); os.IsNotExist(err) {
|
if _, err := os.Stat(loc); os.IsNotExist(err) {
|
||||||
err = os.MkdirAll(loc, 0755)
|
err = os.MkdirAll(loc, 0755)
|
||||||
utils.FailOnErrorWithMessage(err, "could not create postgres logging directory")
|
utils.FailOnErrorWithMessage(err, "could not create postgres logging directory")
|
||||||
@@ -111,5 +112,5 @@ func getLegacyPasswordFileLocation() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getPasswordFileLocation() string {
|
func getPasswordFileLocation() string {
|
||||||
return filepath.Join(constants.InternalDir(), ".passwd")
|
return filepath.Join(filepaths.InternalDir(), ".passwd")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/turbot/go-kit/helpers"
|
"github.com/turbot/go-kit/helpers"
|
||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
|
"github.com/turbot/steampipe/filepaths"
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ func (r *RunningDBInstanceInfo) Save() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return os.WriteFile(constants.RunningInfoFilePath(), content, 0644)
|
return os.WriteFile(filepaths.RunningInfoFilePath(), content, 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RunningDBInstanceInfo) String() string {
|
func (r *RunningDBInstanceInfo) String() string {
|
||||||
@@ -68,23 +69,23 @@ func loadRunningInstanceInfo() (*RunningDBInstanceInfo, error) {
|
|||||||
utils.LogTime("db.loadRunningInstanceInfo start")
|
utils.LogTime("db.loadRunningInstanceInfo start")
|
||||||
defer utils.LogTime("db.loadRunningInstanceInfo end")
|
defer utils.LogTime("db.loadRunningInstanceInfo end")
|
||||||
|
|
||||||
if !helpers.FileExists(constants.RunningInfoFilePath()) {
|
if !helpers.FileExists(filepaths.RunningInfoFilePath()) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fileContent, err := os.ReadFile(constants.RunningInfoFilePath())
|
fileContent, err := os.ReadFile(filepaths.RunningInfoFilePath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var info = new(RunningDBInstanceInfo)
|
var info = new(RunningDBInstanceInfo)
|
||||||
err = json.Unmarshal(fileContent, info)
|
err = json.Unmarshal(fileContent, info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[TRACE] failed to unmarshal database state file %s: %s\n", constants.RunningInfoFilePath(), err.Error())
|
log.Printf("[TRACE] failed to unmarshal database state file %s: %s\n", filepaths.RunningInfoFilePath(), err.Error())
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeRunningInstanceInfo() error {
|
func removeRunningInstanceInfo() error {
|
||||||
return os.Remove(constants.RunningInfoFilePath())
|
return os.Remove(filepaths.RunningInfoFilePath())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/turbot/go-kit/helpers"
|
"github.com/turbot/go-kit/helpers"
|
||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
|
"github.com/turbot/steampipe/filepaths"
|
||||||
|
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
)
|
)
|
||||||
@@ -36,7 +37,7 @@ func GetState() (*RunningDBInstanceInfo, error) {
|
|||||||
if !pidExists {
|
if !pidExists {
|
||||||
log.Printf("[TRACE] GetRunStatus - pid %v does not exist\n", info.Pid)
|
log.Printf("[TRACE] GetRunStatus - pid %v does not exist\n", info.Pid)
|
||||||
// nothing to do here
|
// nothing to do here
|
||||||
os.Remove(constants.RunningInfoFilePath())
|
os.Remove(filepaths.RunningInfoFilePath())
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/turbot/steampipe/db/db_common"
|
"github.com/turbot/steampipe/db/db_common"
|
||||||
"github.com/turbot/steampipe/plugin_manager"
|
"github.com/turbot/steampipe/filepaths"
|
||||||
|
"github.com/turbot/steampipe/pluginmanager"
|
||||||
|
|
||||||
psutils "github.com/shirou/gopsutil/process"
|
psutils "github.com/shirou/gopsutil/process"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
@@ -28,7 +29,7 @@ type StartResult struct {
|
|||||||
Error error
|
Error error
|
||||||
Status StartDbStatus
|
Status StartDbStatus
|
||||||
DbState *RunningDBInstanceInfo
|
DbState *RunningDBInstanceInfo
|
||||||
PluginManagerState *plugin_manager.PluginManagerState
|
PluginManagerState *pluginmanager.PluginManagerState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *StartResult) SetError(err error) *StartResult {
|
func (r *StartResult) SetError(err error) *StartResult {
|
||||||
@@ -92,7 +93,7 @@ func StartServices(ctx context.Context, port int, listen StartListenType, invoke
|
|||||||
res.Status = ServiceAlreadyRunning
|
res.Status = ServiceAlreadyRunning
|
||||||
}
|
}
|
||||||
|
|
||||||
res.PluginManagerState, res.Error = plugin_manager.LoadPluginManagerState()
|
res.PluginManagerState, res.Error = pluginmanager.LoadPluginManagerState()
|
||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
res.Status = ServiceFailedToStart
|
res.Status = ServiceFailedToStart
|
||||||
return res
|
return res
|
||||||
@@ -106,7 +107,7 @@ func StartServices(ctx context.Context, port int, listen StartListenType, invoke
|
|||||||
log.Printf("[WARN] plugin manager start() - failed to get steampipe executable path: %s", err)
|
log.Printf("[WARN] plugin manager start() - failed to get steampipe executable path: %s", err)
|
||||||
return res.SetError(err)
|
return res.SetError(err)
|
||||||
}
|
}
|
||||||
if err := plugin_manager.StartNewInstance(executable); err != nil {
|
if err := pluginmanager.StartNewInstance(executable); err != nil {
|
||||||
log.Printf("[WARN] StartServices plugin manager failed to start: %s", err)
|
log.Printf("[WARN] StartServices plugin manager failed to start: %s", err)
|
||||||
return res.SetError(err)
|
return res.SetError(err)
|
||||||
}
|
}
|
||||||
@@ -355,7 +356,7 @@ func createCmd(ctx context.Context, port int, listenAddresses string) *exec.Cmd
|
|||||||
"-c", fmt.Sprintf("cluster_name=%s", constants.AppName),
|
"-c", fmt.Sprintf("cluster_name=%s", constants.AppName),
|
||||||
|
|
||||||
// log directory
|
// log directory
|
||||||
"-c", fmt.Sprintf("log_directory=%s", constants.LogDir()),
|
"-c", fmt.Sprintf("log_directory=%s", filepaths.LogDir()),
|
||||||
|
|
||||||
// If ssl is off it doesnot matter what we pass in the ssl_cert_file and ssl_key_file
|
// If ssl is off it doesnot matter what we pass in the ssl_cert_file and ssl_key_file
|
||||||
// SSL will only get validated if the ssl is on
|
// SSL will only get validated if the ssl is on
|
||||||
@@ -366,7 +367,7 @@ func createCmd(ctx context.Context, port int, listenAddresses string) *exec.Cmd
|
|||||||
// Data Directory
|
// Data Directory
|
||||||
"-D", getDataLocation())
|
"-D", getDataLocation())
|
||||||
|
|
||||||
postgresCmd.Env = append(os.Environ(), fmt.Sprintf("STEAMPIPE_INSTALL_DIR=%s", constants.SteampipeDir))
|
postgresCmd.Env = append(os.Environ(), fmt.Sprintf("STEAMPIPE_INSTALL_DIR=%s", filepaths.SteampipeDir))
|
||||||
|
|
||||||
// Check if the /etc/ssl directory exist in os
|
// Check if the /etc/ssl directory exist in os
|
||||||
dirExist, _ := os.Stat(constants.SslConfDir)
|
dirExist, _ := os.Stat(constants.SslConfDir)
|
||||||
|
|||||||
@@ -12,9 +12,10 @@ import (
|
|||||||
"github.com/briandowns/spinner"
|
"github.com/briandowns/spinner"
|
||||||
psutils "github.com/shirou/gopsutil/process"
|
psutils "github.com/shirou/gopsutil/process"
|
||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
|
"github.com/turbot/steampipe/constants/runtime"
|
||||||
"github.com/turbot/steampipe/display"
|
"github.com/turbot/steampipe/display"
|
||||||
"github.com/turbot/steampipe/plugin_manager"
|
"github.com/turbot/steampipe/filepaths"
|
||||||
"github.com/turbot/steampipe/runtime_constants"
|
"github.com/turbot/steampipe/pluginmanager"
|
||||||
|
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
)
|
)
|
||||||
@@ -83,7 +84,7 @@ func GetCountOfThirdPartyClients(ctx context.Context) (i int, e error) {
|
|||||||
clientCount := 0
|
clientCount := 0
|
||||||
// get the total number of connected clients
|
// get the total number of connected clients
|
||||||
// which are not us - determined by the unique application_name client parameter
|
// which are not us - determined by the unique application_name client parameter
|
||||||
row := rootClient.QueryRow("select count(*) from pg_stat_activity where client_port IS NOT NULL and backend_type='client backend' and application_name != $1;", runtime_constants.PgClientAppName)
|
row := rootClient.QueryRow("select count(*) from pg_stat_activity where client_port IS NOT NULL and backend_type='client backend' and application_name != $1;", runtime.PgClientAppName)
|
||||||
row.Scan(&clientCount)
|
row.Scan(&clientCount)
|
||||||
// clientCount can never be zero, since the client we are using to run the query counts as a client
|
// clientCount can never be zero, since the client we are using to run the query counts as a client
|
||||||
// deduct the open connections in the pool of this client
|
// deduct the open connections in the pool of this client
|
||||||
@@ -97,14 +98,14 @@ func StopServices(force bool, invoker constants.Invoker, spinner *spinner.Spinne
|
|||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if e == nil {
|
if e == nil {
|
||||||
os.Remove(constants.RunningInfoFilePath())
|
os.Remove(filepaths.RunningInfoFilePath())
|
||||||
}
|
}
|
||||||
utils.LogTime("db_local.StopDB end")
|
utils.LogTime("db_local.StopDB end")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// stop the plugin manager
|
// stop the plugin manager
|
||||||
// this means it may be stopped even if we fail to stop the service - that is ok - we will restart it if needed
|
// this means it may be stopped even if we fail to stop the service - that is ok - we will restart it if needed
|
||||||
pluginManagerStopError := plugin_manager.Stop()
|
pluginManagerStopError := pluginmanager.Stop()
|
||||||
|
|
||||||
// stop the DB Service
|
// stop the DB Service
|
||||||
stopResult, dbStopError := stopDBService(spinner, force)
|
stopResult, dbStopError := stopDBService(spinner, force)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ShowPaged :: displays the `content` in a system dependent pager
|
// ShowPaged displays the `content` in a system dependent pager
|
||||||
func ShowPaged(content string) {
|
func ShowPaged(content string) {
|
||||||
if isPagerNeeded(content) && (runtime.GOOS == "darwin" || runtime.GOOS == "linux") {
|
if isPagerNeeded(content) && (runtime.GOOS == "darwin" || runtime.GOOS == "linux") {
|
||||||
nixPager(content)
|
nixPager(content)
|
||||||
|
|||||||
@@ -9,10 +9,6 @@ import (
|
|||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ALREADY_INSTALLED = "Already installed"
|
|
||||||
const LATEST_ALREADY_INSTALLED = "Latest already installed"
|
|
||||||
const NOT_INSTALLED = "Not installed"
|
|
||||||
|
|
||||||
type InstallReport struct {
|
type InstallReport struct {
|
||||||
Skipped bool
|
Skipped bool
|
||||||
Plugin string
|
Plugin string
|
||||||
@@ -66,7 +62,7 @@ func (i *InstallReport) String() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints out the installation reports onto the console
|
// PrintInstallReports Prints out the installation reports onto the console
|
||||||
func PrintInstallReports(reports []InstallReport, isUpdateReport bool) {
|
func PrintInstallReports(reports []InstallReport, isUpdateReport bool) {
|
||||||
installedOrUpdated := []InstallReport{}
|
installedOrUpdated := []InstallReport{}
|
||||||
canBeInstalled := []InstallReport{}
|
canBeInstalled := []InstallReport{}
|
||||||
@@ -76,9 +72,9 @@ func PrintInstallReports(reports []InstallReport, isUpdateReport bool) {
|
|||||||
report.IsUpdateReport = isUpdateReport
|
report.IsUpdateReport = isUpdateReport
|
||||||
if !report.Skipped {
|
if !report.Skipped {
|
||||||
installedOrUpdated = append(installedOrUpdated, report)
|
installedOrUpdated = append(installedOrUpdated, report)
|
||||||
} else if report.SkipReason == NOT_INSTALLED {
|
} else if report.SkipReason == constants.PluginNotInstalled {
|
||||||
canBeInstalled = append(canBeInstalled, report)
|
canBeInstalled = append(canBeInstalled, report)
|
||||||
} else if report.SkipReason == ALREADY_INSTALLED {
|
} else if report.SkipReason == constants.PluginAlreadyInstalled {
|
||||||
canBeUpdated = append(canBeUpdated, report)
|
canBeUpdated = append(canBeUpdated, report)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package constants
|
package filepaths
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
// Constants for Config
|
// Constants for Config
|
||||||
const (
|
const (
|
||||||
DefaultInstallDir = "~/.steampipe"
|
DefaultInstallDir = "~/.steampipe"
|
||||||
ConnectionsStateFileName = "connection.json"
|
connectionsStateFileName = "connection.json"
|
||||||
versionFileName = "versions.json"
|
versionFileName = "versions.json"
|
||||||
databaseRunningInfoFileName = "steampipe.json"
|
databaseRunningInfoFileName = "steampipe.json"
|
||||||
pluginManagerStateFileName = "plugin_manager.json"
|
pluginManagerStateFileName = "plugin_manager.json"
|
||||||
@@ -40,7 +40,7 @@ func PluginDir() string {
|
|||||||
|
|
||||||
// ConnectionStatePath returns the path of the connections state file
|
// ConnectionStatePath returns the path of the connections state file
|
||||||
func ConnectionStatePath() string {
|
func ConnectionStatePath() string {
|
||||||
return filepath.Join(InternalDir(), ConnectionsStateFileName)
|
return filepath.Join(InternalDir(), connectionsStateFileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigDir returns the path to the config directory (creates if missing)
|
// ConfigDir returns the path to the config directory (creates if missing)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package constants
|
package filepaths
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path"
|
"path"
|
||||||
@@ -14,7 +14,6 @@ const (
|
|||||||
ModFileName = "mod.sp"
|
ModFileName = "mod.sp"
|
||||||
DefaultVarsFileName = "steampipe.spvars"
|
DefaultVarsFileName = "steampipe.spvars"
|
||||||
WorkspaceLockFileName = ".mod.cache.json"
|
WorkspaceLockFileName = ".mod.cache.json"
|
||||||
MaxControlRunAttempts = 2
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func WorkspaceModPath(workspacePath string) string {
|
func WorkspaceModPath(workspacePath string) string {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package autocomplete
|
package interactive
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -47,7 +47,7 @@ func GetTableAutoCompleteSuggestions(schema *schema.Metadata, connectionMap *ste
|
|||||||
// add qualified names of all tables
|
// add qualified names of all tables
|
||||||
for tableName := range schemaDetails {
|
for tableName := range schemaDetails {
|
||||||
if !isTemporarySchema {
|
if !isTemporarySchema {
|
||||||
qualifiedTablesToAdd = append(qualifiedTablesToAdd, fmt.Sprintf("%s.%s", schemaName, escapeIfRequired(tableName)))
|
qualifiedTablesToAdd = append(qualifiedTablesToAdd, fmt.Sprintf("%s.%s", schemaName, sanitiseTableName(tableName)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,11 +77,11 @@ func GetTableAutoCompleteSuggestions(schema *schema.Metadata, connectionMap *ste
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, table := range unqualifiedTablesToAdd {
|
for _, table := range unqualifiedTablesToAdd {
|
||||||
s = append(s, prompt.Suggest{Text: table, Description: "Table", Output: escapeIfRequired(table)})
|
s = append(s, prompt.Suggest{Text: table, Description: "Table", Output: sanitiseTableName(table)})
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, table := range qualifiedTablesToAdd {
|
for _, table := range qualifiedTablesToAdd {
|
||||||
s = append(s, prompt.Suggest{Text: table, Description: "Table", Output: escapeIfRequired(table)})
|
s = append(s, prompt.Suggest{Text: table, Description: "Table", Output: sanitiseTableName(table)})
|
||||||
}
|
}
|
||||||
|
|
||||||
return s
|
return s
|
||||||
@@ -91,7 +91,7 @@ func stripVersionFromPluginName(pluginName string) string {
|
|||||||
return strings.Split(pluginName, "@")[0]
|
return strings.Split(pluginName, "@")[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func escapeIfRequired(strToEscape string) string {
|
func sanitiseTableName(strToEscape string) string {
|
||||||
tokens := utils.SplitByRune(strToEscape, '.')
|
tokens := utils.SplitByRune(strToEscape, '.')
|
||||||
escaped := []string{}
|
escaped := []string{}
|
||||||
for _, token := range tokens {
|
for _, token := range tokens {
|
||||||
@@ -12,15 +12,14 @@ import (
|
|||||||
"github.com/alecthomas/chroma/formatters"
|
"github.com/alecthomas/chroma/formatters"
|
||||||
"github.com/alecthomas/chroma/lexers"
|
"github.com/alecthomas/chroma/lexers"
|
||||||
"github.com/alecthomas/chroma/styles"
|
"github.com/alecthomas/chroma/styles"
|
||||||
"github.com/spf13/viper"
|
|
||||||
|
|
||||||
"github.com/c-bata/go-prompt"
|
"github.com/c-bata/go-prompt"
|
||||||
|
"github.com/spf13/viper"
|
||||||
"github.com/turbot/go-kit/helpers"
|
"github.com/turbot/go-kit/helpers"
|
||||||
"github.com/turbot/steampipe/autocomplete"
|
|
||||||
"github.com/turbot/steampipe/cmdconfig"
|
"github.com/turbot/steampipe/cmdconfig"
|
||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
"github.com/turbot/steampipe/db/db_common"
|
"github.com/turbot/steampipe/db/db_common"
|
||||||
"github.com/turbot/steampipe/display"
|
"github.com/turbot/steampipe/display"
|
||||||
|
"github.com/turbot/steampipe/query"
|
||||||
"github.com/turbot/steampipe/query/metaquery"
|
"github.com/turbot/steampipe/query/metaquery"
|
||||||
"github.com/turbot/steampipe/query/queryhistory"
|
"github.com/turbot/steampipe/query/queryhistory"
|
||||||
"github.com/turbot/steampipe/query/queryresult"
|
"github.com/turbot/steampipe/query/queryresult"
|
||||||
@@ -37,10 +36,9 @@ const (
|
|||||||
AfterPromptCloseRestart
|
AfterPromptCloseRestart
|
||||||
)
|
)
|
||||||
|
|
||||||
// InteractiveClient :: wrapper over *LocalClient and *prompt.Prompt along
|
// InteractiveClient is a wrapper over a LocalClient and a Prompt to facilitate interactive query prompt
|
||||||
// to facilitate interactive query prompt
|
|
||||||
type InteractiveClient struct {
|
type InteractiveClient struct {
|
||||||
initData *db_common.QueryInitData
|
initData *query.InitData
|
||||||
resultsStreamer *queryresult.ResultStreamer
|
resultsStreamer *queryresult.ResultStreamer
|
||||||
interactiveBuffer []string
|
interactiveBuffer []string
|
||||||
interactivePrompt *prompt.Prompt
|
interactivePrompt *prompt.Prompt
|
||||||
@@ -51,17 +49,14 @@ type InteractiveClient struct {
|
|||||||
cancelActiveQuery context.CancelFunc
|
cancelActiveQuery context.CancelFunc
|
||||||
cancelPrompt context.CancelFunc
|
cancelPrompt context.CancelFunc
|
||||||
// channel from which we read the result of the external initialisation process
|
// channel from which we read the result of the external initialisation process
|
||||||
initDataChan *chan *db_common.QueryInitData
|
initDataChan *chan *query.InitData
|
||||||
// channel used internally to pass the initialisation result
|
// channel used internally to pass the initialisation result
|
||||||
initResultChan chan *db_common.InitResult
|
initResultChan chan *db_common.InitResult
|
||||||
|
afterClose AfterPromptCloseAction
|
||||||
afterClose AfterPromptCloseAction
|
|
||||||
// lock while execution is occurring to avoid errors/warnings being shown
|
// lock while execution is occurring to avoid errors/warnings being shown
|
||||||
executionLock sync.Mutex
|
executionLock sync.Mutex
|
||||||
|
|
||||||
schemaMetadata *schema.Metadata
|
schemaMetadata *schema.Metadata
|
||||||
|
highlighter *Highlighter
|
||||||
highlighter *Highlighter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHighlighter(theme string) *Highlighter {
|
func getHighlighter(theme string) *Highlighter {
|
||||||
@@ -72,7 +67,7 @@ func getHighlighter(theme string) *Highlighter {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newInteractiveClient(initChan *chan *db_common.QueryInitData, resultsStreamer *queryresult.ResultStreamer) (*InteractiveClient, error) {
|
func newInteractiveClient(initChan *chan *query.InitData, resultsStreamer *queryresult.ResultStreamer) (*InteractiveClient, error) {
|
||||||
c := &InteractiveClient{
|
c := &InteractiveClient{
|
||||||
resultsStreamer: resultsStreamer,
|
resultsStreamer: resultsStreamer,
|
||||||
interactiveQueryHistory: queryhistory.New(),
|
interactiveQueryHistory: queryhistory.New(),
|
||||||
@@ -512,7 +507,7 @@ func (c *InteractiveClient) queryCompleter(d prompt.Document) []prompt.Suggest {
|
|||||||
if isFirstWord(text) {
|
if isFirstWord(text) {
|
||||||
// add all we know that can be the first words
|
// add all we know that can be the first words
|
||||||
|
|
||||||
//named queries
|
// named queries
|
||||||
s = append(s, c.namedQuerySuggestions()...)
|
s = append(s, c.namedQuerySuggestions()...)
|
||||||
// "select"
|
// "select"
|
||||||
s = append(s, prompt.Suggest{Text: "select", Output: "select"}, prompt.Suggest{Text: "with", Output: "with"})
|
s = append(s, prompt.Suggest{Text: "select", Output: "select"}, prompt.Suggest{Text: "with", Output: "with"})
|
||||||
@@ -523,9 +518,8 @@ func (c *InteractiveClient) queryCompleter(d prompt.Document) []prompt.Suggest {
|
|||||||
} else if metaquery.IsMetaQuery(text) {
|
} else if metaquery.IsMetaQuery(text) {
|
||||||
client := c.client()
|
client := c.client()
|
||||||
suggestions := metaquery.Complete(&metaquery.CompleterInput{
|
suggestions := metaquery.Complete(&metaquery.CompleterInput{
|
||||||
Query: text,
|
Query: text,
|
||||||
Schema: c.schemaMetadata,
|
TableSuggestions: GetTableAutoCompleteSuggestions(c.schemaMetadata, client.ConnectionMap()),
|
||||||
Connections: client.ConnectionMap(),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
s = append(s, suggestions...)
|
s = append(s, suggestions...)
|
||||||
@@ -534,7 +528,7 @@ func (c *InteractiveClient) queryCompleter(d prompt.Document) []prompt.Suggest {
|
|||||||
|
|
||||||
// only add table suggestions if the client is initialised
|
// only add table suggestions if the client is initialised
|
||||||
if queryInfo.EditingTable && c.isInitialised() && c.schemaMetadata != nil {
|
if queryInfo.EditingTable && c.isInitialised() && c.schemaMetadata != nil {
|
||||||
s = append(s, autocomplete.GetTableAutoCompleteSuggestions(c.schemaMetadata, c.initData.Client.ConnectionMap())...)
|
s = append(s, GetTableAutoCompleteSuggestions(c.schemaMetadata, c.initData.Client.ConnectionMap())...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not sure this is working. comment out for now!
|
// Not sure this is working. comment out for now!
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ package interactive
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
"github.com/turbot/steampipe/db/db_common"
|
|
||||||
"github.com/turbot/steampipe/db/db_local"
|
"github.com/turbot/steampipe/db/db_local"
|
||||||
|
"github.com/turbot/steampipe/query"
|
||||||
"github.com/turbot/steampipe/query/queryresult"
|
"github.com/turbot/steampipe/query/queryresult"
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RunInteractivePrompt starts the interactive query prompt
|
// RunInteractivePrompt starts the interactive query prompt
|
||||||
func RunInteractivePrompt(initChan *chan *db_common.QueryInitData) (*queryresult.ResultStreamer, error) {
|
func RunInteractivePrompt(initChan *chan *query.InitData) (*queryresult.ResultStreamer, error) {
|
||||||
resultsStreamer := queryresult.NewResultStreamer()
|
resultsStreamer := queryresult.NewResultStreamer()
|
||||||
|
|
||||||
interactiveClient, err := newInteractiveClient(initChan, resultsStreamer)
|
interactiveClient, err := newInteractiveClient(initChan, resultsStreamer)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
"github.com/turbot/steampipe/steampipeconfig/input_vars"
|
"github.com/turbot/steampipe/steampipeconfig/inputvars"
|
||||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ func PromptForMissingVariables(ctx context.Context, missingVariables []*modconfi
|
|||||||
}
|
}
|
||||||
|
|
||||||
func promptForVariable(ctx context.Context, name, description string) (string, error) {
|
func promptForVariable(ctx context.Context, name, description string) (string, error) {
|
||||||
uiInput := &input_vars.UIInput{}
|
uiInput := &inputvars.UIInput{}
|
||||||
rawValue, err := uiInput.Input(ctx, &terraform.InputOpts{
|
rawValue, err := uiInput.Input(ctx, &terraform.InputOpts{
|
||||||
Id: fmt.Sprintf("var.%s", name),
|
Id: fmt.Sprintf("var.%s", name),
|
||||||
Query: fmt.Sprintf("var.%s", name),
|
Query: fmt.Sprintf("var.%s", name),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package mod_installer
|
package modinstaller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
package mod_installer
|
package modinstaller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Masterminds/semver"
|
"github.com/Masterminds/semver"
|
||||||
"github.com/turbot/steampipe/version_helpers"
|
"github.com/turbot/steampipe/versionhelpers"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getVersionSatisfyingConstraint(constraint *version_helpers.Constraints, availableVersions []*semver.Version) *semver.Version {
|
func getVersionSatisfyingConstraint(constraint *versionhelpers.Constraints, availableVersions []*semver.Version) *semver.Version {
|
||||||
// search the reverse sorted versions, finding the highest version which satisfies ALL constraints
|
// search the reverse sorted versions, finding the highest version which satisfies ALL constraints
|
||||||
for _, version := range availableVersions {
|
for _, version := range availableVersions {
|
||||||
if constraint.Check(version) {
|
if constraint.Check(version) {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package mod_installer
|
package modinstaller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/turbot/go-kit/helpers"
|
"github.com/turbot/go-kit/helpers"
|
||||||
@@ -1,50 +1,50 @@
|
|||||||
package mod_installer
|
package modinstaller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/Masterminds/semver"
|
"github.com/Masterminds/semver"
|
||||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||||
"github.com/turbot/steampipe/steampipeconfig/version_map"
|
"github.com/turbot/steampipe/steampipeconfig/versionmap"
|
||||||
"github.com/turbot/steampipe/version_helpers"
|
"github.com/turbot/steampipe/versionhelpers"
|
||||||
"github.com/xlab/treeprint"
|
"github.com/xlab/treeprint"
|
||||||
)
|
)
|
||||||
|
|
||||||
type InstallData struct {
|
type InstallData struct {
|
||||||
// record of the full dependency tree
|
// record of the full dependency tree
|
||||||
Lock *version_map.WorkspaceLock
|
Lock *versionmap.WorkspaceLock
|
||||||
NewLock *version_map.WorkspaceLock
|
NewLock *versionmap.WorkspaceLock
|
||||||
|
|
||||||
// ALL the available versions for each dependency mod(we populate this in a lazy fashion)
|
// ALL the available versions for each dependency mod(we populate this in a lazy fashion)
|
||||||
allAvailable version_map.VersionListMap
|
allAvailable versionmap.VersionListMap
|
||||||
|
|
||||||
// list of dependencies installed by recent install operation
|
// list of dependencies installed by recent install operation
|
||||||
Installed version_map.DependencyVersionMap
|
Installed versionmap.DependencyVersionMap
|
||||||
// list of dependencies which have been upgraded
|
// list of dependencies which have been upgraded
|
||||||
Upgraded version_map.DependencyVersionMap
|
Upgraded versionmap.DependencyVersionMap
|
||||||
// list of dependencies which have been downgraded
|
// list of dependencies which have been downgraded
|
||||||
Downgraded version_map.DependencyVersionMap
|
Downgraded versionmap.DependencyVersionMap
|
||||||
// list of dependencies which have been uninstalled
|
// list of dependencies which have been uninstalled
|
||||||
Uninstalled version_map.DependencyVersionMap
|
Uninstalled versionmap.DependencyVersionMap
|
||||||
WorkspaceMod *modconfig.Mod
|
WorkspaceMod *modconfig.Mod
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewInstallData(workspaceLock *version_map.WorkspaceLock, workspaceMod *modconfig.Mod) *InstallData {
|
func NewInstallData(workspaceLock *versionmap.WorkspaceLock, workspaceMod *modconfig.Mod) *InstallData {
|
||||||
return &InstallData{
|
return &InstallData{
|
||||||
Lock: workspaceLock,
|
Lock: workspaceLock,
|
||||||
WorkspaceMod: workspaceMod,
|
WorkspaceMod: workspaceMod,
|
||||||
NewLock: version_map.EmptyWorkspaceLock(workspaceLock),
|
NewLock: versionmap.EmptyWorkspaceLock(workspaceLock),
|
||||||
allAvailable: make(version_map.VersionListMap),
|
allAvailable: make(versionmap.VersionListMap),
|
||||||
Installed: make(version_map.DependencyVersionMap),
|
Installed: make(versionmap.DependencyVersionMap),
|
||||||
Upgraded: make(version_map.DependencyVersionMap),
|
Upgraded: make(versionmap.DependencyVersionMap),
|
||||||
Downgraded: make(version_map.DependencyVersionMap),
|
Downgraded: make(versionmap.DependencyVersionMap),
|
||||||
Uninstalled: make(version_map.DependencyVersionMap),
|
Uninstalled: make(versionmap.DependencyVersionMap),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAvailableUpdates returns a map of all installed mods which are not in the lock file
|
// GetAvailableUpdates returns a map of all installed mods which are not in the lock file
|
||||||
func (d *InstallData) GetAvailableUpdates() (version_map.DependencyVersionMap, error) {
|
func (d *InstallData) GetAvailableUpdates() (versionmap.DependencyVersionMap, error) {
|
||||||
res := make(version_map.DependencyVersionMap)
|
res := make(versionmap.DependencyVersionMap)
|
||||||
for parent, deps := range d.Lock.InstallCache {
|
for parent, deps := range d.Lock.InstallCache {
|
||||||
for name, resolvedConstraint := range deps {
|
for name, resolvedConstraint := range deps {
|
||||||
includePrerelease := resolvedConstraint.IsPrerelease()
|
includePrerelease := resolvedConstraint.IsPrerelease()
|
||||||
@@ -52,7 +52,7 @@ func (d *InstallData) GetAvailableUpdates() (version_map.DependencyVersionMap, e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
constraint, _ := version_helpers.NewConstraint(resolvedConstraint.Constraint)
|
constraint, _ := versionhelpers.NewConstraint(resolvedConstraint.Constraint)
|
||||||
var latestVersion = getVersionSatisfyingConstraint(constraint, availableVersions)
|
var latestVersion = getVersionSatisfyingConstraint(constraint, availableVersions)
|
||||||
if latestVersion.GreaterThan(resolvedConstraint.Version) {
|
if latestVersion.GreaterThan(resolvedConstraint.Version) {
|
||||||
res.Add(name, latestVersion, constraint.Original, parent)
|
res.Add(name, latestVersion, constraint.Original, parent)
|
||||||
@@ -72,7 +72,7 @@ func (d *InstallData) onModInstalled(dependency *ResolvedModRef, parent *modconf
|
|||||||
}
|
}
|
||||||
|
|
||||||
// addExisting is called when a dependency is satisfied by a mod which is already installed
|
// addExisting is called when a dependency is satisfied by a mod which is already installed
|
||||||
func (d *InstallData) addExisting(name string, version *semver.Version, constraint *version_helpers.Constraints, parent *modconfig.Mod) {
|
func (d *InstallData) addExisting(name string, version *semver.Version, constraint *versionhelpers.Constraints, parent *modconfig.Mod) {
|
||||||
// update lock
|
// update lock
|
||||||
parentPath := parent.GetModDependencyPath()
|
parentPath := parent.GetModDependencyPath()
|
||||||
d.NewLock.InstallCache.Add(name, version, constraint.Original, parentPath)
|
d.NewLock.InstallCache.Add(name, version, constraint.Original, parentPath)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package mod_installer
|
package modinstaller
|
||||||
|
|
||||||
type InstallOpts struct {
|
type InstallOpts struct {
|
||||||
WorkspacePath string
|
WorkspacePath string
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package mod_installer
|
package modinstaller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -11,9 +11,10 @@ import (
|
|||||||
"github.com/otiai10/copy"
|
"github.com/otiai10/copy"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
|
"github.com/turbot/steampipe/filepaths"
|
||||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||||
"github.com/turbot/steampipe/steampipeconfig/parse"
|
"github.com/turbot/steampipe/steampipeconfig/parse"
|
||||||
"github.com/turbot/steampipe/steampipeconfig/version_map"
|
"github.com/turbot/steampipe/steampipeconfig/versionmap"
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,7 +30,7 @@ type ModInstaller struct {
|
|||||||
// what command is being run
|
// what command is being run
|
||||||
command string
|
command string
|
||||||
// are dependencies being added to the workspace
|
// are dependencies being added to the workspace
|
||||||
mods version_map.VersionConstraintMap
|
mods versionmap.VersionConstraintMap
|
||||||
dryRun bool
|
dryRun bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ func NewModInstaller(opts *InstallOpts) (*ModInstaller, error) {
|
|||||||
i.workspaceMod = workspaceMod
|
i.workspaceMod = workspaceMod
|
||||||
|
|
||||||
// load lock file
|
// load lock file
|
||||||
workspaceLock, err := version_map.LoadWorkspaceLock(i.workspacePath)
|
workspaceLock, err := versionmap.LoadWorkspaceLock(i.workspacePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -75,7 +76,7 @@ func (i *ModInstaller) setModsPath() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
i.tmpPath = dir
|
i.tmpPath = dir
|
||||||
i.modsPath = constants.WorkspaceModPath(i.workspacePath)
|
i.modsPath = filepaths.WorkspaceModPath(i.workspacePath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +302,7 @@ func (i *ModInstaller) getCurrentlyInstalledVersionToUse(requiredModVersion *mod
|
|||||||
}
|
}
|
||||||
|
|
||||||
// determine if we should update this mod, and if so whether there is an update available
|
// determine if we should update this mod, and if so whether there is an update available
|
||||||
func (i *ModInstaller) canUpdateMod(installedVersion *version_map.ResolvedVersionConstraint, requiredModVersion *modconfig.ModVersionConstraint, forceUpdate bool) (bool, error) {
|
func (i *ModInstaller) canUpdateMod(installedVersion *versionmap.ResolvedVersionConstraint, requiredModVersion *modconfig.ModVersionConstraint, forceUpdate bool) (bool, error) {
|
||||||
// so should we update?
|
// so should we update?
|
||||||
// if forceUpdate is set or if the required version constraint is different to the locked version constraint, update
|
// if forceUpdate is set or if the required version constraint is different to the locked version constraint, update
|
||||||
// TODO check * vs latest - maybe need a custom equals?
|
// TODO check * vs latest - maybe need a custom equals?
|
||||||
@@ -421,7 +422,7 @@ func (i *ModInstaller) getDependencyDestPath(dependencyFullName string) string {
|
|||||||
return filepath.Join(i.modsPath, dependencyFullName)
|
return filepath.Join(i.modsPath, dependencyFullName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *ModInstaller) loadDependencyMod(modVersion *version_map.ResolvedVersionConstraint) (*modconfig.Mod, error) {
|
func (i *ModInstaller) loadDependencyMod(modVersion *versionmap.ResolvedVersionConstraint) (*modconfig.Mod, error) {
|
||||||
modPath := i.getDependencyDestPath(modconfig.ModVersionFullName(modVersion.Name, modVersion.Version))
|
modPath := i.getDependencyDestPath(modconfig.ModVersionFullName(modVersion.Name, modVersion.Version))
|
||||||
modDef, err := i.loadModfile(modPath, false)
|
modDef, err := i.loadModfile(modPath, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
package mod_installer
|
package modinstaller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||||
"github.com/turbot/steampipe/steampipeconfig/version_map"
|
"github.com/turbot/steampipe/steampipeconfig/versionmap"
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (i *ModInstaller) GetRequiredModVersionsFromArgs(modsArgs []string) (version_map.VersionConstraintMap, error) {
|
func (i *ModInstaller) GetRequiredModVersionsFromArgs(modsArgs []string) (versionmap.VersionConstraintMap, error) {
|
||||||
var errors []error
|
var errors []error
|
||||||
mods := make(version_map.VersionConstraintMap, len(modsArgs))
|
mods := make(versionmap.VersionConstraintMap, len(modsArgs))
|
||||||
for _, modArg := range modsArgs {
|
for _, modArg := range modsArgs {
|
||||||
// create mod version from arg
|
// create mod version from arg
|
||||||
modVersion, err := modconfig.NewModVersionConstraint(modArg)
|
modVersion, err := modconfig.NewModVersionConstraint(modArg)
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
package mod_installer
|
package modinstaller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||||
"github.com/turbot/steampipe/steampipeconfig/version_map"
|
"github.com/turbot/steampipe/steampipeconfig/versionmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (i *ModInstaller) Prune() (version_map.VersionListMap, error) {
|
func (i *ModInstaller) Prune() (versionmap.VersionListMap, error) {
|
||||||
unusedMods := i.installData.Lock.GetUnreferencedMods()
|
unusedMods := i.installData.Lock.GetUnreferencedMods()
|
||||||
// now delete any mod folders which are not in the lock file
|
// now delete any mod folders which are not in the lock file
|
||||||
for name, versions := range unusedMods {
|
for name, versions := range unusedMods {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package mod_installer
|
package modinstaller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package mod_installer
|
package modinstaller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Masterminds/semver"
|
"github.com/Masterminds/semver"
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||||
"github.com/turbot/steampipe/version_helpers"
|
"github.com/turbot/steampipe/versionhelpers"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ResolvedModRef is a struct to represent a resolved mod git reference
|
// ResolvedModRef is a struct to represent a resolved mod git reference
|
||||||
@@ -14,7 +14,7 @@ type ResolvedModRef struct {
|
|||||||
// the mod version
|
// the mod version
|
||||||
Version *semver.Version
|
Version *semver.Version
|
||||||
// the vestion constraint
|
// the vestion constraint
|
||||||
Constraint *version_helpers.Constraints
|
Constraint *versionhelpers.Constraints
|
||||||
// the Git branch/tag
|
// the Git branch/tag
|
||||||
GitReference plumbing.ReferenceName
|
GitReference plumbing.ReferenceName
|
||||||
// the file path for local mods
|
// the file path for local mods
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
package mod_installer
|
package modinstaller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/turbot/steampipe/constants"
|
"github.com/turbot/steampipe/constants"
|
||||||
"github.com/turbot/steampipe/steampipeconfig/version_map"
|
"github.com/turbot/steampipe/steampipeconfig/versionmap"
|
||||||
"github.com/turbot/steampipe/utils"
|
"github.com/turbot/steampipe/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ func BuildInstallSummary(installData *InstallData) string {
|
|||||||
return fmt.Sprintf("%s%s%s%s", installString, upgradeString, downgradeString, uninstallString)
|
return fmt.Sprintf("%s%s%s%s", installString, upgradeString, downgradeString, uninstallString)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInstallationResultString(items version_map.DependencyVersionMap, modDependencyPath string) (int, string) {
|
func getInstallationResultString(items versionmap.DependencyVersionMap, modDependencyPath string) (int, string) {
|
||||||
var res string
|
var res string
|
||||||
count := len(items.FlatMap())
|
count := len(items.FlatMap())
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
@@ -89,7 +89,7 @@ func BuildUninstallSummary(installData *InstallData) string {
|
|||||||
return fmt.Sprintf("\n%s %d %s:\n\n%s", verb, uninstallCount, utils.Pluralize("mod", uninstallCount), uninstalledTree.String())
|
return fmt.Sprintf("\n%s %d %s:\n\n%s", verb, uninstallCount, utils.Pluralize("mod", uninstallCount), uninstalledTree.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildPruneSummary(pruned version_map.VersionListMap) string {
|
func BuildPruneSummary(pruned versionmap.VersionListMap) string {
|
||||||
pruneCount := len(pruned.FlatMap())
|
pruneCount := len(pruned.FlatMap())
|
||||||
|
|
||||||
verb := getVerb(VerbPruned)
|
verb := getVerb(VerbPruned)
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user