|
1 | 1 | package cli
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "bufio" |
4 | 5 | "context"
|
5 | 6 | "crypto/tls"
|
6 | 7 | "encoding/json"
|
@@ -38,6 +39,40 @@ import (
|
38 | 39 |
|
39 | 40 | func runTroubleshoot(v *viper.Viper, args []string) error {
|
40 | 41 | ctx := context.Background()
|
| 42 | + if len(args) == 1 && args[0] == "lint" { |
| 43 | + // Read from stdin |
| 44 | + scanner := bufio.NewScanner(os.Stdin) |
| 45 | + specYaml := "" |
| 46 | + for scanner.Scan() { |
| 47 | + input := scanner.Text() |
| 48 | + specYaml = fmt.Sprintf("%s\n%s", specYaml, input) |
| 49 | + } |
| 50 | + if err := scanner.Err(); err != nil { |
| 51 | + return fmt.Errorf("error reading standard input: %v", err) |
| 52 | + } |
| 53 | + fmt.Println(specYaml) |
| 54 | + return nil |
| 55 | + } else if len(args) > 1 && args[0] == "lint" { |
| 56 | + mainBundle, additionalRedactors, err := validateSpecs(args[1:], "") |
| 57 | + if err != nil { |
| 58 | + return err |
| 59 | + } |
| 60 | + 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} |
| 66 | + } |
| 67 | + |
| 68 | + out, err := k.ToYaml() |
| 69 | + if err != nil { |
| 70 | + return types.NewExitCodeError(constants.EXIT_CODE_CATCH_ALL, errors.Wrap(err, "failed to convert specs to yaml")) |
| 71 | + } |
| 72 | + fmt.Printf("%s", out) |
| 73 | + return nil |
| 74 | + } |
| 75 | + |
41 | 76 | if !v.GetBool("load-cluster-specs") && len(args) < 1 {
|
42 | 77 | return errors.New("flag load-cluster-specs must be set if no specs are provided on the command line")
|
43 | 78 | }
|
@@ -277,6 +312,80 @@ func loadSupportBundleSpecsFromURIs(ctx context.Context, kinds *loader.Troublesh
|
277 | 312 | return nil
|
278 | 313 | }
|
279 | 314 |
|
| 315 | +func validateSpecs(args []string, specYaml string) (*troubleshootv1beta2.SupportBundle, *troubleshootv1beta2.Redactor, error) { |
| 316 | + // Append redactor uris to the args |
| 317 | + allArgs := append(args, viper.GetStringSlice("redactors")...) |
| 318 | + fmt.Println(allArgs) |
| 319 | + kinds, err := specs.LoadFromCLIArgs(context.TODO(), nil, allArgs, viper.GetViper()) |
| 320 | + if err != nil { |
| 321 | + return nil, nil, err |
| 322 | + } |
| 323 | + |
| 324 | + // Check if we have any collectors to run in the troubleshoot specs |
| 325 | + // TODO: Do we use the RemoteCollectors anymore? |
| 326 | + if len(kinds.CollectorsV1Beta2) == 0 && |
| 327 | + len(kinds.HostCollectorsV1Beta2) == 0 && |
| 328 | + len(kinds.SupportBundlesV1Beta2) == 0 { |
| 329 | + return nil, nil, errors.New("no collectors specified to run") |
| 330 | + } |
| 331 | + |
| 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 | + }, |
| 343 | + } |
| 344 | + for _, sb := range kinds.SupportBundlesV1Beta2 { |
| 345 | + sb := sb |
| 346 | + mainBundle = supportbundle.ConcatSpec(mainBundle, &sb) |
| 347 | + } |
| 348 | + |
| 349 | + for _, c := range kinds.CollectorsV1Beta2 { |
| 350 | + mainBundle.Spec.Collectors = util.Append(mainBundle.Spec.Collectors, c.Spec.Collectors) |
| 351 | + } |
| 352 | + |
| 353 | + for _, hc := range kinds.HostCollectorsV1Beta2 { |
| 354 | + mainBundle.Spec.HostCollectors = util.Append(mainBundle.Spec.HostCollectors, hc.Spec.Collectors) |
| 355 | + } |
| 356 | + |
| 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 | + ) |
| 371 | + } |
| 372 | + |
| 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 | + }, |
| 381 | + } |
| 382 | + for _, r := range kinds.RedactorsV1Beta2 { |
| 383 | + additionalRedactors.Spec.Redactors = util.Append(additionalRedactors.Spec.Redactors, r.Spec.Redactors) |
| 384 | + } |
| 385 | + |
| 386 | + return mainBundle, additionalRedactors, nil |
| 387 | +} |
| 388 | + |
280 | 389 | func loadSpecs(ctx context.Context, args []string, client kubernetes.Interface) (*troubleshootv1beta2.SupportBundle, *troubleshootv1beta2.Redactor, error) {
|
281 | 390 | // Append redactor uris to the args
|
282 | 391 | allArgs := append(args, viper.GetStringSlice("redactors")...)
|
|
0 commit comments