From d95ddedafa384bef1cdff07b18f2f1c98908d271 Mon Sep 17 00:00:00 2001 From: Gerald Pape Date: Wed, 6 Mar 2024 20:30:37 +0100 Subject: [PATCH] Enable correct handling of $ref schema annotations --- pkg/schema/schema.go | 117 ++++++++++++++++++++------------------ pkg/schema/schema_test.go | 7 +++ 2 files changed, 68 insertions(+), 56 deletions(-) diff --git a/pkg/schema/schema.go b/pkg/schema/schema.go index 4fed80b..4e42594 100644 --- a/pkg/schema/schema.go +++ b/pkg/schema/schema.go @@ -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 ( @@ -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) diff --git a/pkg/schema/schema_test.go b/pkg/schema/schema_test.go index 3ac9dc3..443677e 100644 --- a/pkg/schema/schema_test.go +++ b/pkg/schema/schema_test.go @@ -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, },