Skip to content

Commit 563e1db

Browse files
authored
Try to expose JSON paths (#173)
* Try to expose JSON paths * update validationErrors format in json output * Add test to JSON output with validationError
1 parent 9860cde commit 563e1db

File tree

3 files changed

+107
-13
lines changed

3 files changed

+107
-13
lines changed

pkg/output/json.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ import (
99
)
1010

1111
type oresult struct {
12-
Filename string `json:"filename"`
13-
Kind string `json:"kind"`
14-
Name string `json:"name"`
15-
Version string `json:"version"`
16-
Status string `json:"status"`
17-
Msg string `json:"msg"`
12+
Filename string `json:"filename"`
13+
Kind string `json:"kind"`
14+
Name string `json:"name"`
15+
Version string `json:"version"`
16+
Status string `json:"status"`
17+
Msg string `json:"msg"`
18+
ValidationErrors []validator.ValidationError `json:"validationErrors,omitempty"`
1819
}
1920

2021
type jsono struct {
@@ -49,11 +50,15 @@ func (o *jsono) Write(result validator.Result) error {
4950
o.nValid++
5051
case validator.Invalid:
5152
st = "statusInvalid"
52-
msg = result.Err.Error()
53+
if result.Err != nil {
54+
msg = result.Err.Error()
55+
}
5356
o.nInvalid++
5457
case validator.Error:
5558
st = "statusError"
56-
msg = result.Err.Error()
59+
if result.Err != nil {
60+
msg = result.Err.Error()
61+
}
5762
o.nErrors++
5863
case validator.Skipped:
5964
st = "statusSkipped"
@@ -63,7 +68,15 @@ func (o *jsono) Write(result validator.Result) error {
6368

6469
if o.verbose || (result.Status != validator.Valid && result.Status != validator.Skipped && result.Status != validator.Empty) {
6570
sig, _ := result.Resource.Signature()
66-
o.results = append(o.results, oresult{Filename: result.Resource.Path, Kind: sig.Kind, Name: sig.Name, Version: sig.Version, Status: st, Msg: msg})
71+
o.results = append(o.results, oresult{
72+
Filename: result.Resource.Path,
73+
Kind: sig.Kind,
74+
Name: sig.Name,
75+
Version: sig.Version,
76+
Status: st,
77+
Msg: msg,
78+
ValidationErrors: result.ValidationErrors,
79+
})
6780
}
6881

6982
return nil

pkg/output/json_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,60 @@ metadata:
9393
"skipped": 0
9494
}
9595
}
96+
`,
97+
},
98+
{
99+
"a single invalid deployment, verbose, with summary",
100+
true,
101+
false,
102+
true,
103+
[]validator.Result{
104+
{
105+
Resource: resource.Resource{
106+
Path: "deployment.yml",
107+
Bytes: []byte(`apiVersion: apps/v1
108+
kind: Deployment
109+
metadata:
110+
name: "my-app"
111+
`),
112+
},
113+
Status: validator.Invalid,
114+
Err: &validator.ValidationError{
115+
Path: "foo",
116+
Msg: "bar",
117+
},
118+
ValidationErrors: []validator.ValidationError{
119+
{
120+
Path: "foo",
121+
Msg: "bar",
122+
},
123+
},
124+
},
125+
},
126+
`{
127+
"resources": [
128+
{
129+
"filename": "deployment.yml",
130+
"kind": "Deployment",
131+
"name": "my-app",
132+
"version": "apps/v1",
133+
"status": "statusInvalid",
134+
"msg": "bar",
135+
"validationErrors": [
136+
{
137+
"path": "foo",
138+
"msg": "bar"
139+
}
140+
]
141+
}
142+
],
143+
"summary": {
144+
"valid": 0,
145+
"invalid": 1,
146+
"errors": 0,
147+
"skipped": 0
148+
}
149+
}
96150
`,
97151
},
98152
} {

pkg/validator/validator.go

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package validator
33

44
import (
55
"context"
6+
"errors"
67
"fmt"
78
"io"
89

@@ -26,11 +27,21 @@ const (
2627
Empty // resource is empty. Note: is triggered for files starting with a --- separator.
2728
)
2829

30+
type ValidationError struct {
31+
Path string `json:"path"`
32+
Msg string `json:"msg"`
33+
}
34+
35+
func (ve *ValidationError) Error() string {
36+
return ve.Msg
37+
}
38+
2939
// Result contains the details of the result of a resource validation
3040
type Result struct {
31-
Resource resource.Resource
32-
Err error
33-
Status Status
41+
Resource resource.Resource
42+
Err error
43+
Status Status
44+
ValidationErrors []ValidationError
3445
}
3546

3647
// Validator exposes multiple methods to validate your Kubernetes resources.
@@ -181,7 +192,23 @@ func (val *v) ValidateResource(res resource.Resource) Result {
181192

182193
err = schema.Validate(r)
183194
if err != nil {
184-
return Result{Resource: res, Status: Invalid, Err: fmt.Errorf("problem validating schema. Check JSON formatting: %s", err)}
195+
validationErrors := []ValidationError{}
196+
var e *jsonschema.ValidationError
197+
if errors.As(err, &e) {
198+
for _, ve := range e.Causes {
199+
validationErrors = append(validationErrors, ValidationError{
200+
Path: ve.KeywordLocation,
201+
Msg: ve.Message,
202+
})
203+
}
204+
205+
}
206+
return Result{
207+
Resource: res,
208+
Status: Invalid,
209+
Err: fmt.Errorf("problem validating schema. Check JSON formatting: %s", err),
210+
ValidationErrors: validationErrors,
211+
}
185212
}
186213

187214
return Result{Resource: res, Status: Valid}

0 commit comments

Comments
 (0)