Skip to content

Commit 324f069

Browse files
committed
add lint tips
1 parent b9a13e5 commit 324f069

File tree

1 file changed

+101
-54
lines changed

1 file changed

+101
-54
lines changed

cmd/troubleshoot/cli/run.go

Lines changed: 101 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"os"
1111
"os/signal"
1212
"path/filepath"
13+
"reflect"
14+
"strings"
1315
"sync"
1416
"time"
1517

@@ -31,6 +33,7 @@ import (
3133
"github.com/replicatedhq/troubleshoot/pkg/types"
3234
"github.com/spf13/viper"
3335
spin "github.com/tj/go-spin"
36+
"gopkg.in/yaml.v3"
3437
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3538
"k8s.io/client-go/kubernetes"
3639
"k8s.io/client-go/rest"
@@ -53,22 +56,20 @@ func runTroubleshoot(v *viper.Viper, args []string) error {
5356
fmt.Println(specYaml)
5457
return nil
5558
} else if len(args) > 1 && args[0] == "lint" {
56-
mainBundle, additionalRedactors, err := validateSpecs(args[1:], "")
59+
supportBundles, err := validateSpecs(args[1:], "")
5760
if err != nil {
5861
return err
5962
}
63+
6064
k := loader.TroubleshootKinds{
61-
SupportBundlesV1Beta2: []troubleshootv1beta2.SupportBundle{*mainBundle},
62-
}
63-
// If we have redactors, add them to the temp kinds object
64-
if len(additionalRedactors.Spec.Redactors) > 0 {
65-
k.RedactorsV1Beta2 = []troubleshootv1beta2.Redactor{*additionalRedactors}
65+
SupportBundlesV1Beta2: *supportBundles,
6666
}
6767

6868
out, err := k.ToYaml()
6969
if err != nil {
7070
return types.NewExitCodeError(constants.EXIT_CODE_CATCH_ALL, errors.Wrap(err, "failed to convert specs to yaml"))
7171
}
72+
fmt.Println("-----------\n")
7273
fmt.Printf("%s", out)
7374
return nil
7475
}
@@ -312,78 +313,124 @@ func loadSupportBundleSpecsFromURIs(ctx context.Context, kinds *loader.Troublesh
312313
return nil
313314
}
314315

315-
func validateSpecs(args []string, specYaml string) (*troubleshootv1beta2.SupportBundle, *troubleshootv1beta2.Redactor, error) {
316+
func validateSpecs(args []string, specYaml string) (*[]troubleshootv1beta2.SupportBundle, error) {
316317
// Append redactor uris to the args
317318
allArgs := append(args, viper.GetStringSlice("redactors")...)
318-
fmt.Println(allArgs)
319319
kinds, err := specs.LoadFromCLIArgs(context.TODO(), nil, allArgs, viper.GetViper())
320320
if err != nil {
321-
return nil, nil, err
321+
return nil, err
322322
}
323323

324324
// Check if we have any collectors to run in the troubleshoot specs
325-
// TODO: Do we use the RemoteCollectors anymore?
326325
if len(kinds.CollectorsV1Beta2) == 0 &&
327326
len(kinds.HostCollectorsV1Beta2) == 0 &&
328327
len(kinds.SupportBundlesV1Beta2) == 0 {
329-
return nil, nil, errors.New("no collectors specified to run")
328+
return nil, errors.New("no collectors specified to run")
330329
}
331330

332-
// Merge specs
333-
// We need to add the default type information to the support bundle spec
334-
// since by default these fields would be empty
335-
mainBundle := &troubleshootv1beta2.SupportBundle{
336-
TypeMeta: metav1.TypeMeta{
337-
APIVersion: "troubleshoot.sh/v1beta2",
338-
Kind: "SupportBundle",
339-
},
340-
ObjectMeta: metav1.ObjectMeta{
341-
Name: "merged-support-bundle-spec",
342-
},
331+
for _, arg := range args {
332+
err := checkSpecStructure(arg)
333+
if err != nil {
334+
return nil, err
335+
}
343336
}
337+
344338
for _, sb := range kinds.SupportBundlesV1Beta2 {
345339
sb := sb
346-
mainBundle = supportbundle.ConcatSpec(mainBundle, &sb)
340+
warning := validateTroubleshootSpecsItems(sb.Spec.Collectors, sb.Spec.Analyzers)
341+
if warning != nil {
342+
return nil, errors.New(warning.Warning())
343+
}
347344
}
348345

349-
for _, c := range kinds.CollectorsV1Beta2 {
350-
mainBundle.Spec.Collectors = util.Append(mainBundle.Spec.Collectors, c.Spec.Collectors)
351-
}
346+
// for _, c := range kinds.CollectorsV1Beta2 {
347+
// mainBundle.Spec.Collectors = util.Append(mainBundle.Spec.Collectors, c.Spec.Collectors)
348+
// }
352349

353-
for _, hc := range kinds.HostCollectorsV1Beta2 {
354-
mainBundle.Spec.HostCollectors = util.Append(mainBundle.Spec.HostCollectors, hc.Spec.Collectors)
355-
}
350+
// for _, hc := range kinds.HostCollectorsV1Beta2 {
351+
// mainBundle.Spec.HostCollectors = util.Append(mainBundle.Spec.HostCollectors, hc.Spec.Collectors)
352+
// }
356353

357-
if !(len(mainBundle.Spec.HostCollectors) > 0 && len(mainBundle.Spec.Collectors) == 0) {
358-
// Always add default collectors unless we only have host collectors
359-
// We need to add them here so when we --dry-run, these collectors
360-
// are included. supportbundle.runCollectors duplicates this bit.
361-
// We'll need to refactor it out later when its clearer what other
362-
// code depends on this logic e.g KOTS
363-
mainBundle.Spec.Collectors = collect.EnsureCollectorInList(
364-
mainBundle.Spec.Collectors,
365-
troubleshootv1beta2.Collect{ClusterInfo: &troubleshootv1beta2.ClusterInfo{}},
366-
)
367-
mainBundle.Spec.Collectors = collect.EnsureCollectorInList(
368-
mainBundle.Spec.Collectors,
369-
troubleshootv1beta2.Collect{ClusterResources: &troubleshootv1beta2.ClusterResources{}},
370-
)
354+
return &kinds.SupportBundlesV1Beta2, nil
355+
}
356+
357+
func validateTroubleshootSpecsItems(collectors []*troubleshootv1beta2.Collect, analyzers []*troubleshootv1beta2.Analyze) *types.ExitCodeWarning {
358+
numberOfCollectors := len(collectors)
359+
numberOfAnalyzers := len(analyzers)
360+
361+
if numberOfCollectors > 0 {
362+
for _, c := range collectors {
363+
if isStructEmpty(c) {
364+
return types.NewExitCodeWarning("Wrong collector found")
365+
}
366+
}
367+
} else {
368+
return types.NewExitCodeWarning("No collectors found")
371369
}
372370

373-
additionalRedactors := &troubleshootv1beta2.Redactor{
374-
TypeMeta: metav1.TypeMeta{
375-
APIVersion: "troubleshoot.sh/v1beta2",
376-
Kind: "Redactor",
377-
},
378-
ObjectMeta: metav1.ObjectMeta{
379-
Name: "merged-redactors-spec",
380-
},
371+
if numberOfAnalyzers > 0 {
372+
for _, a := range analyzers {
373+
if isStructEmpty(a) {
374+
return types.NewExitCodeWarning("Wrong analyzer found")
375+
}
376+
}
377+
} else {
378+
return types.NewExitCodeWarning("No analyzers found")
381379
}
382-
for _, r := range kinds.RedactorsV1Beta2 {
383-
additionalRedactors.Spec.Redactors = util.Append(additionalRedactors.Spec.Redactors, r.Spec.Redactors)
380+
return nil
381+
}
382+
383+
func checkSpecStructure(path string) error {
384+
if _, err := os.Stat(path); err == nil {
385+
rawSpec, err := os.ReadFile(path)
386+
if err != nil {
387+
return types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, err)
388+
}
389+
390+
decoder := yaml.NewDecoder(strings.NewReader(string(rawSpec)))
391+
var node yaml.Node
392+
err = decoder.Decode(&node)
393+
if err != nil {
394+
return err
395+
}
396+
397+
for _, n := range node.Content[0].Content { // Traverse the root map
398+
if n.Kind == yaml.MappingNode && n.Tag == "!!map" {
399+
for i := 0; i < len(n.Content); i += 2 {
400+
keyNode := n.Content[i]
401+
valNode := n.Content[i+1]
402+
if keyNode.Value == "analyzers" {
403+
for _, specNode := range valNode.Content {
404+
for j := 0; j < len(specNode.Content); j += 2 {
405+
analyzerKey := specNode.Content[j]
406+
analyzerVal := specNode.Content[j+1]
407+
if analyzerKey.Value == "distribution" {
408+
if len(analyzerVal.Content) == 0 {
409+
fmt.Println("distribution is empty")
410+
if specNode.Content[j+2] != nil && specNode.Content[j+2].Value == "outcomes" {
411+
fmt.Println("outcomes is misaligned in distribution")
412+
}
413+
}
414+
}
415+
}
416+
}
417+
}
418+
}
419+
}
420+
}
384421
}
385422

386-
return mainBundle, additionalRedactors, nil
423+
return nil
424+
}
425+
426+
func isStructEmpty(s interface{}) bool {
427+
val := reflect.ValueOf(s).Elem()
428+
for i := 0; i < val.NumField(); i++ {
429+
if !val.Field(i).IsNil() {
430+
return false
431+
}
432+
}
433+
return true
387434
}
388435

389436
func loadSpecs(ctx context.Context, args []string, client kubernetes.Interface) (*troubleshootv1beta2.SupportBundle, *troubleshootv1beta2.Redactor, error) {

0 commit comments

Comments
 (0)