From b825013d736432175e603e66f920410b2d9cb3eb Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Mon, 12 Oct 2026 11:00:49 +0200 Subject: [PATCH] schema/validate: migrate to santhosh-tekuri/jsonschema/v6 github.com/xeipuuv/gojsonschema is unmaintained; migrate to a maintained json-schema module. Signed-off-by: Sebastiaan van Stijn --- schema/validate/go.mod | 7 +--- schema/validate/go.sum | 19 +++------- schema/validate/validate.go | 74 ++++++++++++++++++++++++++++--------- 3 files changed, 64 insertions(+), 36 deletions(-) diff --git a/schema/validate/go.mod b/schema/validate/go.mod index 363c711f7..ce4a8f042 100644 --- a/schema/validate/go.mod +++ b/schema/validate/go.mod @@ -2,9 +2,6 @@ module github.com/opencontainers/runtime-spec/schema/validate go 1.21 -require github.com/xeipuuv/gojsonschema v1.2.0 +require github.com/santhosh-tekuri/jsonschema/v6 v6.0.3 -require ( - github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect - github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect -) +require golang.org/x/text v0.14.0 // indirect diff --git a/schema/validate/go.sum b/schema/validate/go.sum index ebda4aba2..5b447c861 100644 --- a/schema/validate/go.sum +++ b/schema/validate/go.sum @@ -1,13 +1,6 @@ -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= +github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.3 h1:1EYB5IzjZawrrnELUi78f9fPu57HuXjmddZPjrls/28= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.3/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= diff --git a/schema/validate/validate.go b/schema/validate/validate.go index 68fc24f9b..f01423046 100644 --- a/schema/validate/validate.go +++ b/schema/validate/validate.go @@ -3,11 +3,14 @@ package main import ( "fmt" "io" + "net/http" + "net/url" "os" "path/filepath" + "runtime" "strings" - "github.com/xeipuuv/gojsonschema" + "github.com/santhosh-tekuri/jsonschema/v6" ) const usage = `Validate is used to check document with specified schema. @@ -24,6 +27,21 @@ You can use validate in following ways: [INPUT DOCUMENT CONTENT HERE] ` +type httpURLLoader struct{} + +func (httpURLLoader) Load(url string) (any, error) { + resp, err := http.Get(url) + if err != nil { + return nil, err + } + defer func() { _ = resp.Body.Close() }() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("unexpected HTTP status: %s", resp.Status) + } + return jsonschema.UnmarshalJSON(resp.Body) +} + func main() { nargs := len(os.Args[1:]) if nargs == 0 || nargs > 2 { @@ -41,50 +59,55 @@ func main() { schemaPath := os.Args[1] if !strings.Contains(schemaPath, "://") { var err error - schemaPath, err = formatFilePath(schemaPath) + schemaPath, err = formatFileURL(schemaPath) if err != nil { fmt.Printf("ERROR: invalid schema-file path: %s\n", err) os.Exit(1) } - schemaPath = "file://" + schemaPath } - schemaLoader := gojsonschema.NewReferenceLoader(schemaPath) + compiler := jsonschema.NewCompiler() + compiler.DefaultDraft(jsonschema.Draft4) + compiler.UseLoader(jsonschema.SchemeURLLoader{ + "file": jsonschema.FileLoader{}, + "http": httpURLLoader{}, + "https": httpURLLoader{}, + }) - var documentLoader gojsonschema.JSONLoader + schema, err := compiler.Compile(schemaPath) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + var document io.Reader = os.Stdin if nargs > 1 { documentPath, err := formatFilePath(os.Args[2]) if err != nil { fmt.Printf("ERROR: invalid document-file path: %s\n", err) os.Exit(1) } - documentLoader = gojsonschema.NewReferenceLoader("file://" + documentPath) - } else { - documentBytes, err := io.ReadAll(os.Stdin) + f, err := os.Open(documentPath) if err != nil { fmt.Println(err) os.Exit(1) } - documentString := string(documentBytes) - documentLoader = gojsonschema.NewStringLoader(documentString) + defer func() { _ = f.Close() }() + document = f } - result, err := gojsonschema.Validate(schemaLoader, documentLoader) + instance, err := jsonschema.UnmarshalJSON(document) if err != nil { fmt.Println(err) os.Exit(1) } - if result.Valid() { - fmt.Printf("The document is valid\n") - } else { - fmt.Printf("The document is not valid. see errors :\n") - for _, desc := range result.Errors() { - fmt.Printf("- %s\n", desc) - } + if err := schema.Validate(instance); err != nil { + fmt.Println("The document is not valid. see errors :") + fmt.Println(err) os.Exit(1) } + fmt.Println("The document is valid") } func formatFilePath(path string) (string, error) { @@ -98,3 +121,18 @@ func formatFilePath(path string) (string, error) { } return absPath, nil } + +func formatFileURL(path string) (string, error) { + fp, err := formatFilePath(path) + if err != nil { + return "", err + } + + path = filepath.ToSlash(fp) + if runtime.GOOS == "windows" { + // FileLoader removes one leading slash on Windows. + // Preserve both leading slashes for UNC paths. + path = "/" + path + } + return (&url.URL{Scheme: "file", Path: path}).String(), nil +}