Add functionality to generate a schema from a values.yaml

Signed-off-by: Ian Howell <ian.howell0@gmail.com>
pull/5350/head
Ian Howell 7 years ago
parent 686b620a1f
commit 8e6433a53f

@ -203,6 +203,73 @@ func ReadSchematizedValues(data, schemaData []byte) (Values, error) {
return values, nil
}
// GenerateSchema will create a JSON Schema (in YAML format) for the given values
func GenerateSchema(values Values) Schema {
schema := Schema{
"type": "object",
"title": "Values",
}
if len(values) > 0 {
schema["properties"] = parsePropertiesFromValues(values)
}
return schema
}
func parsePropertiesFromValues(values Values) map[string]map[string]interface{} {
properties := make(map[string]map[string]interface{})
for k, v := range values {
// If the value is null, then there's no way to determine the properties attributes
if v == nil || v == "" {
continue
}
properties[k] = make(map[string]interface{})
// the following types are the only types possible from unmarshalling
switch v.(type) {
case bool:
properties[k]["type"] = "bool"
case float64:
properties[k]["type"] = "number"
case string:
properties[k]["type"] = "string"
case []interface{}:
properties[k]["type"] = "array"
properties[k]["items"] = parseItemsFromValues(v.([]interface{}))
case map[string]interface{}:
properties[k]["type"] = "object"
object := parsePropertiesFromValues(v.(map[string]interface{}))
if len(object) > 0 {
properties[k]["object"] = object
}
}
}
return properties
}
func parseItemsFromValues(items []interface{}) map[string]interface{} {
properties := make(map[string]interface{})
v := items[0]
// the following types are the only types possible from unmarshalling
switch v.(type) {
case bool:
properties["type"] = "bool"
case float64:
properties["type"] = "number"
case string:
properties["type"] = "string"
case []interface{}:
properties["type"] = "array"
properties["items"] = parseItemsFromValues(v.([]interface{}))
case map[string]interface{}:
properties["type"] = "object"
object := parsePropertiesFromValues(v.(map[string]interface{}))
if len(object) > 0 {
properties["object"] = object
}
}
return properties
}
// CoalesceValues coalesces all of the values in a chart (and its subcharts).
//
// Values are coalesced together using the following rules:

@ -435,6 +435,7 @@ func TestCoalesceTables(t *testing.T) {
t.Errorf("Expected boat string, got %v", dst["boat"])
}
}
func TestPathValue(t *testing.T) {
doc := `
title: "Moby Dick"
@ -627,6 +628,48 @@ func matchSchema(t *testing.T, data Schema) {
assertEqualProperty(t, property, expected, data)
}
func TestGenerateSchema(t *testing.T) {
doc := `# Test YAML parse
firstname: John
middlename: null
lastname: Doe
age: 25
likesCoffee: true
employmentInfo:
title: Software Developer
salary: 100000
addresses:
- city: Springfield
street: Main
number: 12345
- city: New York
street: Broadway
number: 67890
phoneNumbers:
- "(888) 888-8888"
- "(555) 555-5555"
`
values, _ := ReadValues([]byte(doc))
schema := GenerateSchema(values)
assertEqualProperty(t, ".title", "Values", schema)
assertEqualProperty(t, ".type", "object", schema)
assertEqualProperty(t, ".properties.firstname.type", "string", schema)
assertEqualProperty(t, ".properties.lastname.type", "string", schema)
assertEqualProperty(t, ".properties.age.type", "number", schema)
assertEqualProperty(t, ".properties.likesCoffee.type", "bool", schema)
assertEqualProperty(t, ".properties.employmentInfo.type", "object", schema)
assertEqualProperty(t, ".properties.employmentInfo.object.title.type", "string", schema)
assertEqualProperty(t, ".properties.employmentInfo.object.salary.type", "number", schema)
assertEqualProperty(t, ".properties.addresses.type", "array", schema)
assertEqualProperty(t, ".properties.addresses.items.type", "object", schema)
assertEqualProperty(t, ".properties.addresses.items.object.street.type", "string", schema)
assertEqualProperty(t, ".properties.addresses.items.object.number.type", "number", schema)
assertEqualProperty(t, ".properties.addresses.items.object.city.type", "string", schema)
assertEqualProperty(t, ".properties.phoneNumbers.type", "array", schema)
assertEqualProperty(t, ".properties.phoneNumbers.items.type", "string", schema)
}
func assertEqualProperty(t *testing.T, property, expected string, data map[string]interface{}) {
if o, err := ttpl("{{"+property+"}}", data); err != nil {
t.Errorf("%s: %s", property, err)

Loading…
Cancel
Save