mirror of https://github.com/databricks/cli.git
refactor logic out of the cmd
This commit is contained in:
parent
f5384fc5ed
commit
a21fbdd383
|
@ -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)
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,3 +46,4 @@ var validators map[FieldType]Validator = map[FieldType]Validator{
|
||||||
FieldTypeInt: validateInteger,
|
FieldTypeInt: validateInteger,
|
||||||
FieldTypeFloat: validateFloat,
|
FieldTypeFloat: validateFloat,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue