Skip to content

Commit 465a533

Browse files
authored
store analysis in the support bundle (#417)
* store analysis in the support bundle
1 parent 1078598 commit 465a533

File tree

3 files changed

+75
-122
lines changed

3 files changed

+75
-122
lines changed

cmd/troubleshoot/cli/run.go

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -153,41 +153,29 @@ func runTroubleshoot(v *viper.Viper, arg string) error {
153153
Namespace: v.GetString("namespace"),
154154
ProgressChan: progressChan,
155155
SinceTime: sinceTime,
156-
}
157-
158-
archivePath, err := supportbundle.CollectSupportBundleFromSpec(&supportBundle.Spec, additionalRedactors, createOpts)
159-
if err != nil {
160-
return errors.Wrap(err, "run collectors")
156+
FromCLI: true,
161157
}
162158

163159
c := color.New()
164160
c.Println(fmt.Sprintf("\r%s\r", cursor.ClearEntireLine()))
165161

166-
fileUploaded, err := supportbundle.ProcessSupportBundleAfterCollection(&supportBundle.Spec, archivePath)
162+
response, err := supportbundle.CollectSupportBundleFromSpec(&supportBundle.Spec, additionalRedactors, createOpts)
167163
if err != nil {
168-
c := color.New(color.FgHiRed)
169-
c.Printf("%s\r * %v\n", cursor.ClearEntireLine(), err)
170-
// don't die
164+
return errors.Wrap(err, "failed to run collect and analyze process")
171165
}
172166

173-
analyzeResults, err := supportbundle.AnalyzeAndExtractSupportBundle(&supportBundle.Spec, archivePath)
174-
if err != nil {
175-
c := color.New(color.FgHiRed)
176-
c.Printf("%s\r * %v\n", cursor.ClearEntireLine(), err)
177-
// Don't die
178-
} else if len(analyzeResults) > 0 {
179-
167+
if len(response.AnalyzerResults) > 0 {
180168
interactive := v.GetBool("interactive") && isatty.IsTerminal(os.Stdout.Fd())
181169

182170
if interactive {
183171
close(finishedCh) // this removes the spinner
184172
isFinishedChClosed = true
185173

186-
if err := showInteractiveResults(supportBundle.Name, analyzeResults); err != nil {
174+
if err := showInteractiveResults(supportBundle.Name, response.AnalyzerResults); err != nil {
187175
interactive = false
188176
}
189177
} else {
190-
data := convert.FromAnalyzerResult(analyzeResults)
178+
data := convert.FromAnalyzerResult(response.AnalyzerResults)
191179
formatted, err := json.MarshalIndent(data, "", " ")
192180
if err != nil {
193181
c := color.New(color.FgHiRed)
@@ -198,13 +186,13 @@ func runTroubleshoot(v *viper.Viper, arg string) error {
198186
}
199187
}
200188

201-
if !fileUploaded {
202-
msg := archivePath
189+
if !response.FileUploaded {
190+
msg := response.ArchivePath
203191
if appName := supportBundle.Labels["applicationName"]; appName != "" {
204192
f := `A support bundle for %s has been created in this directory
205193
named %s. Please upload it on the Troubleshoot page of
206194
the %s Admin Console to begin analysis.`
207-
msg = fmt.Sprintf(f, appName, archivePath, appName)
195+
msg = fmt.Sprintf(f, appName, response.ArchivePath, appName)
208196
}
209197

210198
fmt.Printf("%s\n", msg)
@@ -213,11 +201,11 @@ the %s Admin Console to begin analysis.`
213201
}
214202

215203
fmt.Printf("\r%s\r", cursor.ClearEntireLine())
216-
if fileUploaded {
204+
if response.FileUploaded {
217205
fmt.Printf("A support bundle has been created and uploaded to your cluster for analysis. Please visit the Troubleshoot page to continue.\n")
218-
fmt.Printf("A copy of this support bundle was written to the current directory, named %q\n", archivePath)
206+
fmt.Printf("A copy of this support bundle was written to the current directory, named %q\n", response.ArchivePath)
219207
} else {
220-
fmt.Printf("A support bundle has been created in the current directory named %q\n", archivePath)
208+
fmt.Printf("A support bundle has been created in the current directory named %q\n", response.ArchivePath)
221209
}
222210
return nil
223211
}

pkg/supportbundle/collect.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"bytes"
66
"compress/gzip"
77
"context"
8+
"encoding/json"
89
"fmt"
910
"io"
1011
"io/ioutil"
@@ -14,8 +15,10 @@ import (
1415
"time"
1516

1617
"github.com/pkg/errors"
18+
analyze "github.com/replicatedhq/troubleshoot/pkg/analyze"
1719
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
1820
"github.com/replicatedhq/troubleshoot/pkg/collect"
21+
"github.com/replicatedhq/troubleshoot/pkg/convert"
1922
"github.com/replicatedhq/troubleshoot/pkg/version"
2023
"gopkg.in/yaml.v2"
2124
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -156,6 +159,24 @@ func writeVersionFile(path string) error {
156159
return nil
157160
}
158161

162+
const AnalysisFilename = "analysis.json"
163+
164+
func writeAnalysisFile(path string, analyzeResults []*analyze.AnalyzeResult) error {
165+
data := convert.FromAnalyzerResult(analyzeResults)
166+
analysis, err := json.MarshalIndent(data, "", " ")
167+
if err != nil {
168+
return errors.Wrap(err, "failed to marshal analysis")
169+
}
170+
171+
filename := filepath.Join(path, AnalysisFilename)
172+
err = ioutil.WriteFile(filename, analysis, 0644)
173+
if err != nil {
174+
return errors.Wrap(err, "failed to write file")
175+
}
176+
177+
return nil
178+
}
179+
159180
func applyLogSinceTime(sinceTime time.Time, collectors *collect.Collectors) {
160181

161182
for _, collector := range *collectors {

pkg/supportbundle/supportbundle.go

Lines changed: 42 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package supportbundle
22

33
import (
4+
"fmt"
45
"io/ioutil"
56
"net/http"
67
"os"
78
"path/filepath"
89
"strings"
910
"time"
1011

12+
cursor "github.com/ahmetalpbalkan/go-cursor"
13+
"github.com/fatih/color"
1114
"github.com/pkg/errors"
1215
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
1316
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
@@ -22,19 +25,20 @@ type SupportBundleCreateOpts struct {
2225
Namespace string
2326
ProgressChan chan interface{}
2427
SinceTime *time.Time
28+
FromCLI bool
2529
}
2630

2731
type SupportBundleResponse struct {
2832
AnalyzerResults []*analyzer.AnalyzeResult
2933
ArchivePath string
30-
fileUploaded bool
34+
FileUploaded bool
3135
}
3236

33-
// SupportBundleCollectAnalyzeProcess collects support bundle from start to finish, including running
37+
// CollectSupportBundleFromSpec collects support bundle from start to finish, including running
3438
// collectors, analyzers and after collection steps. Input arguments are specifications.
35-
// The support bundle is archived in the OS temp folder (os.TempDir()).
36-
func SupportBundleCollectAnalyzeProcess(spec *troubleshootv1beta2.SupportBundleSpec, additionalRedactors *troubleshootv1beta2.Redactor, opts SupportBundleCreateOpts) (*SupportBundleResponse, error) {
37-
39+
// if FromCLI option is set to true, the output is the name of the archive on disk in the cwd.
40+
// if FromCLI option is set to false, the support bundle is archived in the OS temp folder (os.TempDir()).
41+
func CollectSupportBundleFromSpec(spec *troubleshootv1beta2.SupportBundleSpec, additionalRedactors *troubleshootv1beta2.Redactor, opts SupportBundleCreateOpts) (*SupportBundleResponse, error) {
3842
resultsResponse := SupportBundleResponse{}
3943

4044
if opts.KubernetesRestConfig == nil {
@@ -51,7 +55,11 @@ func SupportBundleCollectAnalyzeProcess(spec *troubleshootv1beta2.SupportBundleS
5155
}
5256
defer os.RemoveAll(tmpDir)
5357

54-
basename := filepath.Join(os.TempDir(), "support-bundle-"+time.Now().Format("2006-01-02T15_04_05"))
58+
basename := fmt.Sprintf("support-bundle-%s", time.Now().Format("2006-01-02T15_04_05"))
59+
if !opts.FromCLI {
60+
basename = filepath.Join(os.TempDir(), basename)
61+
}
62+
5563
filename, err := findFileName(basename, "tar.gz")
5664
if err != nil {
5765
return nil, errors.Wrap(err, "find file name")
@@ -74,21 +82,38 @@ func SupportBundleCollectAnalyzeProcess(spec *troubleshootv1beta2.SupportBundleS
7482
}
7583

7684
// Run Analyzers
77-
analyzeResults, err := AnalyzeSupportBundle(spec, tmpDir)
85+
analyzeResults, err := AnalyzeSupportBundle(spec, bundlePath)
7886
if err != nil {
79-
return nil, errors.Wrap(err, "failed to run analysis")
87+
if opts.FromCLI {
88+
c := color.New(color.FgHiRed)
89+
c.Printf("%s\r * %v\n", cursor.ClearEntireLine(), err)
90+
// don't die
91+
} else {
92+
return nil, errors.Wrap(err, "failed to run analysis")
93+
}
8094
}
8195
resultsResponse.AnalyzerResults = analyzeResults
8296

97+
// Add the analysis to the support bundle
98+
if err = writeAnalysisFile(bundlePath, analyzeResults); err != nil {
99+
return nil, errors.Wrap(err, "write version file")
100+
}
101+
83102
if err := tarSupportBundleDir(bundlePath, filename); err != nil {
84103
return nil, errors.Wrap(err, "create bundle file")
85104
}
86105

87106
fileUploaded, err := ProcessSupportBundleAfterCollection(spec, filename)
88107
if err != nil {
89-
return nil, errors.Wrap(err, "failed to process bundle after collection")
108+
if opts.FromCLI {
109+
c := color.New(color.FgHiRed)
110+
c.Printf("%s\r * %v\n", cursor.ClearEntireLine(), err)
111+
// don't die
112+
} else {
113+
return nil, errors.Wrap(err, "failed to process bundle after collection")
114+
}
90115
}
91-
resultsResponse.fileUploaded = fileUploaded
116+
resultsResponse.FileUploaded = fileUploaded
92117

93118
return &resultsResponse, nil
94119
}
@@ -97,7 +122,6 @@ func SupportBundleCollectAnalyzeProcess(spec *troubleshootv1beta2.SupportBundleS
97122
// collectors, analyzers and after collection steps. Input arguments are the URIs of the support bundle and redactor specs.
98123
// The support bundle is archived in the OS temp folder (os.TempDir()).
99124
func CollectSupportBundleFromURI(specURI string, redactorURIs []string, opts SupportBundleCreateOpts) (*SupportBundleResponse, error) {
100-
101125
supportbundle, err := GetSupportBundleFromURI(specURI)
102126
if err != nil {
103127
return nil, errors.Wrap(err, "could not bundle from URI")
@@ -115,53 +139,7 @@ func CollectSupportBundleFromURI(specURI string, redactorURIs []string, opts Sup
115139
}
116140
}
117141

118-
return SupportBundleCollectAnalyzeProcess(&supportbundle.Spec, additionalRedactors, opts)
119-
}
120-
121-
// CollectSupportBundleFromSpec run the support bundle collectors and creates an archive. The output is the name of the archive on disk
122-
// in the pwd (the caller must remove)
123-
func CollectSupportBundleFromSpec(spec *troubleshootv1beta2.SupportBundleSpec, additionalRedactors *troubleshootv1beta2.Redactor, opts SupportBundleCreateOpts) (string, error) {
124-
125-
if opts.KubernetesRestConfig == nil {
126-
return "", errors.New("did not receive kube rest config")
127-
}
128-
129-
if opts.ProgressChan == nil {
130-
return "", errors.New("did not receive collector progress chan")
131-
}
132-
133-
tmpDir, err := ioutil.TempDir("", "supportbundle")
134-
if err != nil {
135-
return "", errors.Wrap(err, "create temp dir")
136-
}
137-
defer os.RemoveAll(tmpDir)
138-
139-
// Do we need to put this in some kind of swap space?
140-
filename, err := findFileName("support-bundle-"+time.Now().Format("2006-01-02T15_04_05"), "tar.gz")
141-
if err != nil {
142-
return "", errors.Wrap(err, "find file name")
143-
}
144-
145-
bundlePath := filepath.Join(tmpDir, strings.TrimSuffix(filename, ".tar.gz"))
146-
if err := os.MkdirAll(bundlePath, 0777); err != nil {
147-
return "", errors.Wrap(err, "create bundle dir")
148-
}
149-
150-
if err = writeVersionFile(bundlePath); err != nil {
151-
return "", errors.Wrap(err, "write version file")
152-
}
153-
154-
// Run collectors
155-
err = runCollectors(spec.Collectors, additionalRedactors, filename, bundlePath, opts)
156-
if err != nil {
157-
return "", errors.Wrap(err, "run collectors")
158-
}
159-
160-
if err := tarSupportBundleDir(bundlePath, filename); err != nil {
161-
return "", errors.Wrap(err, "create bundle file")
162-
}
163-
164-
return filename, nil
142+
return CollectSupportBundleFromSpec(&supportbundle.Spec, additionalRedactors, opts)
165143
}
166144

167145
// ProcessSupportBundleAfterCollection performs the after collection actions, like Callbacks and sending the archive to a remote server.
@@ -185,49 +163,15 @@ func ProcessSupportBundleAfterCollection(spec *troubleshootv1beta2.SupportBundle
185163
return fileUploaded, nil
186164
}
187165

188-
// AnalyzeAndExtractSupportBundle performs analysis on a support bundle using the archive and spec.
189-
func AnalyzeAndExtractSupportBundle(spec *troubleshootv1beta2.SupportBundleSpec, archivePath string) ([]*analyzer.AnalyzeResult, error) {
190-
191-
var analyzeResults []*analyzer.AnalyzeResult
192-
193-
if len(spec.Analyzers) > 0 {
194-
195-
tmpDir, err := ioutil.TempDir("", "troubleshoot")
196-
if err != nil {
197-
return analyzeResults, errors.Wrap(err, "failed to make directory for analysis")
198-
}
199-
defer os.RemoveAll(tmpDir)
200-
201-
f, err := os.Open(archivePath)
202-
if err != nil {
203-
return analyzeResults, errors.Wrap(err, "failed to open support bundle for analysis")
204-
}
205-
defer f.Close()
206-
207-
if err := analyzer.ExtractTroubleshootBundle(f, tmpDir); err != nil {
208-
return analyzeResults, errors.Wrap(err, "failed to extract support bundle for analysis")
209-
}
210-
211-
analyzeResults, err = analyzer.AnalyzeLocal(tmpDir, spec.Analyzers)
212-
if err != nil {
213-
return analyzeResults, errors.Wrap(err, "failed to analyze support bundle")
214-
}
215-
}
216-
return analyzeResults, nil
217-
}
218-
219166
// AnalyzeSupportBundle performs analysis on a support bundle using the support bundle spec and an already unpacked support
220167
// bundle on disk
221168
func AnalyzeSupportBundle(spec *troubleshootv1beta2.SupportBundleSpec, tmpDir string) ([]*analyzer.AnalyzeResult, error) {
222-
223-
var analyzeResults []*analyzer.AnalyzeResult
224-
225-
if len(spec.Analyzers) > 0 {
226-
227-
analyzeResults, err := analyzer.AnalyzeLocal(tmpDir, spec.Analyzers)
228-
if err != nil {
229-
return analyzeResults, errors.Wrap(err, "failed to analyze support bundle")
230-
}
169+
if len(spec.Analyzers) == 0 {
170+
return nil, nil
171+
}
172+
analyzeResults, err := analyzer.AnalyzeLocal(tmpDir, spec.Analyzers)
173+
if err != nil {
174+
return nil, errors.Wrap(err, "failed to analyze support bundle")
231175
}
232176
return analyzeResults, nil
233177
}

0 commit comments

Comments
 (0)