refactor logic out of the cmd

This commit is contained in:
Shreyas Goenka 2023-05-21 22:37:38 +02:00
parent f5384fc5ed
commit a21fbdd383
No known key found for this signature in database
GPG Key ID: 92A07DF49CCB0622
5 changed files with 71 additions and 51 deletions

View File

@ -1,63 +1,17 @@
package bundle package bundle
import ( import (
"encoding/json"
"os"
"path/filepath"
"github.com/databricks/cli/libs/template" "github.com/databricks/cli/libs/template"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
const ConfigFileName = "config.json"
const SchemaFileName = "schema.json"
const TemplateDirName = "template"
var initCmd = &cobra.Command{ var initCmd = &cobra.Command{
Use: "init", Use: "init",
Short: "Initialize Template", Short: "Initialize Template",
Long: `Initialize template`, Long: `Initialize template`,
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
templateLocation := args[0] return template.Materialize(args[0], targetDir)
// read the file containing schema for template input parameters
schemaBytes, err := os.ReadFile(filepath.Join(templateLocation, SchemaFileName))
if err != nil {
return err
}
schema := template.Schema{}
err = json.Unmarshal(schemaBytes, &schema)
if err != nil {
return err
}
// read user config to initalize the template with
var config map[string]interface{}
b, err := os.ReadFile(filepath.Join(targetDir, ConfigFileName))
if err != nil {
return err
}
err = json.Unmarshal(b, &config)
if err != nil {
return err
}
// cast any fields that are supported to be integers. The json unmarshalling
// for a generic map converts all numbers to floating point
err = schema.CastFloatToInt(config)
if err != nil {
return err
}
// validate config according to schema
err = schema.ValidateConfig(config)
if err != nil {
return err
}
// materialize the template
return template.WalkFileTree(config, filepath.Join(args[0], TemplateDirName), targetDir)
}, },
} }

View File

@ -0,0 +1,24 @@
package template
import "path/filepath"
const ConfigFileName = "config.json"
const SchemaFileName = "schema.json"
const TemplateDirName = "template"
func Materialize(templatePath, instancePath string) error {
// read the file containing schema for template input parameters
schema, err := ReadSchema(filepath.Join(templatePath, SchemaFileName))
if err != nil {
return err
}
// read user config to initalize the template with
config, err := schema.ReadConfig(filepath.Join(instancePath, ConfigFileName))
if err != nil {
return err
}
// materialize the template
return WalkFileTree(config, filepath.Join(templatePath, TemplateDirName), instancePath)
}

View File

@ -1,7 +1,9 @@
package template package template
import ( import (
"encoding/json"
"fmt" "fmt"
"os"
"reflect" "reflect"
) )
@ -31,7 +33,7 @@ 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 (schema Schema) CastFloatToInt(config map[string]any) 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[k]; !ok {
@ -93,3 +95,42 @@ func (schema Schema) ValidateConfig(config map[string]any) error {
} }
return nil return nil
} }
func ReadSchema(path string) (Schema, error) {
schemaBytes, err := os.ReadFile(path)
if err != nil {
return nil, err
}
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) {
var config map[string]any
b, err := os.ReadFile(path)
if err != nil {
return nil, err
}
err = json.Unmarshal(b, &config)
if err != nil {
return nil, err
}
// cast any fields that are supposed to be integers. The json unmarshalling
// for a generic map converts all numbers to floating point
err = castFloatToInt(config, schema)
if err != nil {
return nil, err
}
// validate config according to schema
err = schema.ValidateConfig(config)
if err != nil {
return nil, err
}
return config, nil
}

View File

@ -56,7 +56,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 = schema.CastFloatToInt(config) 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
@ -86,7 +86,7 @@ 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 = schema.CastFloatToInt(config) 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")
} }
@ -109,7 +109,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 = schema.CastFloatToInt(config) 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")
} }

View File

@ -46,3 +46,4 @@ var validators map[FieldType]Validator = map[FieldType]Validator{
FieldTypeInt: validateInteger, FieldTypeInt: validateInteger,
FieldTypeFloat: validateFloat, FieldTypeFloat: validateFloat,
} }