From 1a431dd26c02dbb611c20395b236928185798e1d Mon Sep 17 00:00:00 2001 From: Shreyas Goenka Date: Mon, 15 May 2023 11:25:01 +0200 Subject: [PATCH] wip --- cmd/init/Untitled-1.json | 21 ++++++++++++ cmd/init/file_tree.go | 74 ++++++++++++++++++++++++++++++++++++++++ cmd/init/helpers.go | 31 +++++++++++++++++ cmd/init/init.go | 45 ++++++++++++++++++++++++ main.go | 1 + 5 files changed, 172 insertions(+) create mode 100644 cmd/init/Untitled-1.json create mode 100644 cmd/init/file_tree.go create mode 100644 cmd/init/helpers.go create mode 100644 cmd/init/init.go diff --git a/cmd/init/Untitled-1.json b/cmd/init/Untitled-1.json new file mode 100644 index 00000000..35c17247 --- /dev/null +++ b/cmd/init/Untitled-1.json @@ -0,0 +1,21 @@ +{ + "foo": { + "type": "string", + "default": "abc", + "validation": ["regex ^[abcd]*$"] + }, + "bar": { + "type": "integer", + "default": 123, + "validation": ["greaterThan 5", "lessThan 10"] + }, + "isAws": { + "type": "boolean", + "default": true + }, + "project_name": { + "type": "string", + "default": "my_project", + "validation": ["startsWith my_"] + } +} diff --git a/cmd/init/file_tree.go b/cmd/init/file_tree.go new file mode 100644 index 00000000..1f8b8791 --- /dev/null +++ b/cmd/init/file_tree.go @@ -0,0 +1,74 @@ +package init + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "text/template" +) + +// TODO: cleanup if template initialization fails +// TODO: need robust way to clean up half generated files +// TODO: define default files +// TODO: self reference for + +func walkFileTree(config map[string]interface{}, templatePath string, instancePath string) error { + enteries, err := os.ReadDir(templatePath) + if err != nil { + return err + } + for _, entry := range enteries { + if entry.Name() == SchemaFileName { + continue + } + fileName := entry.Name() + tmpl, err := template.New("filename").Parse(fileName) + if err != nil { + return err + } + result := strings.Builder{} + err = tmpl.Execute(&result, config) + if err != nil { + return err + } + resolvedFileName := result.String() + fmt.Println(resolvedFileName) + if entry.IsDir() { + err := os.Mkdir(resolvedFileName, os.ModePerm) + if err != nil { + return err + } + err = walkFileTree(config, filepath.Join(templatePath, fileName), filepath.Join(instancePath, resolvedFileName)) + if err != nil { + return err + } + } else { + f, err := os.Create(filepath.Join(instancePath, resolvedFileName)) + if err != nil { + return err + } + b, err := os.ReadFile(filepath.Join(templatePath, fileName)) + if err != nil { + return err + } + // TODO: Might be able to use ParseFiles or ParseFS. Might be more suited + contentTmpl, err := template.New("content").Funcs(HelperFuncs).Parse(string(b)) + if err != nil { + return err + } + err = contentTmpl.Execute(f, config) + + // Make this assertion more robust + if err != nil && strings.Contains(err.Error(), ErrSkipThisFile.Error()) { + err := os.Remove(filepath.Join(instancePath, resolvedFileName)) + if err != nil { + return err + } + } else if err != nil { + return err + } + } + } + return nil +} diff --git a/cmd/init/helpers.go b/cmd/init/helpers.go new file mode 100644 index 00000000..b1df69fb --- /dev/null +++ b/cmd/init/helpers.go @@ -0,0 +1,31 @@ +package init + +import ( + "errors" + "fmt" + "strings" + "text/template" +) + +var ErrSkipThisFile = errors.New("skip generating this file") + +var HelperFuncs = template.FuncMap{ + "skipThisFile": func() error { + panic(ErrSkipThisFile) + }, + "eqString": func(a string, b string) bool { + return a == b + }, + "eqNumber": func(a float64, b int) bool { + return int(a) == b + }, + "validationError": func(message string) error { + panic(fmt.Errorf(message)) + }, + "assertStartsWith": func(s string, substr string) error { + if !strings.HasPrefix(s, substr) { + panic(fmt.Errorf("%s does not start with %s.", s, substr)) + } + return nil + }, +} diff --git a/cmd/init/init.go b/cmd/init/init.go new file mode 100644 index 00000000..fed7321b --- /dev/null +++ b/cmd/init/init.go @@ -0,0 +1,45 @@ +package init + +import ( + "encoding/json" + "os" + + "github.com/databricks/bricks/cmd/root" + "github.com/spf13/cobra" +) + +const SchemaFileName = "config.json" + +// root template defination at schema.json +// decide on semantics of defination later + +// initCmd represents the fs command +var initCmd = &cobra.Command{ + Use: "init", + Short: "Initialize Template", + Long: `Initialize bundle template`, + RunE: func(cmd *cobra.Command, args []string) error { + var config map[string]interface{} + b, err := os.ReadFile(SchemaFileName) + if err != nil { + return err + } + err = json.Unmarshal(b, &config) + if err != nil { + return err + } + err = walkFileTree(config, ".", ".") + if err != nil { + err2 := os.RemoveAll("favela") + if err2 != nil { + return err2 + } + return err + } + return nil + }, +} + +func init() { + root.RootCmd.AddCommand(initCmd) +} diff --git a/main.go b/main.go index fd5d31f3..1ef34ccc 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( _ "github.com/databricks/bricks/cmd/bundle/debug" _ "github.com/databricks/bricks/cmd/configure" _ "github.com/databricks/bricks/cmd/fs" + _ "github.com/databricks/bricks/cmd/init" "github.com/databricks/bricks/cmd/root" _ "github.com/databricks/bricks/cmd/sync" _ "github.com/databricks/bricks/cmd/version"