diff --git a/cmd/analyze/analyze.go b/cmd/analyze/analyze.go index 535c0d08f3..85b6ac7c0e 100644 --- a/cmd/analyze/analyze.go +++ b/cmd/analyze/analyze.go @@ -51,7 +51,7 @@ var AnalyzeCmd = &cobra.Command{ os.Exit(1) } - config.RunAnalysis() + errorsList := config.RunAnalysis() if explain { err := config.GetAIResults(output, anonymize) @@ -62,7 +62,7 @@ var AnalyzeCmd = &cobra.Command{ } // print results - output, err := config.PrintOutput(output) + output, err := config.PrintOutput(output, errorsList) if err != nil { color.Red("Error: %v", err) os.Exit(1) diff --git a/pkg/analysis/analysis.go b/pkg/analysis/analysis.go index f496b4dde0..3987963ebf 100644 --- a/pkg/analysis/analysis.go +++ b/pkg/analysis/analysis.go @@ -39,7 +39,7 @@ type Analysis struct { Client *kubernetes.Client AIClient ai.IAI Results []common.Result - Errors []string + Errors []error Namespace string Cache cache.ICache Explain bool @@ -116,7 +116,7 @@ func NewAnalysis(backend string, language string, filters []string, namespace st }, nil } -func (a *Analysis) RunAnalysis() { +func (a *Analysis) RunAnalysis() []error { activeFilters := viper.GetStringSlice("active_filters") analyzerMap := analyzer.GetAnalyzerMap() @@ -128,6 +128,7 @@ func (a *Analysis) RunAnalysis() { AIClient: a.AIClient, } + var errorsList []error semaphore := make(chan struct{}, a.MaxConcurrency) // if there are no filters selected and no active_filters then run all of them if len(a.Filters) == 0 && len(activeFilters) == 0 { @@ -141,7 +142,7 @@ func (a *Analysis) RunAnalysis() { results, err := analyzer.Analyze(analyzerConfig) if err != nil { mutex.Lock() - a.Errors = append(a.Errors, fmt.Sprintf(fmt.Sprintf("[%s] %s", reflect.TypeOf(analyzer).Name(), err))) + errorsList = append(errorsList, fmt.Errorf(fmt.Sprintf("[%s] %s", reflect.TypeOf(analyzer).Name(), err))) mutex.Unlock() } mutex.Lock() @@ -152,7 +153,9 @@ func (a *Analysis) RunAnalysis() { } wg.Wait() + return errorsList } + semaphore = make(chan struct{}, a.MaxConcurrency) // if the filters flag is specified if len(a.Filters) != 0 { @@ -167,7 +170,7 @@ func (a *Analysis) RunAnalysis() { results, err := analyzer.Analyze(analyzerConfig) if err != nil { mutex.Lock() - a.Errors = append(a.Errors, fmt.Sprintf(fmt.Sprintf("[%s] %s", filter, err))) + errorsList = append(errorsList, fmt.Errorf(fmt.Sprintf("[%s] %s", filter, err))) mutex.Unlock() } mutex.Lock() @@ -176,10 +179,11 @@ func (a *Analysis) RunAnalysis() { <-semaphore }(analyzer, filter) } else { - a.Errors = append(a.Errors, fmt.Sprintf(fmt.Sprintf("\"%s\" filter does not exist. Please run k8sgpt filters list.", filter))) + errorsList = append(errorsList, fmt.Errorf(fmt.Sprintf("\"%s\" filter does not exist. Please run k8sgpt filters list.", filter))) } } wg.Wait() + return errorsList } var wg sync.WaitGroup @@ -195,7 +199,7 @@ func (a *Analysis) RunAnalysis() { results, err := analyzer.Analyze(analyzerConfig) if err != nil { mutex.Lock() - a.Errors = append(a.Errors, fmt.Sprintf("[%s] %s", filter, err)) + errorsList = append(errorsList, fmt.Errorf("[%s] %s", filter, err)) mutex.Unlock() } mutex.Lock() @@ -206,6 +210,7 @@ func (a *Analysis) RunAnalysis() { } } wg.Wait() + return errorsList } func (a *Analysis) GetAIResults(output string, anonymize bool) error { diff --git a/pkg/analysis/analysis_test.go b/pkg/analysis/analysis_test.go index 1a556692fc..1ba600be5c 100644 --- a/pkg/analysis/analysis_test.go +++ b/pkg/analysis/analysis_test.go @@ -35,7 +35,7 @@ func TestAnalysis_NoProblemJsonOutput(t *testing.T) { Results: []common.Result{}, } - gotJson, err := analysis.PrintOutput("json") + gotJson, err := analysis.PrintOutput("json", []error{}) if err != nil { t.Error(err) } @@ -88,7 +88,7 @@ func TestAnalysis_ProblemJsonOutput(t *testing.T) { }, } - gotJson, err := analysis.PrintOutput("json") + gotJson, err := analysis.PrintOutput("json", []error{}) if err != nil { t.Error(err) } @@ -149,7 +149,7 @@ func TestAnalysis_MultipleProblemJsonOutput(t *testing.T) { }, } - gotJson, err := analysis.PrintOutput("json") + gotJson, err := analysis.PrintOutput("json", []error{}) if err != nil { t.Error(err) } diff --git a/pkg/analysis/output.go b/pkg/analysis/output.go index e4459660fd..0cbc5e135c 100644 --- a/pkg/analysis/output.go +++ b/pkg/analysis/output.go @@ -21,7 +21,8 @@ func getOutputFormats() []string { return formats } -func (a *Analysis) PrintOutput(format string) ([]byte, error) { +func (a *Analysis) PrintOutput(format string, errorsList []error) ([]byte, error) { + a.Errors = errorsList outputFunc, ok := outputFormats[format] if !ok { return nil, fmt.Errorf("unsupported output format: %s. Available format %s", format, strings.Join(getOutputFormats(), ",")) @@ -41,10 +42,15 @@ func (a *Analysis) jsonOutput() ([]byte, error) { status = StateOK } + errorMessages := make([]string, len(a.Errors)) + for i, err := range a.Errors { + errorMessages[i] = err.Error() + } + result := JsonOutput{ Problems: problems, Results: a.Results, - Errors: a.Errors, + Errors: errorMessages, Status: status, } output, err := json.MarshalIndent(result, "", " ") @@ -60,7 +66,7 @@ func (a *Analysis) textOutput() ([]byte, error) { output.WriteString("\n") output.WriteString(color.YellowString("Warnings : \n")) for _, aerror := range a.Errors { - output.WriteString(fmt.Sprintf("- %s\n", color.YellowString(aerror))) + output.WriteString(fmt.Sprintf("- %s\n", color.YellowString(aerror.Error()))) } } output.WriteString("\n") diff --git a/pkg/server/server.go b/pkg/server/server.go index e65edbdaf1..f7c6179e6a 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -75,7 +75,7 @@ func (s *Config) analyzeHandler(w http.ResponseWriter, r *http.Request) { return } - config.RunAnalysis() + errorsList := config.RunAnalysis() if explain { err := config.GetAIResults(s.Output, anonymize) @@ -86,7 +86,7 @@ func (s *Config) analyzeHandler(w http.ResponseWriter, r *http.Request) { } } - out, err := config.PrintOutput(s.Output) + out, err := config.PrintOutput(s.Output, errorsList) if err != nil { health.Failure++ http.Error(w, err.Error(), http.StatusInternalServerError)