@@ -4,14 +4,11 @@ import (
4
4
"errors"
5
5
"fmt"
6
6
"log"
7
- "strings"
8
7
9
- "github.com/daveshanley/vacuum/motor"
10
- "github.com/daveshanley/vacuum/rulesets"
8
+ "github.com/kong/deck/lint"
11
9
"github.com/kong/go-apiops/filebasics"
12
10
"github.com/kong/go-apiops/logbasics"
13
11
"github.com/spf13/cobra"
14
- "sigs.k8s.io/yaml"
15
12
)
16
13
17
14
var (
@@ -24,156 +21,24 @@ var (
24
21
25
22
const plainTextFormat = "plain"
26
23
27
- type Severity int
28
-
29
- const (
30
- SeverityHint Severity = iota
31
- SeverityInfo
32
- SeverityWarn
33
- SeverityError
34
- )
35
-
36
- var severityStrings = [... ]string {
37
- "hint" ,
38
- "info" ,
39
- "warn" ,
40
- "error" ,
41
- }
42
-
43
- type LintResult struct {
44
- Message string
45
- Severity string
46
- Line int
47
- Column int
48
- Character int
49
- Path string
50
- }
51
-
52
- func ParseSeverity (s string ) Severity {
53
- for i , str := range severityStrings {
54
- if s == str {
55
- return Severity (i )
56
- }
57
- }
58
- return SeverityWarn
59
- }
60
-
61
- func isOpenAPISpec (fileBytes []byte ) bool {
62
- var contents map [string ]interface {}
63
-
64
- // This marshalling is redundant with what happens
65
- // in the linting command. There is likely an algorithm
66
- // we could use to determine JSON vs YAML and pull out the
67
- // openapi key without unmarshalling the entire file.
68
- err := yaml .Unmarshal (fileBytes , & contents )
69
- if err != nil {
70
- return false
71
- }
72
-
73
- return contents ["openapi" ] != nil
74
- }
75
-
76
- // getRuleSet reads the ruleset file by the provided name and returns a RuleSet object.
77
- func getRuleSet (ruleSetFile string ) (* rulesets.RuleSet , error ) {
78
- ruleSetBytes , err := filebasics .ReadFile (ruleSetFile )
79
- if err != nil {
80
- return nil , fmt .Errorf ("error reading ruleset file: %w" , err )
81
- }
82
-
83
- customRuleSet , err := rulesets .CreateRuleSetFromData (ruleSetBytes )
84
- if err != nil {
85
- return nil , fmt .Errorf ("error creating ruleset: %w" , err )
86
- }
87
-
88
- extends := customRuleSet .GetExtendsValue ()
89
- if len (extends ) > 0 {
90
- defaultRuleSet := rulesets .BuildDefaultRuleSets ()
91
- return defaultRuleSet .GenerateRuleSetFromSuppliedRuleSet (customRuleSet ), nil
92
- }
93
-
94
- return customRuleSet , nil
95
- }
96
-
97
24
// Executes the CLI command "lint"
98
25
func executeLint (cmd * cobra.Command , args []string ) error {
99
26
verbosity , _ := cmd .Flags ().GetInt ("verbose" )
100
27
logbasics .Initialize (log .LstdFlags , verbosity )
101
28
_ = sendAnalytics ("file-lint" , "" , modeLocal )
102
29
103
- customRuleSet , err := getRuleSet (args [0 ])
30
+ lintErrs , err := lint .Lint (cmdLintInputFilename , args [0 ],
31
+ cmdLintFailSeverity , cmdLintOnlyFailures )
104
32
if err != nil {
105
33
return err
106
34
}
107
35
108
- stateFileBytes , err := filebasics . ReadFile ( cmdLintInputFilename )
36
+ silenceErrors , err := lint . GetLintOutput ( lintErrs , cmdLintFormat , cmdLintOutputFilename )
109
37
if err != nil {
110
- return fmt .Errorf ("failed to read input file '%s'; %w" , cmdLintInputFilename , err )
111
- }
112
-
113
- ruleSetResults := motor .ApplyRulesToRuleSet (& motor.RuleSetExecution {
114
- RuleSet : customRuleSet ,
115
- Spec : stateFileBytes ,
116
- SkipDocumentCheck : ! isOpenAPISpec (stateFileBytes ),
117
- AllowLookup : true ,
118
- })
119
-
120
- var (
121
- failingCount int
122
- totalCount int
123
- lintResults = make ([]LintResult , 0 )
124
- )
125
- for _ , x := range ruleSetResults .Results {
126
- if cmdLintOnlyFailures && ParseSeverity (x .Rule .Severity ) < ParseSeverity (cmdLintFailSeverity ) {
127
- continue
128
- }
129
- if ParseSeverity (x .Rule .Severity ) >= ParseSeverity (cmdLintFailSeverity ) {
130
- failingCount ++
131
- }
132
- totalCount ++
133
- lintResults = append (lintResults , LintResult {
134
- Message : x .Message ,
135
- Path : func () string {
136
- if path , ok := x .Rule .Given .(string ); ok {
137
- return path
138
- }
139
- return ""
140
- }(),
141
- Line : x .StartNode .Line ,
142
- Column : x .StartNode .Column ,
143
- Severity : x .Rule .Severity ,
144
- })
145
- }
146
-
147
- lintErrs := map [string ]interface {}{
148
- "total_count" : totalCount ,
149
- "fail_count" : failingCount ,
150
- "results" : lintResults ,
38
+ return err
151
39
}
152
40
153
- outputFormat := strings .ToUpper (cmdLintFormat )
154
- switch outputFormat {
155
- case strings .ToUpper (string (filebasics .OutputFormatJSON )):
156
- fallthrough
157
- case strings .ToUpper (string (filebasics .OutputFormatYaml )):
158
- if err = filebasics .WriteSerializedFile (
159
- cmdLintOutputFilename , lintErrs , filebasics .OutputFormat (outputFormat ),
160
- ); err != nil {
161
- return fmt .Errorf ("error writing lint results: %w" , err )
162
- }
163
- case strings .ToUpper (plainTextFormat ):
164
- if totalCount > 0 {
165
- fmt .Printf ("Linting Violations: %d\n " , totalCount )
166
- fmt .Printf ("Failures: %d\n \n " , failingCount )
167
- for _ , violation := range lintErrs ["results" ].([]LintResult ) {
168
- fmt .Printf ("[%s][%d:%d] %s\n " ,
169
- violation .Severity , violation .Line , violation .Column , violation .Message ,
170
- )
171
- }
172
- }
173
- default :
174
- return fmt .Errorf ("invalid output format: %s" , cmdLintFormat )
175
- }
176
- if failingCount > 0 {
41
+ if silenceErrors {
177
42
// We don't want to print the error here as they're already output above
178
43
// But we _do_ want to set an exit code of failure.
179
44
//
0 commit comments