Skip to content

Commit

Permalink
Merge pull request #215 from replicatedhq/analyzer-cli
Browse files Browse the repository at this point in the history
Interactive results for support bundle kinds
  • Loading branch information
marccampbell authored Jun 12, 2020
2 parents 890cbb1 + b070b40 commit d98172e
Show file tree
Hide file tree
Showing 2 changed files with 223 additions and 7 deletions.
200 changes: 200 additions & 0 deletions cmd/troubleshoot/cli/interactive_results.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
package cli

import (
"fmt"
"io/ioutil"
"os"
"path"
"time"

ui "github.com/gizak/termui/v3"
"github.com/gizak/termui/v3/widgets"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/cmd/util"
analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
)

var (
selectedResult = 0
isShowingSaved = false
)

func showInteractiveResults(analyzeResults []*analyzerunner.AnalyzeResult) error {
if err := ui.Init(); err != nil {
return errors.Wrap(err, "failed to create terminal ui")
}
defer ui.Close()
drawUI(analyzeResults)

uiEvents := ui.PollEvents()
for {
select {
case e := <-uiEvents:
switch e.ID {
case "<C-c>":
return nil
case "q":
if isShowingSaved == true {
isShowingSaved = false
ui.Clear()
drawUI(analyzeResults)
} else {
return nil
}
case "s":
filename, err := save(analyzeResults)
if err != nil {
// show
} else {
showSaved(filename)
go func() {
time.Sleep(time.Second * 5)
isShowingSaved = false
ui.Clear()
drawUI(analyzeResults)
}()
}
case "<Resize>":
ui.Clear()
drawUI(analyzeResults)
case "<Down>":
if selectedResult < len(analyzeResults)-1 {
selectedResult++
} else {
selectedResult = 0
}
ui.Clear()
drawUI(analyzeResults)
case "<Up>":
if selectedResult > 0 {
selectedResult--
} else {
selectedResult = len(analyzeResults) - 1
}
ui.Clear()
drawUI(analyzeResults)
}
}
}
}

func drawUI(analyzeResults []*analyzerunner.AnalyzeResult) {
drawGrid(analyzeResults)
drawFooter()
}

func drawGrid(analyzeResults []*analyzerunner.AnalyzeResult) {
termWidth, _ := ui.TerminalDimensions()

tileWidth := 40
tileHeight := 10

columnCount := termWidth / tileWidth

row := 0
col := 0

for _, analyzeResult := range analyzeResults {
// draw this file

tile := widgets.NewParagraph()
tile.Title = analyzeResult.Title
tile.Text = analyzeResult.Message
tile.PaddingLeft = 1
tile.PaddingBottom = 1
tile.PaddingRight = 1
tile.PaddingTop = 1

tile.SetRect(col*tileWidth, row*tileHeight, col*tileWidth+tileWidth, row*tileHeight+tileHeight)

if analyzeResult.IsFail {
tile.BorderStyle.Fg = ui.ColorRed
} else if analyzeResult.IsWarn {
tile.BorderStyle.Fg = ui.ColorYellow
} else {
tile.BorderStyle.Fg = ui.ColorGreen
}

ui.Render(tile)

col++

if col >= columnCount {
col = 0
row++
}
}
}

func drawFooter() {
termWidth, termHeight := ui.TerminalDimensions()

instructions := widgets.NewParagraph()
instructions.Text = "[q] quit [s] save [↑][↓] scroll"
instructions.Border = false

left := 0
right := termWidth
top := termHeight - 1
bottom := termHeight

instructions.SetRect(left, top, right, bottom)
ui.Render(instructions)
}

func showSaved(filename string) {
termWidth, termHeight := ui.TerminalDimensions()

savedMessage := widgets.NewParagraph()
savedMessage.Text = fmt.Sprintf("Preflight results saved to\n\n%s", filename)
savedMessage.WrapText = true
savedMessage.Border = true

left := termWidth/2 - 20
right := termWidth/2 + 20
top := termHeight/2 - 4
bottom := termHeight/2 + 4

savedMessage.SetRect(left, top, right, bottom)
ui.Render(savedMessage)

isShowingSaved = true
}

func save(analyzeResults []*analyzerunner.AnalyzeResult) (string, error) {
filename := path.Join(util.HomeDir(), fmt.Sprintf("%s-results.txt", "support-bundle"))
_, err := os.Stat(filename)
if err == nil {
os.Remove(filename)
}

results := ""
for _, analyzeResult := range analyzeResults {
result := ""

if analyzeResult.IsPass {
result = "Check PASS\n"
} else if analyzeResult.IsWarn {
result = "Check WARN\n"
} else if analyzeResult.IsFail {
result = "Check FAIL\n"
}

result = result + fmt.Sprintf("Title: %s\n", analyzeResult.Title)
result = result + fmt.Sprintf("Message: %s\n", analyzeResult.Message)

if analyzeResult.URI != "" {
result = result + fmt.Sprintf("URI: %s\n", analyzeResult.URI)
}

result = result + "\n------------\n"

results = results + result
}

if err := ioutil.WriteFile(filename, []byte(results), 0644); err != nil {
return "", errors.Wrap(err, "failed to save preflight results")
}

return filename, nil
}
30 changes: 23 additions & 7 deletions cmd/troubleshoot/cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ func runTroubleshoot(v *viper.Viper, arg string) error {
s := spin.New()
finishedCh := make(chan bool, 1)
progressChan := make(chan interface{}, 0) // non-zero buffer can result in missed messages
isFinishedChClosed := false
go func() {
currentDir := ""
for {
Expand All @@ -124,7 +125,9 @@ func runTroubleshoot(v *viper.Viper, arg string) error {
}
}()
defer func() {
close(finishedCh)
if !isFinishedChClosed {
close(finishedCh)
}
}()

archivePath, err := runCollectors(v, supportBundleSpec.Spec.Collectors, additionalRedactors, progressChan)
Expand Down Expand Up @@ -180,14 +183,27 @@ func runTroubleshoot(v *viper.Viper, arg string) error {
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)
interactive := isatty.IsTerminal(os.Stdout.Fd())

if interactive {
close(finishedCh) // this removes the spinner
isFinishedChClosed = true

if err := showInteractiveResults(analyzeResults); err != nil {
interactive = false
}
}

fmt.Printf("%s", formatted)
if !interactive {
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 {
Expand Down

0 comments on commit d98172e

Please sign in to comment.