Analyze from the CLI

This commit is contained in:
Marc Campbell
2020-06-12 12:47:45 -07:00
parent 8d991e1f9e
commit a22e2e25df
4 changed files with 99 additions and 40 deletions

View File

@@ -128,7 +128,7 @@ run-preflight: preflight
.PHONY: run-troubleshoot
run-troubleshoot: support-bundle
./bin/support-bundle ./examples/troubleshoot/sample-troubleshoot.yaml
./bin/support-bundle ./examples/troubleshoot/sample-supportbundle.yaml
.PHONY: run-analyze
run-analyze: analyze

View File

@@ -21,10 +21,12 @@ import (
"github.com/mholt/archiver"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/cmd/util"
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
"github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
troubleshootclientsetscheme "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
"github.com/replicatedhq/troubleshoot/pkg/collect"
"github.com/replicatedhq/troubleshoot/pkg/convert"
"github.com/replicatedhq/troubleshoot/pkg/redact"
"github.com/spf13/viper"
spin "github.com/tj/go-spin"
@@ -132,7 +134,63 @@ func runTroubleshoot(v *viper.Viper, arg string) error {
fmt.Printf("\r%s\r", cursor.ClearEntireLine())
if len(supportBundleSpec.Spec.AfterCollection) == 0 {
// upload if needed
fileUploaded := false
if len(supportBundleSpec.Spec.AfterCollection) > 0 {
for _, ac := range supportBundleSpec.Spec.AfterCollection {
if ac.UploadResultsTo != nil {
if err := uploadSupportBundle(ac.UploadResultsTo, archivePath); err != nil {
c := color.New(color.FgHiRed)
c.Printf("%s\r * Failed to upload support bundle: %v\n", cursor.ClearEntireLine(), err)
} else {
fileUploaded = true
}
} else if ac.Callback != nil {
if err := callbackSupportBundleAPI(ac.Callback, archivePath); err != nil {
c := color.New(color.FgHiRed)
c.Printf("%s\r * Failed to notify API that support bundle has been uploaded: %v\n", cursor.ClearEntireLine(), err)
}
}
}
}
// perform analysis, if possible
if len(supportBundleSpec.Spec.Analyzers) > 0 {
tmpDir, err := ioutil.TempDir("", "troubleshoot")
if err != nil {
c := color.New(color.FgHiRed)
c.Printf("%s\r * Failed to make directory for analysis: %v\n", cursor.ClearEntireLine(), err)
}
f, err := os.Open(archivePath)
if err != nil {
c := color.New(color.FgHiRed)
c.Printf("%s\r * Failed to open support bundle for analysis: %v\n", cursor.ClearEntireLine(), err)
}
if err := analyzer.ExtractTroubleshootBundle(f, tmpDir); err != nil {
c := color.New(color.FgHiRed)
c.Printf("%s\r * Failed to extract support bundle for analysis: %v\n", cursor.ClearEntireLine(), err)
}
analyzeResults, err := analyzer.AnalyzeLocal(tmpDir, supportBundleSpec.Spec.Analyzers)
if err != nil {
c := color.New(color.FgHiRed)
c.Printf("%s\r * Failed to analyze support bundle: %v\n", cursor.ClearEntireLine(), err)
}
data := convert.FromAnalyzerResult(analyzeResults)
formatted, err := json.MarshalIndent(data, "", " ")
if err != nil {
c := color.New(color.FgHiRed)
c.Printf("%s\r * Failed to format analysis: %v\n", cursor.ClearEntireLine(), err)
}
fmt.Printf("%s", formatted)
}
if !fileUploaded {
msg := archivePath
if appName := supportBundleSpec.Labels["applicationName"]; appName != "" {
f := `A support bundle for %s has been created in this directory
@@ -146,23 +204,6 @@ the %s Admin Console to begin analysis.`
return nil
}
fileUploaded := false
for _, ac := range supportBundleSpec.Spec.AfterCollection {
if ac.UploadResultsTo != nil {
if err := uploadSupportBundle(ac.UploadResultsTo, archivePath); err != nil {
c := color.New(color.FgHiRed)
c.Printf("%s\r * Failed to upload support bundle: %v\n", cursor.ClearEntireLine(), err)
} else {
fileUploaded = true
}
} else if ac.Callback != nil {
if err := callbackSupportBundleAPI(ac.Callback, archivePath); err != nil {
c := color.New(color.FgHiRed)
c.Printf("%s\r * Failed to notify API that support bundle has been uploaded: %v\n", cursor.ClearEntireLine(), err)
}
}
}
fmt.Printf("\r%s\r", cursor.ClearEntireLine())
if fileUploaded {
fmt.Printf("A support bundle has been created and uploaded to your cluster for analysis. Please visit the Troubleshoot page to continue.\n")

View File

@@ -4,4 +4,17 @@ metadata:
name: supportbundle-sample
spec:
collectors: []
analyzers: []
analyzers:
- clusterVersion:
outcomes:
- fail:
when: "< 1.13.0"
message: The application requires at Kubernetes 1.13.0 or later, and recommends 1.15.0.
uri: https://www.kubernetes.io
- warn:
when: "< 1.15.0"
message: Your cluster meets the minimum version of Kubernetes, but we recommend you update to 1.15.0 or later.
uri: https://kubernetes.io
- pass:
when: ">= 1.15.0"
message: Your cluster meets the recommended and required versions of Kubernetes.

View File

@@ -20,6 +20,26 @@ type fileContentProvider struct {
rootDir string
}
// Analyze local will analyze a locally available (already downloaded) bundle
func AnalyzeLocal(localBundlePath string, analyzers []*troubleshootv1beta1.Analyze) ([]*AnalyzeResult, error) {
fcp := fileContentProvider{rootDir: localBundlePath}
analyzeResults := []*AnalyzeResult{}
for _, analyzer := range analyzers {
analyzeResult, err := Analyze(analyzer, fcp.getFileContents, fcp.getChildFileContents)
if err != nil {
logger.Printf("an analyzer failed to run: %v\n", err)
continue
}
if analyzeResult != nil {
analyzeResults = append(analyzeResults, analyzeResult)
}
}
return analyzeResults, nil
}
func DownloadAndAnalyze(bundleURL string, analyzersSpec string) ([]*AnalyzeResult, error) {
tmpDir, err := ioutil.TempDir("", "troubleshoot-k8s")
if err != nil {
@@ -52,22 +72,7 @@ func DownloadAndAnalyze(bundleURL string, analyzersSpec string) ([]*AnalyzeResul
analyzers = parsedAnalyzers
}
fcp := fileContentProvider{rootDir: tmpDir}
analyzeResults := []*AnalyzeResult{}
for _, analyzer := range analyzers {
analyzeResult, err := Analyze(analyzer, fcp.getFileContents, fcp.getChildFileContents)
if err != nil {
logger.Printf("an analyzer failed to run: %v\n", err)
continue
}
if analyzeResult != nil {
analyzeResults = append(analyzeResults, analyzeResult)
}
}
return analyzeResults, nil
return AnalyzeLocal(tmpDir, analyzers)
}
func downloadTroubleshootBundle(bundleURL string, destDir string) error {
@@ -77,7 +82,7 @@ func downloadTroubleshootBundle(bundleURL string, destDir string) error {
return errors.Wrap(err, "failed to open support bundle")
}
defer f.Close()
return extractTroubleshootBundle(f, destDir)
return ExtractTroubleshootBundle(f, destDir)
}
pwd, err := os.Getwd()
@@ -85,7 +90,7 @@ func downloadTroubleshootBundle(bundleURL string, destDir string) error {
return errors.Wrap(err, "failed to get workdir")
}
tmpDir, err := ioutil.TempDir("", "getter")
tmpDir, err := ioutil.TempDir("", "troubleshoot")
if err != nil {
return errors.Wrap(err, "failed to create tmp dir")
}
@@ -107,10 +112,10 @@ func downloadTroubleshootBundle(bundleURL string, destDir string) error {
}
defer f.Close()
return extractTroubleshootBundle(f, destDir)
return ExtractTroubleshootBundle(f, destDir)
}
func extractTroubleshootBundle(reader io.Reader, destDir string) error {
func ExtractTroubleshootBundle(reader io.Reader, destDir string) error {
gzReader, err := gzip.NewReader(reader)
if err != nil {
return errors.Wrap(err, "failed to create gzip reader")