Skip to content

Commit

Permalink
feat: Make $ref from external source usable
Browse files Browse the repository at this point in the history
  • Loading branch information
dadav authored Mar 6, 2024
2 parents 0554303 + d95dded commit 26a28f3
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 56 deletions.
117 changes: 61 additions & 56 deletions pkg/schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
jsonschema "github.com/santhosh-tekuri/jsonschema/v5"
log "github.com/sirupsen/logrus"
yaml "gopkg.in/yaml.v3"

_ "github.com/santhosh-tekuri/jsonschema/v5/httploader"
)

const (
Expand Down Expand Up @@ -476,71 +478,74 @@ func YamlToSchema(
keyNodeSchema.Type = nodeType
}

// Add key to required array of parent
if keyNodeSchema.Required || (!skipAutoGeneration.Required && !keyNodeSchema.HasData) {
*parentRequiredProperties = append(*parentRequiredProperties, keyNode.Value)
}

if !skipAutoGeneration.AdditionalProperties && valueNode.Kind == yaml.MappingNode &&
(!keyNodeSchema.HasData || keyNodeSchema.AdditionalProperties == nil) {
keyNodeSchema.AdditionalProperties = new(bool)
}

// If no title was set, use the key value
if keyNodeSchema.Title == "" && !skipAutoGeneration.Title {
keyNodeSchema.Title = keyNode.Value
}
// only validate or default if $ref is not set
if keyNodeSchema.Ref == "" {
// Add key to required array of parent
if keyNodeSchema.Required || (!skipAutoGeneration.Required && !keyNodeSchema.HasData) {
*parentRequiredProperties = append(*parentRequiredProperties, keyNode.Value)
}

// If no description was set, use the rest of the comment as description
if keyNodeSchema.Description == "" && !skipAutoGeneration.Description {
keyNodeSchema.Description = description
}
if !skipAutoGeneration.AdditionalProperties && valueNode.Kind == yaml.MappingNode &&
(!keyNodeSchema.HasData || keyNodeSchema.AdditionalProperties == nil) {
keyNodeSchema.AdditionalProperties = new(bool)
}

// If no default value was set, use the values node value as default
if !skipAutoGeneration.Default && keyNodeSchema.Default == nil && valueNode.Kind == yaml.ScalarNode {
keyNodeSchema.Default = valueNode.Value
}
// If no title was set, use the key value
if keyNodeSchema.Title == "" && !skipAutoGeneration.Title {
keyNodeSchema.Title = keyNode.Value
}

// If the value is another map and no properties are set, get them from default values
if valueNode.Kind == yaml.MappingNode && keyNodeSchema.Properties == nil {
requiredProperties := []string{}
keyNodeSchema.Properties = YamlToSchema(
valueNode,
keepFullComment,
dontRemoveHelmDocsPrefix,
skipAutoGeneration,
&requiredProperties,
).Properties
if len(requiredProperties) > 0 {
keyNodeSchema.RequiredProperties = requiredProperties
// If no description was set, use the rest of the comment as description
if keyNodeSchema.Description == "" && !skipAutoGeneration.Description {
keyNodeSchema.Description = description
}
} else if valueNode.Kind == yaml.SequenceNode && keyNodeSchema.Items == nil {
// If the value is a sequence, but no items are predefined
var seqSchema Schema

for _, itemNode := range valueNode.Content {
if itemNode.Kind == yaml.ScalarNode {
itemNodeType, err := typeFromTag(itemNode.Tag)
if err != nil {
log.Fatal(err)
}
seqSchema.AnyOf = append(seqSchema.AnyOf, &Schema{Type: itemNodeType})
} else {
itemRequiredProperties := []string{}
itemSchema := YamlToSchema(itemNode, keepFullComment, dontRemoveHelmDocsPrefix, skipAutoGeneration, &itemRequiredProperties)

if len(itemRequiredProperties) > 0 {
itemSchema.RequiredProperties = itemRequiredProperties
}
// If no default value was set, use the values node value as default
if !skipAutoGeneration.Default && keyNodeSchema.Default == nil && valueNode.Kind == yaml.ScalarNode {
keyNodeSchema.Default = valueNode.Value
}

if !skipAutoGeneration.AdditionalProperties && itemNode.Kind == yaml.MappingNode && (!itemSchema.HasData || itemSchema.AdditionalProperties == nil) {
itemSchema.AdditionalProperties = new(bool)
// If the value is another map and no properties are set, get them from default values
if valueNode.Kind == yaml.MappingNode && keyNodeSchema.Properties == nil {
requiredProperties := []string{}
keyNodeSchema.Properties = YamlToSchema(
valueNode,
keepFullComment,
dontRemoveHelmDocsPrefix,
skipAutoGeneration,
&requiredProperties,
).Properties
if len(requiredProperties) > 0 {
keyNodeSchema.RequiredProperties = requiredProperties
}
} else if valueNode.Kind == yaml.SequenceNode && keyNodeSchema.Items == nil {
// If the value is a sequence, but no items are predefined
var seqSchema Schema

for _, itemNode := range valueNode.Content {
if itemNode.Kind == yaml.ScalarNode {
itemNodeType, err := typeFromTag(itemNode.Tag)
if err != nil {
log.Fatal(err)
}
seqSchema.AnyOf = append(seqSchema.AnyOf, &Schema{Type: itemNodeType})
} else {
itemRequiredProperties := []string{}
itemSchema := YamlToSchema(itemNode, keepFullComment, dontRemoveHelmDocsPrefix, skipAutoGeneration, &itemRequiredProperties)

if len(itemRequiredProperties) > 0 {
itemSchema.RequiredProperties = itemRequiredProperties
}

if !skipAutoGeneration.AdditionalProperties && itemNode.Kind == yaml.MappingNode && (!itemSchema.HasData || itemSchema.AdditionalProperties == nil) {
itemSchema.AdditionalProperties = new(bool)
}

seqSchema.AnyOf = append(seqSchema.AnyOf, &itemSchema)
}

seqSchema.AnyOf = append(seqSchema.AnyOf, &itemSchema)
}
keyNodeSchema.Items = &seqSchema
}
keyNodeSchema.Items = &seqSchema
}
if schema.Properties == nil {
schema.Properties = make(map[string]*Schema)
Expand Down
7 changes: 7 additions & 0 deletions pkg/schema/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ func TestValidate(t *testing.T) {
# description: If set to null, this will do nothing
# else:
# description: Here goes the description for date-time
# @schema`,
expectedValid: true,
},
{
comment: `
# @schema
# $ref: https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.29.2/affinity-v1.json
# @schema`,
expectedValid: true,
},
Expand Down

0 comments on commit 26a28f3

Please sign in to comment.