Skip to content

Commit

Permalink
Merge pull request #66 from losisin/feature/addtional-cli-flags
Browse files Browse the repository at this point in the history
feature: add schemaRoot CLI flags for json root object
  • Loading branch information
losisin authored Jun 4, 2024
2 parents 68b7752 + 7061ff6 commit 1448cdc
Show file tree
Hide file tree
Showing 14 changed files with 134 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ repos:
hooks:
- id: helm-schema
args:
# Single or multiple yamlFiles as inputs (comma-separated)
# Single or multiple yaml files as inputs (comma-separated)
- --input=values.yaml
# Output file path (default "values.schema.json")
- --output=values.schema.json
Expand Down
55 changes: 54 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,15 @@ usage: helm schema [-input STR] [-draft INT] [-output STR]
-indent int
Indentation spaces (even number) (default 4)
-input value
Multiple yamlFiles as inputs (comma-separated)
Multiple yaml files as inputs (comma-separated)
-output string
Output file path (default "values.schema.json")
-schemaRoot.description string
JSON schema description
-schemaRoot.id string
JSON schema ID
-schemaRoot.title string
JSON schema title
```

### Basic
Expand All @@ -112,6 +118,8 @@ This will read `values.yaml`, set draft version to `2020-12` and save outpout to

### Extended

#### Multiple values files

Merge multiple values files, set json-schema draft version explicitly and save output to `my.schema.json`:

`values_1.yaml`
Expand Down Expand Up @@ -207,6 +215,51 @@ Output will be something like this:
}
```

#### Root JSON object properties

Adding ID, title and description to the schema:

`basic.yaml`

```yaml
image:
repository: nginx
tag: latest
pullPolicy: Always
```

```bash
$ helm schema -input basic.yaml -schemaRoot.id "https://example.com/schema" -schemaRoot.title "My schema" -schemaRoot.description "This is my schema"
```

Generated schema will be:

```json
{
"$id": "https://example.com/schema",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "This is my schema",
"properties": {
"image": {
"properties": {
"pullPolicy": {
"type": "string"
},
"repository": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"type": "object"
}
},
"title": "My schema",
"type": "object"
}
```

## Issues, Features, Feedback

Your input matters. Feel free to open [issues](https://github.com/losisin/helm-values-schema-json/issues) for bugs, feature requests, or any feedback you may have. Check if a similar issue exists before creating a new one, and please use clear titles and explanations to help understand your point better. Your thoughts help me improve this project!
Expand Down
37 changes: 32 additions & 5 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ The following annotations are supported:
* [required](#required)
* [patternProperties](#patternproperties)
* [additionalProperties](#additionalproperties)
* [$id](#id)
* [Meta-Data Annotations](#meta-data-annotations)
* [title and description](#title-and-description)
* [default](#default)
Expand Down Expand Up @@ -373,7 +374,7 @@ image:

### patternProperties

JSON string added "AS IS" to the node. [documentation](https://json-schema.org/understanding-json-schema/reference/object#patternProperties)
JSON string added "AS IS" to the node. [section 10.3.2.2](https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00#section-10.3.2.2)

```yaml
image: # @schema patternProperties: {"^[a-z]$": {"type": "string"}}
Expand All @@ -398,7 +399,7 @@ image: # @schema patternProperties: {"^[a-z]$": {"type": "string"}}

### additionalProperties

Boolean. [documentation](https://json-schema.org/understanding-json-schema/reference/object#additionalproperties)
Boolean. [section 10.3.2.3](https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00#section-10.3.2.3)

```yaml
image: # @schema additionalProperties: false
Expand All @@ -417,6 +418,35 @@ image: # @schema additionalProperties: false
}
```

### $id

String. [section 8.2.1](https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00#section-8.2.1)

```yaml
image: # @schema $id: https://example.com/schema.json
repository: nginx
tag: latest
pullPolicy: Always
```
```json
"image": {
"$id": "https://example.com/schema.json",
"properties": {
"pullPolicy": {
"type": "string"
},
"repository": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"type": "object"
}
```

## Meta-Data Annotations

### title and description
Expand All @@ -427,9 +457,6 @@ String. [section 9.1](https://json-schema.org/draft/2020-12/json-schema-validati
fullnameOverride: bar # @schema title: My title ; description: My description
```
```json
```

```json
"fullnameOverride": {
"title": "My title",
Expand Down
5 changes: 5 additions & 0 deletions pkg/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ func ParseFlags(progname string, args []string) (config *Config, output string,
flags.IntVar(&conf.draft, "draft", 2020, "Draft version (4, 6, 7, 2019, or 2020)")
flags.IntVar(&conf.indent, "indent", 4, "Indentation spaces (even number)")

// Nested SchemaRoot flags
flags.StringVar(&conf.SchemaRoot.ID, "schemaRoot.id", "", "JSON schema ID")
flags.StringVar(&conf.SchemaRoot.Title, "schemaRoot.title", "", "JSON schema title")
flags.StringVar(&conf.SchemaRoot.Description, "schemaRoot.description", "", "JSON schema description")

err = flags.Parse(args)
if err != nil {
fmt.Println("Usage: helm schema [-input STR] [-draft INT] [-output STR]")
Expand Down
3 changes: 3 additions & 0 deletions pkg/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ func TestParseFlagsPass(t *testing.T) {

{[]string{"-input", "values.yaml", "-output", "my.schema.json", "-draft", "2019"},
Config{input: multiStringFlag{"values.yaml"}, outputPath: "my.schema.json", draft: 2019, indent: 4, args: []string{}}},

{[]string{"-input", "values.yaml", "-schemaRoot.id", "http://example.com/schema", "-schemaRoot.title", "MySchema", "-schemaRoot.description", "My schema description"},
Config{input: multiStringFlag{"values.yaml"}, outputPath: "values.schema.json", draft: 2020, indent: 4, SchemaRoot: SchemaRoot{ID: "http://example.com/schema", Title: "MySchema", Description: "My schema description"}, args: []string{}}},
}

for _, tt := range tests {
Expand Down
9 changes: 6 additions & 3 deletions pkg/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,12 @@ func GenerateJsonSchema(config *Config) error {

// Create a temporary Schema to merge from the nodes
tempSchema := &Schema{
Type: "object",
Properties: properties,
Required: required,
Type: "object",
Properties: properties,
Required: required,
Title: config.SchemaRoot.Title,
Description: config.SchemaRoot.Description,
ID: config.SchemaRoot.ID,
}

// Merge with existing data
Expand Down
5 changes: 5 additions & 0 deletions pkg/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ func TestGenerateJsonSchema(t *testing.T) {
outputPath: "../testdata/output.json",
draft: 2020,
indent: 4,
SchemaRoot: SchemaRoot{
ID: "",
Title: "",
Description: "",
},
}

err := GenerateJsonSchema(config)
Expand Down
6 changes: 6 additions & 0 deletions pkg/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ func mergeSchemas(dest, src *Schema) *Schema {
if src.AdditionalProperties != nil {
dest.AdditionalProperties = src.AdditionalProperties
}
if src.ID != "" {
dest.ID = src.ID
}

// Merge 'enum' field (assuming that maintaining order doesn't matter)
dest.Enum = append(dest.Enum, src.Enum...)
Expand Down Expand Up @@ -173,6 +176,9 @@ func convertSchemaToMapRec(schema *Schema, visited map[uintptr]bool) (map[string
if schema.AdditionalProperties != nil {
schemaMap["additionalProperties"] = *schema.AdditionalProperties
}
if schema.ID != "" {
schemaMap["$id"] = schema.ID
}

// Arrays
if len(schema.Required) > 0 {
Expand Down
8 changes: 5 additions & 3 deletions pkg/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,9 @@ func TestMergeSchemas(t *testing.T) {
},
{
name: "meta-data properties",
dest: &Schema{Type: "object", Title: "My Title", Description: "My description", ReadOnly: true, Default: "default value"},
src: &Schema{Type: "object", Title: "My Title", Description: "My description", ReadOnly: true, Default: "default value"},
want: &Schema{Type: "object", Title: "My Title", Description: "My description", ReadOnly: true, Default: "default value"},
dest: &Schema{Type: "object", Title: "My Title", Description: "My description", ReadOnly: true, Default: "default value", ID: "http://example.com/schema"},
src: &Schema{Type: "object", Title: "My Title", Description: "My description", ReadOnly: true, Default: "default value", ID: "http://example.com/schema"},
want: &Schema{Type: "object", Title: "My Title", Description: "My description", ReadOnly: true, Default: "default value", ID: "http://example.com/schema"},
},
}

Expand Down Expand Up @@ -201,6 +201,7 @@ func TestConvertSchemaToMap(t *testing.T) {
},
},
Required: []string{"foo"},
ID: "http://example.com/schema",
},
want: map[string]interface{}{
"type": "object",
Expand All @@ -212,6 +213,7 @@ func TestConvertSchemaToMap(t *testing.T) {
},
},
"required": []string{"foo"},
"$id": "http://example.com/schema",
},
},
{
Expand Down
3 changes: 3 additions & 0 deletions pkg/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Schema struct {
ReadOnly bool `json:"readOnly,omitempty"`
Default interface{} `json:"default,omitempty"`
AdditionalProperties *bool `json:"additionalProperties"`
ID string `json:"$id,omitempty"`
}

func getKind(value string) string {
Expand Down Expand Up @@ -190,6 +191,8 @@ func processComment(schema *Schema, comment string) (isRequired bool) {
if v, err := strconv.ParseBool(value); err == nil {
schema.AdditionalProperties = &v
}
case "$id":
schema.ID = value
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,8 @@ func TestProcessComment(t *testing.T) {
{
name: "Set object",
schema: &Schema{},
comment: "# @schema minProperties:1;maxProperties:10;additionalProperties:false",
expectedSchema: &Schema{MinProperties: uint64Ptr(1), MaxProperties: uint64Ptr(10), AdditionalProperties: boolPtr(false)},
comment: "# @schema minProperties:1;maxProperties:10;additionalProperties:false;$id:https://example.com/schema",
expectedSchema: &Schema{MinProperties: uint64Ptr(1), MaxProperties: uint64Ptr(10), AdditionalProperties: boolPtr(false), ID: "https://example.com/schema"},
expectedRequired: false,
},
{
Expand Down
11 changes: 10 additions & 1 deletion pkg/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,26 @@ package pkg

import "strings"

// SchemaRoot struct defines root object of schema
type SchemaRoot struct {
ID string
Title string
Description string
}

// Save values of parsed flags in Config
type Config struct {
input multiStringFlag
outputPath string
draft int
indent int

SchemaRoot SchemaRoot

args []string
}

// Define a custom flag type to accept multiple yamlFiles
// Define a custom flag type to accept multiple yaml files
type multiStringFlag []string

func (m *multiStringFlag) String() string {
Expand Down
1 change: 1 addition & 0 deletions testdata/full.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"items": {
"properties": {
"preference": {
"$id": "https://example.com/schema.json",
"patternProperties": {
"^[a-z]$": {
"type": "string"
Expand Down
2 changes: 1 addition & 1 deletion testdata/full.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ affinity:
- antarctica-west1
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference: # @schema patternProperties: {"^[a-z]$": {"type": "string"}}
preference: # @schema patternProperties: {"^[a-z]$": {"type": "string"}} ; $id: https://example.com/schema.json
matchExpressions:
- key: another-node-label-key
operator: In
Expand Down

0 comments on commit 1448cdc

Please sign in to comment.