Skip to content

Commit a5f4afb

Browse files
committed
added lint subcommand
1 parent b7f499c commit a5f4afb

14 files changed

+904
-0
lines changed

cmd/preflight/cli/lint.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package cli
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/pkg/errors"
8+
"github.com/replicatedhq/troubleshoot/pkg/constants"
9+
"github.com/replicatedhq/troubleshoot/pkg/lint"
10+
"github.com/spf13/cobra"
11+
"github.com/spf13/viper"
12+
)
13+
14+
func LintCmd() *cobra.Command {
15+
cmd := &cobra.Command{
16+
Use: "lint [spec-files...]",
17+
Args: cobra.MinimumNArgs(1),
18+
Short: "Lint v1beta3 preflight specs for syntax and structural errors",
19+
Long: `Lint v1beta3 preflight specs for syntax and structural errors.
20+
21+
This command validates v1beta3 preflight specs and checks for:
22+
- YAML syntax errors
23+
- Missing required fields (apiVersion, kind, metadata, spec)
24+
- Invalid template syntax ({{ .Values.* }})
25+
- Missing analyzers or collectors
26+
- Common structural issues
27+
- Missing docStrings (warning)
28+
29+
The linter only validates v1beta3 specs. For v1beta2 specs, use the 'convert' command first.
30+
31+
Examples:
32+
# Lint a single spec file
33+
preflight lint my-preflight.yaml
34+
35+
# Lint multiple spec files
36+
preflight lint spec1.yaml spec2.yaml spec3.yaml
37+
38+
# Lint with automatic fixes
39+
preflight lint --fix my-preflight.yaml
40+
41+
# Lint and output as JSON for CI/CD integration
42+
preflight lint --format json my-preflight.yaml
43+
44+
Exit codes:
45+
0 - No errors found
46+
2 - Validation errors found`,
47+
PreRun: func(cmd *cobra.Command, args []string) {
48+
viper.BindPFlags(cmd.Flags())
49+
},
50+
RunE: func(cmd *cobra.Command, args []string) error {
51+
v := viper.GetViper()
52+
53+
opts := lint.LintOptions{
54+
FilePaths: args,
55+
Fix: v.GetBool("fix"),
56+
Format: v.GetString("format"),
57+
}
58+
59+
return runLint(opts)
60+
},
61+
}
62+
63+
cmd.Flags().Bool("fix", false, "Automatically fix issues where possible")
64+
cmd.Flags().String("format", "text", "Output format: text or json")
65+
66+
return cmd
67+
}
68+
69+
func runLint(opts lint.LintOptions) error {
70+
// Validate file paths exist
71+
for _, filePath := range opts.FilePaths {
72+
if _, err := os.Stat(filePath); err != nil {
73+
return errors.Wrapf(err, "file not found: %s", filePath)
74+
}
75+
}
76+
77+
// Run linting
78+
results, err := lint.LintFiles(opts)
79+
if err != nil {
80+
return errors.Wrap(err, "failed to lint files")
81+
}
82+
83+
// Format and print results
84+
output := lint.FormatResults(results, opts.Format)
85+
fmt.Print(output)
86+
87+
// Return appropriate exit code
88+
if lint.HasErrors(results) {
89+
os.Exit(constants.EXIT_CODE_SPEC_ISSUES)
90+
}
91+
92+
return nil
93+
}

cmd/preflight/cli/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ that a cluster meets the requirements to run an application.`,
8989
cmd.AddCommand(TemplateCmd())
9090
cmd.AddCommand(DocsCmd())
9191
cmd.AddCommand(ConvertCmd())
92+
cmd.AddCommand(LintCmd())
9293

9394
preflight.AddFlags(cmd.PersistentFlags())
9495

cmd/troubleshoot/cli/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ If no arguments are provided, specs are automatically loaded from the cluster by
109109
cmd.AddCommand(Schedule())
110110
cmd.AddCommand(UploadCmd())
111111
cmd.AddCommand(util.VersionCmd())
112+
cmd.AddCommand(LintCmd())
112113

113114
cmd.Flags().StringSlice("redactors", []string{}, "names of the additional redactors to use")
114115
cmd.Flags().Bool("redact", true, "enable/disable default redactions")
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
apiVersion: troubleshoot.sh/v1beta3
2+
kind: Preflight
3+
metadata:
4+
name: helm-builtins-example
5+
labels:
6+
release: {{ .Release.Name }}
7+
spec:
8+
analyzers:
9+
- docString: |
10+
Title: Example using Helm builtin objects
11+
Requirement: Demonstrates .Values, .Release, .Chart, etc.
12+
13+
Supported Helm builtin objects:
14+
- .Values.* - User-provided values
15+
- .Release.Name - Release name (default: "preflight")
16+
- .Release.Namespace - Release namespace (default: "default")
17+
- .Release.IsInstall - Whether this is an install (true)
18+
- .Release.IsUpgrade - Whether this is an upgrade (false)
19+
- .Release.Revision - Release revision (1)
20+
- .Chart.Name - Chart name
21+
- .Chart.Version - Chart version
22+
- .Capabilities.KubeVersion - Kubernetes version capabilities
23+
clusterVersion:
24+
checkName: Kubernetes version check in {{ .Release.Namespace }}
25+
outcomes:
26+
- fail:
27+
when: '< {{ .Values.minVersion | default "1.19.0" }}'
28+
message: |
29+
Release {{ .Release.Name }} requires Kubernetes {{ .Values.minVersion | default "1.19.0" }} or later.
30+
Chart: {{ .Chart.Name }}
31+
- pass:
32+
when: '>= {{ .Values.minVersion | default "1.19.0" }}'
33+
message: Kubernetes version is supported for release {{ .Release.Name }}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
apiVersion: troubleshoot.sh/v1beta3
2+
kind: Preflight
3+
metadata
4+
name: invalid-yaml
5+
spec:
6+
analyzers:
7+
- clusterVersion:
8+
checkName: Kubernetes version
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
kind: Preflight
2+
metadata:
3+
name: missing-apiversion
4+
spec:
5+
analyzers:
6+
- clusterVersion:
7+
checkName: Kubernetes version
8+
outcomes:
9+
- pass:
10+
when: '>= 1.19.0'
11+
message: Kubernetes version is supported
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
apiVersion: troubleshoot.sh/v1beta3
2+
kind: Preflight
3+
spec:
4+
analyzers:
5+
- clusterVersion:
6+
checkName: Kubernetes version
7+
outcomes:
8+
- pass:
9+
when: '>= 1.19.0'
10+
message: Kubernetes version is supported
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: troubleshoot.sh/v1beta3
2+
kind: Preflight
3+
metadata:
4+
name: no-analyzers
5+
spec:
6+
collectors:
7+
- clusterInfo: {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
apiVersion: troubleshoot.sh/v1beta3
2+
kind: Preflight
3+
metadata:
4+
name: simple-no-template
5+
spec:
6+
analyzers:
7+
- docString: |
8+
Title: Kubernetes Version Check
9+
Requirement: Kubernetes 1.19.0 or later
10+
clusterVersion:
11+
checkName: Kubernetes version
12+
outcomes:
13+
- fail:
14+
when: '< 1.19.0'
15+
message: Kubernetes version must be at least 1.19.0
16+
- pass:
17+
when: '>= 1.19.0'
18+
message: Kubernetes version is supported
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
apiVersion: troubleshoot.sh/v1beta3
2+
kind: SupportBundle
3+
metadata:
4+
name: no-collectors
5+
spec:
6+
analyzers:
7+
- clusterVersion:
8+
checkName: Kubernetes version
9+
outcomes:
10+
- pass:
11+
when: '>= 1.19.0'
12+
message: Kubernetes version is supported

0 commit comments

Comments
 (0)