adding support for JSON Schema 2020

Signed-off-by: Kurnia D Win <kurnia.d.win@gmail.com>
pull/13283/head
Kurnia D Win 1 year ago
parent 415c7e10fd
commit 32a87dff39

@ -29,6 +29,7 @@ require (
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/rubenv/sql-migrate v1.7.1 github.com/rubenv/sql-migrate v1.7.1
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.1 github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5

@ -83,6 +83,8 @@ github.com/distribution/distribution/v3 v3.0.0-rc.2 h1:tTrzntanYMbd20SyvdeR83Ya1
github.com/distribution/distribution/v3 v3.0.0-rc.2/go.mod h1:H2zIRRXS20ylnv2HTuKILAWuANjuA60GB7MLOsQag7Y= github.com/distribution/distribution/v3 v3.0.0-rc.2/go.mod h1:H2zIRRXS20ylnv2HTuKILAWuANjuA60GB7MLOsQag7Y=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
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/docker/cli v27.1.0+incompatible h1:P0KSYmPtNbmx59wHZvG6+rjivhKDRA1BvvWM0f5DgHc= github.com/docker/cli v27.1.0+incompatible h1:P0KSYmPtNbmx59wHZvG6+rjivhKDRA1BvvWM0f5DgHc=
github.com/docker/cli v27.1.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v27.1.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
@ -330,6 +332,8 @@ github.com/rubenv/sql-migrate v1.7.1 h1:f/o0WgfO/GqNuVg+6801K/KW3WdDSupzSjDYODmi
github.com/rubenv/sql-migrate v1.7.1/go.mod h1:Ob2Psprc0/3ggbM6wCzyYVFFuc6FyZrb2AS+ezLDFb4= github.com/rubenv/sql-migrate v1.7.1/go.mod h1:Ob2Psprc0/3ggbM6wCzyYVFFuc6FyZrb2AS+ezLDFb4=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=

@ -18,10 +18,12 @@ package chartutil
import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"strings" "strings"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/santhosh-tekuri/jsonschema/v6"
"github.com/xeipuuv/gojsonschema" "github.com/xeipuuv/gojsonschema"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
@ -73,6 +75,11 @@ func ValidateAgainstSingleSchema(values Values, schemaJSON []byte) (reterr error
if bytes.Equal(valuesJSON, []byte("null")) { if bytes.Equal(valuesJSON, []byte("null")) {
valuesJSON = []byte("{}") valuesJSON = []byte("{}")
} }
if schemaIs2020(schemaJSON) {
return validateUsingNewValidator(valuesJSON, schemaJSON)
}
schemaLoader := gojsonschema.NewBytesLoader(schemaJSON) schemaLoader := gojsonschema.NewBytesLoader(schemaJSON)
valuesLoader := gojsonschema.NewBytesLoader(valuesJSON) valuesLoader := gojsonschema.NewBytesLoader(valuesJSON)
@ -91,3 +98,35 @@ func ValidateAgainstSingleSchema(values Values, schemaJSON []byte) (reterr error
return nil return nil
} }
func validateUsingNewValidator(valuesJSON, schemaJSON []byte) error {
schema, err := jsonschema.UnmarshalJSON(bytes.NewReader(schemaJSON))
if err != nil {
return err
}
values, err := jsonschema.UnmarshalJSON(bytes.NewReader(valuesJSON))
if err != nil {
return err
}
compiler := jsonschema.NewCompiler()
err = compiler.AddResource("file:///values.schema.json", schema)
if err != nil {
return err
}
validator, err := compiler.Compile("file:///values.schema.json")
if err != nil {
return err
}
return validator.Validate(values)
}
func schemaIs2020(schemaJSON []byte) bool {
var partialSchema struct {
Schema string `json:"$schema"`
}
_ = json.Unmarshal(schemaJSON, &partialSchema)
return partialSchema.Schema == "https://json-schema.org/draft/2020-12/schema"
}

@ -104,6 +104,21 @@ const subchartSchema = `{
} }
` `
const subchartSchema2020 = `{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Values",
"type": "object",
"properties": {
"data": {
"type": "array",
"contains": { "type": "string" },
"unevaluatedItems": { "type": "number" }
}
},
"required": ["data"]
}
`
func TestValidateAgainstSchema(t *testing.T) { func TestValidateAgainstSchema(t *testing.T) {
subchartJSON := []byte(subchartSchema) subchartJSON := []byte(subchartSchema)
subchart := &chart.Chart{ subchart := &chart.Chart{
@ -165,3 +180,68 @@ func TestValidateAgainstSchemaNegative(t *testing.T) {
t.Errorf("Error string :\n`%s`\ndoes not match expected\n`%s`", errString, expectedErrString) t.Errorf("Error string :\n`%s`\ndoes not match expected\n`%s`", errString, expectedErrString)
} }
} }
func TestValidateAgainstSchema2020(t *testing.T) {
subchartJSON := []byte(subchartSchema2020)
subchart := &chart.Chart{
Metadata: &chart.Metadata{
Name: "subchart",
},
Schema: subchartJSON,
}
chrt := &chart.Chart{
Metadata: &chart.Metadata{
Name: "chrt",
},
}
chrt.AddDependency(subchart)
vals := map[string]interface{}{
"name": "John",
"subchart": map[string]interface{}{
"data": []any{"hello", 12},
},
}
if err := ValidateAgainstSchema(chrt, vals); err != nil {
t.Errorf("Error validating Values against Schema: %s", err)
}
}
func TestValidateAgainstSchema2020Negative(t *testing.T) {
subchartJSON := []byte(subchartSchema2020)
subchart := &chart.Chart{
Metadata: &chart.Metadata{
Name: "subchart",
},
Schema: subchartJSON,
}
chrt := &chart.Chart{
Metadata: &chart.Metadata{
Name: "chrt",
},
}
chrt.AddDependency(subchart)
vals := map[string]interface{}{
"name": "John",
"subchart": map[string]interface{}{
"data": []any{12},
},
}
var errString string
if err := ValidateAgainstSchema(chrt, vals); err == nil {
t.Fatalf("Expected an error, but got nil")
} else {
errString = err.Error()
}
expectedErrString := `subchart:
jsonschema validation failed with 'file:///values.schema.json#'
- at '/data': no items match contains schema
- at '/data/0': got number, want string`
if errString != expectedErrString {
t.Errorf("Error string :\n`%s`\ndoes not match expected\n`%s`", errString, expectedErrString)
}
}

Loading…
Cancel
Save