Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package kubeconform for openSUSE:Factory checked in at 2023-09-20 13:25:51 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/kubeconform (Old) and /work/SRC/openSUSE:Factory/.kubeconform.new.16627 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "kubeconform" Wed Sep 20 13:25:51 2023 rev:3 rq:1111809 version:0.6.3 Changes: -------- --- /work/SRC/openSUSE:Factory/kubeconform/kubeconform.changes 2023-03-27 18:17:04.331357335 +0200 +++ /work/SRC/openSUSE:Factory/.kubeconform.new.16627/kubeconform.changes 2023-09-20 13:27:39.255345124 +0200 @@ -1,0 +2,33 @@ +Sun Sep 17 18:32:50 UTC 2023 - jkowalc...@suse.com + +- Update to version 0.6.3: + * Add test validating using CRD that misses explicit draft version + * Force Draft version of JsonSchema + * Update Readme.md to add `fullgroup` explanation (#220) + * Fix #130 in a backward-compatible way (#219) + * Update Readme.md + * fix: add missing output formats in error message (#213) + +------------------------------------------------------------------- +Sun Sep 17 18:16:35 UTC 2023 - jkowalc...@suse.com + +- Update to version 0.6.2: + * Fix for 196: Multi-architecture image (#204) + * Fix anchored link on Readme.md (#205) + * Revert "Add support for Arm64 Docker images (#201)" + * Add support for Arm64 Docker images (#201) + * Move cfg parsing out of realmain, rename realmain to kubeconform + * Add JSON/YAML annotations to Config struct + * Do not hardcode output stream in pkg/output + * Add support for "pretty" output (#195) + * docs: Add winget as installation method on Windows (#192) + * Fix CI badge image (#184) + +------------------------------------------------------------------- +Sun Sep 17 18:12:17 UTC 2023 - jkowalc...@suse.com + +- _service change disabled to manual per osc deprecation warning: + WARNING: Command 'disabledrun/dr' is obsolete, please convert + your _service to use 'manual' and then 'manualrun/mr' instead. + +------------------------------------------------------------------- Old: ---- kubeconform-0.6.1.tar.gz New: ---- kubeconform-0.6.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ kubeconform.spec ++++++ --- /var/tmp/diff_new_pack.fSpjDI/_old 2023-09-20 13:27:40.631394422 +0200 +++ /var/tmp/diff_new_pack.fSpjDI/_new 2023-09-20 13:27:40.635394566 +0200 @@ -20,7 +20,7 @@ %global import_path %{provider_prefix} Name: kubeconform -Version: 0.6.1 +Version: 0.6.3 Release: 0 Summary: A fast Kubernetes manifests validator, with support for custom resources License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.fSpjDI/_old 2023-09-20 13:27:40.671395855 +0200 +++ /var/tmp/diff_new_pack.fSpjDI/_new 2023-09-20 13:27:40.675395999 +0200 @@ -1,19 +1,19 @@ <services> - <service name="tar_scm" mode="disabled"> + <service name="tar_scm" mode="manual"> <param name="url">https://github.com/yannh/kubeconform.git</param> <param name="scm">git</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> - <param name="revision">v0.6.1</param> + <param name="revision">v0.6.3</param> <param name="changesgenerate">enable</param> </service> - <service name="recompress" mode="disabled"> + <service name="recompress" mode="manual"> <param name="file">kubeconform-*.tar</param> <param name="compression">gz</param> </service> - <service name="set_version" mode="disabled"> + <service name="set_version" mode="manual"> <param name="basename">kubeconform</param> </service> - <service name="go_modules" mode="disabled"/> + <service name="go_modules" mode="manual"/> </services> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.fSpjDI/_old 2023-09-20 13:27:40.699396858 +0200 +++ /var/tmp/diff_new_pack.fSpjDI/_new 2023-09-20 13:27:40.703397002 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/yannh/kubeconform.git</param> - <param name="changesrevision">e3bb34851d02b04671be2792153eb2eff5c05c56</param></service></servicedata> + <param name="changesrevision">a2ad239853944dda1d615310d8b2ded384567bb1</param></service></servicedata> (No newline at EOF) ++++++ kubeconform-0.6.1.tar.gz -> kubeconform-0.6.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubeconform-0.6.1/.github/workflows/main.yml new/kubeconform-0.6.3/.github/workflows/main.yml --- old/kubeconform-0.6.1/.github/workflows/main.yml 2023-02-27 16:16:00.000000000 +0100 +++ new/kubeconform-0.6.3/.github/workflows/main.yml 2023-07-16 09:39:52.000000000 +0200 @@ -38,6 +38,9 @@ with: fetch-depth: 0 # https://github.com/goreleaser/goreleaser-action/issues/56 + - uses: docker/setup-qemu-action@v2 + - uses: docker/setup-buildx-action@v2 + - name: goreleaser run: | echo "${{ github.token }}" | docker login https://ghcr.io -u ${GITHUB_ACTOR} --password-stdin diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubeconform-0.6.1/.goreleaser.yml new/kubeconform-0.6.3/.goreleaser.yml --- old/kubeconform-0.6.1/.goreleaser.yml 2023-02-27 16:16:00.000000000 +0100 +++ new/kubeconform-0.6.3/.goreleaser.yml 2023-07-16 09:39:52.000000000 +0200 @@ -32,23 +32,63 @@ dockers: - image_templates: - - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:latest' - - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:{{ .Tag }}' - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:{{ .Tag }}-amd64' + - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:latest-amd64' dockerfile: Dockerfile + use: buildx build_flag_templates: + - "--pull" - "--platform=linux/amd64" goos: linux goarch: amd64 - image_templates: - - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:latest-alpine' - - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:{{ .Tag }}-alpine' + - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:{{ .Tag }}-arm64' + - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:latest-arm64' + dockerfile: Dockerfile + use: buildx + build_flag_templates: + - "--pull" + - "--platform=linux/arm64" + goos: linux + goarch: arm64 + - image_templates: - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:{{ .Tag }}-amd64-alpine' + - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:latest-amd64-alpine' dockerfile: Dockerfile-alpine + use: buildx build_flag_templates: + - "--pull" - "--platform=linux/amd64" goos: linux goarch: amd64 + - image_templates: + - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:{{ .Tag }}-arm64-alpine' + - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:latest-arm64-alpine' + dockerfile: Dockerfile-alpine + use: buildx + build_flag_templates: + - "--pull" + - "--platform=linux/arm64" + goos: linux + goarch: arm64 + +docker_manifests: + - name_template: 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:{{ .Tag }}' + image_templates: + - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:{{ .Tag }}-amd64' + - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:{{ .Tag }}-arm64' + - name_template: 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:latest' + image_templates: + - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:latest-amd64' + - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:latest-arm64' + - name_template: 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:latest-alpine' + image_templates: + - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:latest-amd64-alpine' + - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:latest-arm64-alpine' + - name_template: 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:{{ .Tag }}-alpine' + image_templates: + - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:{{ .Tag }}-amd64-alpine' + - 'ghcr.io/{{.Env.GIT_OWNER}}/kubeconform:{{ .Tag }}-arm64-alpine' checksum: name_template: 'CHECKSUMS' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubeconform-0.6.1/Readme.md new/kubeconform-0.6.3/Readme.md --- old/kubeconform-0.6.1/Readme.md 2023-02-27 16:16:00.000000000 +0100 +++ new/kubeconform-0.6.3/Readme.md 2023-07-16 09:39:52.000000000 +0200 @@ -1,7 +1,7 @@ <img width="50%" alt="Kubeconform-GitHub-Hero" src="https://user-images.githubusercontent.com/19731161/142411871-f695e40c-bfa8-43ca-97c0-94c256749732.png"> <hr> -[](https://github.com/yannh/kubeconform/actions?query=branch%3Amaster) +[](https://github.com/yannh/kubeconform/actions?query=branch%3Amaster) [](https://formulae.brew.sh/formula/kubeconform) [](https://goreportcard.com/report/github.com/yannh/kubeconform) [](https://pkg.go.dev/github.com/yannh/kubeconform/pkg/validator) @@ -44,7 +44,7 @@ * [Usage examples](#Usage-examples) * [Proxy support](#Proxy-support) * [Overriding schemas location](#Overriding-schemas-location) - * [CustomResourceDefinition (CRD) Support](#CustomResourceDefinition-(CRD)-Support) + * [CustomResourceDefinition (CRD) Support](#CustomResourceDefinition-CRD-Support) * [OpenShift schema Support](#OpenShift-schema-Support) * [Integrating Kubeconform in the CI](#Integrating-Kubeconform-in-the-CI) * [Github Workflow](#Github-Workflow) @@ -81,6 +81,12 @@ $ brew install kubeconform ``` +If you are a Windows user, you can install with [winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/) by running: + +```cmd +winget install YannHamon.kubeconform +``` + You can also download the latest version from the [release page](https://github.com/yannh/kubeconform/releases). Another way of installation is via Golang's package manager: @@ -250,12 +256,16 @@ JSON schema written to trainingjob_v1.json ``` -By default, the file name output format is `{kind}_{version}`. The `FILENAME_FORMAT` environment variable can be used to change the output file name (Available variables: `kind`, `group`, `version`): +By default, the file name output format is `{kind}_{version}`. The `FILENAME_FORMAT` environment variable can be used to change the output file name (Available variables: `kind`, `group`, `fullgroup`, `version`): ``` $ export FILENAME_FORMAT='{kind}-{group}-{version}' $ ./scripts/openapi2jsonschema.py https://raw.githubusercontent.com/aws/amazon-sagemaker-operator-for-k8s/master/config/crd/bases/sagemaker.aws.amazon.com_trainingjobs.yaml JSON schema written to trainingjob-sagemaker-v1.json + +$ export FILENAME_FORMAT='{kind}-{fullgroup}-{version}' +$ ./scripts/openapi2jsonschema.py https://raw.githubusercontent.com/aws/amazon-sagemaker-operator-for-k8s/master/config/crd/bases/sagemaker.aws.amazon.com_trainingjobs.yaml +JSON schema written to trainingjob-sagemaker.aws.amazon.com-v1.json ``` After converting your CRDs to JSON schema files, you can use `kubeconform` to validate your CRs against them: @@ -298,7 +308,7 @@ - name: login to Github Packages run: echo "${{ github.token }}" | docker login https://ghcr.io -u ${GITHUB_ACTOR} --password-stdin - uses: actions/checkout@v2 - - uses: docker://ghcr.io/yannh/kubeconform:master + - uses: docker://ghcr.io/yannh/kubeconform:latest with: entrypoint: '/kubeconform' args: "-summary -output json kubeconfigs/" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubeconform-0.6.1/acceptance.bats new/kubeconform-0.6.3/acceptance.bats --- old/kubeconform-0.6.1/acceptance.bats 2023-02-27 16:16:00.000000000 +0100 +++ new/kubeconform-0.6.3/acceptance.bats 2023-07-16 09:39:52.000000000 +0200 @@ -340,3 +340,8 @@ run xmllint --noout --schema fixtures/junit.xsd output.xml [ "$status" -eq 0 ] } + +@test "passes when trying to use a CRD that does not have the JSONSchema set" { + run bash -c "bin/kubeconform -schema-location default -schema-location 'https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json' fixtures/httpproxy.yaml" + [ "$status" -eq 0 ] +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubeconform-0.6.1/cmd/kubeconform/main.go new/kubeconform-0.6.3/cmd/kubeconform/main.go --- old/kubeconform-0.6.1/cmd/kubeconform/main.go 2023-02-27 16:16:00.000000000 +0100 +++ new/kubeconform-0.6.3/cmd/kubeconform/main.go 2023-07-16 09:39:52.000000000 +0200 @@ -46,29 +46,8 @@ return result } -func realMain() int { - cfg, out, err := config.FromFlags(os.Args[0], os.Args[1:]) - if out != "" { - o := os.Stderr - errCode := 1 - if cfg.Help { - o = os.Stdout - errCode = 0 - } - fmt.Fprintln(o, out) - return errCode - } - - if cfg.Version { - fmt.Println(version) - return 0 - } - - if err != nil { - fmt.Fprintf(os.Stderr, "failed parsing command line: %s\n", err.Error()) - return 1 - } - +func kubeconform(cfg config.Config) int { + var err error cpuProfileFile := os.Getenv("KUBECONFORM_CPUPROFILE_FILE") if cpuProfileFile != "" { f, err := os.Create(cpuProfileFile) @@ -94,7 +73,7 @@ } var o output.Output - if o, err = output.New(cfg.OutputFormat, cfg.Summary, useStdin, cfg.Verbose); err != nil { + if o, err = output.New(os.Stdout, cfg.OutputFormat, cfg.Summary, useStdin, cfg.Verbose); err != nil { fmt.Fprintln(os.Stderr, err) return 1 } @@ -178,5 +157,27 @@ } func main() { - os.Exit(realMain()) + cfg, out, err := config.FromFlags(os.Args[0], os.Args[1:]) + if out != "" { + o := os.Stderr + errCode := 1 + if cfg.Help { + o = os.Stdout + errCode = 0 + } + fmt.Fprintln(o, out) + os.Exit(errCode) + } + + if cfg.Version { + fmt.Println(version) + return + } + + if err != nil { + fmt.Fprintf(os.Stderr, "failed parsing command line: %s\n", err.Error()) + os.Exit(1) + } + + os.Exit(kubeconform(cfg)) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubeconform-0.6.1/fixtures/httpproxy.yaml new/kubeconform-0.6.3/fixtures/httpproxy.yaml --- old/kubeconform-0.6.1/fixtures/httpproxy.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/kubeconform-0.6.3/fixtures/httpproxy.yaml 2023-07-16 09:39:52.000000000 +0200 @@ -0,0 +1,13 @@ +apiVersion: projectcontour.io/v1 +kind: HTTPProxy +metadata: + name: basic +spec: + virtualhost: + fqdn: foo-basic.example.com + routes: + - conditions: + - prefix: / + services: + - name: s1 + port: 80 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubeconform-0.6.1/pkg/config/config.go new/kubeconform-0.6.3/pkg/config/config.go --- old/kubeconform-0.6.1/pkg/config/config.go 2023-02-27 16:16:00.000000000 +0100 +++ new/kubeconform-0.6.3/pkg/config/config.go 2023-07-16 09:39:52.000000000 +0200 @@ -8,24 +8,24 @@ ) type Config struct { - Cache string - Debug bool - ExitOnError bool - Files []string - SchemaLocations []string - SkipTLS bool - SkipKinds map[string]struct{} - RejectKinds map[string]struct{} - OutputFormat string - KubernetesVersion string - NumberOfWorkers int - Summary bool - Strict bool - Verbose bool - IgnoreMissingSchemas bool - IgnoreFilenamePatterns []string - Help bool - Version bool + Cache string `yaml:"cache" json:"cache"` + Debug bool `yaml:"debug" json:"debug"` + ExitOnError bool `yaml:"exitOnError" json:"exitOnError"` + Files []string `yaml:"files" json:"files"` + Help bool `yaml:"help" json:"help"` + IgnoreFilenamePatterns []string `yaml:"ignoreFilenamePatterns" json:"ignoreFilenamePatterns"` + IgnoreMissingSchemas bool `yaml:"ignoreMissingSchemas" json:"ignoreMissingSchemas"` + KubernetesVersion string `yaml:"kubernetesVersion" json:"kubernetesVersion"` + NumberOfWorkers int `yaml:"numberOfWorkers" json:"numberOfWorkers"` + OutputFormat string `yaml:"output" json:"output"` + RejectKinds map[string]struct{} `yaml:"reject" json:"reject"` + SchemaLocations []string `yaml:"schemaLocations" json:"schemaLocations"` + SkipKinds map[string]struct{} `yaml:"skip" json:"skip"` + SkipTLS bool `yaml:"insecureSkipTLSVerify" json:"insecureSkipTLSVerify"` + Strict bool `yaml:"strict" json:"strict"` + Summary bool `yaml:"summary" json:"summary"` + Verbose bool `yaml:"verbose" json:"verbose"` + Version bool `yaml:"version" json:"version"` } type arrayParam []string @@ -74,7 +74,7 @@ flags.BoolVar(&c.Summary, "summary", false, "print a summary at the end (ignored for junit output)") flags.IntVar(&c.NumberOfWorkers, "n", 4, "number of goroutines to run concurrently") flags.BoolVar(&c.Strict, "strict", false, "disallow additional properties not in schema or duplicated keys") - flags.StringVar(&c.OutputFormat, "output", "text", "output format - json, junit, tap, text") + flags.StringVar(&c.OutputFormat, "output", "text", "output format - json, junit, pretty, tap, text") flags.BoolVar(&c.Verbose, "verbose", false, "print results for all resources (ignored for tap and junit output)") flags.BoolVar(&c.SkipTLS, "insecure-skip-tls-verify", false, "disable verification of the server's SSL certificate. This will make your HTTPS connections insecure") flags.StringVar(&c.Cache, "cache", "", "cache schemas downloaded via HTTP to this folder") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubeconform-0.6.1/pkg/output/output.go new/kubeconform-0.6.3/pkg/output/output.go --- old/kubeconform-0.6.1/pkg/output/output.go 2023-02-27 16:16:00.000000000 +0100 +++ new/kubeconform-0.6.3/pkg/output/output.go 2023-07-16 09:39:52.000000000 +0200 @@ -2,7 +2,7 @@ import ( "fmt" - "os" + "io" "github.com/yannh/kubeconform/pkg/validator" ) @@ -12,19 +12,19 @@ Flush() error } -func New(outputFormat string, printSummary, isStdin, verbose bool) (Output, error) { - w := os.Stdout - +func New(w io.Writer, outputFormat string, printSummary, isStdin, verbose bool) (Output, error) { switch { case outputFormat == "json": return jsonOutput(w, printSummary, isStdin, verbose), nil case outputFormat == "junit": return junitOutput(w, printSummary, isStdin, verbose), nil + case outputFormat == "pretty": + return prettyOutput(w, printSummary, isStdin, verbose), nil case outputFormat == "tap": return tapOutput(w, printSummary, isStdin, verbose), nil case outputFormat == "text": return textOutput(w, printSummary, isStdin, verbose), nil default: - return nil, fmt.Errorf("`outputFormat` must be 'json', 'tap' or 'text'") + return nil, fmt.Errorf("'outputFormat' must be 'json', 'junit', 'pretty', 'tap' or 'text'") } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubeconform-0.6.1/pkg/output/pretty.go new/kubeconform-0.6.3/pkg/output/pretty.go --- old/kubeconform-0.6.1/pkg/output/pretty.go 1970-01-01 01:00:00.000000000 +0100 +++ new/kubeconform-0.6.3/pkg/output/pretty.go 2023-07-16 09:39:52.000000000 +0200 @@ -0,0 +1,109 @@ +package output + +import ( + "fmt" + "io" + "sync" + + "github.com/yannh/kubeconform/pkg/validator" +) + +type prettyo struct { + sync.Mutex + w io.Writer + withSummary bool + isStdin bool + verbose bool + files map[string]bool + nValid, nInvalid, nErrors, nSkipped int +} + +// Text will output the results of the validation as a texto +func prettyOutput(w io.Writer, withSummary, isStdin, verbose bool) Output { + return &prettyo{ + w: w, + withSummary: withSummary, + isStdin: isStdin, + verbose: verbose, + files: map[string]bool{}, + nValid: 0, + nInvalid: 0, + nErrors: 0, + nSkipped: 0, + } +} + +func (o *prettyo) Write(result validator.Result) error { + checkmark := "\u2714" + multiplicationSign := "\u2716" + reset := "\033[0m" + cRed := "\033[31m" + cGreen := "\033[32m" + cYellow := "\033[33m" + + o.Lock() + defer o.Unlock() + + var err error + + sig, _ := result.Resource.Signature() + + o.files[result.Resource.Path] = true + switch result.Status { + case validator.Valid: + if o.verbose { + fmt.Fprintf(o.w, "%s%s%s %s: %s%s %s is valid%s\n", cGreen, checkmark, reset, result.Resource.Path, cGreen, sig.Kind, sig.Name, reset) + } + o.nValid++ + case validator.Invalid: + fmt.Fprintf(o.w, "%s%s%s %s: %s%s %s is invalid: %s%s\n", cRed, multiplicationSign, reset, result.Resource.Path, cRed, sig.Kind, sig.Name, result.Err.Error(), reset) + + o.nInvalid++ + case validator.Error: + fmt.Fprintf(o.w, "%s%s%s %s: ", cRed, multiplicationSign, reset, result.Resource.Path) + if sig.Kind != "" && sig.Name != "" { + fmt.Fprintf(o.w, "%s%s failed validation: %s %s%s\n", cRed, sig.Kind, sig.Name, result.Err.Error(), reset) + } else { + fmt.Fprintf(o.w, "%sfailed validation: %s %s%s\n", cRed, sig.Name, result.Err.Error(), reset) + } + o.nErrors++ + case validator.Skipped: + if o.verbose { + fmt.Fprintf(o.w, "%s-%s %s: ", cYellow, reset, result.Resource.Path) + if sig.Kind != "" && sig.Name != "" { + fmt.Fprintf(o.w, "%s%s %s skipped%s\n", cYellow, sig.Kind, sig.Name, reset) + } else if sig.Kind != "" { + fmt.Fprintf(o.w, "%s%s skipped%s\n", cYellow, sig.Kind, reset) + } else { + fmt.Fprintf(o.w, "%sskipped%s\n", cYellow, reset) + } + } + o.nSkipped++ + case validator.Empty: // sent to ensure we count the filename as parsed + } + + return err +} + +func (o *prettyo) Flush() error { + var err error + if o.withSummary { + nFiles := len(o.files) + nResources := o.nValid + o.nInvalid + o.nErrors + o.nSkipped + resourcesPlural := "" + if nResources > 1 { + resourcesPlural = "s" + } + filesPlural := "" + if nFiles > 1 { + filesPlural = "s" + } + if o.isStdin { + _, err = fmt.Fprintf(o.w, "Summary: %d resource%s found parsing stdin - Valid: %d, Invalid: %d, Errors: %d, Skipped: %d\n", nResources, resourcesPlural, o.nValid, o.nInvalid, o.nErrors, o.nSkipped) + } else { + _, err = fmt.Fprintf(o.w, "Summary: %d resource%s found in %d file%s - Valid: %d, Invalid: %d, Errors: %d, Skipped: %d\n", nResources, resourcesPlural, nFiles, filesPlural, o.nValid, o.nInvalid, o.nErrors, o.nSkipped) + } + } + + return err +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubeconform-0.6.1/pkg/output/pretty_test.go new/kubeconform-0.6.3/pkg/output/pretty_test.go --- old/kubeconform-0.6.1/pkg/output/pretty_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/kubeconform-0.6.3/pkg/output/pretty_test.go 2023-07-16 09:39:52.000000000 +0200 @@ -0,0 +1,84 @@ +package output + +import ( + "bytes" + "testing" + + "github.com/yannh/kubeconform/pkg/resource" + "github.com/yannh/kubeconform/pkg/validator" +) + +func TestPrettyTextWrite(t *testing.T) { + for _, testCase := range []struct { + name string + withSummary bool + isStdin bool + verbose bool + results []validator.Result + expect string + }{ + { + "a single deployment, no summary, no verbose", + false, + false, + false, + []validator.Result{}, + "", + }, + { + "a single deployment, summary, no verbose", + true, + false, + false, + []validator.Result{ + { + Resource: resource.Resource{ + Path: "deployment.yml", + Bytes: []byte(`apiVersion: apps/v1 +kind: Deployment +metadata: + name: "my-app" +`), + }, + Status: validator.Valid, + Err: nil, + }, + }, + "Summary: 1 resource found in 1 file - Valid: 1, Invalid: 0, Errors: 0, Skipped: 0\n", + }, + { + "a single deployment, verbose, with summary", + true, + false, + true, + []validator.Result{ + { + Resource: resource.Resource{ + Path: "deployment.yml", + Bytes: []byte(`apiVersion: apps/v1 +kind: Deployment +metadata: + name: "my-app" +`), + }, + Status: validator.Valid, + Err: nil, + }, + }, + "\033[32mâ\033[0m deployment.yml: \033[32mDeployment my-app is valid\033[0m\n" + + "Summary: 1 resource found in 1 file - Valid: 1, Invalid: 0, Errors: 0, Skipped: 0\n", + }, + } { + w := new(bytes.Buffer) + o := prettyOutput(w, testCase.withSummary, testCase.isStdin, testCase.verbose) + + for _, res := range testCase.results { + o.Write(res) + } + o.Flush() + + if w.String() != testCase.expect { + t.Errorf("%s - expected, but got:\n%s\n%s\n", testCase.name, testCase.expect, w) + } + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubeconform-0.6.1/pkg/validator/validator.go new/kubeconform-0.6.3/pkg/validator/validator.go --- old/kubeconform-0.6.1/pkg/validator/validator.go 2023-02-27 16:16:00.000000000 +0100 +++ new/kubeconform-0.6.3/pkg/validator/validator.go 2023-07-16 09:39:52.000000000 +0200 @@ -6,6 +6,7 @@ "errors" "fmt" "io" + "strings" jsonschema "github.com/santhosh-tekuri/jsonschema/v5" _ "github.com/santhosh-tekuri/jsonschema/v5/httploader" @@ -254,7 +255,12 @@ for _, reg := range registries { path, schemaBytes, err = reg.DownloadSchema(kind, version, k8sVersion) if err == nil { - schema, err := jsonschema.CompileString(path, string(schemaBytes)) + c := jsonschema.NewCompiler() + c.Draft = jsonschema.Draft4 + if err := c.AddResource(path, strings.NewReader(string(schemaBytes))); err != nil { + continue + } + schema, err := c.Compile(path) // If we got a non-parseable response, we try the next registry if err != nil { continue diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kubeconform-0.6.1/scripts/openapi2jsonschema.py new/kubeconform-0.6.3/scripts/openapi2jsonschema.py --- old/kubeconform-0.6.1/scripts/openapi2jsonschema.py 2023-02-27 16:16:00.000000000 +0100 +++ new/kubeconform-0.6.3/scripts/openapi2jsonschema.py 2023-07-16 09:39:52.000000000 +0200 @@ -155,6 +155,7 @@ filename = filename_format.format( kind=y["spec"]["names"]["kind"], group=y["spec"]["group"].split(".")[0], + fullgroup=y["spec"]["group"], version=version["name"], ).lower() + ".json" @@ -164,6 +165,7 @@ filename = filename_format.format( kind=y["spec"]["names"]["kind"], group=y["spec"]["group"].split(".")[0], + fullgroup=y["spec"]["group"], version=version["name"], ).lower() + ".json" @@ -173,6 +175,7 @@ filename = filename_format.format( kind=y["spec"]["names"]["kind"], group=y["spec"]["group"].split(".")[0], + fullgroup=y["spec"]["group"], version=y["spec"]["version"], ).lower() + ".json" ++++++ vendor.tar.gz ++++++