diff --git a/cmd/devstream/apply.go b/cmd/devstream/apply.go index 367404720..79511ed6e 100644 --- a/cmd/devstream/apply.go +++ b/cmd/devstream/apply.go @@ -2,6 +2,7 @@ package main import ( "os" + "strings" "github.com/spf13/cobra" @@ -23,6 +24,9 @@ func applyCMDFunc(cmd *cobra.Command, args []string) { log.Info("Apply started.") if err := pluginengine.Apply(configFilePath, continueDirectly); err != nil { log.Errorf("Apply failed => %s.", err) + if strings.Contains(err.Error(), "config not valid") { + log.Info("It seems your config file is not valid. Please check the official documentation https://docs.devstream.io, or use the \"dtm show config\" command to get an example.") + } os.Exit(1) } log.Success("Apply finished.") diff --git a/internal/pkg/configmanager/configmanager.go b/internal/pkg/configmanager/configmanager.go index 22c4e3770..b1e750dc2 100644 --- a/internal/pkg/configmanager/configmanager.go +++ b/internal/pkg/configmanager/configmanager.go @@ -3,6 +3,7 @@ package configmanager import ( "fmt" "os" + "strings" ) // Manager is used to load the config file from the ConfigFilePath and finally get the Config object. @@ -61,15 +62,26 @@ func (m *Manager) getConfigFromFileWithGlobalVars() (*Config, error) { return nil, fmt.Errorf("failed to get variables from config file. Error: %w", err) } + missingVariableErrorMsg := "map has no entry for key " + // 2. tools with global variables rendered tools, err := r.getToolsWithVars(vars) if err != nil { + keyNotFoundIndex := strings.Index(err.Error(), missingVariableErrorMsg) + if keyNotFoundIndex != -1 { + return nil, fmt.Errorf("failed to process variables in the tools section. Missing variable definition: %s", err.Error()[keyNotFoundIndex+len(missingVariableErrorMsg):]) + } return nil, fmt.Errorf("failed to get tools from config file. Error: %w", err) + } // 3. apps tools with global variables rendered appTools, err := r.getAppToolsWithVars(vars) if err != nil { + keyNotFoundIndex := strings.Index(err.Error(), "map has no entry for key ") + if keyNotFoundIndex != -1 { + return nil, fmt.Errorf("failed to process variables in the apps section. Missing variable definition: %s", err.Error()[keyNotFoundIndex+len(missingVariableErrorMsg):]) + } return nil, fmt.Errorf("failed to get apps from config file. Error: %w", err) } // all tools from apps should depend on the original tools, diff --git a/internal/pkg/configmanager/rawconfig.go b/internal/pkg/configmanager/rawconfig.go index 491970630..b2464deaf 100644 --- a/internal/pkg/configmanager/rawconfig.go +++ b/internal/pkg/configmanager/rawconfig.go @@ -59,7 +59,7 @@ func newRawConfigFromConfigBytes(fileText []byte) (*rawConfig, error) { // validate will check config data is valid func (c *rawConfig) validate() error { - errorFmt := "configmanager can't found valid [%s], please check your config file" + errorFmt := "config not valid; check the [%s] section of your config file" if (len(c.config)) == 0 { return fmt.Errorf(errorFmt, "config") } diff --git a/internal/pkg/configmanager/rawconfig_test.go b/internal/pkg/configmanager/rawconfig_test.go index a2c413a12..e1bec38be 100644 --- a/internal/pkg/configmanager/rawconfig_test.go +++ b/internal/pkg/configmanager/rawconfig_test.go @@ -69,7 +69,7 @@ var _ = Describe("rawConfig struct", func() { It("should return error", func() { e := r.validate() Expect(e).Error().Should(HaveOccurred()) - Expect(e.Error()).Should(Equal("configmanager can't found valid [config], please check your config file")) + Expect(e.Error()).Should(Equal("config not valid; check the [config] section of your config file")) }) }) When("apps and tools is not exist", func() { @@ -81,7 +81,7 @@ var _ = Describe("rawConfig struct", func() { It("should return error", func() { e := r.validate() Expect(e).Error().Should(HaveOccurred()) - Expect(e.Error()).Should(Equal("configmanager can't found valid [tools and apps], please check your config file")) + Expect(e.Error()).Should(Equal("config not valid; check the [tools and apps] section of your config file")) }) }) })