diff --git a/pkg/analyze/analyzer.go b/pkg/analyze/analyzer.go index f553296d..002b42ca 100644 --- a/pkg/analyze/analyzer.go +++ b/pkg/analyze/analyzer.go @@ -36,7 +36,8 @@ func isExcluded(excludeVal multitype.BoolOrString) (bool, error) { return parsed, nil } -func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileContents, findFiles getChildCollectedFileContents) (*AnalyzeResult, error) { +func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileContents, findFiles getChildCollectedFileContents) ([]*AnalyzeResult, error) { + results := []*AnalyzeResult{} if analyzer.ClusterVersion != nil { isExcluded, err := isExcluded(analyzer.ClusterVersion.Exclude) if err != nil { @@ -45,7 +46,11 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - return analyzeClusterVersion(analyzer.ClusterVersion, getFile) + result, err := analyzeClusterVersion(analyzer.ClusterVersion, getFile) + if err != nil { + return nil, err + } + results = append(results, result) } if analyzer.StorageClass != nil { isExcluded, err := isExcluded(analyzer.StorageClass.Exclude) @@ -55,7 +60,11 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - return analyzeStorageClass(analyzer.StorageClass, getFile) + result, err := analyzeStorageClass(analyzer.StorageClass, getFile) + if err != nil { + return nil, err + } + results = append(results, result) } if analyzer.CustomResourceDefinition != nil { isExcluded, err := isExcluded(analyzer.CustomResourceDefinition.Exclude) @@ -65,7 +74,11 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - return analyzeCustomResourceDefinition(analyzer.CustomResourceDefinition, getFile) + result, err := analyzeCustomResourceDefinition(analyzer.CustomResourceDefinition, getFile) + if err != nil { + return nil, err + } + results = append(results, result) } if analyzer.Ingress != nil { isExcluded, err := isExcluded(analyzer.Ingress.Exclude) @@ -75,7 +88,11 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - return analyzeIngress(analyzer.Ingress, getFile) + result, err := analyzeIngress(analyzer.Ingress, getFile) + if err != nil { + return nil, err + } + results = append(results, result) } if analyzer.Secret != nil { isExcluded, err := isExcluded(analyzer.Secret.Exclude) @@ -85,7 +102,11 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - return analyzeSecret(analyzer.Secret, getFile) + result, err := analyzeSecret(analyzer.Secret, getFile) + if err != nil { + return nil, err + } + results = append(results, result) } if analyzer.ImagePullSecret != nil { isExcluded, err := isExcluded(analyzer.ImagePullSecret.Exclude) @@ -95,7 +116,11 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - return analyzeImagePullSecret(analyzer.ImagePullSecret, findFiles) + result, err := analyzeImagePullSecret(analyzer.ImagePullSecret, findFiles) + if err != nil { + return nil, err + } + results = append(results, result) } if analyzer.DeploymentStatus != nil { isExcluded, err := isExcluded(analyzer.DeploymentStatus.Exclude) @@ -105,7 +130,11 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - return analyzeDeploymentStatus(analyzer.DeploymentStatus, getFile) + result, err := analyzeDeploymentStatus(analyzer.DeploymentStatus, getFile) + if err != nil { + return nil, err + } + results = append(results, result) } if analyzer.StatefulsetStatus != nil { isExcluded, err := isExcluded(analyzer.StatefulsetStatus.Exclude) @@ -115,7 +144,11 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - return analyzeStatefulsetStatus(analyzer.StatefulsetStatus, getFile) + result, err := analyzeStatefulsetStatus(analyzer.StatefulsetStatus, getFile) + if err != nil { + return nil, err + } + results = append(results, result) } if analyzer.ContainerRuntime != nil { isExcluded, err := isExcluded(analyzer.ContainerRuntime.Exclude) @@ -125,7 +158,11 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - return analyzeContainerRuntime(analyzer.ContainerRuntime, getFile) + result, err := analyzeContainerRuntime(analyzer.ContainerRuntime, getFile) + if err != nil { + return nil, err + } + results = append(results, result) } if analyzer.Distribution != nil { isExcluded, err := isExcluded(analyzer.Distribution.Exclude) @@ -135,7 +172,11 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - return analyzeDistribution(analyzer.Distribution, getFile) + result, err := analyzeDistribution(analyzer.Distribution, getFile) + if err != nil { + return nil, err + } + results = append(results, result) } if analyzer.NodeResources != nil { isExcluded, err := isExcluded(analyzer.NodeResources.Exclude) @@ -145,7 +186,11 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - return analyzeNodeResources(analyzer.NodeResources, getFile) + result, err := analyzeNodeResources(analyzer.NodeResources, getFile) + if err != nil { + return nil, err + } + results = append(results, result) } if analyzer.TextAnalyze != nil { isExcluded, err := isExcluded(analyzer.TextAnalyze.Exclude) @@ -155,7 +200,11 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - return analyzeTextAnalyze(analyzer.TextAnalyze, getFile) + multiResult, err := analyzeTextAnalyze(analyzer.TextAnalyze, findFiles) + if err != nil { + return nil, err + } + results = append(results, multiResult...) } if analyzer.Postgres != nil { isExcluded, err := isExcluded(analyzer.Postgres.Exclude) @@ -165,7 +214,11 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - return analyzePostgres(analyzer.Postgres, getFile) + result, err := analyzePostgres(analyzer.Postgres, getFile) + if err != nil { + return nil, err + } + results = append(results, result) } if analyzer.Mysql != nil { isExcluded, err := isExcluded(analyzer.Mysql.Exclude) @@ -175,7 +228,11 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - return analyzeMysql(analyzer.Mysql, getFile) + result, err := analyzeMysql(analyzer.Mysql, getFile) + if err != nil { + return nil, err + } + results = append(results, result) } if analyzer.Redis != nil { isExcluded, err := isExcluded(analyzer.Redis.Exclude) @@ -185,8 +242,15 @@ func Analyze(analyzer *troubleshootv1beta1.Analyze, getFile getCollectedFileCont if isExcluded { return nil, nil } - return analyzeRedis(analyzer.Redis, getFile) + result, err := analyzeRedis(analyzer.Redis, getFile) + if err != nil { + return nil, err + } + results = append(results, result) } - return nil, errors.New("invalid analyzer") + if len(results) == 0 { + return nil, errors.New("invalid analyzer") + } + return results, nil } diff --git a/pkg/analyze/download.go b/pkg/analyze/download.go index 2c40617e..84b09ef8 100644 --- a/pkg/analyze/download.go +++ b/pkg/analyze/download.go @@ -63,7 +63,7 @@ func DownloadAndAnalyze(bundleURL string, analyzersSpec string) ([]*AnalyzeResul } if analyzeResult != nil { - analyzeResults = append(analyzeResults, analyzeResult) + analyzeResults = append(analyzeResults, analyzeResult...) } } @@ -192,6 +192,6 @@ func (f fileContentProvider) getFileContents(fileName string) ([]byte, error) { func (f fileContentProvider) getChildFileContents(dirName string) (map[string][]byte, error) { // TODO: walk sub-dirs - // return nil, errors.New("not implemnted") + // return nil, errors.New("not implemented") return map[string][]byte{}, nil } diff --git a/pkg/analyze/text_analyze.go b/pkg/analyze/text_analyze.go index 7e5aa703..0aeccc42 100644 --- a/pkg/analyze/text_analyze.go +++ b/pkg/analyze/text_analyze.go @@ -10,7 +10,7 @@ import ( troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1" ) -func analyzeTextAnalyze(analyzer *troubleshootv1beta1.TextAnalyze, getCollectedFileContents func(string) ([]byte, error)) (*AnalyzeResult, error) { +func analyzeTextAnalyze(analyzer *troubleshootv1beta1.TextAnalyze, getCollectedFileContents func(string) (map[string][]byte, error)) ([]*AnalyzeResult, error) { fullPath := filepath.Join(analyzer.CollectorName, analyzer.FileName) collected, err := getCollectedFileContents(fullPath) if err != nil { @@ -22,20 +22,44 @@ func analyzeTextAnalyze(analyzer *troubleshootv1beta1.TextAnalyze, getCollectedF checkName = analyzer.CollectorName } + results := []*AnalyzeResult{} + if analyzer.RegexPattern != "" { - return analyzeRegexPattern(analyzer.RegexPattern, collected, analyzer.Outcomes, checkName) + for _, fileContents := range collected { + result, err := analyzeRegexPattern(analyzer.RegexPattern, fileContents, analyzer.Outcomes, checkName) + if err != nil { + return nil, err + } + if result != nil { + results = append(results, result) + } + } } if analyzer.RegexGroups != "" { - return analyzeRegexGroups(analyzer.RegexGroups, collected, analyzer.Outcomes, checkName) + for _, fileContents := range collected { + result, err := analyzeRegexGroups(analyzer.RegexGroups, fileContents, analyzer.Outcomes, checkName) + if err != nil { + return nil, err + } + if result != nil { + results = append(results, result) + } + } } - return &AnalyzeResult{ - Title: checkName, - IconKey: "kubernetes_text_analyze", - IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg", - IsFail: true, - Message: "Invalid analyzer", + if len(results) > 0 { + return results, nil + } + + return []*AnalyzeResult{ + { + Title: checkName, + IconKey: "kubernetes_text_analyze", + IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg", + IsFail: true, + Message: "Invalid analyzer", + }, }, nil } diff --git a/pkg/analyze/text_analyze_test.go b/pkg/analyze/text_analyze_test.go index 2643a39a..8916de8f 100644 --- a/pkg/analyze/text_analyze_test.go +++ b/pkg/analyze/text_analyze_test.go @@ -2,6 +2,7 @@ package analyzer import ( "fmt" + "strings" "testing" troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1" @@ -14,7 +15,7 @@ func Test_textAnalyze(t *testing.T) { tests := []struct { name string analyzer troubleshootv1beta1.TextAnalyze - expectResult AnalyzeResult + expectResult []AnalyzeResult files map[string][]byte }{ { @@ -36,12 +37,14 @@ func Test_textAnalyze(t *testing.T) { FileName: "cfile-1.txt", RegexPattern: "succeeded", }, - expectResult: AnalyzeResult{ - IsPass: true, - IsWarn: false, - IsFail: false, - Title: "text-collector-1", - Message: "pass", + expectResult: []AnalyzeResult{ + { + IsPass: true, + IsWarn: false, + IsFail: false, + Title: "text-collector-1", + Message: "pass", + }, }, files: map[string][]byte{ "text-collector-1/cfile-1.txt": []byte("Yes it all succeeded"), @@ -66,14 +69,16 @@ func Test_textAnalyze(t *testing.T) { FileName: "cfile-2.txt", RegexPattern: "succeeded", }, - expectResult: AnalyzeResult{ - IsPass: false, - IsWarn: false, - IsFail: true, - Title: "text-collector-2", - Message: "fail", - IconKey: "kubernetes_text_analyze", - IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg", + expectResult: []AnalyzeResult{ + { + IsPass: false, + IsWarn: false, + IsFail: true, + Title: "text-collector-2", + Message: "fail", + IconKey: "kubernetes_text_analyze", + IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg", + }, }, files: map[string][]byte{ "text-collector-2/cfile-2.txt": []byte(""), @@ -98,14 +103,16 @@ func Test_textAnalyze(t *testing.T) { FileName: "cfile-3.txt", RegexPattern: "", }, - expectResult: AnalyzeResult{ - IsPass: false, - IsWarn: false, - IsFail: true, - Title: "text-collector-3", - Message: "Invalid analyzer", - IconKey: "kubernetes_text_analyze", - IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg", + expectResult: []AnalyzeResult{ + { + IsPass: false, + IsWarn: false, + IsFail: true, + Title: "text-collector-3", + Message: "Invalid analyzer", + IconKey: "kubernetes_text_analyze", + IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg", + }, }, files: map[string][]byte{ "text-collector-3/cfile-3.txt": []byte("Connection to service succeeded"), @@ -130,12 +137,14 @@ func Test_textAnalyze(t *testing.T) { FileName: "cfile-5.txt", RegexPattern: "([a-zA-Z0-9\\-_:*\\s])*succe([a-zA-Z0-9\\-_:*\\s!])*", }, - expectResult: AnalyzeResult{ - IsPass: true, - IsWarn: false, - IsFail: false, - Title: "text-collector-5", - Message: "success", + expectResult: []AnalyzeResult{ + { + IsPass: true, + IsWarn: false, + IsFail: false, + Title: "text-collector-5", + Message: "success", + }, }, files: map[string][]byte{ "text-collector-5/cfile-5.txt": []byte("Connection to service succeeded!"), @@ -160,14 +169,16 @@ func Test_textAnalyze(t *testing.T) { FileName: "cfile-4.txt", RegexPattern: "succeeded", }, - expectResult: AnalyzeResult{ - IsPass: false, - IsWarn: false, - IsFail: true, - Title: "text-collector-4", - Message: "fail", - IconKey: "kubernetes_text_analyze", - IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg", + expectResult: []AnalyzeResult{ + { + IsPass: false, + IsWarn: false, + IsFail: true, + Title: "text-collector-4", + Message: "fail", + IconKey: "kubernetes_text_analyze", + IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg", + }, }, files: map[string][]byte{ "text-collector-4/cfile-4.txt": []byte("A different message"), @@ -192,19 +203,64 @@ func Test_textAnalyze(t *testing.T) { FileName: "cfile-6.txt", RegexPattern: "([a-zA-Z0-9\\-_:*\\s])*succe([a-zA-Z0-9\\-_:*\\s!])*", }, - expectResult: AnalyzeResult{ - IsPass: false, - IsWarn: false, - IsFail: true, - Title: "text-collector-6", - Message: "fail", - IconKey: "kubernetes_text_analyze", - IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg", + expectResult: []AnalyzeResult{ + { + IsPass: false, + IsWarn: false, + IsFail: true, + Title: "text-collector-6", + Message: "fail", + IconKey: "kubernetes_text_analyze", + IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg", + }, }, files: map[string][]byte{ "text-collector-6/cfile-6.txt": []byte("A different message"), }, }, + { + name: "multiple results case 1", + analyzer: troubleshootv1beta1.TextAnalyze{ + Outcomes: []*troubleshootv1beta1.Outcome{ + { + Pass: &troubleshootv1beta1.SingleOutcome{ + Message: "pass", + }, + }, + { + Fail: &troubleshootv1beta1.SingleOutcome{ + Message: "fail", + }, + }, + }, + CollectorName: "text-collector-1", + FileName: "cfile", + RegexPattern: "succeeded", + }, + expectResult: []AnalyzeResult{ + { + IsPass: true, + IsWarn: false, + IsFail: false, + Title: "text-collector-1", + Message: "pass", + }, + { + IsPass: false, + IsWarn: false, + IsFail: true, + Title: "text-collector-1", + Message: "fail", + IconKey: "kubernetes_text_analyze", + IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg", + }, + }, + files: map[string][]byte{ + "text-collector-1/cfile-1.txt": []byte("Yes it all succeeded"), + "text-collector-1/cfile-2.txt": []byte("no success here"), + "text-collector-2/cfile-3.txt": []byte("Yes it all succeeded"), + }, + }, } for _, test := range tests { @@ -213,17 +269,27 @@ func Test_textAnalyze(t *testing.T) { defer scopetest.End() req := require.New(t) - getFiles := func(n string) ([]byte, error) { - val, ok := test.files[n] - if !ok { + getFiles := func(n string) (map[string][]byte, error) { + matching := make(map[string][]byte) + for k, v := range test.files { + if strings.HasPrefix(k, n) { + matching[k] = v + } + } + if len(matching) == 0 { return nil, fmt.Errorf("File not found: %s", n) } - return val, nil + return matching, nil } actual, err := analyzeTextAnalyze(&test.analyzer, getFiles) req.NoError(err) - assert.Equal(t, &test.expectResult, actual) + + unPointered := []AnalyzeResult{} + for _, v := range actual { + unPointered = append(unPointered, *v) + } + assert.Equal(t, test.expectResult, unPointered) }) } } diff --git a/pkg/preflight/analyze.go b/pkg/preflight/analyze.go index 1c5c1e17..342506ab 100644 --- a/pkg/preflight/analyze.go +++ b/pkg/preflight/analyze.go @@ -32,15 +32,17 @@ func (c CollectResult) Analyze() []*analyze.AnalyzeResult { for _, analyzer := range c.Spec.Spec.Analyzers { analyzeResult, err := analyze.Analyze(analyzer, getCollectedFileContents, getChildCollectedFileContents) if err != nil { - analyzeResult = &analyze.AnalyzeResult{ - IsFail: true, - Title: "Analyzer Failed", - Message: err.Error(), + analyzeResult = []*analyze.AnalyzeResult{ + { + IsFail: true, + Title: "Analyzer Failed", + Message: err.Error(), + }, } } if analyzeResult != nil { - analyzeResults = append(analyzeResults, analyzeResult) + analyzeResults = append(analyzeResults, analyzeResult...) } }