diff --git a/internal/testdata/init/templateDefinition/schema.json b/internal/testdata/init/templateDefinition/schema.json index 5f927011b..7a682f6da 100644 --- a/internal/testdata/init/templateDefinition/schema.json +++ b/internal/testdata/init/templateDefinition/schema.json @@ -1,17 +1,20 @@ { - "project_name": { - "description": "Name of the project", - "type": "string" - }, - "cloud_type": { - "description": "type of the cloud for the project", - "type": "string" - }, - "is_production": { - "type": "boolean" - }, - "ci_type": { - "type": "string", - "description": "type of the CI runner, eg: github, azure devops" + "version": 0, + "properties": { + "project_name": { + "description": "Name of the project", + "type": "string" + }, + "cloud_type": { + "description": "type of the cloud for the project", + "type": "string" + }, + "is_production": { + "type": "boolean" + }, + "ci_type": { + "type": "string", + "description": "type of the CI runner, eg: github, azure devops" + } } } diff --git a/libs/template/schema.go b/libs/template/schema.go index 9759eee66..14bacf0ee 100644 --- a/libs/template/schema.go +++ b/libs/template/schema.go @@ -7,7 +7,15 @@ import ( "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 @@ -33,15 +41,15 @@ func isIntegerValue(v float64) bool { // integeres according to the schema // // 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 { // 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) } // skip non integer fields - fieldInfo := schema[k] + fieldInfo := schema.Properties[k] if fieldInfo.Type != FieldTypeInt { continue } @@ -74,10 +82,10 @@ func validateType(v any, fieldType FieldType) error { 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 for k, v := range config { - fieldMetadata, ok := schema[k] + fieldMetadata, ok := schema.Properties[k] if !ok { 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 - for k := range schema { + for k := range schema.Properties { if _, ok := config[k]; !ok { 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 } -func ReadSchema(path string) (Schema, error) { +func ReadSchema(path string) (*Schema, error) { schemaBytes, err := os.ReadFile(path) if err != nil { return nil, err } - schema := Schema{} - err = json.Unmarshal(schemaBytes, &schema) + schema := &Schema{} + err = json.Unmarshal(schemaBytes, schema) if err != nil { return nil, err } 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 b, err := os.ReadFile(path) if err != nil { diff --git a/libs/template/schema_test.go b/libs/template/schema_test.go index 75d8f5034..cac1da814 100644 --- a/libs/template/schema_test.go +++ b/libs/template/schema_test.go @@ -21,17 +21,20 @@ func TestTemplateSchematIsInterger(t *testing.T) { func TestTemplateSchemaCastFloatToInt(t *testing.T) { // define schema for config schemaJson := `{ - "int_val": { - "type": "integer" - }, - "float_val": { - "type": "float" - }, - "bool_val": { - "type": "boolean" - }, - "string_val": { - "type": "string" + "version": 0, + "properties": { + "int_val": { + "type": "integer" + }, + "float_val": { + "type": "float" + }, + "bool_val": { + "type": "boolean" + }, + "string_val": { + "type": "string" + } } }` var schema Schema @@ -56,7 +59,7 @@ func TestTemplateSchemaCastFloatToInt(t *testing.T) { assert.IsType(t, true, config["bool_val"]) assert.IsType(t, "abc", config["string_val"]) - err = castFloatToInt(config, schema) + err = castFloatToInt(config, &schema) require.NoError(t, err) // assert type after casting, that the float value was converted to an integer @@ -70,8 +73,11 @@ func TestTemplateSchemaCastFloatToInt(t *testing.T) { func TestTemplateSchemaCastFloatToIntFailsForUnknownTypes(t *testing.T) { // define schema for config schemaJson := `{ - "foo": { - "type": "integer" + "version": 0, + "properties": { + "foo": { + "type": "integer" + } } }` var schema Schema @@ -86,15 +92,18 @@ func TestTemplateSchemaCastFloatToIntFailsForUnknownTypes(t *testing.T) { err = json.Unmarshal([]byte(configJson), &config) 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") } func TestTemplateSchemaCastFloatToIntFailsWhenWithNonIntValues(t *testing.T) { // define schema for config schemaJson := `{ - "foo": { - "type": "integer" + "version": 0, + "properties": { + "foo": { + "type": "integer" + } } }` var schema Schema @@ -109,7 +118,7 @@ func TestTemplateSchemaCastFloatToIntFailsWhenWithNonIntValues(t *testing.T) { err = json.Unmarshal([]byte(configJson), &config) 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") } @@ -172,17 +181,20 @@ func TestTemplateSchemaValidateType(t *testing.T) { func TestTemplateSchemaValidateConfig(t *testing.T) { // define schema for config schemaJson := `{ - "int_val": { - "type": "integer" - }, - "float_val": { - "type": "float" - }, - "bool_val": { - "type": "boolean" - }, - "string_val": { - "type": "string" + "version": 0, + "properties": { + "int_val": { + "type": "integer" + }, + "float_val": { + "type": "float" + }, + "bool_val": { + "type": "boolean" + }, + "string_val": { + "type": "string" + } } }` var schema Schema @@ -236,6 +248,8 @@ func TestTemplateSchemaValidateConfigFailsForUnknownField(t *testing.T) { func TestTemplateSchemaValidateConfigFailsForWhenIncorrectTypes(t *testing.T) { // define schema for config schemaJson := `{ + "version": 0, + "properties": { "int_val": { "type": "integer" }, @@ -248,7 +262,8 @@ func TestTemplateSchemaValidateConfigFailsForWhenIncorrectTypes(t *testing.T) { "string_val": { "type": "string" } - }` + } + }` var schema Schema err := json.Unmarshal([]byte(schemaJson), &schema) require.NoError(t, err) @@ -268,12 +283,15 @@ func TestTemplateSchemaValidateConfigFailsForWhenIncorrectTypes(t *testing.T) { func TestTemplateSchemaValidateConfigFailsForWhenMissingInputParams(t *testing.T) { // define schema for config schemaJson := `{ + "version": 0, + "properties": { "int_val": { "type": "integer" }, "string_val": { "type": "string" } + } }` var schema Schema err := json.Unmarshal([]byte(schemaJson), &schema) diff --git a/libs/template/testdata/skip_dir/schema.json b/libs/template/testdata/skip_dir/schema.json index 9687bce76..945b7df84 100644 --- a/libs/template/testdata/skip_dir/schema.json +++ b/libs/template/testdata/skip_dir/schema.json @@ -1,14 +1,17 @@ { - "a": { - "type": "string" - }, - "b": { - "type": "string" - }, - "c": { - "type": "string" - }, - "d": { - "type": "string" + "version": 0, + "properties": { + "a": { + "type": "string" + }, + "b": { + "type": "string" + }, + "c": { + "type": "string" + }, + "d": { + "type": "string" + } } }