Skip to content

Commit

Permalink
Merge pull request #6 from replicatedhq/preflight
Browse files Browse the repository at this point in the history
Add StorageClass and CRD preflight
  • Loading branch information
marccampbell authored Jul 17, 2019
2 parents 9b4b03c + 92862ff commit cc8bf57
Show file tree
Hide file tree
Showing 15 changed files with 489 additions and 32 deletions.
104 changes: 104 additions & 0 deletions cmd/preflight/cli/interactive_results.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package cli

import (
"fmt"

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

type nodeValue string

func (nv nodeValue) String() string {
return string(nv)
}

func showInteractiveResults(analyzeResults []*analyzerunner.AnalyzeResult) error {
if err := ui.Init(); err != nil {
return err
}
defer ui.Close()

selectedResult := 0

preflightTable := getPreflightTable(analyzeResults)
details := getDetails(analyzeResults[selectedResult])

grid := ui.NewGrid()
termWidth, termHeight := ui.TerminalDimensions()
grid.SetRect(0, 0, termWidth, termHeight)

grid.Set(
ui.NewRow(1.0,
ui.NewCol(1.0/2, preflightTable),
ui.NewCol(1.0/2, details),
),
)

ui.Render(grid)

uiEvents := ui.PollEvents()
for {
select {
case e := <-uiEvents:
switch e.ID {
case "q", "<C-c>":
return nil
case "<Resize>":
payload := e.Payload.(ui.Resize)
grid.SetRect(0, 0, payload.Width, payload.Height)
ui.Clear()
ui.Render(grid)
}
}
}
}

func getPreflightTable(analyzeResults []*analyzerunner.AnalyzeResult) *widgets.Table {
table := widgets.NewTable()
table.Border = true
table.Rows = [][]string{}

for i, analyzeResult := range analyzeResults {
table.Rows = append(table.Rows, []string{
analyzeResult.Title,
})

if analyzeResult.IsPass {
table.RowStyles[i] = ui.NewStyle(ui.ColorGreen, ui.ColorClear, ui.ModifierBold)
} else if analyzeResult.IsWarn {
table.RowStyles[i] = ui.NewStyle(ui.ColorYellow, ui.ColorClear, ui.ModifierBold)
} else if analyzeResult.IsFail {
table.RowStyles[i] = ui.NewStyle(ui.ColorRed, ui.ColorClear)
}
}

return table
}

func getDetails(analysisResult *analyzerunner.AnalyzeResult) *ui.Grid {
grid := ui.NewGrid()

entries := []interface{}{}

title := widgets.NewParagraph()
title.Text = analysisResult.Title
title.Border = false
entries = append(entries, ui.NewRow(0.2, ui.NewCol(1.0, title)))

message := widgets.NewParagraph()
message.Text = analysisResult.Message
message.Border = false
entries = append(entries, ui.NewRow(0.2, ui.NewCol(1.0, message)))

if analysisResult.URI != "" {
uri := widgets.NewParagraph()
uri.Text = fmt.Sprintf("For more information: %s", analysisResult.URI)
uri.Border = false
entries = append(entries, ui.NewRow(0.2, ui.NewCol(1.0, uri)))
}

grid.Set(entries...)
return grid
}
3 changes: 3 additions & 0 deletions cmd/preflight/cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ func Run() *cobra.Command {
},
}

cmd.Flags().Bool("interactive", true, "interactive preflights")
cmd.Flags().String("format", "human", "output format, one of human, json, yaml. only used when interactive is set to false")

cmd.Flags().String("preflight", "", "name of the preflight to use")
cmd.Flags().String("namespace", "default", "namespace the preflight can be found in")

Expand Down
9 changes: 8 additions & 1 deletion cmd/preflight/cli/run_nocrd.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,21 @@ func runPreflightsNoCRD(v *viper.Viper, arg string) error {
return contents, nil
}

analyzeResults := []*analyzerunner.AnalyzeResult{}
for _, analyzer := range preflight.Spec.Analyzers {
analyzeResult, err := analyzerunner.Analyze(analyzer, getCollectedFileContents)
if err != nil {
return err
}

fmt.Printf("%#v\n", analyzeResult)
analyzeResults = append(analyzeResults, analyzeResult)
}

if v.GetBool("interactive") {
return showInteractiveResults(analyzeResults)
}

fmt.Printf("only interactive results are supported\n")
return nil
}

Expand Down
50 changes: 48 additions & 2 deletions config/crds/troubleshoot.replicated.com_preflights.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,49 @@ spec:
properties:
clusterVersion:
properties:
checkName:
type: string
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
required:
- outcomes
type: object
customResourceDefinition:
properties:
checkName:
type: string
customResourceDefinitionName:
type: string
outcomes:
items:
properties:
Expand Down Expand Up @@ -430,10 +473,11 @@ spec:
type: array
required:
- outcomes
- customResourceDefinitionName
type: object
storageClass:
properties:
name:
checkName:
type: string
outcomes:
items:
Expand Down Expand Up @@ -467,9 +511,11 @@ spec:
type: object
type: object
type: array
storageClassName:
type: string
required:
- outcomes
- name
- storageClassName
type: object
type: object
type: array
Expand Down
53 changes: 51 additions & 2 deletions config/crds/zz_generated.deepcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ func (in *Analyze) DeepCopyInto(out *Analyze) {
*out = new(StorageClass)
(*in).DeepCopyInto(*out)
}
if in.CustomResourceDefinition != nil {
in, out := &in.CustomResourceDefinition, &out.CustomResourceDefinition
*out = new(CustomResourceDefinition)
(*in).DeepCopyInto(*out)
}
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Analyze.
Expand All @@ -33,6 +38,21 @@ func (in *Analyze) DeepCopy() *Analyze {
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AnalyzeMeta) DeepCopyInto(out *AnalyzeMeta) {
*out = *in
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AnalyzeMeta.
func (in *AnalyzeMeta) DeepCopy() *AnalyzeMeta {
if in == nil {
return nil
}
out := new(AnalyzeMeta)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Analyzer) DeepCopyInto(out *Analyzer) {
*out = *in
Expand Down Expand Up @@ -244,6 +264,7 @@ func (in *ClusterResources) DeepCopy() *ClusterResources {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterVersion) DeepCopyInto(out *ClusterVersion) {
*out = *in
out.AnalyzeMeta = in.AnalyzeMeta
if in.Outcomes != nil {
in, out := &in.Outcomes, &out.Outcomes
*out = make([]*Outcome, len(*in))
Expand Down Expand Up @@ -496,6 +517,33 @@ func (in *CollectorStatus) DeepCopy() *CollectorStatus {
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CustomResourceDefinition) DeepCopyInto(out *CustomResourceDefinition) {
*out = *in
out.AnalyzeMeta = in.AnalyzeMeta
if in.Outcomes != nil {
in, out := &in.Outcomes, &out.Outcomes
*out = make([]*Outcome, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = new(Outcome)
(*in).DeepCopyInto(*out)
}
}
}
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinition.
func (in *CustomResourceDefinition) DeepCopy() *CustomResourceDefinition {
if in == nil {
return nil
}
out := new(CustomResourceDefinition)
in.DeepCopyInto(out)
return out
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Outcome) DeepCopyInto(out *Outcome) {
*out = *in
Expand Down Expand Up @@ -790,8 +838,9 @@ func (in *SingleOutcome) DeepCopy() *SingleOutcome {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *StorageClass) DeepCopyInto(out *StorageClass) {
*out = *in
if in.Outcome != nil {
in, out := &in.Outcome, &out.Outcome
out.AnalyzeMeta = in.AnalyzeMeta
if in.Outcomes != nil {
in, out := &in.Outcomes, &out.Outcomes
*out = make([]*Outcome, len(*in))
for i := range *in {
if (*in)[i] != nil {
Expand Down
29 changes: 17 additions & 12 deletions config/samples/troubleshoot_v1beta1_preflight.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@ spec:
- fail:
when: "< 1.14.0"
message: You need more kubernetes
uri: https://help.replicated.com/kubernetes-version
- warn:
when: "< 1.15.0"
message: You have barely enough kubernetes
uri: https://help.replicated.com/kubernetes-version
- pass:
message: Good job keeping k8s current
# - storageClass:
# name: "my-custom-storage-class"
# fail:
# message: The custom storage class thing was not found
# pass:
# message: All good on storage classes
- storageClass:
checkName: Required storage classes
storageClassName: "microk8s-hostpath"
outcomes:
- fail:
message: The micr0k8s storage class thing was not found
- pass:
message: All good on storage classes
# - manifests:
# - secret:
# namespace: default
Expand All @@ -43,9 +47,10 @@ spec:
# message: Can't pull the images
# pass:
# message: Connected to docker registry
# - customResourceDefinitions:
# name: rook
# fail:
# message: You don't have rook installed
# pass:
# message: Found rook!
- customResourceDefinition:
customResourceDefinitionName: rook
outcomes:
- fail:
message: You don't have rook installed
- pass:
message: Found rook!
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ require (
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c // indirect
github.com/dsnet/compress v0.0.1 // indirect
github.com/gin-gonic/gin v1.4.0
github.com/gizak/termui/v3 v3.1.0
github.com/golang/snappy v0.0.1 // indirect
github.com/manifoldco/promptui v0.3.2
github.com/mholt/archiver v3.1.1+incompatible
github.com/nwaples/rardecode v1.0.0 // indirect
github.com/onsi/gomega v1.5.0
Expand All @@ -21,6 +23,7 @@ require (
golang.org/x/net v0.0.0-20190522155817-f3200d17e092
gopkg.in/yaml.v2 v2.2.2
k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b
k8s.io/apiextensions-apiserver v0.0.0-20190409022649-727a075fdec8
k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d
k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible
sigs.k8s.io/controller-runtime v0.2.0-beta.2
Expand Down
Loading

0 comments on commit cc8bf57

Please sign in to comment.