mirror of
https://github.com/yannh/kubeconform.git
synced 2026-02-23 19:57:02 +00:00
Add resource name to logging
This commit is contained in:
parent
07883b8bb4
commit
52437c00d1
8 changed files with 41 additions and 32 deletions
|
|
@ -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" {
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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++
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue