From 6ad533721046b570c816d16ef36b4e285179025d Mon Sep 17 00:00:00 2001 From: Aleksey Levenstein Date: Wed, 7 Jun 2023 20:45:28 +0300 Subject: [PATCH] feat: early exit on invalid k8s version flag --- cmd/kubeconform/main.go | 2 +- pkg/config/config.go | 21 ++++++++++++++++++--- pkg/config/config_test.go | 31 +++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) 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..316ecff 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,20 @@ func (ap *arrayParam) Set(value string) error { return nil } +type k8sVersionValue string + +func (kv *k8sVersionValue) String() string { + return string(*kv) +} + +func (kv *k8sVersionValue) Set(value string) error { + if ok, _ := regexp.MatchString(`^(master|\d+\.\d+\.\d+)$`, value); 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')", value) + } + *kv = k8sVersionValue(value) + return nil +} + func splitCSV(csvStr string) map[string]struct{} { splitValues := strings.Split(csvStr, ",") valuesMap := map[string]struct{}{} @@ -60,10 +75,10 @@ func FromFlags(progName string, args []string) (Config, string, error) { var buf bytes.Buffer flags.SetOutput(&buf) - c := Config{} + c := Config{KubernetesVersion: "master"} c.Files = []string{} - flags.StringVar(&c.KubernetesVersion, "kubernetes-version", "master", "version of Kubernetes to validate against, e.g.: 1.18.0") + flags.Var(&c.KubernetesVersion, "kubernetes-version", "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") diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 9a184d5..4387ec9 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -138,3 +138,34 @@ func TestFromFlags(t *testing.T) { } } } + +func TestKubernetesVersionFlag(t *testing.T) { + for _, testCase := range []struct { + k8sVersion string + expectError bool + }{ + { + "master", + false, + }, + { + "1.2.3", + false, + }, + { + "1.2", + true, + }, + { + "foo", + true, + }, + } { + _, _, err := FromFlags("kubeconform", []string{"-kubernetes-version", testCase.k8sVersion}) + if testCase.expectError && err == nil { + t.Errorf("expected error for kubernetes version flag %s", testCase.k8sVersion) + } else if !testCase.expectError && err != nil { + t.Errorf("unexpected error for kubernetes version flag %s: %s", testCase.k8sVersion, err) + } + } +}