diff --git a/Readme.md b/Readme.md index 9b058fe..f419427 100644 --- a/Readme.md +++ b/Readme.md @@ -42,7 +42,7 @@ Usage of ./bin/kubeconform: -output string output format - text, json (default "text") -registry value - filepath template for registry + override schemas registry path (can be specified multiple times) -skip string comma-separated list of kinds to ignore -strict @@ -57,14 +57,14 @@ Usage of ./bin/kubeconform: * Validating a single, valid file ``` -$ ./bin/kubeconform -registry kubernetesjsonschema.dev fixtures/valid.yaml +$ ./bin/kubeconform fixtures/valid.yaml $ echo $? 0 ``` * Validating a single invalid file, setting output to json, and printing a summary ``` -$ ./bin/kubeconform -registry kubernetesjsonschema.dev -summary -output json fixtures/invalid.yaml +$ ./bin/kubeconform -summary -output json fixtures/invalid.yaml { "resources": [ { @@ -88,13 +88,35 @@ $ echo $? * Validating a folder, increasing the number of parallel workers ``` -$ ./bin/kubeconform -summary -registry kubernetesjsonschema.dev -n 16 fixtures +$ ./bin/kubeconform -summary -n 16 fixtures fixtures/multi_invalid.yaml - Service is invalid: Invalid type. Expected: integer, given: string fixtures/invalid.yaml - ReplicationController is invalid: Invalid type. Expected: [integer,null], given: string [...] Summary: 48 resources found in 25 files - Valid: 39, Invalid: 2, Errors: 7 Skipped: 0 ``` +### Overriding schemas registries lookup order - CRD support + +When the `-registry` file is not used, kubeconform will default to downloading schemas from +`kubernetesjsonschema.dev`. Kubeconform however supports the use of one, or multiple, custom schemas +registries - with access over HTTP or local filesystem. Kubeconform will lookup for schema definitions +in each of them, in order, stopping as soon as a matching file is found. + +All 3 following command lines are equivalent: +``` +$ ./bin/kubeconform fixtures/valid.yaml +$ ./bin/kubeconform -registry kubernetesjsonschema.dev fixtures/valid.yaml +$ ./bin/kubeconform -registry 'https://kubernetesjsonschema.dev/{{ .NormalizedVersion }}-standalone{{ .StrictSuffix }}/{{ .ResourceKind }}{{ .KindSuffix }}.json' fixtures/valid.yaml +``` + +To support validating CRDs, we need to convert OpenAPI files to JSON schema, storing the JSON schemas +in a local folder - for example schemas. Then we specify this folder as an additional registry to lookup: + +``` +# If the resource Kind is not found in kubernetesjsonschema.dev, also lookup in the schemas/ folder for a matching file +$ ./bin/kubeconform -registry kubernetesjsonschema.dev -registry 'schemas/{{ .ResourceKind }}{{ .KindSuffix }}.json' fixtures/custom-resource.yaml +``` + ### Credits * @garethr for the [Kubeval](https://github.com/instrumenta/kubeval) and diff --git a/acceptance.bats b/acceptance.bats index 2d3f2cf..adec878 100755 --- a/acceptance.bats +++ b/acceptance.bats @@ -1,63 +1,63 @@ #!/usr/bin/env bats @test "Pass when parsing a valid Kubernetes config YAML file" { - run bin/kubeconform -registry kubernetesjsonschema.dev -summary fixtures/valid.yaml + run bin/kubeconform -summary fixtures/valid.yaml [ "$status" -eq 0 ] [ "$output" = "Summary: 1 resource found in 1 file - Valid: 1, Invalid: 0, Errors: 0 Skipped: 0" ] } @test "Pass when parsing a folder containing valid YAML files" { - run bin/kubeconform -registry kubernetesjsonschema.dev -summary fixtures/folder + run bin/kubeconform -summary fixtures/folder [ "$status" -eq 0 ] [ "$output" = "Summary: 7 resources found in 2 files - Valid: 7, Invalid: 0, Errors: 0 Skipped: 0" ] } @test "Pass when parsing a Kubernetes file with string and integer quantities" { - run bin/kubeconform -registry kubernetesjsonschema.dev -verbose fixtures/quantity.yaml + run bin/kubeconform -verbose fixtures/quantity.yaml [ "$status" -eq 0 ] [ "$output" = "fixtures/quantity.yaml - LimitRange is valid" ] } @test "Pass when parsing a valid Kubernetes config file with null arrays" { - run bin/kubeconform -registry kubernetesjsonschema.dev -verbose fixtures/null_string.yaml + run bin/kubeconform -verbose fixtures/null_string.yaml [ "$status" -eq 0 ] [ "$output" = "fixtures/null_string.yaml - Service is valid" ] } @test "Pass when parsing a multi-document config file" { - run bin/kubeconform -registry kubernetesjsonschema.dev -summary fixtures/multi_valid.yaml + run bin/kubeconform -summary fixtures/multi_valid.yaml [ "$status" -eq 0 ] [ "$output" = "Summary: 6 resources found in 1 file - Valid: 6, Invalid: 0, Errors: 0 Skipped: 0" ] } @test "Fail when parsing a multi-document config file with one invalid resource" { - run bin/kubeconform -registry kubernetesjsonschema.dev fixtures/multi_invalid.yaml + run bin/kubeconform fixtures/multi_invalid.yaml [ "$status" -eq 1 ] } @test "Fail when parsing an invalid Kubernetes config file" { - run bin/kubeconform -registry kubernetesjsonschema.dev fixtures/invalid.yaml + run bin/kubeconform fixtures/invalid.yaml [ "$status" -eq 1 ] } @test "Return relevant error for non-existent file" { - run bin/kubeconform -registry kubernetesjsonschema.dev fixtures/not-here + run bin/kubeconform fixtures/not-here [ "$status" -eq 1 ] [ "$output" = "fixtures/not-here - failed validation: open fixtures/not-here: no such file or directory" ] } @test "Fail when parsing a config with additional properties and strict set" { - run bin/kubeconform -registry kubernetesjsonschema.dev -strict -k8sversion 1.16.0 fixtures/extra_property.yaml + run bin/kubeconform -strict -k8sversion 1.16.0 fixtures/extra_property.yaml [ "$status" -eq 1 ] } @test "Fail when parsing a config with CRD" { - run bin/kubeconform -registry kubernetesjsonschema.dev fixtures/test_crd.yaml + run bin/kubeconform fixtures/test_crd.yaml [ "$status" -eq 1 ] } @test "Pass when parsing a config with CRD and ignoring missing schemas" { - run bin/kubeconform -registry kubernetesjsonschema.dev -ignore-missing-schemas fixtures/test_crd.yaml + run bin/kubeconform -ignore-missing-schemas fixtures/test_crd.yaml [ "$status" -eq 0 ] } diff --git a/cmd/kubeconform/main.go b/cmd/kubeconform/main.go index 0860223..a9e2a7a 100644 --- a/cmd/kubeconform/main.go +++ b/cmd/kubeconform/main.go @@ -217,7 +217,7 @@ func realMain() int { var files []string flag.StringVar(&k8sVersion, "k8sversion", "1.18.0", "version of Kubernetes to test against") - flag.Var(®s, "registry", "filepath template for registry") + flag.Var(®s, "registry", "override schemas registry 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") @@ -240,8 +240,7 @@ func realMain() int { registries := []registry.Registry{} if len(regs) == 0 { - fmt.Println("At least one registry needs to be set - add -registry kubernetesjsonschema.dev ?") - return 1 + regs = append(regs, "kubernetesjsonschema.dev") // if not specified, default behaviour is to use kubernetesjson-schema.dev as registry } for _, reg := range regs {