Add resource name to logging

This commit is contained in:
Yann Hamon 2020-10-18 12:50:52 +02:00
parent 07883b8bb4
commit 52437c00d1
8 changed files with 41 additions and 32 deletions

View file

@ -15,13 +15,13 @@
@test "Pass when parsing a Kubernetes file with string and integer quantities" { @test "Pass when parsing a Kubernetes file with string and integer quantities" {
run bin/kubeconform -verbose fixtures/quantity.yaml run bin/kubeconform -verbose fixtures/quantity.yaml
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
[ "$output" = "fixtures/quantity.yaml - LimitRange is valid" ] [ "$output" = "fixtures/quantity.yaml - LimitRange mem-limit-range is valid" ]
} }
@test "Pass when parsing a valid Kubernetes config file with null arrays" { @test "Pass when parsing a valid Kubernetes config file with null arrays" {
run bin/kubeconform -verbose fixtures/null_string.yaml run bin/kubeconform -verbose fixtures/null_string.yaml
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
[ "$output" = "fixtures/null_string.yaml - Service is valid" ] [ "$output" = "fixtures/null_string.yaml - Service frontend is valid" ]
} }
@test "Pass when parsing a multi-document config file" { @test "Pass when parsing a multi-document config file" {
@ -43,7 +43,7 @@
@test "Return relevant error for non-existent file" { @test "Return relevant error for non-existent file" {
run bin/kubeconform fixtures/not-here run bin/kubeconform fixtures/not-here
[ "$status" -eq 1 ] [ "$status" -eq 1 ]
[ "$output" = "fixtures/not-here - failed validation: open fixtures/not-here: no such file or directory" ] [ "$output" = "fixtures/not-here - failed validation: open fixtures/not-here: no such file or directory" ]
} }
@test "Fail when parsing a config with additional properties and strict set" { @test "Fail when parsing a config with additional properties and strict set" {

View file

@ -20,9 +20,9 @@ import (
) )
type validationResult struct { type validationResult struct {
filename, kind, version string filename, kind, version, Name string
err error err error
skipped bool skipped bool
} }
func resourcesFromReader(r io.Reader) ([][]byte, error) { func resourcesFromReader(r io.Reader) ([][]byte, error) {
@ -70,7 +70,7 @@ func ValidateStream(r io.Reader, regs []registry.Registry, k8sVersion string, c
for _, rawResource := range rawResources { for _, rawResource := range rawResources {
var sig resource.Signature var sig resource.Signature
if sig, err = resource.SignatureFromBytes(rawResource); err != nil { if sig, err = resource.SignatureFromBytes(rawResource); err != nil {
validationResults = append(validationResults, validationResult{kind: sig.Kind, version: sig.Version, err: fmt.Errorf("error while parsing: %s", err)}) validationResults = append(validationResults, validationResult{kind: sig.Kind, version: sig.Version, Name: sig.Name, err: fmt.Errorf("error while parsing: %s", err)})
continue continue
} }
@ -79,7 +79,7 @@ func ValidateStream(r io.Reader, regs []registry.Registry, k8sVersion string, c
} }
if skip(sig) { if skip(sig) {
validationResults = append(validationResults, validationResult{kind: sig.Kind, version: sig.Version, err: nil, skipped: true}) validationResults = append(validationResults, validationResult{kind: sig.Kind, version: sig.Version, Name: sig.Name, err: nil, skipped: true})
continue continue
} }
@ -95,7 +95,7 @@ func ValidateStream(r io.Reader, regs []registry.Registry, k8sVersion string, c
if !ok { if !ok {
schema, err = downloadSchema(regs, sig.Kind, sig.Version, k8sVersion) schema, err = downloadSchema(regs, sig.Kind, sig.Version, k8sVersion)
if err != nil { if err != nil {
validationResults = append(validationResults, validationResult{kind: sig.Kind, version: sig.Version, err: err, skipped: false}) validationResults = append(validationResults, validationResult{kind: sig.Kind, version: sig.Version, Name: sig.Name, err: err, skipped: false})
continue continue
} }
@ -106,14 +106,14 @@ func ValidateStream(r io.Reader, regs []registry.Registry, k8sVersion string, c
if schema == nil { if schema == nil {
if ignoreMissingSchemas { if ignoreMissingSchemas {
validationResults = append(validationResults, validationResult{kind: sig.Kind, version: sig.Version, err: nil, skipped: true}) validationResults = append(validationResults, validationResult{kind: sig.Kind, version: sig.Version, Name: sig.Name, err: nil, skipped: true})
} else { } else {
validationResults = append(validationResults, validationResult{kind: sig.Kind, version: sig.Version, err: fmt.Errorf("could not find schema for %s", sig.Kind), skipped: false}) validationResults = append(validationResults, validationResult{kind: sig.Kind, version: sig.Version, Name: sig.Name, err: fmt.Errorf("could not find schema for %s", sig.Kind), skipped: false})
} }
} }
err = validator.Validate(rawResource, schema) err = validator.Validate(rawResource, schema)
validationResults = append(validationResults, validationResult{kind: sig.Kind, version: sig.Version, err: err}) validationResults = append(validationResults, validationResult{kind: sig.Kind, version: sig.Version, Name: sig.Name, err: err})
} }
return validationResults return validationResults
@ -162,7 +162,7 @@ func processResults(o output.Output, validationResults chan []validationResult,
success = false success = false
} }
if err := o.Write(result.filename, result.kind, result.version, result.err, result.skipped); err != nil { if err := o.Write(result.filename, result.kind, result.Name, result.version, result.err, result.skipped); err != nil {
fmt.Fprint(os.Stderr, "failed writing log\n") fmt.Fprint(os.Stderr, "failed writing log\n")
} }
} }

View file

@ -9,6 +9,7 @@ import (
type result struct { type result struct {
Filename string `json:"filename"` Filename string `json:"filename"`
Kind string `json:"kind"` Kind string `json:"kind"`
Name string `json:"name"`
Version string `json:"version"` Version string `json:"version"`
Status string `json:"status"` Status string `json:"status"`
Msg string `json:"msg"` Msg string `json:"msg"`
@ -37,7 +38,7 @@ func JSON(w io.Writer, withSummary bool, verbose bool) Output {
} }
// JSON.Write will only write when JSON.Flush has been called // JSON.Write will only write when JSON.Flush has been called
func (o *jsono) Write(filename, kind, version string, err error, skipped bool) error { func (o *jsono) Write(filename, kind, name, version string, err error, skipped bool) error {
msg, st := "", "" msg, st := "", ""
s := status(err, skipped) s := status(err, skipped)
@ -60,7 +61,7 @@ func (o *jsono) Write(filename, kind, version string, err error, skipped bool) e
} }
if o.verbose || (s != VALID && s != SKIPPED) { if o.verbose || (s != VALID && s != SKIPPED) {
o.results = append(o.results, result{Filename: filename, Kind: kind, Version: version, Status: st, Msg: msg}) o.results = append(o.results, result{Filename: filename, Kind: kind, Name: name, Version: version, Status: st, Msg: msg})
} }
return nil return nil

View file

@ -7,9 +7,9 @@ import (
func TestJSONWrite(t *testing.T) { func TestJSONWrite(t *testing.T) {
type result struct { type result struct {
fileName, kind, version string fileName, kind, name, version string
err error err error
skipped bool skipped bool
} }
for _, testCase := range []struct { for _, testCase := range []struct {
@ -28,6 +28,7 @@ func TestJSONWrite(t *testing.T) {
{ {
"deployment.yml", "deployment.yml",
"Deployment", "Deployment",
"my-app",
"apps/v1", "apps/v1",
nil, nil,
false, false,
@ -46,6 +47,7 @@ func TestJSONWrite(t *testing.T) {
{ {
"deployment.yml", "deployment.yml",
"Deployment", "Deployment",
"my-app",
"apps/v1", "apps/v1",
nil, nil,
false, false,
@ -70,6 +72,7 @@ func TestJSONWrite(t *testing.T) {
{ {
"deployment.yml", "deployment.yml",
"Deployment", "Deployment",
"my-app",
"apps/v1", "apps/v1",
nil, nil,
false, false,
@ -80,6 +83,7 @@ func TestJSONWrite(t *testing.T) {
{ {
"filename": "deployment.yml", "filename": "deployment.yml",
"kind": "Deployment", "kind": "Deployment",
"name": "my-app",
"version": "apps/v1", "version": "apps/v1",
"status": "VALID", "status": "VALID",
"msg": "" "msg": ""
@ -99,7 +103,7 @@ func TestJSONWrite(t *testing.T) {
o := JSON(w, testCase.withSummary, testCase.verbose) o := JSON(w, testCase.withSummary, testCase.verbose)
for _, res := range testCase.res { for _, res := range testCase.res {
o.Write(res.fileName, res.kind, res.version, res.err, res.skipped) o.Write(res.fileName, res.kind, res.name, res.version, res.err, res.skipped)
} }
o.Flush() o.Flush()

View file

@ -13,7 +13,7 @@ const (
) )
type Output interface { type Output interface {
Write(filename, kind, version string, err error, skipped bool) error Write(filename, kind, name, version string, err error, skipped bool) error
Flush() error Flush() error
} }

View file

@ -29,7 +29,7 @@ func Text(w io.Writer, withSummary, verbose bool) Output {
} }
} }
func (o *text) Write(filename, kind, version string, reserr error, skipped bool) error { func (o *text) Write(filename, kind, name, version string, reserr error, skipped bool) error {
o.Lock() o.Lock()
defer o.Unlock() defer o.Unlock()
@ -39,18 +39,18 @@ func (o *text) Write(filename, kind, version string, reserr error, skipped bool)
switch status(reserr, skipped) { switch status(reserr, skipped) {
case VALID: case VALID:
if o.verbose { if o.verbose {
_, err = fmt.Fprintf(o.w, "%s - %s is valid\n", filename, kind) _, err = fmt.Fprintf(o.w, "%s - %s %s is valid\n", filename, kind, name)
} }
o.nValid++ o.nValid++
case INVALID: case INVALID:
_, err = fmt.Fprintf(o.w, "%s - %s is invalid: %s\n", filename, kind, reserr) _, err = fmt.Fprintf(o.w, "%s - %s %s is invalid: %s\n", filename, kind, name, reserr)
o.nInvalid++ o.nInvalid++
case ERROR: case ERROR:
_, err = fmt.Fprintf(o.w, "%s - %s failed validation: %s\n", filename, kind, reserr) _, err = fmt.Fprintf(o.w, "%s - %s %s failed validation: %s\n", filename, kind, name, reserr)
o.nErrors++ o.nErrors++
case SKIPPED: case SKIPPED:
if o.verbose { if o.verbose {
_, err = fmt.Fprintf(o.w, "%s - %s skipped\n", filename, kind) _, err = fmt.Fprintf(o.w, "%s - %s %s skipped\n", filename, name, kind)
} }
o.nSkipped++ o.nSkipped++
} }

View file

@ -7,9 +7,9 @@ import (
func TestTextWrite(t *testing.T) { func TestTextWrite(t *testing.T) {
type result struct { type result struct {
fileName, kind, version string fileName, kind, name, version string
err error err error
skipped bool skipped bool
} }
for _, testCase := range []struct { for _, testCase := range []struct {
@ -28,6 +28,7 @@ func TestTextWrite(t *testing.T) {
{ {
"deployment.yml", "deployment.yml",
"Deployment", "Deployment",
"my-app",
"apps/v1", "apps/v1",
nil, nil,
false, false,
@ -43,6 +44,7 @@ func TestTextWrite(t *testing.T) {
{ {
"deployment.yml", "deployment.yml",
"Deployment", "Deployment",
"my-app",
"apps/v1", "apps/v1",
nil, nil,
false, false,
@ -58,12 +60,13 @@ func TestTextWrite(t *testing.T) {
{ {
"deployment.yml", "deployment.yml",
"Deployment", "Deployment",
"my-app",
"apps/v1", "apps/v1",
nil, nil,
false, false,
}, },
}, },
`deployment.yml - Deployment is valid `deployment.yml - Deployment my-app is valid
Summary: 1 resource found in 1 file - Valid: 1, Invalid: 0, Errors: 0 Skipped: 0 Summary: 1 resource found in 1 file - Valid: 1, Invalid: 0, Errors: 0 Skipped: 0
`, `,
}, },
@ -72,7 +75,7 @@ Summary: 1 resource found in 1 file - Valid: 1, Invalid: 0, Errors: 0 Skipped: 0
o := Text(w, testCase.withSummary, testCase.verbose) o := Text(w, testCase.withSummary, testCase.verbose)
for _, res := range testCase.res { for _, res := range testCase.res {
o.Write(res.fileName, res.kind, res.version, res.err, res.skipped) o.Write(res.fileName, res.kind, res.name, res.version, res.err, res.skipped)
} }
o.Flush() o.Flush()

View file

@ -5,7 +5,7 @@ import (
) )
type Signature struct { type Signature struct {
Kind, Version, Namespace string Kind, Version, Namespace, Name string
} }
// SignatureFromBytes returns key identifying elements from a []byte representing the resource // SignatureFromBytes returns key identifying elements from a []byte representing the resource
@ -14,10 +14,11 @@ func SignatureFromBytes(res []byte) (Signature, error) {
APIVersion string `yaml:"apiVersion"` APIVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"` Kind string `yaml:"kind"`
Metadata struct { Metadata struct {
Name string `yaml:"Name"`
Namespace string `yaml:"Namespace"` Namespace string `yaml:"Namespace"`
} `yaml:"Metadata"` } `yaml:"Metadata"`
}{} }{}
err := yaml.Unmarshal(res, &resource) err := yaml.Unmarshal(res, &resource)
return Signature{Kind: resource.Kind, Version: resource.APIVersion, Namespace: resource.Metadata.Namespace}, err return Signature{Kind: resource.Kind, Version: resource.APIVersion, Namespace: resource.Metadata.Namespace, Name: resource.Metadata.Name}, err
} }