diff --git a/Makefile b/Makefile index e88b26d..6e34f64 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ RELEASE_VERSION ?= latest .PHONY: local-test local-build local-build-static docker-test docker-build docker-build-static build-bats docker-acceptance release update-deps build-single-target local-test: - go test -race ./... + go test -race ./... -count=1 local-build: git config --global --add safe.directory $$PWD diff --git a/acceptance.bats b/acceptance.bats index a9d3bcd..a59fe38 100755 --- a/acceptance.bats +++ b/acceptance.bats @@ -180,6 +180,13 @@ resetCacheFolder() { [ "$status" -eq 1 ] } +@test "Fail early when passing a non valid -kubernetes-version" { + run bin/kubeconform -kubernetes-version 1.25 fixtures/valid.yaml + [[ "$output" == "invalid value "1.25" for flag -kubernetes-version: 1.25 is not a valid version. Valid values are 'master' (default) or full version x.y.z (e.g. '1.27.2')"* ]] + [[ `echo "$output" | wc -l` -eq 1 ]] + [ "$status" -eq 1 ] +} + @test "Pass with a valid input when validating against openshift manifests" { run bin/kubeconform -kubernetes-version 3.8.0 -schema-location 'https://raw.githubusercontent.com/garethr/openshift-json-schema/master/{{ .NormalizedKubernetesVersion }}-standalone{{ .StrictSuffix }}/{{ .ResourceKind }}.json' -summary fixtures/valid.yaml [ "$status" -eq 0 ] diff --git a/cmd/kubeconform/main.go b/cmd/kubeconform/main.go index e6ca3c0..d1ae4b3 100644 --- a/cmd/kubeconform/main.go +++ b/cmd/kubeconform/main.go @@ -84,7 +84,7 @@ func kubeconform(cfg config.Config) int { SkipTLS: cfg.SkipTLS, SkipKinds: cfg.SkipKinds, RejectKinds: cfg.RejectKinds, - KubernetesVersion: cfg.KubernetesVersion, + KubernetesVersion: cfg.KubernetesVersion.String(), Strict: cfg.Strict, IgnoreMissingSchemas: cfg.IgnoreMissingSchemas, }) diff --git a/pkg/config/config.go b/pkg/config/config.go index 093454e..336959e 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -4,6 +4,7 @@ import ( "bytes" "flag" "fmt" + "regexp" "strings" ) @@ -15,7 +16,7 @@ type Config struct { Help bool `yaml:"help" json:"help"` IgnoreFilenamePatterns []string `yaml:"ignoreFilenamePatterns" json:"ignoreFilenamePatterns"` IgnoreMissingSchemas bool `yaml:"ignoreMissingSchemas" json:"ignoreMissingSchemas"` - KubernetesVersion string `yaml:"kubernetesVersion" json:"kubernetesVersion"` + KubernetesVersion k8sVersionValue `yaml:"kubernetesVersion" json:"kubernetesVersion"` NumberOfWorkers int `yaml:"numberOfWorkers" json:"numberOfWorkers"` OutputFormat string `yaml:"output" json:"output"` RejectKinds map[string]struct{} `yaml:"reject" json:"reject"` @@ -39,6 +40,24 @@ func (ap *arrayParam) Set(value string) error { return nil } +type k8sVersionValue string + +func (kv *k8sVersionValue) String() string { + return string(*kv) +} + +func (kv k8sVersionValue) MarshalText() ([]byte, error) { + return []byte(kv), nil +} + +func (kv *k8sVersionValue) UnmarshalText(v []byte) error { + if ok, _ := regexp.MatchString(`^(master|\d+\.\d+\.\d+)$`, string(v)); ok != true { + return fmt.Errorf("%v is not a valid version. Valid values are 'master' (default) or full version x.y.z (e.g. '1.27.2')", kv.String()) + } + *kv = k8sVersionValue(v) + return nil +} + func splitCSV(csvStr string) map[string]struct{} { splitValues := strings.Split(csvStr, ",") valuesMap := map[string]struct{}{} @@ -63,7 +82,7 @@ func FromFlags(progName string, args []string) (Config, string, error) { c := Config{} c.Files = []string{} - flags.StringVar(&c.KubernetesVersion, "kubernetes-version", "master", "version of Kubernetes to validate against, e.g.: 1.18.0") + flags.TextVar(&c.KubernetesVersion, "kubernetes-version", k8sVersionValue("master"), "version of Kubernetes to validate against, e.g.: 1.18.0") flags.Var(&schemaLocationsParam, "schema-location", "override schemas location search path (can be specified multiple times)") flags.StringVar(&skipKindsCSV, "skip", "", "comma-separated list of kinds or GVKs to ignore") flags.StringVar(&rejectKindsCSV, "reject", "", "comma-separated list of kinds or GVKs to reject")