From d8e348a5978ce85d8bd614e1da6a3acf2d6be635 Mon Sep 17 00:00:00 2001 From: Andrea Tosatto Date: Sun, 16 Oct 2022 13:59:48 +0100 Subject: [PATCH] Allow to skip resources using the GVK notation (#92) * Allow to skip resources using the GVK notation * Update flags description, add integration tests and update readme Co-authored-by: Yann Hamon --- Readme.md | 15 +++++++++++++-- acceptance.bats | 12 ++++++++++++ pkg/config/config.go | 4 ++-- pkg/resource/resource.go | 17 ++++++++++++----- pkg/validator/validator.go | 11 +++++++++++ pkg/validator/validator_test.go | 3 ++- 6 files changed, 52 insertions(+), 10 deletions(-) diff --git a/Readme.md b/Readme.md index 46dda20..4d26201 100644 --- a/Readme.md +++ b/Readme.md @@ -92,11 +92,11 @@ Usage: ./bin/kubeconform [OPTION]... [FILE OR FOLDER]... -output string output format - json, junit, tap, text (default "text") -reject string - comma-separated list of kinds to reject + comma-separated list of kinds or GVKs to reject -schema-location value override schemas location search path (can be specified multiple times) -skip string - comma-separated list of kinds to ignore + comma-separated list of kinds or GVKs to ignore -strict disallow additional properties not in schema or duplicated keys -summary @@ -145,6 +145,17 @@ cat fixtures/valid.yaml | ./bin/kubeconform -summary Summary: 1 resource found parsing stdin - Valid: 1, Invalid: 0, Errors: 0 Skipped: 0 ``` +* Validating a file, ignoring its resource using both Kind, and GVK (Group, Version, Kind) notations +``` +# This will ignore ReplicationController for all apiVersions +./bin/kubeconform -summary -skip ReplicationController fixtures/valid.yaml +Summary: 1 resource found in 1 file - Valid: 0, Invalid: 0, Errors: 0, Skipped: 1 + +# This will ignore ReplicationController only for apiVersion v1 +$ ./bin/kubeconform -summary -skip v1/ReplicationController fixtures/valid.yaml +Summary: 1 resource found in 1 file - Valid: 0, Invalid: 0, Errors: 0, Skipped: 1 +``` + * Validating a folder, increasing the number of parallel workers ``` $ ./bin/kubeconform -summary -n 16 fixtures diff --git a/acceptance.bats b/acceptance.bats index e16c220..a8525ad 100755 --- a/acceptance.bats +++ b/acceptance.bats @@ -218,6 +218,18 @@ resetCacheFolder() { [ "$output" = "fixtures/valid.yaml - bob ReplicationController skipped" ] } +@test "Skip when parsing a resource with a GVK to skip" { + run bin/kubeconform -verbose -skip v1/ReplicationController fixtures/valid.yaml + [ "$status" -eq 0 ] + [ "$output" = "fixtures/valid.yaml - bob ReplicationController skipped" ] +} + +@test "Do not skip when parsing a resource with a GVK to skip, where the Kind matches but not the version" { + run bin/kubeconform -verbose -skip v2/ReplicationController fixtures/valid.yaml + [ "$status" -eq 0 ] + [ "$output" = "fixtures/valid.yaml - ReplicationController bob is valid" ] +} + @test "Fail when parsing a resource from a kind to reject" { run bin/kubeconform -verbose -reject ReplicationController fixtures/valid.yaml [ "$status" -eq 1 ] diff --git a/pkg/config/config.go b/pkg/config/config.go index 85be2a0..b64a3c1 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -65,8 +65,8 @@ func FromFlags(progName string, args []string) (Config, string, error) { flags.StringVar(&c.KubernetesVersion, "kubernetes-version", "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 to ignore") - flags.StringVar(&rejectKindsCSV, "reject", "", "comma-separated list of kinds to reject") + 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") flags.BoolVar(&c.Debug, "debug", false, "print debug information") 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") diff --git a/pkg/resource/resource.go b/pkg/resource/resource.go index 6bf9eed..102eabd 100644 --- a/pkg/resource/resource.go +++ b/pkg/resource/resource.go @@ -20,6 +20,18 @@ type Signature struct { Kind, Version, Namespace, Name string } +// GroupVersionKind returns a string with the GVK encoding of a resource signature. +// This encoding slightly differs from the Kubernetes upstream implementation +// in order to be suitable for being used in the kubeconform command-line arguments. +func (sig *Signature) GroupVersionKind() string { + return fmt.Sprintf("%s/%s", sig.Version, sig.Kind) +} + +// QualifiedName returns a string for a signature in the format version/kind/namespace/name +func (sig *Signature) QualifiedName() string { + return fmt.Sprintf("%s/%s/%s/%s", sig.Version, sig.Kind, sig.Namespace, sig.Name) +} + // Signature computes a signature for a resource, based on its Kind, Version, Namespace & Name func (res *Resource) Signature() (*Signature, error) { if res.sig != nil { @@ -119,8 +131,3 @@ func (res *Resource) Resources() []Resource { return []Resource{*res} } - -// QualifiedName returns a string for a signature in the format version/kind/namespace/name -func (sig *Signature) QualifiedName() string { - return fmt.Sprintf("%s/%s/%s/%s", sig.Version, sig.Kind, sig.Namespace, sig.Name) -} diff --git a/pkg/validator/validator.go b/pkg/validator/validator.go index f1ae723..09eeb53 100644 --- a/pkg/validator/validator.go +++ b/pkg/validator/validator.go @@ -98,12 +98,23 @@ type v struct { // ValidateResource validates a single resource. This allows to validate // large resource streams using multiple Go Routines. func (val *v) ValidateResource(res resource.Resource) Result { + // For backward compatibility reasons when determining whether + // a resource should be skipped or rejected we use both + // the GVK encoding of the resource signatures (the recommended method + // for skipping/rejecting resources) and the raw Kind. + skip := func(signature resource.Signature) bool { + if _, ok := val.opts.SkipKinds[signature.GroupVersionKind()]; ok { + return ok + } _, ok := val.opts.SkipKinds[signature.Kind] return ok } reject := func(signature resource.Signature) bool { + if _, ok := val.opts.RejectKinds[signature.GroupVersionKind()]; ok { + return ok + } _, ok := val.opts.RejectKinds[signature.Kind] return ok } diff --git a/pkg/validator/validator_test.go b/pkg/validator/validator_test.go index f78548a..f6fcd15 100644 --- a/pkg/validator/validator_test.go +++ b/pkg/validator/validator_test.go @@ -1,9 +1,10 @@ package validator import ( - "github.com/yannh/kubeconform/pkg/registry" "testing" + "github.com/yannh/kubeconform/pkg/registry" + "github.com/yannh/kubeconform/pkg/resource" )