add version of schema

This commit is contained in:
Shreyas Goenka 2023-05-22 11:06:10 +02:00
parent 89d02cda6b
commit 601e16e9e8
No known key found for this signature in database
GPG Key ID: 92A07DF49CCB0622
4 changed files with 98 additions and 66 deletions

View File

@ -1,4 +1,6 @@
{ {
"version": 0,
"properties": {
"project_name": { "project_name": {
"description": "Name of the project", "description": "Name of the project",
"type": "string" "type": "string"
@ -15,3 +17,4 @@
"description": "type of the CI runner, eg: github, azure devops" "description": "type of the CI runner, eg: github, azure devops"
} }
} }
}

View File

@ -7,7 +7,15 @@ import (
"reflect" "reflect"
) )
type Schema map[string]FieldInfo const LatestSchemaVersion = 0
type Schema struct {
// A version for the template schema
Version int `json:"version"`
// A list of properties that can be used in the config
Properties map[string]FieldInfo `json:"properties"`
}
type FieldType string type FieldType string
@ -33,15 +41,15 @@ func isIntegerValue(v float64) bool {
// integeres according to the schema // integeres according to the schema
// //
// Needed because the default json unmarshaller for maps converts all numbers to floats // Needed because the default json unmarshaller for maps converts all numbers to floats
func castFloatToInt(config map[string]any, schema Schema) error { func castFloatToInt(config map[string]any, schema *Schema) error {
for k, v := range config { for k, v := range config {
// error because all config keys should be defined in schema too // error because all config keys should be defined in schema too
if _, ok := schema[k]; !ok { if _, ok := schema.Properties[k]; !ok {
return fmt.Errorf("%s is not defined as an input parameter for the template", k) return fmt.Errorf("%s is not defined as an input parameter for the template", k)
} }
// skip non integer fields // skip non integer fields
fieldInfo := schema[k] fieldInfo := schema.Properties[k]
if fieldInfo.Type != FieldTypeInt { if fieldInfo.Type != FieldTypeInt {
continue continue
} }
@ -74,10 +82,10 @@ func validateType(v any, fieldType FieldType) error {
return validateFunc(v) return validateFunc(v)
} }
func (schema Schema) ValidateConfig(config map[string]any) error { func (schema *Schema) ValidateConfig(config map[string]any) error {
// validate types defined in config // validate types defined in config
for k, v := range config { for k, v := range config {
fieldMetadata, ok := schema[k] fieldMetadata, ok := schema.Properties[k]
if !ok { if !ok {
return fmt.Errorf("%s is not defined as an input parameter for the template", k) return fmt.Errorf("%s is not defined as an input parameter for the template", k)
} }
@ -87,7 +95,7 @@ func (schema Schema) ValidateConfig(config map[string]any) error {
} }
} }
// assert all fields are defined in // assert all fields are defined in
for k := range schema { for k := range schema.Properties {
if _, ok := config[k]; !ok { if _, ok := config[k]; !ok {
return fmt.Errorf("input parameter %s is not defined in config", k) return fmt.Errorf("input parameter %s is not defined in config", k)
} }
@ -95,20 +103,20 @@ func (schema Schema) ValidateConfig(config map[string]any) error {
return nil return nil
} }
func ReadSchema(path string) (Schema, error) { func ReadSchema(path string) (*Schema, error) {
schemaBytes, err := os.ReadFile(path) schemaBytes, err := os.ReadFile(path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
schema := Schema{} schema := &Schema{}
err = json.Unmarshal(schemaBytes, &schema) err = json.Unmarshal(schemaBytes, schema)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return schema, nil return schema, nil
} }
func (schema Schema) ReadConfig(path string) (map[string]any, error) { func (schema *Schema) ReadConfig(path string) (map[string]any, error) {
var config map[string]any var config map[string]any
b, err := os.ReadFile(path) b, err := os.ReadFile(path)
if err != nil { if err != nil {

View File

@ -21,6 +21,8 @@ func TestTemplateSchematIsInterger(t *testing.T) {
func TestTemplateSchemaCastFloatToInt(t *testing.T) { func TestTemplateSchemaCastFloatToInt(t *testing.T) {
// define schema for config // define schema for config
schemaJson := `{ schemaJson := `{
"version": 0,
"properties": {
"int_val": { "int_val": {
"type": "integer" "type": "integer"
}, },
@ -33,6 +35,7 @@ func TestTemplateSchemaCastFloatToInt(t *testing.T) {
"string_val": { "string_val": {
"type": "string" "type": "string"
} }
}
}` }`
var schema Schema var schema Schema
err := json.Unmarshal([]byte(schemaJson), &schema) err := json.Unmarshal([]byte(schemaJson), &schema)
@ -56,7 +59,7 @@ func TestTemplateSchemaCastFloatToInt(t *testing.T) {
assert.IsType(t, true, config["bool_val"]) assert.IsType(t, true, config["bool_val"])
assert.IsType(t, "abc", config["string_val"]) assert.IsType(t, "abc", config["string_val"])
err = castFloatToInt(config, schema) err = castFloatToInt(config, &schema)
require.NoError(t, err) require.NoError(t, err)
// assert type after casting, that the float value was converted to an integer // assert type after casting, that the float value was converted to an integer
@ -70,9 +73,12 @@ func TestTemplateSchemaCastFloatToInt(t *testing.T) {
func TestTemplateSchemaCastFloatToIntFailsForUnknownTypes(t *testing.T) { func TestTemplateSchemaCastFloatToIntFailsForUnknownTypes(t *testing.T) {
// define schema for config // define schema for config
schemaJson := `{ schemaJson := `{
"version": 0,
"properties": {
"foo": { "foo": {
"type": "integer" "type": "integer"
} }
}
}` }`
var schema Schema var schema Schema
err := json.Unmarshal([]byte(schemaJson), &schema) err := json.Unmarshal([]byte(schemaJson), &schema)
@ -86,16 +92,19 @@ func TestTemplateSchemaCastFloatToIntFailsForUnknownTypes(t *testing.T) {
err = json.Unmarshal([]byte(configJson), &config) err = json.Unmarshal([]byte(configJson), &config)
require.NoError(t, err) require.NoError(t, err)
err = castFloatToInt(config, schema) err = castFloatToInt(config, &schema)
assert.ErrorContains(t, err, "bar is not defined as an input parameter for the template") assert.ErrorContains(t, err, "bar is not defined as an input parameter for the template")
} }
func TestTemplateSchemaCastFloatToIntFailsWhenWithNonIntValues(t *testing.T) { func TestTemplateSchemaCastFloatToIntFailsWhenWithNonIntValues(t *testing.T) {
// define schema for config // define schema for config
schemaJson := `{ schemaJson := `{
"version": 0,
"properties": {
"foo": { "foo": {
"type": "integer" "type": "integer"
} }
}
}` }`
var schema Schema var schema Schema
err := json.Unmarshal([]byte(schemaJson), &schema) err := json.Unmarshal([]byte(schemaJson), &schema)
@ -109,7 +118,7 @@ func TestTemplateSchemaCastFloatToIntFailsWhenWithNonIntValues(t *testing.T) {
err = json.Unmarshal([]byte(configJson), &config) err = json.Unmarshal([]byte(configJson), &config)
require.NoError(t, err) require.NoError(t, err)
err = castFloatToInt(config, schema) err = castFloatToInt(config, &schema)
assert.ErrorContains(t, err, "expected foo to have integer value but it is 1.1") assert.ErrorContains(t, err, "expected foo to have integer value but it is 1.1")
} }
@ -172,6 +181,8 @@ func TestTemplateSchemaValidateType(t *testing.T) {
func TestTemplateSchemaValidateConfig(t *testing.T) { func TestTemplateSchemaValidateConfig(t *testing.T) {
// define schema for config // define schema for config
schemaJson := `{ schemaJson := `{
"version": 0,
"properties": {
"int_val": { "int_val": {
"type": "integer" "type": "integer"
}, },
@ -184,6 +195,7 @@ func TestTemplateSchemaValidateConfig(t *testing.T) {
"string_val": { "string_val": {
"type": "string" "type": "string"
} }
}
}` }`
var schema Schema var schema Schema
err := json.Unmarshal([]byte(schemaJson), &schema) err := json.Unmarshal([]byte(schemaJson), &schema)
@ -236,6 +248,8 @@ func TestTemplateSchemaValidateConfigFailsForUnknownField(t *testing.T) {
func TestTemplateSchemaValidateConfigFailsForWhenIncorrectTypes(t *testing.T) { func TestTemplateSchemaValidateConfigFailsForWhenIncorrectTypes(t *testing.T) {
// define schema for config // define schema for config
schemaJson := `{ schemaJson := `{
"version": 0,
"properties": {
"int_val": { "int_val": {
"type": "integer" "type": "integer"
}, },
@ -248,6 +262,7 @@ func TestTemplateSchemaValidateConfigFailsForWhenIncorrectTypes(t *testing.T) {
"string_val": { "string_val": {
"type": "string" "type": "string"
} }
}
}` }`
var schema Schema var schema Schema
err := json.Unmarshal([]byte(schemaJson), &schema) err := json.Unmarshal([]byte(schemaJson), &schema)
@ -268,12 +283,15 @@ func TestTemplateSchemaValidateConfigFailsForWhenIncorrectTypes(t *testing.T) {
func TestTemplateSchemaValidateConfigFailsForWhenMissingInputParams(t *testing.T) { func TestTemplateSchemaValidateConfigFailsForWhenMissingInputParams(t *testing.T) {
// define schema for config // define schema for config
schemaJson := `{ schemaJson := `{
"version": 0,
"properties": {
"int_val": { "int_val": {
"type": "integer" "type": "integer"
}, },
"string_val": { "string_val": {
"type": "string" "type": "string"
} }
}
}` }`
var schema Schema var schema Schema
err := json.Unmarshal([]byte(schemaJson), &schema) err := json.Unmarshal([]byte(schemaJson), &schema)

View File

@ -1,4 +1,6 @@
{ {
"version": 0,
"properties": {
"a": { "a": {
"type": "string" "type": "string"
}, },
@ -12,3 +14,4 @@
"type": "string" "type": "string"
} }
} }
}