mirror of
https://github.com/yannh/kubeconform.git
synced 2026-02-11 14:09:21 +00:00
Add support for -exit-on-error
This commit is contained in:
parent
7e66425b02
commit
358f145023
5 changed files with 54 additions and 15 deletions
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/xeipuuv/gojsonschema"
|
||||
"os"
|
||||
|
|
@ -85,7 +86,7 @@ func ValidateResources(resources <-chan resource.Resource, validationResults cha
|
|||
}
|
||||
}
|
||||
|
||||
func processResults(o output.Output, validationResults <-chan validator.Result) <-chan bool {
|
||||
func processResults(ctx context.Context, o output.Output, validationResults <-chan validator.Result, exitOnError bool) <-chan bool {
|
||||
success := true
|
||||
result := make(chan bool)
|
||||
|
||||
|
|
@ -99,7 +100,15 @@ func processResults(o output.Output, validationResults <-chan validator.Result)
|
|||
fmt.Fprint(os.Stderr, "failed writing log\n")
|
||||
}
|
||||
}
|
||||
if success == false && exitOnError {
|
||||
ctx.Done() // early exit - signal to stop searching for resources
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for range validationResults { // allow resource finders to exit
|
||||
}
|
||||
|
||||
result <- success
|
||||
close(result)
|
||||
}()
|
||||
|
|
@ -144,12 +153,13 @@ func realMain() int {
|
|||
var errors <-chan error
|
||||
validationResults := make(chan validator.Result)
|
||||
|
||||
successChan := processResults(o, validationResults)
|
||||
ctx := context.Background()
|
||||
successChan := processResults(ctx, o, validationResults, cfg.ExitOnError)
|
||||
|
||||
if isStdin {
|
||||
resourcesChan, errors = resource.FromStream("stdin", os.Stdin)
|
||||
resourcesChan, errors = resource.FromStream(ctx, "stdin", os.Stdin)
|
||||
} else {
|
||||
resourcesChan, errors = resource.FromFiles(cfg.Files...)
|
||||
resourcesChan, errors = resource.FromFiles(ctx, cfg.Files...)
|
||||
}
|
||||
|
||||
c := cache.New()
|
||||
|
|
@ -165,10 +175,13 @@ func realMain() int {
|
|||
wg.Add(1)
|
||||
go func() {
|
||||
for err := range errors {
|
||||
if err != nil {
|
||||
if err, ok := err.(resource.DiscoveryError); ok {
|
||||
validationResults <- validator.NewError(err.Path, err.Err)
|
||||
}
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if err, ok := err.(resource.DiscoveryError); ok {
|
||||
validationResults <- validator.NewError(err.Path, err.Err)
|
||||
ctx.Done()
|
||||
}
|
||||
}
|
||||
wg.Done()
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
)
|
||||
|
||||
type Config struct {
|
||||
ExitOnError bool
|
||||
Files []string
|
||||
SchemaLocations []string
|
||||
SkipKinds map[string]bool
|
||||
|
|
@ -59,6 +60,7 @@ func FromFlags(progName string, args []string) (Config, string, error) {
|
|||
flags.StringVar(&c.KubernetesVersion, "kubernetes-version", "1.18.0", "version of Kubernetes to validate against")
|
||||
flags.Var(&schemaLocationsParam, "schema-location", "override schemas location search path (can be specified multiple times)")
|
||||
flags.StringVar(&skipKindsCSV, "skip", "", "comma-separated list of kinds to ignore")
|
||||
flags.BoolVar(&c.ExitOnError, "exit-on-error", false, "immediately stop execution when the first error is encountered")
|
||||
flags.BoolVar(&c.IgnoreMissingSchemas, "ignore-missing-schemas", false, "skip files with missing schemas instead of failing")
|
||||
flags.BoolVar(&c.Summary, "summary", false, "print a summary at the end")
|
||||
flags.IntVar(&c.NumberOfWorkers, "n", 4, "number of goroutines to run concurrently")
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package resource
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
|
@ -25,17 +27,25 @@ func (de DiscoveryError) Error() string {
|
|||
return de.Err.Error()
|
||||
}
|
||||
|
||||
func FromFiles(paths ...string) (<-chan Resource, <-chan error) {
|
||||
func FromFiles(ctx context.Context, paths ...string) (<-chan Resource, <-chan error) {
|
||||
resources := make(chan Resource)
|
||||
errors := make(chan error)
|
||||
stop := false
|
||||
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
stop = true
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for _, path := range paths {
|
||||
// we handle errors in the walk function directly
|
||||
// so it should be safe to discard the outer error
|
||||
_ = filepath.Walk(path, func(p string, i os.FileInfo, err error) error {
|
||||
err := filepath.Walk(path, func(p string, i os.FileInfo, err error) error {
|
||||
if stop == true {
|
||||
return io.EOF
|
||||
}
|
||||
if err != nil {
|
||||
errors <- DiscoveryError{p, err}
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -45,13 +55,11 @@ func FromFiles(paths ...string) (<-chan Resource, <-chan error) {
|
|||
|
||||
f, err := os.Open(p)
|
||||
if err != nil {
|
||||
errors <- DiscoveryError{p, err}
|
||||
return err
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
errors <- DiscoveryError{p, err}
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -61,6 +69,10 @@ func FromFiles(paths ...string) (<-chan Resource, <-chan error) {
|
|||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil && err != io.EOF {
|
||||
errors <- DiscoveryError{path, err}
|
||||
}
|
||||
}
|
||||
|
||||
close(resources)
|
||||
|
|
|
|||
|
|
@ -2,13 +2,20 @@ package resource
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
func FromStream(path string, r io.Reader) (<-chan Resource, <-chan error) {
|
||||
func FromStream(ctx context.Context, path string, r io.Reader) (<-chan Resource, <-chan error) {
|
||||
resources := make(chan Resource)
|
||||
errors := make(chan error)
|
||||
stop := false
|
||||
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
stop = true
|
||||
}()
|
||||
|
||||
go func() {
|
||||
data, err := ioutil.ReadAll(r)
|
||||
|
|
@ -18,6 +25,9 @@ func FromStream(path string, r io.Reader) (<-chan Resource, <-chan error) {
|
|||
|
||||
rawResources := bytes.Split(data, []byte("---\n"))
|
||||
for _, rawResource := range rawResources {
|
||||
if stop == true {
|
||||
break
|
||||
}
|
||||
resources <- Resource{Path: path, Bytes: rawResource}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package resource_test
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"github.com/yannh/kubeconform/pkg/resource"
|
||||
"io"
|
||||
"reflect"
|
||||
|
|
@ -143,7 +144,8 @@ kind: Deployment
|
|||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
resChan, errChan := resource.FromStream(testCase.Have.Path, testCase.Have.Reader)
|
||||
ctx := context.Background()
|
||||
resChan, errChan := resource.FromStream(ctx, testCase.Have.Path, testCase.Have.Reader)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
wg.Add(2)
|
||||
|
|
|
|||
Loading…
Reference in a new issue