Add the Schema type and a function to read it

Signed-off-by: Ian Howell <ian.howell0@gmail.com>
pull/5350/head
Ian Howell 7 years ago
parent e2ccf13294
commit 34b2b71f86

@ -45,6 +45,25 @@ const GlobalKey = "global"
// Values represents a collection of chart values.
type Values map[string]interface{}
// SchemaProperties represents the nested objects of a schema
type SchemaProperties map[string]*Schema
// Schema is a JSON schema which can be applied to a values file to validate it
type Schema struct {
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
Type string `json:"type,omitempty"`
Properties SchemaProperties `json:"properties,omitempty"`
Required []string `json:"required,omitempty"`
Minimum int `json:"minimum,omitempty"`
}
// YAML encodes the Values into a YAML string.
func (s Schema) YAML() (string, error) {
b, err := yaml.Marshal(s)
return string(b), err
}
// YAML encodes the Values into a YAML string.
func (v Values) YAML() (string, error) {
b, err := yaml.Marshal(v)
@ -124,6 +143,12 @@ func ReadValues(data []byte) (vals Values, err error) {
return vals, err
}
// ReadSchema will parse YAML byte data into a Schema.
func ReadSchema(data []byte) (schema Schema, err error) {
err = yaml.Unmarshal(data, &schema)
return schema, err
}
// ReadValuesFile will parse a YAML file into a map of values.
func ReadValuesFile(filename string) (Values, error) {
data, err := ioutil.ReadFile(filename)

@ -435,3 +435,118 @@ chapter:
}
}
}
func TestReadSchema(t *testing.T) {
schemaTest := `# Test YAML parse
title: Values
type: object
properties:
name:
description: Service name
type: string
protocol:
type: string
port:
description: Port
type: integer
minimum: 0
image:
description: Container Image
type: object
properties:
repo:
type: string
tag:
type: string
required:
- protocol
- port
`
data, err := ReadSchema([]byte(schemaTest))
if err != nil {
t.Fatalf("Error parsing bytes: %s", err)
}
matchSchema(t, data)
}
func matchSchema(t *testing.T, data Schema) {
if data.Title != "Values" {
t.Errorf("Expected .title to be 'Values', got '%s'", data.Title)
}
if data.Type != "object" {
t.Errorf("Expected .type to be 'object', got '%s'", data.Type)
}
if name, ok := data.Properties["name"]; !ok {
t.Errorf("Expected property '.properties.name' is missing")
} else {
if name.Description != "Service name" {
t.Errorf("Expected .properties.name.description to be 'Service name', got '%s'", name.Description)
}
if name.Type != "string" {
t.Errorf("Expected .properties.name.type to be 'string', got '%s'", name.Description)
}
}
if protocol, ok := data.Properties["protocol"]; !ok {
t.Errorf("Expected property '.properties.protocol' is missing")
} else {
if protocol.Type != "string" {
t.Errorf("Expected .properties.protocol.type to be 'string', got '%s'", protocol.Description)
}
}
if port, ok := data.Properties["port"]; !ok {
t.Errorf("Expected property '.properties.port' is missing")
} else {
if port.Description != "Port" {
t.Errorf("Expected .properties.port.description to be 'Port', got '%s'", port.Description)
}
if port.Type != "integer" {
t.Errorf("Expected .properties.port.type to be 'string', got '%s'", port.Description)
}
if port.Minimum != 0 {
t.Errorf("Expected .properties.port.minimum to be 0, got %d", port.Minimum)
}
}
if image, ok := data.Properties["image"]; !ok {
t.Errorf("Expected property '.properties.image' is missing")
} else {
if image.Description != "Container Image" {
t.Errorf("Expected .properties.image.description to be 'Container Image', got '%s'", image.Description)
}
if image.Type != "object" {
t.Errorf("Expected .properties.image.type to be 'object', got '%s'", image.Description)
}
if repo, ok := image.Properties["repo"]; !ok {
t.Errorf("Expected property '.properties.repo' is missing")
} else {
if repo.Type != "string" {
t.Errorf("Expected .properties.repo.type to be 'string', got '%s'", repo.Description)
}
}
if tag, ok := image.Properties["tag"]; !ok {
t.Errorf("Expected property '.properties.tag' is missing")
} else {
if tag.Type != "string" {
t.Errorf("Expected .properties.tag.type to be 'string', got '%s'", tag.Description)
}
}
}
if len(data.Required) != 2 {
t.Errorf("Expected length of .required to be 2, got %d", len(data.Required))
}
expectedRequired := []string{
"protocol",
"port",
}
for i := 0; i < 2; i++ {
if data.Required[i] != expectedRequired[i] {
t.Errorf("Expected .required to be %v, got %v", expectedRequired, data.Required)
}
}
}

Loading…
Cancel
Save