mirror of
https://github.com/yannh/kubeconform.git
synced 2026-02-22 11:17:01 +00:00
move flag handling to pkg
This commit is contained in:
parent
0e07499946
commit
5bd09a483e
3 changed files with 97 additions and 43 deletions
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/xeipuuv/gojsonschema"
|
"github.com/xeipuuv/gojsonschema"
|
||||||
|
"github.com/yannh/kubeconform/pkg/config"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -201,31 +202,11 @@ func getFiles(files []string, fileBatches chan []string, validationResults chan
|
||||||
}
|
}
|
||||||
|
|
||||||
func realMain() int {
|
func realMain() int {
|
||||||
var schemaLocationsParam arrayParam
|
|
||||||
var skipKindsCSV, k8sVersion, outputFormat string
|
|
||||||
var summary, strict, verbose, ignoreMissingSchemas, help bool
|
|
||||||
var nWorkers int
|
|
||||||
var err error
|
var err error
|
||||||
var files []string
|
|
||||||
|
|
||||||
flag.StringVar(&k8sVersion, "kubernetes-version", "1.18.0", "version of Kubernetes to validate against")
|
cfg := config.FromFlags()
|
||||||
flag.Var(&schemaLocationsParam, "schema-location", "override schemas location search path (can be specified multiple times)")
|
|
||||||
flag.BoolVar(&ignoreMissingSchemas, "ignore-missing-schemas", false, "skip files with missing schemas instead of failing")
|
|
||||||
flag.BoolVar(&summary, "summary", false, "print a summary at the end")
|
|
||||||
flag.IntVar(&nWorkers, "n", 4, "number of routines to run in parallel")
|
|
||||||
flag.StringVar(&skipKindsCSV, "skip", "", "comma-separated list of kinds to ignore")
|
|
||||||
flag.BoolVar(&strict, "strict", false, "disallow additional properties not in schema")
|
|
||||||
flag.StringVar(&outputFormat, "output", "text", "output format - text, json")
|
|
||||||
flag.BoolVar(&verbose, "verbose", false, "print results for all resources")
|
|
||||||
flag.BoolVar(&help, "h", false, "show help information")
|
|
||||||
flag.Usage = func() {
|
|
||||||
fmt.Fprintf(os.Stderr, "Usage: %s [OPTION]... [FILE OR FOLDER]...\n", os.Args[0])
|
|
||||||
flag.PrintDefaults()
|
|
||||||
}
|
|
||||||
|
|
||||||
flag.Parse()
|
if cfg.Help {
|
||||||
|
|
||||||
if help {
|
|
||||||
flag.Usage()
|
flag.Usage()
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
@ -234,35 +215,25 @@ func realMain() int {
|
||||||
stat, _ := os.Stdin.Stat()
|
stat, _ := os.Stdin.Stat()
|
||||||
isStdin := (stat.Mode() & os.ModeCharDevice) == 0
|
isStdin := (stat.Mode() & os.ModeCharDevice) == 0
|
||||||
|
|
||||||
skipKinds := skipKindsMap(skipKindsCSV)
|
|
||||||
|
|
||||||
if len(flag.Args()) == 1 && flag.Args()[0] == "-" {
|
if len(flag.Args()) == 1 && flag.Args()[0] == "-" {
|
||||||
isStdin = true
|
isStdin = true
|
||||||
} else {
|
|
||||||
for _, file := range flag.Args() {
|
|
||||||
files = append(files, file)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
filter := func(signature resource.Signature) bool {
|
filter := func(signature resource.Signature) bool {
|
||||||
isSkipKind, ok := skipKinds[signature.Kind]
|
isSkipKind, ok := cfg.SkipKinds[signature.Kind]
|
||||||
return ok && isSkipKind
|
return ok && isSkipKind
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(schemaLocationsParam) == 0 {
|
|
||||||
schemaLocationsParam = append(schemaLocationsParam, "https://kubernetesjsonschema.dev") // if not specified, default behaviour is to use kubernetesjson-schema.dev as registry
|
|
||||||
}
|
|
||||||
|
|
||||||
registries := []registry.Registry{}
|
registries := []registry.Registry{}
|
||||||
for _, schemaLocation := range schemaLocationsParam {
|
for _, schemaLocation := range cfg.SchemaLocations {
|
||||||
if !strings.HasSuffix(schemaLocation, "json") { // If we dont specify a full templated path, we assume the paths of kubernetesjsonschema.dev
|
if !strings.HasSuffix(schemaLocation, "json") { // If we dont specify a full templated path, we assume the paths of kubernetesjsonschema.dev
|
||||||
schemaLocation += "/{{ .NormalizedVersion }}-standalone{{ .StrictSuffix }}/{{ .ResourceKind }}{{ .KindSuffix }}.json"
|
schemaLocation += "/{{ .NormalizedVersion }}-standalone{{ .StrictSuffix }}/{{ .ResourceKind }}{{ .KindSuffix }}.json"
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(schemaLocation, "http") {
|
if strings.HasPrefix(schemaLocation, "http") {
|
||||||
registries = append(registries, registry.NewHTTPRegistry(schemaLocation, strict))
|
registries = append(registries, registry.NewHTTPRegistry(schemaLocation, cfg.Strict))
|
||||||
} else {
|
} else {
|
||||||
registries = append(registries, registry.NewLocalRegistry(schemaLocation, strict))
|
registries = append(registries, registry.NewLocalRegistry(schemaLocation, cfg.Strict))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -271,12 +242,12 @@ func realMain() int {
|
||||||
|
|
||||||
fileBatches := make(chan []string)
|
fileBatches := make(chan []string)
|
||||||
go func() {
|
go func() {
|
||||||
getFiles(files, fileBatches, validationResults)
|
getFiles(cfg.Files, fileBatches, validationResults)
|
||||||
close(fileBatches)
|
close(fileBatches)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var o output.Output
|
var o output.Output
|
||||||
if o, err = output.New(outputFormat, summary, isStdin, verbose); err != nil {
|
if o, err = output.New(cfg.OutputFormat, cfg.Summary, isStdin, cfg.Verbose); err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
@ -285,14 +256,14 @@ func realMain() int {
|
||||||
go processResults(o, validationResults, res)
|
go processResults(o, validationResults, res)
|
||||||
|
|
||||||
if isStdin {
|
if isStdin {
|
||||||
res := ValidateStream(os.Stdin, registries, k8sVersion, c, filter, ignoreMissingSchemas)
|
res := ValidateStream(os.Stdin, registries, cfg.KubernetesVersion, c, filter, cfg.IgnoreMissingSchemas)
|
||||||
for i := range res {
|
for i := range res {
|
||||||
res[i].filename = "stdin"
|
res[i].filename = "stdin"
|
||||||
}
|
}
|
||||||
validationResults <- res
|
validationResults <- res
|
||||||
} else {
|
} else {
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
for i := 0; i < nWorkers; i++ {
|
for i := 0; i < cfg.NumberOfWorkers; i++ {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
@ -309,7 +280,7 @@ func realMain() int {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
res := ValidateStream(f, registries, k8sVersion, c, filter, ignoreMissingSchemas)
|
res := ValidateStream(f, registries, cfg.KubernetesVersion, c, filter, cfg.IgnoreMissingSchemas)
|
||||||
f.Close()
|
f.Close()
|
||||||
|
|
||||||
for i := range res {
|
for i := range res {
|
||||||
|
|
|
||||||
83
pkg/config/config.go
Normal file
83
pkg/config/config.go
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Files []string
|
||||||
|
SchemaLocations []string
|
||||||
|
SkipKinds map[string]bool
|
||||||
|
OutputFormat string
|
||||||
|
KubernetesVersion string
|
||||||
|
NumberOfWorkers int
|
||||||
|
Summary bool
|
||||||
|
Strict bool
|
||||||
|
Verbose bool
|
||||||
|
IgnoreMissingSchemas bool
|
||||||
|
Help bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type arrayParam []string
|
||||||
|
|
||||||
|
func (ap *arrayParam) String() string {
|
||||||
|
return strings.Join(*ap, " - ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ap *arrayParam) Set(value string) error {
|
||||||
|
*ap = append(*ap, value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func skipKinds(skipKindsCSV string) map[string]bool {
|
||||||
|
splitKinds := strings.Split(skipKindsCSV, ",")
|
||||||
|
skipKinds := map[string]bool{}
|
||||||
|
|
||||||
|
for _, kind := range splitKinds {
|
||||||
|
if len(kind) > 0 {
|
||||||
|
skipKinds[kind] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return skipKinds
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromFlags() Config {
|
||||||
|
var schemaLocationsParam arrayParam
|
||||||
|
var skipKindsCSV string
|
||||||
|
|
||||||
|
c := Config{}
|
||||||
|
c.Files = []string{}
|
||||||
|
|
||||||
|
flag.StringVar(&c.KubernetesVersion, "kubernetes-version", "1.18.0", "version of Kubernetes to validate against")
|
||||||
|
flag.Var(&schemaLocationsParam, "schema-location", "override schemas location search path (can be specified multiple times)")
|
||||||
|
flag.StringVar(&skipKindsCSV, "skip", "", "comma-separated list of kinds to ignore")
|
||||||
|
flag.BoolVar(&c.IgnoreMissingSchemas, "ignore-missing-schemas", false, "skip files with missing schemas instead of failing")
|
||||||
|
flag.BoolVar(&c.Summary, "summary", false, "print a summary at the end")
|
||||||
|
flag.IntVar(&c.NumberOfWorkers, "n", 4, "number of goroutines to run concurrently")
|
||||||
|
flag.BoolVar(&c.Strict, "strict", false, "disallow additional properties not in schema")
|
||||||
|
flag.StringVar(&c.OutputFormat, "output", "text", "output format - text, json")
|
||||||
|
flag.BoolVar(&c.Verbose, "verbose", false, "print results for all resources")
|
||||||
|
flag.BoolVar(&c.Help, "h", false, "show help information")
|
||||||
|
flag.Usage = func() {
|
||||||
|
fmt.Fprintf(os.Stderr, "Usage: %s [OPTION]... [FILE OR FOLDER]...\n", os.Args[0])
|
||||||
|
flag.PrintDefaults()
|
||||||
|
}
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
c.SkipKinds = skipKinds(skipKindsCSV)
|
||||||
|
c.SchemaLocations = schemaLocationsParam
|
||||||
|
if len(c.SchemaLocations) == 0 {
|
||||||
|
c.SchemaLocations = append(c.SchemaLocations, "https://kubernetesjsonschema.dev") // if not specified, default behaviour is to use kubernetesjson-schema.dev as registry
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range flag.Args() {
|
||||||
|
c.Files = append(c.Files, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package main
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
@ -33,7 +33,7 @@ func TestSkipKindMaps(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
got := skipKindsMap(testCase.csvSkipKinds)
|
got := skipKinds(testCase.csvSkipKinds)
|
||||||
if !reflect.DeepEqual(got, testCase.expect) {
|
if !reflect.DeepEqual(got, testCase.expect) {
|
||||||
t.Errorf("%s - got %+v, expected %+v", testCase.name, got, testCase.expect)
|
t.Errorf("%s - got %+v, expected %+v", testCase.name, got, testCase.expect)
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue