mirror of
https://github.com/turbot/steampipe.git
synced 2025-12-19 18:12:43 -05:00
Warn users to not have mod.sp files in home directory. Closes #2321
This commit is contained in:
@@ -248,7 +248,7 @@ func initDashboard(ctx context.Context) *initialisation.InitData {
|
||||
func getInitData(ctx context.Context) *initialisation.InitData {
|
||||
w, errAndWarnings := workspace.LoadWorkspacePromptingForVariables(ctx)
|
||||
if errAndWarnings.GetError() != nil {
|
||||
return initialisation.NewErrorInitData(fmt.Errorf("failed to load workspace: %s", errAndWarnings.GetError().Error()))
|
||||
return initialisation.NewErrorInitData(fmt.Errorf("failed to load workspace: %s", error_helpers.HandleCancelError(errAndWarnings.GetError()).Error()))
|
||||
}
|
||||
|
||||
i := initialisation.NewInitData()
|
||||
|
||||
@@ -335,7 +335,11 @@ func runModInitCmd(cmd *cobra.Command, args []string) {
|
||||
|
||||
// helpers
|
||||
func createWorkspaceMod(ctx context.Context, cmd *cobra.Command, workspacePath string) (*modconfig.Mod, error) {
|
||||
if !modinstaller.ValidateModLocation(ctx, workspacePath) {
|
||||
cancel, err := modinstaller.ValidateModLocation(ctx, workspacePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !cancel {
|
||||
return nil, fmt.Errorf("mod %s cancelled", cmd.Name())
|
||||
}
|
||||
|
||||
@@ -355,7 +359,7 @@ func createWorkspaceMod(ctx context.Context, cmd *cobra.Command, workspacePath s
|
||||
|
||||
// load up the written mod file so that we get the updated
|
||||
// block ranges
|
||||
mod, err := parse.LoadModfile(workspacePath)
|
||||
mod, err = parse.LoadModfile(workspacePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -136,8 +136,11 @@ func runQueryCmd(cmd *cobra.Command, args []string) {
|
||||
// set config to indicate whether we are running an interactive query
|
||||
viper.Set(constants.ConfigKeyInteractive, interactiveMode)
|
||||
|
||||
// initialize the cancel handler - for context cancellation
|
||||
initCtx, cancel := context.WithCancel(ctx)
|
||||
contexthelpers.StartCancelHandler(cancel)
|
||||
// start the initializer
|
||||
initData := query.NewInitData(ctx, args)
|
||||
initData := query.NewInitData(initCtx, args)
|
||||
if initData.Result.Error != nil {
|
||||
exitCode = constants.ExitCodeInitializationFailed
|
||||
error_helpers.ShowError(ctx, initData.Result.Error)
|
||||
|
||||
2
go.mod
2
go.mod
@@ -43,7 +43,7 @@ require (
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.16.0
|
||||
github.com/stevenle/topsort v0.2.0
|
||||
github.com/turbot/go-kit v0.8.1
|
||||
github.com/turbot/go-kit v0.9.0-rc.0
|
||||
github.com/turbot/steampipe-cloud-sdk-go v0.6.0
|
||||
github.com/turbot/steampipe-plugin-sdk/v5 v5.6.0-rc.30
|
||||
github.com/xlab/treeprint v1.2.0
|
||||
|
||||
4
go.sum
4
go.sum
@@ -1092,8 +1092,8 @@ github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQ
|
||||
github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tombuildsstuff/giovanni v0.15.1/go.mod h1:0TZugJPEtqzPlMpuJHYfXY6Dq2uLPrXf98D2XQSxNbA=
|
||||
github.com/turbot/go-kit v0.8.1 h1:Su2RFhwiCAlbVXlG5f3w+t/8vpr1YXwfVfAIXlL+Xbc=
|
||||
github.com/turbot/go-kit v0.8.1/go.mod h1:AY17SDL/JnVnqUlQIc0Y9mQ2Gbtw0+IwEX4ErywH9bw=
|
||||
github.com/turbot/go-kit v0.9.0-rc.0 h1:lPVYl2UGC9fzvMSddg4+l17HT6N/CH7tBLxpeCIk53I=
|
||||
github.com/turbot/go-kit v0.9.0-rc.0/go.mod h1:AY17SDL/JnVnqUlQIc0Y9mQ2Gbtw0+IwEX4ErywH9bw=
|
||||
github.com/turbot/go-prompt v0.2.6-steampipe.0.0.20221028122246-eb118ec58d50 h1:zs87uA6QZsYLk4RRxDOIxt8ro/B2V6HzoMWm05Lo7ao=
|
||||
github.com/turbot/go-prompt v0.2.6-steampipe.0.0.20221028122246-eb118ec58d50/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7FVlAwDAVw=
|
||||
github.com/turbot/steampipe-cloud-sdk-go v0.6.0 h1:ufAxOpKS1uq7eejuE5sfEu1+d7QAd0RBjl8Bn6+mIs8=
|
||||
|
||||
@@ -2,11 +2,12 @@ package constants
|
||||
|
||||
// viper config keys
|
||||
const (
|
||||
ConfigKeyInteractive = "interactive"
|
||||
ConfigKeyActiveCommand = "cmd"
|
||||
ConfigKeyActiveCommandArgs = "cmd_args"
|
||||
ConfigInteractiveVariables = "interactive_var"
|
||||
ConfigKeyIsTerminalTTY = "is_terminal"
|
||||
ConfigKeyServerSearchPath = "server-search-path"
|
||||
ConfigKeyServerSearchPathPrefix = "server-search-path-prefix"
|
||||
ConfigKeyInteractive = "interactive"
|
||||
ConfigKeyActiveCommand = "cmd"
|
||||
ConfigKeyActiveCommandArgs = "cmd_args"
|
||||
ConfigInteractiveVariables = "interactive_var"
|
||||
ConfigKeyIsTerminalTTY = "is_terminal"
|
||||
ConfigKeyServerSearchPath = "server-search-path"
|
||||
ConfigKeyServerSearchPathPrefix = "server-search-path-prefix"
|
||||
ConfigKeyBypassHomeDirModfileWarning = "bypass-home-dir-modfile-warning"
|
||||
)
|
||||
|
||||
@@ -36,7 +36,7 @@ func NewInitData(ctx context.Context) *InitData {
|
||||
w, errAndWarnings := workspace.LoadWorkspacePromptingForVariables(ctx)
|
||||
if errAndWarnings.GetError() != nil {
|
||||
return &InitData{
|
||||
InitData: *initialisation.NewErrorInitData(fmt.Errorf("failed to load workspace: %s", errAndWarnings.GetError().Error())),
|
||||
InitData: *initialisation.NewErrorInitData(fmt.Errorf("failed to load workspace: %s", error_helpers.HandleCancelError(errAndWarnings.GetError()).Error())),
|
||||
}
|
||||
}
|
||||
i.Workspace = w
|
||||
|
||||
@@ -15,14 +15,18 @@ import (
|
||||
|
||||
// ValidateModLocation checks whether you are running from the home directory or if you have
|
||||
// a lot of non .sql and .sp file in your current directory, and asks for confirmation to continue
|
||||
func ValidateModLocation(ctx context.Context, workspacePath string) bool {
|
||||
func ValidateModLocation(ctx context.Context, workspacePath string) (bool, error) {
|
||||
const MaxResults = 10
|
||||
cmd := viper.Get(constants.ConfigKeyActiveCommand).(*cobra.Command)
|
||||
home, _ := os.UserHomeDir()
|
||||
|
||||
// check if running in home directory
|
||||
if workspacePath == home {
|
||||
return utils.UserConfirmation(fmt.Sprintf("%s: Creating a mod file in the home directory is not recommended.\nBest practice is to create a new directory and run %s from there.\nDo you want to continue? (y/n)", color.YellowString("Warning"), constants.Bold(fmt.Sprintf("steampipe mod %s", cmd.Name()))))
|
||||
cont, err := utils.UserConfirmation(ctx, fmt.Sprintf("%s: Creating a mod file in the home directory is not recommended.\nBest practice is to create a new directory and run %s from there.\nDo you want to continue? (y/n)", color.YellowString("Warning"), constants.Bold(fmt.Sprintf("steampipe mod %s", cmd.Name()))))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return cont, nil
|
||||
}
|
||||
// else check if running in a directory containing lot of sql and sp files
|
||||
fileList, _ := filehelpers.ListFiles(workspacePath, &filehelpers.ListOptions{
|
||||
@@ -31,8 +35,11 @@ func ValidateModLocation(ctx context.Context, workspacePath string) bool {
|
||||
MaxResults: MaxResults,
|
||||
})
|
||||
if len(fileList) == MaxResults {
|
||||
return utils.UserConfirmation(fmt.Sprintf("%s: Creating a mod file in a directory with a lot of files or subdirectories is not recommended.\nBest practice is to create a new directory and run %s from there.\nDo you want to continue? (y/n)", color.YellowString("Warning"), constants.Bold(fmt.Sprintf("steampipe mod %s", cmd.Name()))))
|
||||
cont, err := utils.UserConfirmation(ctx, fmt.Sprintf("%s: Creating a mod file in a directory with a lot of files or subdirectories is not recommended.\nBest practice is to create a new directory and run %s from there.\nDo you want to continue? (y/n)", color.YellowString("Warning"), constants.Bold(fmt.Sprintf("steampipe mod %s", cmd.Name()))))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return cont, nil
|
||||
}
|
||||
|
||||
return true
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -3,11 +3,13 @@ package query
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/turbot/steampipe/pkg/constants"
|
||||
"github.com/turbot/steampipe/pkg/db/db_client"
|
||||
"github.com/turbot/steampipe/pkg/error_helpers"
|
||||
"github.com/turbot/steampipe/pkg/export"
|
||||
"github.com/turbot/steampipe/pkg/initialisation"
|
||||
"github.com/turbot/steampipe/pkg/statushooks"
|
||||
@@ -32,6 +34,20 @@ func NewInitData(ctx context.Context, args []string) *InitData {
|
||||
InitData: *initialisation.NewInitData(),
|
||||
Loaded: make(chan struct{}),
|
||||
}
|
||||
// for interactive mode - do the home directory modfile check before init
|
||||
if viper.GetBool(constants.ConfigKeyInteractive) {
|
||||
path := viper.GetString(constants.ArgModLocation)
|
||||
modFilePath, _ := workspace.FindModFilePath(path)
|
||||
|
||||
// if the user cancels - no need to continue init
|
||||
if err := workspace.HomeDirectoryModfileCheck(ctx, filepath.Dir(modFilePath)); err != nil {
|
||||
i.Result.Error = err
|
||||
close(i.Loaded)
|
||||
return i
|
||||
}
|
||||
// home dir modfile already done - set the viper config
|
||||
viper.Set(constants.ConfigKeyBypassHomeDirModfileWarning, true)
|
||||
}
|
||||
go i.init(ctx, args)
|
||||
|
||||
return i
|
||||
@@ -89,7 +105,7 @@ func (i *InitData) init(ctx context.Context, args []string) {
|
||||
statushooks.SetStatus(ctx, "Loading workspace")
|
||||
w, errAndWarnings := workspace.LoadWorkspacePromptingForVariables(ctx)
|
||||
if errAndWarnings.GetError() != nil {
|
||||
i.Result.Error = fmt.Errorf("failed to load workspace: %s", errAndWarnings.GetError().Error())
|
||||
i.Result.Error = fmt.Errorf("failed to load workspace: %s", error_helpers.HandleCancelError(errAndWarnings.GetError()).Error())
|
||||
return
|
||||
}
|
||||
i.Result.AddWarnings(errAndWarnings.Warnings...)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package steampipeconfig
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
@@ -21,14 +22,14 @@ import (
|
||||
// if CreatePseudoResources flag is set, construct hcl resources for files with specific extensions
|
||||
// NOTE: it is an error if there is more than 1 mod defined, however zero mods is acceptable
|
||||
// - a default mod will be created assuming there are any resource files
|
||||
func LoadMod(modPath string, parseCtx *parse.ModParseContext) (mod *modconfig.Mod, errorsAndWarnings *error_helpers.ErrorAndWarnings) {
|
||||
func LoadMod(ctx context.Context, modPath string, parseCtx *parse.ModParseContext) (mod *modconfig.Mod, errorsAndWarnings *error_helpers.ErrorAndWarnings) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
errorsAndWarnings = error_helpers.NewErrorsAndWarning(helpers.ToError(r))
|
||||
}
|
||||
}()
|
||||
|
||||
mod, loadModResult := loadModDefinition(modPath, parseCtx)
|
||||
mod, loadModResult := loadModDefinition(ctx, modPath, parseCtx)
|
||||
if loadModResult.Error != nil {
|
||||
return nil, loadModResult
|
||||
}
|
||||
@@ -44,21 +45,21 @@ func LoadMod(modPath string, parseCtx *parse.ModParseContext) (mod *modconfig.Mo
|
||||
}
|
||||
|
||||
// load the mod dependencies
|
||||
if err := loadModDependencies(mod, parseCtx); err != nil {
|
||||
if err := loadModDependencies(ctx, mod, parseCtx); err != nil {
|
||||
return nil, error_helpers.NewErrorsAndWarning(err)
|
||||
}
|
||||
|
||||
// populate the resource maps of the current mod using the dependency mods
|
||||
mod.ResourceMaps = parseCtx.GetResourceMaps()
|
||||
// now load the mod resource hcl (
|
||||
mod, errorsAndWarnings = loadModResources(mod, parseCtx)
|
||||
mod, errorsAndWarnings = loadModResources(ctx, mod, parseCtx)
|
||||
|
||||
// add in any warnings from mod load
|
||||
errorsAndWarnings.AddWarning(loadModResult.Warnings...)
|
||||
return mod, errorsAndWarnings
|
||||
}
|
||||
|
||||
func loadModDefinition(modPath string, parseCtx *parse.ModParseContext) (mod *modconfig.Mod, errorsAndWarnings *error_helpers.ErrorAndWarnings) {
|
||||
func loadModDefinition(ctx context.Context, modPath string, parseCtx *parse.ModParseContext) (mod *modconfig.Mod, errorsAndWarnings *error_helpers.ErrorAndWarnings) {
|
||||
errorsAndWarnings = &error_helpers.ErrorAndWarnings{}
|
||||
// verify the mod folder exists
|
||||
_, err := os.Stat(modPath)
|
||||
@@ -88,7 +89,7 @@ func loadModDefinition(modPath string, parseCtx *parse.ModParseContext) (mod *mo
|
||||
return mod, errorsAndWarnings
|
||||
}
|
||||
|
||||
func loadModDependencies(parent *modconfig.Mod, parseCtx *parse.ModParseContext) error {
|
||||
func loadModDependencies(ctx context.Context, parent *modconfig.Mod, parseCtx *parse.ModParseContext) error {
|
||||
var errors []error
|
||||
if parent.Require != nil {
|
||||
// now ensure there is a lock file - if we have any mod dependnecies there MUST be a lock file -
|
||||
@@ -106,7 +107,7 @@ func loadModDependencies(parent *modconfig.Mod, parseCtx *parse.ModParseContext)
|
||||
if lockedVersion == nil {
|
||||
return fmt.Errorf("not all dependencies are installed - run 'steampipe mod install'")
|
||||
}
|
||||
if err := loadModDependency(lockedVersion, parseCtx); err != nil {
|
||||
if err := loadModDependency(ctx, lockedVersion, parseCtx); err != nil {
|
||||
errors = append(errors, err)
|
||||
}
|
||||
}
|
||||
@@ -115,7 +116,7 @@ func loadModDependencies(parent *modconfig.Mod, parseCtx *parse.ModParseContext)
|
||||
return error_helpers.CombineErrors(errors...)
|
||||
}
|
||||
|
||||
func loadModDependency(modDependency *versionmap.ResolvedVersionConstraint, parseCtx *parse.ModParseContext) error {
|
||||
func loadModDependency(ctx context.Context, modDependency *versionmap.ResolvedVersionConstraint, parseCtx *parse.ModParseContext) error {
|
||||
// dependency mods are installed to <mod path>/<mod nam>@version
|
||||
// for example workspace_folder/.steampipe/mods/github.com/turbot/steampipe-mod-aws-compliance@v1.0
|
||||
|
||||
@@ -135,7 +136,7 @@ func loadModDependency(modDependency *versionmap.ResolvedVersionConstraint, pars
|
||||
|
||||
childParseCtx := parse.NewChildModParseContext(parseCtx, modDependency, dependencyDir)
|
||||
// NOTE: pass in the version and dependency path of the mod - these must be set before it loads its dependencies
|
||||
dependencyMod, errAndWarnings := LoadMod(dependencyDir, childParseCtx)
|
||||
dependencyMod, errAndWarnings := LoadMod(ctx, dependencyDir, childParseCtx)
|
||||
if errAndWarnings.GetError() != nil {
|
||||
return errAndWarnings.GetError()
|
||||
}
|
||||
@@ -151,20 +152,20 @@ func loadModDependency(modDependency *versionmap.ResolvedVersionConstraint, pars
|
||||
|
||||
}
|
||||
|
||||
func loadModResources(mod *modconfig.Mod, parseCtx *parse.ModParseContext) (*modconfig.Mod, *error_helpers.ErrorAndWarnings) {
|
||||
func loadModResources(ctx context.Context, mod *modconfig.Mod, parseCtx *parse.ModParseContext) (*modconfig.Mod, *error_helpers.ErrorAndWarnings) {
|
||||
// if flag is set, create pseudo resources by mapping files
|
||||
var pseudoResources []modconfig.MappableResource
|
||||
var err error
|
||||
if parseCtx.CreatePseudoResources() {
|
||||
// now execute any pseudo-resource creations based on file mappings
|
||||
pseudoResources, err = createPseudoResources(mod, parseCtx)
|
||||
pseudoResources, err = createPseudoResources(ctx, mod, parseCtx)
|
||||
if err != nil {
|
||||
return nil, error_helpers.NewErrorsAndWarning(err)
|
||||
}
|
||||
}
|
||||
|
||||
// get the source files
|
||||
sourcePaths, err := getSourcePaths(mod.ModPath, parseCtx.ListOptions)
|
||||
sourcePaths, err := getSourcePaths(ctx, mod.ModPath, parseCtx.ListOptions)
|
||||
if err != nil {
|
||||
log.Printf("[WARN] LoadMod: failed to get mod file paths: %v\n", err)
|
||||
return nil, error_helpers.NewErrorsAndWarning(err)
|
||||
@@ -177,13 +178,13 @@ func loadModResources(mod *modconfig.Mod, parseCtx *parse.ModParseContext) (*mod
|
||||
}
|
||||
|
||||
// parse all hcl files (NOTE - this reads the CurrentMod out of ParseContext and adds to it)
|
||||
mod, errAndWarnings := parse.ParseMod(fileData, pseudoResources, parseCtx)
|
||||
mod, errAndWarnings := parse.ParseMod(ctx, fileData, pseudoResources, parseCtx)
|
||||
|
||||
return mod, errAndWarnings
|
||||
}
|
||||
|
||||
// LoadModResourceNames parses all hcl files in modPath and returns the names of all resources
|
||||
func LoadModResourceNames(mod *modconfig.Mod, parseCtx *parse.ModParseContext) (resources *modconfig.WorkspaceResources, err error) {
|
||||
func LoadModResourceNames(ctx context.Context, mod *modconfig.Mod, parseCtx *parse.ModParseContext) (resources *modconfig.WorkspaceResources, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = helpers.ToError(r)
|
||||
@@ -200,7 +201,7 @@ func LoadModResourceNames(mod *modconfig.Mod, parseCtx *parse.ModParseContext) (
|
||||
}
|
||||
|
||||
// now execute any pseudo-resource creations based on file mappings
|
||||
pseudoResources, err := createPseudoResources(mod, parseCtx)
|
||||
pseudoResources, err := createPseudoResources(ctx, mod, parseCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -212,7 +213,7 @@ func LoadModResourceNames(mod *modconfig.Mod, parseCtx *parse.ModParseContext) (
|
||||
}
|
||||
}
|
||||
|
||||
sourcePaths, err := getSourcePaths(mod.ModPath, parseCtx.ListOptions)
|
||||
sourcePaths, err := getSourcePaths(ctx, mod.ModPath, parseCtx.ListOptions)
|
||||
if err != nil {
|
||||
log.Printf("[WARN] LoadModResourceNames: failed to get mod file paths: %v\n", err)
|
||||
return nil, err
|
||||
@@ -240,8 +241,8 @@ func GetModFileExtensions() []string {
|
||||
// this will include hcl files (with .sp extension)
|
||||
// as well as any other files with extensions that have been registered for pseudo resource creation
|
||||
// (see steampipeconfig/modconfig/resource_type_map.go)
|
||||
func getSourcePaths(modPath string, listOpts *filehelpers.ListOptions) ([]string, error) {
|
||||
sourcePaths, err := filehelpers.ListFiles(modPath, listOpts)
|
||||
func getSourcePaths(ctx context.Context, modPath string, listOpts *filehelpers.ListOptions) ([]string, error) {
|
||||
sourcePaths, err := filehelpers.ListFilesWithContext(ctx, modPath, listOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -249,7 +250,7 @@ func getSourcePaths(modPath string, listOpts *filehelpers.ListOptions) ([]string
|
||||
}
|
||||
|
||||
// create pseudo-resources for any files whose extensions are registered
|
||||
func createPseudoResources(mod *modconfig.Mod, parseCtx *parse.ModParseContext) ([]modconfig.MappableResource, error) {
|
||||
func createPseudoResources(ctx context.Context, mod *modconfig.Mod, parseCtx *parse.ModParseContext) ([]modconfig.MappableResource, error) {
|
||||
// create list options to find pseudo resources
|
||||
listOpts := &filehelpers.ListOptions{
|
||||
Flags: parseCtx.ListOptions.Flags,
|
||||
@@ -257,7 +258,7 @@ func createPseudoResources(mod *modconfig.Mod, parseCtx *parse.ModParseContext)
|
||||
Exclude: parseCtx.ListOptions.Exclude,
|
||||
}
|
||||
// list all registered files
|
||||
sourcePaths, err := getSourcePaths(mod.ModPath, listOpts)
|
||||
sourcePaths, err := getSourcePaths(ctx, mod.ModPath, listOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@ import (
|
||||
"golang.org/x/exp/maps"
|
||||
)
|
||||
|
||||
func LoadVariableDefinitions(variablePath string, parseCtx *parse.ModParseContext) (*modconfig.ModVariableMap, error) {
|
||||
func LoadVariableDefinitions(ctx context.Context, variablePath string, parseCtx *parse.ModParseContext) (*modconfig.ModVariableMap, error) {
|
||||
// only load mod and variables blocks
|
||||
parseCtx.BlockTypes = []string{modconfig.BlockTypeVariable}
|
||||
mod, errAndWarnings := LoadMod(variablePath, parseCtx)
|
||||
mod, errAndWarnings := LoadMod(ctx, variablePath, parseCtx)
|
||||
if errAndWarnings.GetError() != nil {
|
||||
return nil, errAndWarnings.GetError()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package parse
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
@@ -97,7 +98,7 @@ func ParseModDefinition(modPath string, evalCtx *hcl.EvalContext) (*modconfig.Mo
|
||||
|
||||
// ParseMod parses all source hcl files for the mod path and associated resources, and returns the mod object
|
||||
// NOTE: the mod definition has already been parsed (or a default created) and is in opts.RunCtx.RootMod
|
||||
func ParseMod(fileData map[string][]byte, pseudoResources []modconfig.MappableResource, parseCtx *ModParseContext) (*modconfig.Mod, *error_helpers.ErrorAndWarnings) {
|
||||
func ParseMod(ctx context.Context, fileData map[string][]byte, pseudoResources []modconfig.MappableResource, parseCtx *ModParseContext) (*modconfig.Mod, *error_helpers.ErrorAndWarnings) {
|
||||
body, diags := ParseHclFiles(fileData)
|
||||
if diags.HasErrors() {
|
||||
return nil, error_helpers.NewErrorsAndWarning(plugin.DiagsToError("Failed to load all mod source files", diags))
|
||||
|
||||
@@ -161,7 +161,7 @@ func showNotificationsForCommand(cmd *cobra.Command, cmdArgs []string) bool {
|
||||
return !(isPluginUpdateCmd(cmd) ||
|
||||
IsPluginManagerCmd(cmd) ||
|
||||
isServiceStopCmd(cmd) ||
|
||||
isBatchQueryCmd(cmd, cmdArgs) ||
|
||||
IsBatchQueryCmd(cmd, cmdArgs) ||
|
||||
isCompletionCmd(cmd))
|
||||
}
|
||||
|
||||
@@ -177,6 +177,6 @@ func IsPluginManagerCmd(cmd *cobra.Command) bool {
|
||||
func isPluginUpdateCmd(cmd *cobra.Command) bool {
|
||||
return cmd.Name() == "update" && cmd.Parent() != nil && cmd.Parent().Name() == "plugin"
|
||||
}
|
||||
func isBatchQueryCmd(cmd *cobra.Command, cmdArgs []string) bool {
|
||||
func IsBatchQueryCmd(cmd *cobra.Command, cmdArgs []string) bool {
|
||||
return cmd.Name() == "query" && len(cmdArgs) > 0
|
||||
}
|
||||
|
||||
@@ -1,19 +1,37 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// UserConfirmation displays the warning message and asks the user for input
|
||||
// regarding whether to continue or not
|
||||
func UserConfirmation(warning string) bool {
|
||||
fmt.Println(warning)
|
||||
var userConfirm string
|
||||
_, err := fmt.Scanf("%s", &userConfirm)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
func UserConfirmation(ctx context.Context, warningMsg string) (bool, error) {
|
||||
fmt.Println(warningMsg)
|
||||
confirm := make(chan string, 1)
|
||||
confirmErr := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
defer func() {
|
||||
close(confirm)
|
||||
close(confirmErr)
|
||||
}()
|
||||
var userConfirm string
|
||||
_, err := fmt.Scanf("%s", &userConfirm)
|
||||
if err != nil {
|
||||
confirmErr <- err
|
||||
return
|
||||
}
|
||||
confirm <- userConfirm
|
||||
}()
|
||||
select {
|
||||
case err := <-confirmErr:
|
||||
return false, err
|
||||
case <-ctx.Done():
|
||||
return false, ctx.Err()
|
||||
case c := <-confirm:
|
||||
return strings.ToUpper(c) == "Y", nil
|
||||
}
|
||||
return strings.ToUpper(userConfirm) == "Y"
|
||||
}
|
||||
|
||||
@@ -10,10 +10,14 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
filehelpers "github.com/turbot/go-kit/files"
|
||||
"github.com/turbot/go-kit/filewatcher"
|
||||
"github.com/turbot/steampipe-plugin-sdk/v5/sperr"
|
||||
"github.com/turbot/steampipe/pkg/cmdconfig"
|
||||
"github.com/turbot/steampipe/pkg/constants"
|
||||
"github.com/turbot/steampipe/pkg/dashboard/dashboardevents"
|
||||
"github.com/turbot/steampipe/pkg/db/db_common"
|
||||
@@ -24,6 +28,7 @@ import (
|
||||
"github.com/turbot/steampipe/pkg/steampipeconfig/modconfig"
|
||||
"github.com/turbot/steampipe/pkg/steampipeconfig/parse"
|
||||
"github.com/turbot/steampipe/pkg/steampipeconfig/versionmap"
|
||||
"github.com/turbot/steampipe/pkg/task"
|
||||
"github.com/turbot/steampipe/pkg/utils"
|
||||
)
|
||||
|
||||
@@ -199,7 +204,7 @@ func (w *Workspace) ModfileExists() bool {
|
||||
// check whether the workspace contains a modfile
|
||||
// this will determine whether we load files recursively, and create pseudo resources for sql files
|
||||
func (w *Workspace) setModfileExists() {
|
||||
modFile, err := w.findModFilePath(w.Path)
|
||||
modFile, err := FindModFilePath(w.Path)
|
||||
modFileExists := err != ErrorNoModDefinition
|
||||
|
||||
if modFileExists {
|
||||
@@ -219,7 +224,8 @@ func (w *Workspace) setModfileExists() {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Workspace) findModFilePath(folder string) (string, error) {
|
||||
// TODO comment
|
||||
func FindModFilePath(folder string) (string, error) {
|
||||
folder, err := filepath.Abs(folder)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -238,12 +244,57 @@ func (w *Workspace) findModFilePath(folder string) (string, error) {
|
||||
// this typically means that we are already in the root directory
|
||||
return "", ErrorNoModDefinition
|
||||
}
|
||||
return w.findModFilePath(filepath.Dir(folder))
|
||||
return FindModFilePath(filepath.Dir(folder))
|
||||
}
|
||||
return modFilePath, nil
|
||||
}
|
||||
|
||||
func HomeDirectoryModfileCheck(ctx context.Context, workspacePath string) error {
|
||||
// bypass all the checks if ConfigKeyBypassHomeDirModfileWarning is set - it means home dir modfile check
|
||||
// has already happened before
|
||||
if viper.GetBool(constants.ConfigKeyBypassHomeDirModfileWarning) {
|
||||
return nil
|
||||
}
|
||||
// get the cmd and home dir
|
||||
cmd := viper.Get(constants.ConfigKeyActiveCommand).(*cobra.Command)
|
||||
home, _ := os.UserHomeDir()
|
||||
_, err := os.Stat(filepaths.ModFilePath(workspacePath))
|
||||
modFileExists := !os.IsNotExist(err)
|
||||
|
||||
// check if your workspace path is home dir and if modfile exists
|
||||
if workspacePath == home && modFileExists {
|
||||
|
||||
// for interactive query - ask for confirmation to continue
|
||||
if cmd.Name() == "query" && viper.GetBool(constants.ConfigKeyInteractive) {
|
||||
confirm, err := utils.UserConfirmation(ctx, fmt.Sprintf("%s: You have a mod.sp file in your home directory. This is not recommended.\nAs a result, steampipe will try to load all the files in home and its sub-directories, which can cause performance issues.\nBest practice is to put mod.sp files in their own directories.\nDo you still want to continue? (y/n)", color.YellowString("Warning")))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !confirm {
|
||||
return sperr.New("failed to load workspace: execution cancelled")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// for batch query mode - if output is table, just warn
|
||||
if task.IsBatchQueryCmd(cmd, viper.GetStringSlice(constants.ConfigKeyActiveCommandArgs)) && cmdconfig.Viper().GetString(constants.ArgOutput) == constants.OutputFormatTable {
|
||||
error_helpers.ShowWarning("You have a mod.sp file in your home directory. This is not recommended.\nAs a result, steampipe will try to load all the files in home and its sub-directories, which can cause performance issues.\nBest practice is to put mod.sp files in their own directories.\nHit Ctrl+C to stop.\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
// for other cmds - if home dir has modfile, just warn
|
||||
error_helpers.ShowWarning("You have a mod.sp file in your home directory. This is not recommended.\nAs a result, steampipe will try to load all the files in home and its sub-directories, which can cause performance issues.\nBest practice is to put mod.sp files in their own directories.\nHit Ctrl+C to stop.\n")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *Workspace) loadWorkspaceMod(ctx context.Context) *error_helpers.ErrorAndWarnings {
|
||||
// check if your workspace path is home dir and if modfile exists - if yes then warn and ask user to continue or not
|
||||
if err := HomeDirectoryModfileCheck(ctx, w.Path); err != nil {
|
||||
return error_helpers.NewErrorsAndWarning(err)
|
||||
}
|
||||
|
||||
// resolve values of all input variables
|
||||
// we WILL validate missing variables when loading
|
||||
validateMissing := true
|
||||
@@ -270,7 +321,8 @@ func (w *Workspace) loadWorkspaceMod(ctx context.Context) *error_helpers.ErrorAn
|
||||
parseCtx.BlockTypeExclusions = []string{modconfig.BlockTypeVariable}
|
||||
|
||||
// load the workspace mod
|
||||
m, otherErrorAndWarning := steampipeconfig.LoadMod(w.Path, parseCtx)
|
||||
log.Println("[INFO] >> 1. ctx:", &ctx)
|
||||
m, otherErrorAndWarning := steampipeconfig.LoadMod(ctx, w.Path, parseCtx)
|
||||
errorsAndWarnings.Merge(otherErrorAndWarning)
|
||||
if errorsAndWarnings.Error != nil {
|
||||
return errorsAndWarnings
|
||||
@@ -293,6 +345,9 @@ func (w *Workspace) loadWorkspaceMod(ctx context.Context) *error_helpers.ErrorAn
|
||||
}
|
||||
|
||||
func (w *Workspace) getInputVariables(ctx context.Context, validateMissing bool) (*modconfig.ModVariableMap, *error_helpers.ErrorAndWarnings) {
|
||||
log.Println("[INFO] >> start getInputVariables")
|
||||
defer log.Println("[INFO] >> end getInputVariables")
|
||||
|
||||
// build a run context just to use to load variable definitions
|
||||
variablesParseCtx, err := w.getParseContext(ctx)
|
||||
if err != nil {
|
||||
@@ -303,8 +358,12 @@ func (w *Workspace) getInputVariables(ctx context.Context, validateMissing bool)
|
||||
}
|
||||
|
||||
func (w *Workspace) getVariableValues(ctx context.Context, variablesParseCtx *parse.ModParseContext, validateMissing bool) (*modconfig.ModVariableMap, *error_helpers.ErrorAndWarnings) {
|
||||
log.Println("[INFO] >> start getVariableValues")
|
||||
defer log.Println("[INFO] >> end getVariableValues")
|
||||
|
||||
// load variable definitions
|
||||
variableMap, err := steampipeconfig.LoadVariableDefinitions(w.Path, variablesParseCtx)
|
||||
log.Println("[INFO] >> 1. ctx:", &ctx)
|
||||
variableMap, err := steampipeconfig.LoadVariableDefinitions(ctx, w.Path, variablesParseCtx)
|
||||
if err != nil {
|
||||
return nil, error_helpers.NewErrorsAndWarning(err)
|
||||
}
|
||||
@@ -315,6 +374,8 @@ func (w *Workspace) getVariableValues(ctx context.Context, variablesParseCtx *pa
|
||||
// build options used to load workspace
|
||||
// set flags to create pseudo resources and a default mod if needed
|
||||
func (w *Workspace) getParseContext(ctx context.Context) (*parse.ModParseContext, error) {
|
||||
log.Println("[INFO] >> start getParseContext")
|
||||
defer log.Println("[INFO] >> end getParseContext")
|
||||
parseFlag := parse.CreateDefaultMod
|
||||
if w.loadPseudoResources {
|
||||
parseFlag |= parse.CreatePseudoResources
|
||||
@@ -401,7 +462,7 @@ func (w *Workspace) loadWorkspaceResourceName(ctx context.Context) (*modconfig.W
|
||||
return nil, err
|
||||
}
|
||||
|
||||
workspaceResourceNames, err := steampipeconfig.LoadModResourceNames(w.Mod, parseCtx)
|
||||
workspaceResourceNames, err := steampipeconfig.LoadModResourceNames(ctx, w.Mod, parseCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -429,6 +429,7 @@ load "$LIB_BATS_SUPPORT/load.bash"
|
||||
}
|
||||
|
||||
@test "verify cache ttl works when set in database options" {
|
||||
skip "re-enable after verifying/fixing the default.spc overwrite issue" # https://github.com/turbot/steampipe/issues/3891
|
||||
export STEAMPIPE_LOG=info
|
||||
|
||||
cp $SRC_DATA_DIR/chaos_no_options.spc $STEAMPIPE_INSTALL_DIR/config/chaos_no_options.spc
|
||||
|
||||
Reference in New Issue
Block a user