Skip to content

Conversation

@Breee
Copy link

@Breee Breee commented Nov 26, 2025

Uses current jsonschema as draft: https://json-schema.org/draft/2020-12

I also hat to add c.AssertFormat() to fix the tests

This fixes my issue #345

tested with:

$ make 
$ go build -o bin/kubeconform cmd/kubeconform/main.go
$ go test -v ./...
?       github.com/yannh/kubeconform/cmd/kubeconform    [no test files]
?       github.com/yannh/kubeconform/examples   [no test files]
?       github.com/yannh/kubeconform/pkg/cache  [no test files]
=== RUN   TestSkipKindMaps
--- PASS: TestSkipKindMaps (0.00s)
=== RUN   TestFromFlags
--- PASS: TestFromFlags (0.00s)
PASS
ok      github.com/yannh/kubeconform/pkg/config 0.002s
=== RUN   TestHTTPURLLoader_Load
=== RUN   TestHTTPURLLoader_Load/successful_load
=== RUN   TestHTTPURLLoader_Load/not_found_error
=== RUN   TestHTTPURLLoader_Load/server_error
=== RUN   TestHTTPURLLoader_Load/cache_hit
=== RUN   TestHTTPURLLoader_Load/Partial_response_from_server
--- PASS: TestHTTPURLLoader_Load (0.01s)
    --- PASS: TestHTTPURLLoader_Load/successful_load (0.00s)
    --- PASS: TestHTTPURLLoader_Load/not_found_error (0.00s)
    --- PASS: TestHTTPURLLoader_Load/server_error (0.00s)
    --- PASS: TestHTTPURLLoader_Load/cache_hit (0.00s)
    --- PASS: TestHTTPURLLoader_Load/Partial_response_from_server (0.00s)
=== RUN   TestHTTPURLLoader_Load_Retries
=== RUN   TestHTTPURLLoader_Load_Retries/retries_on_503
=== RUN   TestHTTPURLLoader_Load_Retries/fails_when_hitting_max_retries
=== RUN   TestHTTPURLLoader_Load_Retries/retry_on_connection_reset
=== RUN   TestHTTPURLLoader_Load_Retries/retry_on_connection_reset#01
--- PASS: TestHTTPURLLoader_Load_Retries (8.01s)
    --- PASS: TestHTTPURLLoader_Load_Retries/retries_on_503 (1.00s)
    --- PASS: TestHTTPURLLoader_Load_Retries/fails_when_hitting_max_retries (3.00s)
    --- PASS: TestHTTPURLLoader_Load_Retries/retry_on_connection_reset (1.00s)
    --- PASS: TestHTTPURLLoader_Load_Retries/retry_on_connection_reset#01 (3.00s)
PASS
ok      github.com/yannh/kubeconform/pkg/loader 8.027s
=== RUN   TestJSONWrite
--- PASS: TestJSONWrite (0.00s)
=== RUN   TestJunitWrite
--- PASS: TestJunitWrite (0.00s)
=== RUN   TestPrettyTextWrite
--- PASS: TestPrettyTextWrite (0.00s)
=== RUN   TestTapWrite
--- PASS: TestTapWrite (0.00s)
=== RUN   TestTextWrite
--- PASS: TestTextWrite (0.00s)
PASS
ok      github.com/yannh/kubeconform/pkg/output 0.012s
=== RUN   TestSchemaPath
--- PASS: TestSchemaPath (0.00s)
PASS
ok      github.com/yannh/kubeconform/pkg/registry       0.010s
=== RUN   TestIsYamlFile
--- PASS: TestIsYamlFile (0.00s)
=== RUN   TestIsJSONFile
--- PASS: TestIsJSONFile (0.00s)
=== RUN   TestFindResourcesInReader
--- PASS: TestFindResourcesInReader (0.00s)
=== RUN   TestSignatureFromBytes
--- PASS: TestSignatureFromBytes (0.00s)
=== RUN   TestSignatureFromMap
--- PASS: TestSignatureFromMap (0.00s)
=== RUN   TestResources
--- PASS: TestResources (0.00s)
=== RUN   TestFromStream
--- PASS: TestFromStream (0.01s)
PASS
ok      github.com/yannh/kubeconform/pkg/resource       0.010s
=== RUN   TestValidate
--- PASS: TestValidate (0.00s)
=== RUN   TestValidationErrors
--- PASS: TestValidationErrors (0.00s)
=== RUN   TestValidateFile
--- PASS: TestValidateFile (0.00s)
PASS
ok      github.com/yannh/kubeconform/pkg/validator      0.010s
$ ./bin/kubeconform -schema-location default -schema-location 'https://raw.githubusercontent.com/datreeio/CRDs-catalog/refs/heads/main/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json' test.yaml 
$ git clone https://github.com/gravitee-io/gravitee-kubernetes-operator /tmp/gravitee-kubernetes-operator

script:

set -euo pipefail

# Configuration
KUBECONFORM_BIN="$(dirname "$0")/bin/kubeconform"
EXAMPLES_DIR="${EXAMPLES_DIR:-/tmp/gravitee-kubernetes-operator}"
SCHEMA_LOCATIONS=(
    "default"
    "https://raw.githubusercontent.com/datreeio/CRDs-catalog/refs/heads/main/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json"
)

# Check if kubeconform binary exists
if [ ! -f "$KUBECONFORM_BIN" ]; then
    echo "Error: kubeconform binary not found at $KUBECONFORM_BIN"
    echo "Please run: go build -o bin/kubeconform cmd/kubeconform/main.go"
    exit 1
fi

# Check if examples directory exists
if [ ! -d "$EXAMPLES_DIR" ]; then
    echo "Error: Examples directory not found at $EXAMPLES_DIR"
    exit 1
fi

# Build schema location arguments
SCHEMA_ARGS=()
for loc in "${SCHEMA_LOCATIONS[@]}"; do
    SCHEMA_ARGS+=("-schema-location" "$loc")
done

# Find all YAML files
find "$EXAMPLES_DIR" -type f \( -name "*.yaml" -o -name "*.yml" \) | while read -r file; do
    echo "Validating: $file"
    "$KUBECONFORM_BIN" "${SCHEMA_ARGS[@]}" "$file"
done

@Breee
Copy link
Author

Breee commented Dec 3, 2025

@yannh would you be so kind to review this?

@yannh
Copy link
Owner

yannh commented Dec 5, 2025

@Breee hi! Thanks for the contribution! Could you provide an explanation what this would change/ why this is needed? This would change the default behavior, is the new spec fully backwards compatible or is there a risk of breakage?

@Breee
Copy link
Author

Breee commented Dec 6, 2025

So in my case i want to run kubeconform with this CRD:

https://github.com/datreeio/CRDs-catalog/blob/main/gravitee.io/apidefinition_v1alpha1.json

here is some minimal example:

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"

	jsonschema "github.com/santhosh-tekuri/jsonschema/v6"
)

func main() {
	schemaURL := "https://raw.githubusercontent.com/datreeio/CRDs-catalog/refs/heads/main/gravitee.io/apidefinition_v1alpha1.json"

	resp, err := http.Get(schemaURL)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	schemaBytes, err := io.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}

	var schemaData interface{}
	json.Unmarshal(schemaBytes, &schemaData)

	// OLD CODE (master branch)
	fmt.Println("OLD CODE (Draft4):")
	c1 := jsonschema.NewCompiler()
	c1.DefaultDraft(jsonschema.Draft4)
	c1.AddResource(schemaURL, schemaData)
	_, err = c1.Compile(schemaURL)
	if err != nil {
		fmt.Printf("FAILED: %v\n\n", err)
	} else {
		fmt.Println("SUCCESS\n")
	}

	// NEW CODE (feature/jsonschema-draft2020 branch)
	fmt.Println("NEW CODE (Draft2020 + AssertFormat):")
	c2 := jsonschema.NewCompiler()
	c2.DefaultDraft(jsonschema.Draft2020)
	c2.AssertFormat()
	c2.AddResource(schemaURL, schemaData)
	_, err = c2.Compile(schemaURL)
	if err != nil {
		fmt.Printf("FAILED: %v\n", err)
	} else {
		fmt.Println("SUCCESS")
	}
}

yields:

OLD CODE (Draft4):
FAILED: "https://raw.githubusercontent.com/datreeio/CRDs-catalog/refs/heads/main/gravitee.io/apidefinition_v1alpha1.json#" is not valid against metaschema: jsonschema validation failed with 'http://json-schema.org/draft-04/schema#'
- at '/properties/spec/properties/additionalProperties': got boolean, want object

NEW CODE (Draft2020 + AssertFormat):
SUCCESS

so its about how the additionalProperties are handled in the latest version of the json spec. I can dig deeper and probably just add a cli flag?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants