Skip to content

Commit

Permalink
Add validation to skip-auto-generation flag
Browse files Browse the repository at this point in the history
  • Loading branch information
ubergesundheit committed Mar 6, 2024
1 parent cddcf5d commit f4eb81b
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 15 deletions.
2 changes: 1 addition & 1 deletion cmd/helm-schema/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func newCommand(run func(cmd *cobra.Command, args []string) error) (*cobra.Comma
cmd.PersistentFlags().
StringP("output-file", "o", "values.schema.json", "jsonschema file path relative to each chart directory to which jsonschema will be written")
cmd.PersistentFlags().
StringSliceP("skip-auto-generation", "k", []string{}, "do not auto-create the given fields (e.g. title,description,...)")
StringSliceP("skip-auto-generation", "k", []string{}, "comma separated list of fields to skip from being created by default (possible: title, description, required, default, additionalProperties)")

viper.AutomaticEnv()
viper.SetEnvPrefix("HELM_SCHEMA")
Expand Down
13 changes: 9 additions & 4 deletions cmd/helm-schema/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ type Result struct {
func worker(
dryRun, keepFullComment, dontRemoveHelmDocsPrefix bool,
valueFileNames []string,
skipAutoGeneration []string,
skipAutoGenerationConfig *schema.SkipAutoGenerationConfig,
outFile string,
queue <-chan string,
results chan<- Result,
Expand Down Expand Up @@ -121,7 +121,7 @@ func worker(
continue
}

result.Schema = schema.YamlToSchema(&values, keepFullComment, dontRemoveHelmDocsPrefix, skipAutoGeneration, nil)
result.Schema = schema.YamlToSchema(&values, keepFullComment, dontRemoveHelmDocsPrefix, skipAutoGenerationConfig, nil)

results <- result
}
Expand All @@ -146,6 +146,11 @@ func exec(cmd *cobra.Command, _ []string) error {
}
workersCount := runtime.NumCPU() * 2

skipConfig, err := schema.NewSkipAutoGenerationConfig(skipAutoGeneration)
if err != nil {
return err
}

// 1. Start a producer that searches Chart.yaml and values.yaml files
queue := make(chan string)
resultsChan := make(chan Result)
Expand All @@ -172,7 +177,7 @@ func exec(cmd *cobra.Command, _ []string) error {
keepFullComment,
dontRemoveHelmDocsPrefix,
valueFileNames,
skipAutoGeneration,
skipConfig,
outFile,
queue,
resultsChan,
Expand All @@ -194,7 +199,7 @@ loop:
}

// sort results with topology sort
results, err := util.TopSort[*Result, string](results, func(i *Result) string {
results, err = util.TopSort[*Result, string](results, func(i *Result) string {
return i.Chart.Name
},
func(d *Result) []string {
Expand Down
59 changes: 49 additions & 10 deletions pkg/schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,45 @@ func (s Schema) Validate() error {
return nil
}

var possibleSkipFields = []string{"title", "description", "required", "default", "additionalProperties"}

type SkipAutoGenerationConfig struct {
Title, Description, Required, Default, AdditionalProperties bool
}

func NewSkipAutoGenerationConfig(flag []string) (*SkipAutoGenerationConfig, error) {
var config SkipAutoGenerationConfig

var invalidFlags []string

for _, fieldName := range flag {
if !slices.Contains(possibleSkipFields, fieldName) {
invalidFlags = append(invalidFlags, fieldName)
}
if fieldName == "title" {
config.Title = true
}
if fieldName == "description" {
config.Description = true
}
if fieldName == "required" {
config.Required = true
}
if fieldName == "default" {
config.Default = true
}
if fieldName == "additionalProperties" {
config.AdditionalProperties = true
}
}

if len(invalidFlags) != 0 {
return nil, fmt.Errorf("unsupported field names '%s' for skipping auto-generation", strings.Join(invalidFlags, "', '"))
}

return &config, nil
}

func typeFromTag(tag string) ([]string, error) {
switch tag {
case nullTag:
Expand Down Expand Up @@ -355,7 +394,7 @@ func YamlToSchema(
node *yaml.Node,
keepFullComment bool,
dontRemoveHelmDocsPrefix bool,
skipAutoGeneration []string,
skipAutoGeneration *SkipAutoGenerationConfig,
parentRequiredProperties *[]string,
) Schema {
var schema Schema
Expand Down Expand Up @@ -386,10 +425,10 @@ func YamlToSchema(
schema.Properties["global"] = &Schema{
Type: []string{"object"},
}
if !slices.Contains(skipAutoGeneration, "title") {
if !skipAutoGeneration.Title {
schema.Properties["global"].Title = "global"
}
if !slices.Contains(skipAutoGeneration, "description") {
if !skipAutoGeneration.Description {
schema.Properties["global"].Description = "Global values are values that can be accessed from any chart or subchart by exactly the same name."
}
}
Expand All @@ -398,7 +437,7 @@ func YamlToSchema(
schema.RequiredProperties = requiredProperties
}
// always disable on top level
if !slices.Contains(skipAutoGeneration, "additionalProperties") {
if !skipAutoGeneration.AdditionalProperties {
schema.AdditionalProperties = new(bool)
}
case yaml.MappingNode:
Expand Down Expand Up @@ -438,27 +477,27 @@ func YamlToSchema(
}

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

if !slices.Contains(skipAutoGeneration, "additionalProperties") && valueNode.Kind == yaml.MappingNode &&
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 == "" && !slices.Contains(skipAutoGeneration, "title") {
if keyNodeSchema.Title == "" && !skipAutoGeneration.Title {
keyNodeSchema.Title = keyNode.Value
}

// If no description was set, use the rest of the comment as description
if keyNodeSchema.Description == "" && !slices.Contains(skipAutoGeneration, "description") {
if keyNodeSchema.Description == "" && !skipAutoGeneration.Description {
keyNodeSchema.Description = description
}

// If no default value was set, use the values node value as default
if !slices.Contains(skipAutoGeneration, "default") && keyNodeSchema.Default == nil && valueNode.Kind == yaml.ScalarNode {
if !skipAutoGeneration.Default && keyNodeSchema.Default == nil && valueNode.Kind == yaml.ScalarNode {
keyNodeSchema.Default = valueNode.Value
}

Expand Down Expand Up @@ -494,7 +533,7 @@ func YamlToSchema(
itemSchema.RequiredProperties = itemRequiredProperties
}

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

Expand Down

0 comments on commit f4eb81b

Please sign in to comment.