mirror of
https://github.com/yannh/kubeconform.git
synced 2026-04-23 11:54:38 +00:00
refactor
This commit is contained in:
parent
939b44e3ca
commit
1bc9283240
15 changed files with 241 additions and 458 deletions
|
|
@ -3,10 +3,11 @@ package output
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/yannh/kubeconform/pkg/validator"
|
||||
"io"
|
||||
)
|
||||
|
||||
type result struct {
|
||||
type oresult struct {
|
||||
Filename string `json:"filename"`
|
||||
Kind string `json:"kind"`
|
||||
Name string `json:"name"`
|
||||
|
|
@ -19,7 +20,7 @@ type jsono struct {
|
|||
w io.Writer
|
||||
withSummary bool
|
||||
verbose bool
|
||||
results []result
|
||||
results []oresult
|
||||
nValid, nInvalid, nErrors, nSkipped int
|
||||
}
|
||||
|
||||
|
|
@ -29,7 +30,7 @@ func jsonOutput(w io.Writer, withSummary bool, isStdin, verbose bool) Output {
|
|||
w: w,
|
||||
withSummary: withSummary,
|
||||
verbose: verbose,
|
||||
results: []result{},
|
||||
results: []oresult{},
|
||||
nValid: 0,
|
||||
nInvalid: 0,
|
||||
nErrors: 0,
|
||||
|
|
@ -38,31 +39,30 @@ func jsonOutput(w io.Writer, withSummary bool, isStdin, verbose bool) Output {
|
|||
}
|
||||
|
||||
// JSON.Write will only write when JSON.Flush has been called
|
||||
func (o *jsono) Write(filename, kind, name, version string, err error, skipped bool) error {
|
||||
func (o *jsono) Write(result validator.Result) error {
|
||||
msg, st := "", ""
|
||||
|
||||
s := status(kind, name, err, skipped)
|
||||
|
||||
switch s {
|
||||
case statusValid:
|
||||
switch result.Status {
|
||||
case validator.Valid:
|
||||
st = "statusValid"
|
||||
o.nValid++
|
||||
case statusInvalid:
|
||||
case validator.Invalid:
|
||||
st = "statusInvalid"
|
||||
msg = err.Error()
|
||||
msg = result.Err.Error()
|
||||
o.nInvalid++
|
||||
case statusError:
|
||||
case validator.Error:
|
||||
st = "statusError"
|
||||
msg = err.Error()
|
||||
msg = result.Err.Error()
|
||||
o.nErrors++
|
||||
case statusSkipped:
|
||||
case validator.Skipped:
|
||||
st = "statusSkipped"
|
||||
o.nSkipped++
|
||||
case statusEmpty:
|
||||
case validator.Empty:
|
||||
}
|
||||
|
||||
if o.verbose || (s != statusValid && s != statusSkipped && s != statusEmpty) {
|
||||
o.results = append(o.results, result{Filename: filename, Kind: kind, Name: name, Version: version, Status: st, Msg: msg})
|
||||
if o.verbose || (result.Status != validator.Valid && result.Status != validator.Skipped && result.Status != validator.Empty) {
|
||||
sig, _ := result.Resource.Signature()
|
||||
o.results = append(o.results, oresult{Filename: result.Resource.Path, Kind: sig.Kind, Name: sig.Name, Version: sig.Version, Status: st, Msg: msg})
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -75,7 +75,7 @@ func (o *jsono) Flush() error {
|
|||
|
||||
if o.withSummary {
|
||||
jsonObj := struct {
|
||||
Resources []result `json:"resources"`
|
||||
Resources []oresult `json:"resources"`
|
||||
Summary struct {
|
||||
Valid int `json:"valid"`
|
||||
Invalid int `json:"invalid"`
|
||||
|
|
@ -100,7 +100,7 @@ func (o *jsono) Flush() error {
|
|||
res, err = json.MarshalIndent(jsonObj, "", " ")
|
||||
} else {
|
||||
jsonObj := struct {
|
||||
Resources []result `json:"resources"`
|
||||
Resources []oresult `json:"resources"`
|
||||
}{
|
||||
Resources: o.results,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,114 +0,0 @@
|
|||
package output
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestJSONWrite(t *testing.T) {
|
||||
type result struct {
|
||||
fileName, kind, name, version string
|
||||
err error
|
||||
skipped bool
|
||||
}
|
||||
|
||||
for _, testCase := range []struct {
|
||||
name string
|
||||
withSummary bool
|
||||
verbose bool
|
||||
|
||||
res []result
|
||||
expect string
|
||||
}{
|
||||
{
|
||||
"a single deployment, no summary, no verbose",
|
||||
false,
|
||||
false,
|
||||
[]result{
|
||||
{
|
||||
"deployment.yml",
|
||||
"Deployment",
|
||||
"my-app",
|
||||
"apps/v1",
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
},
|
||||
`{
|
||||
"resources": []
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
"a single deployment, summary, no verbose",
|
||||
true,
|
||||
false,
|
||||
[]result{
|
||||
{
|
||||
"deployment.yml",
|
||||
"Deployment",
|
||||
"my-app",
|
||||
"apps/v1",
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
},
|
||||
`{
|
||||
"resources": [],
|
||||
"summary": {
|
||||
"valid": 1,
|
||||
"invalid": 0,
|
||||
"errors": 0,
|
||||
"skipped": 0
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
"a single deployment, verbose, with summary",
|
||||
true,
|
||||
true,
|
||||
[]result{
|
||||
{
|
||||
"deployment.yml",
|
||||
"Deployment",
|
||||
"my-app",
|
||||
"apps/v1",
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
},
|
||||
`{
|
||||
"resources": [
|
||||
{
|
||||
"filename": "deployment.yml",
|
||||
"kind": "Deployment",
|
||||
"name": "my-app",
|
||||
"version": "apps/v1",
|
||||
"status": "statusValid",
|
||||
"msg": ""
|
||||
}
|
||||
],
|
||||
"summary": {
|
||||
"valid": 1,
|
||||
"invalid": 0,
|
||||
"errors": 0,
|
||||
"skipped": 0
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
} {
|
||||
w := new(bytes.Buffer)
|
||||
o := jsonOutput(w, testCase.withSummary, false, testCase.verbose)
|
||||
|
||||
for _, res := range testCase.res {
|
||||
o.Write(res.fileName, res.kind, res.name, res.version, res.err, res.skipped)
|
||||
}
|
||||
o.Flush()
|
||||
|
||||
if w.String() != testCase.expect {
|
||||
t.Fatalf("%s - expected %s, got %s", testCase.name, testCase.expect, w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,17 +6,8 @@ import (
|
|||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
_ = iota
|
||||
statusValid
|
||||
statusInvalid
|
||||
statusError
|
||||
statusSkipped
|
||||
statusEmpty
|
||||
)
|
||||
|
||||
type Output interface {
|
||||
Write(filename, kind, name, version string, err error, skipped bool) error
|
||||
Write(validator.Result) error
|
||||
Flush() error
|
||||
}
|
||||
|
||||
|
|
@ -32,22 +23,3 @@ func New(outputFormat string, printSummary, isStdin, verbose bool) (Output, erro
|
|||
return nil, fmt.Errorf("`outputFormat` must be 'text' or 'json'")
|
||||
}
|
||||
}
|
||||
|
||||
func status(kind, name string, err error, skipped bool) int {
|
||||
if name == "" && kind == "" && err == nil && skipped == false {
|
||||
return statusEmpty
|
||||
}
|
||||
|
||||
if skipped {
|
||||
return statusSkipped
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if _, ok := err.(validator.InvalidResourceError); ok {
|
||||
return statusInvalid
|
||||
}
|
||||
return statusError
|
||||
}
|
||||
|
||||
return statusValid
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package output
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/yannh/kubeconform/pkg/validator"
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
|
@ -31,35 +32,37 @@ func textOutput(w io.Writer, withSummary, isStdin, verbose bool) Output {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *texto) Write(filename, kind, name, version string, reserr error, skipped bool) error {
|
||||
func (o *texto) Write(result validator.Result) error {
|
||||
o.Lock()
|
||||
defer o.Unlock()
|
||||
|
||||
var err error
|
||||
|
||||
o.files[filename] = true
|
||||
switch status(kind, name, reserr, skipped) {
|
||||
case statusValid:
|
||||
sig, _ := result.Resource.Signature()
|
||||
|
||||
o.files[result.Resource.Path] = true
|
||||
switch result.Status {
|
||||
case validator.Valid:
|
||||
if o.verbose {
|
||||
_, err = fmt.Fprintf(o.w, "%s - %s %s is valid\n", filename, kind, name)
|
||||
_, err = fmt.Fprintf(o.w, "%s - %s %s is valid\n", result.Resource.Path, sig.Kind, sig.Name)
|
||||
}
|
||||
o.nValid++
|
||||
case statusInvalid:
|
||||
_, err = fmt.Fprintf(o.w, "%s - %s %s is invalid: %s\n", filename, kind, name, reserr)
|
||||
case validator.Invalid:
|
||||
_, err = fmt.Fprintf(o.w, "%s - %s %s is invalid: %s\n", result.Resource.Path, sig.Kind, sig.Name, result.Err)
|
||||
o.nInvalid++
|
||||
case statusError:
|
||||
if kind != "" && name != "" {
|
||||
_, err = fmt.Fprintf(o.w, "%s - %s %s failed validation: %s\n", filename, kind, name, reserr)
|
||||
case validator.Error:
|
||||
if sig.Kind != "" && sig.Name != "" {
|
||||
_, err = fmt.Fprintf(o.w, "%s - %s %s failed validation: %s\n", result.Resource.Path, sig.Kind, sig.Name, result.Err)
|
||||
} else {
|
||||
_, err = fmt.Fprintf(o.w, "%s - failed validation: %s\n", filename, reserr)
|
||||
_, err = fmt.Fprintf(o.w, "%s - failed validation: %s\n", result.Resource.Path, result.Err)
|
||||
}
|
||||
o.nErrors++
|
||||
case statusSkipped:
|
||||
case validator.Skipped:
|
||||
if o.verbose {
|
||||
_, err = fmt.Fprintf(o.w, "%s - %s %s skipped\n", filename, name, kind)
|
||||
_, err = fmt.Fprintf(o.w, "%s - %s %s skipped\n", result.Resource.Path, sig.Name, sig.Kind)
|
||||
}
|
||||
o.nSkipped++
|
||||
case statusEmpty: // sent to ensure we count the filename as parsed
|
||||
case validator.Empty: // sent to ensure we count the filename as parsed
|
||||
}
|
||||
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -1,86 +0,0 @@
|
|||
package output
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTextWrite(t *testing.T) {
|
||||
type result struct {
|
||||
fileName, kind, name, version string
|
||||
err error
|
||||
skipped bool
|
||||
}
|
||||
|
||||
for _, testCase := range []struct {
|
||||
name string
|
||||
withSummary bool
|
||||
verbose bool
|
||||
|
||||
res []result
|
||||
expect string
|
||||
}{
|
||||
{
|
||||
"a single deployment, no summary, no verbose",
|
||||
false,
|
||||
false,
|
||||
[]result{
|
||||
{
|
||||
"deployment.yml",
|
||||
"Deployment",
|
||||
"my-app",
|
||||
"apps/v1",
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"a single deployment, summary, no verbose",
|
||||
true,
|
||||
false,
|
||||
[]result{
|
||||
{
|
||||
"deployment.yml",
|
||||
"Deployment",
|
||||
"my-app",
|
||||
"apps/v1",
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
},
|
||||
"Summary: 1 resource found in 1 file - Valid: 1, Invalid: 0, Errors: 0 Skipped: 0\n",
|
||||
},
|
||||
{
|
||||
"a single deployment, verbose, with summary",
|
||||
true,
|
||||
true,
|
||||
[]result{
|
||||
{
|
||||
"deployment.yml",
|
||||
"Deployment",
|
||||
"my-app",
|
||||
"apps/v1",
|
||||
nil,
|
||||
false,
|
||||
},
|
||||
},
|
||||
`deployment.yml - Deployment my-app is valid
|
||||
Summary: 1 resource found in 1 file - Valid: 1, Invalid: 0, Errors: 0 Skipped: 0
|
||||
`,
|
||||
},
|
||||
} {
|
||||
w := new(bytes.Buffer)
|
||||
o := textOutput(w, testCase.withSummary, false, testCase.verbose)
|
||||
|
||||
for _, res := range testCase.res {
|
||||
o.Write(res.fileName, res.kind, res.name, res.version, res.err, res.skipped)
|
||||
}
|
||||
o.Flush()
|
||||
|
||||
if w.String() != testCase.expect {
|
||||
t.Errorf("%s - expected: %s, got: %s", testCase.name, testCase.expect, w)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue