diff --git a/cmd/troubleshoot/cli/run.go b/cmd/troubleshoot/cli/run.go index 6830813d..28e5f4b2 100644 --- a/cmd/troubleshoot/cli/run.go +++ b/cmd/troubleshoot/cli/run.go @@ -376,11 +376,21 @@ func canTryInsecure() bool { } func runCollectors(v *viper.Viper, collectors []*troubleshootv1beta2.Collect, additionalRedactors *troubleshootv1beta2.Redactor, progressChan chan interface{}) (string, error) { - bundlePath, err := ioutil.TempDir("", "troubleshoot") + tmpDir, err := ioutil.TempDir("", "troubleshoot") if err != nil { return "", errors.Wrap(err, "create temp dir") } - defer os.RemoveAll(bundlePath) + defer os.RemoveAll(tmpDir) + + filename, err := findFileName("support-bundle-"+time.Now().Format("2006-01-02T15_04_05"), "tar.gz") + if err != nil { + return "", errors.Wrap(err, "find file name") + } + + bundlePath := filepath.Join(tmpDir, strings.TrimSuffix(filename, ".tar.gz")) + if err := os.MkdirAll(bundlePath, 0777); err != nil { + return "", errors.Wrap(err, "create bundle dir") + } if err = writeVersionFile(bundlePath); err != nil { return "", errors.Wrap(err, "write version file") @@ -403,6 +413,7 @@ func runCollectors(v *viper.Viper, collectors []*troubleshootv1beta2.Collect, ad Collect: desiredCollector, ClientConfig: config, Namespace: v.GetString("namespace"), + PathPrefix: filepath.Base(bundlePath), } cleanedCollectors = append(cleanedCollectors, &collector) } @@ -447,7 +458,8 @@ func runCollectors(v *viper.Viper, collectors []*troubleshootv1beta2.Collect, ad } if result != nil { - err = saveCollectorOutput(result, bundlePath, collector) + // results already contain the bundle dir name in their paths + err = saveCollectorOutput(result, filepath.Dir(bundlePath), collector) if err != nil { progressChan <- fmt.Errorf("failed to parse collector spec %q: %v", collector.GetDisplayName(), err) continue @@ -455,11 +467,6 @@ func runCollectors(v *viper.Viper, collectors []*troubleshootv1beta2.Collect, ad } } - filename, err := findFileName("support-bundle-"+time.Now().Format("2006-01-02T15_04_05"), "tar.gz") - if err != nil { - return "", errors.Wrap(err, "find file name") - } - if err := tarSupportBundleDir(bundlePath, filename); err != nil { return "", errors.Wrap(err, "create bundle file") } @@ -662,22 +669,7 @@ func tarSupportBundleDir(inputDir, outputFilename string) error { }, } - paths := []string{ - filepath.Join(inputDir, VersionFilename), // version file should be first in tar archive for quick extraction - } - - topLevelFiles, err := ioutil.ReadDir(inputDir) - if err != nil { - return errors.Wrap(err, "list bundle directory contents") - } - for _, f := range topLevelFiles { - if f.Name() == VersionFilename { - continue - } - paths = append(paths, filepath.Join(inputDir, f.Name())) - } - - if err := tarGz.Archive(paths, outputFilename); err != nil { + if err := tarGz.Archive([]string{inputDir}, outputFilename); err != nil { return errors.Wrap(err, "create archive") } diff --git a/pkg/analyze/download.go b/pkg/analyze/download.go index fe0aaf7e..c017b512 100644 --- a/pkg/analyze/download.go +++ b/pkg/analyze/download.go @@ -23,7 +23,12 @@ type fileContentProvider struct { // Analyze local will analyze a locally available (already downloaded) bundle func AnalyzeLocal(localBundlePath string, analyzers []*troubleshootv1beta2.Analyze) ([]*AnalyzeResult, error) { - fcp := fileContentProvider{rootDir: localBundlePath} + rootDir, err := FindBundleRootDir(localBundlePath) + if err != nil { + return nil, errors.Wrap(err, "failed to find root dir") + } + + fcp := fileContentProvider{rootDir: rootDir} analyzeResults := []*AnalyzeResult{} for _, analyzer := range analyzers { @@ -52,7 +57,12 @@ func DownloadAndAnalyze(bundleURL string, analyzersSpec string) ([]*AnalyzeResul return nil, errors.Wrap(err, "failed to download bundle") } - _, err = os.Stat(filepath.Join(tmpDir, "version.yaml")) + rootDir, err := FindBundleRootDir(tmpDir) + if err != nil { + return nil, errors.Wrap(err, "failed to find root dir") + } + + _, err = os.Stat(filepath.Join(rootDir, "version.yaml")) if err != nil { return nil, errors.Wrap(err, "failed to read version.yaml") } @@ -73,7 +83,7 @@ func DownloadAndAnalyze(bundleURL string, analyzersSpec string) ([]*AnalyzeResul analyzers = parsedAnalyzers } - return AnalyzeLocal(tmpDir, analyzers) + return AnalyzeLocal(rootDir, analyzers) } func downloadTroubleshootBundle(bundleURL string, destDir string) error { @@ -197,6 +207,39 @@ spec: return parseAnalyzers(spec) } +// FindBundleRootDir detects whether the bundle is stored inside a subdirectory or not. +// returns the subdirectory path if so, otherwise, returns the path unchanged +func FindBundleRootDir(localBundlePath string) (string, error) { + f, err := os.Open(localBundlePath) + if err != nil { + return "", errors.Wrap(err, "failed to open bundle dir") + } + defer f.Close() + + names, err := f.Readdirnames(0) + if err != nil { + return "", errors.Wrap(err, "failed to read dirnames") + } + + if len(names) == 0 { + return "", errors.New("bundle directory is empty") + } + + isInSubDir := true + for _, name := range names { + if name == "version.yaml" { + isInSubDir = false + break + } + } + + if isInSubDir { + return filepath.Join(localBundlePath, names[0]), nil + } + + return localBundlePath, nil +} + func (f fileContentProvider) getFileContents(fileName string) ([]byte, error) { return ioutil.ReadFile(filepath.Join(f.rootDir, fileName)) } diff --git a/pkg/collect/collector.go b/pkg/collect/collector.go index 93402833..719a06ac 100644 --- a/pkg/collect/collector.go +++ b/pkg/collect/collector.go @@ -2,6 +2,7 @@ package collect import ( "context" + "path/filepath" "strconv" "github.com/pkg/errors" @@ -19,6 +20,7 @@ type Collector struct { RBACErrors []error ClientConfig *rest.Config Namespace string + PathPrefix string } type Collectors []*Collector @@ -155,10 +157,19 @@ func (c *Collector) RunCollectorSync(globalRedactors []*troubleshootv1beta2.Reda } else { return nil, errors.New("no spec found to run") } - if err != nil { return nil, err } + + if c.PathPrefix != "" { + // prefix file paths + prefixed := map[string][]byte{} + for k, v := range unRedacted { + prefixed[filepath.Join(c.PathPrefix, k)] = v + } + unRedacted = prefixed + } + if c.Redact { return redactMap(unRedacted, globalRedactors) } diff --git a/support-bundle-2020-09-25T15:15:16.tar.gz b/support-bundle-2020-09-25T15:15:16.tar.gz deleted file mode 100644 index a24028e1..00000000 Binary files a/support-bundle-2020-09-25T15:15:16.tar.gz and /dev/null differ