mirror of https://github.com/databricks/cli.git
added basic init command for `databricks.yml`
This commit is contained in:
parent
77198bdfd0
commit
154fb8a967
|
@ -0,0 +1,105 @@
|
|||
package init
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/databricks/bricks/cmd/root"
|
||||
"github.com/databricks/bricks/project"
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
//go:embed templates
|
||||
var templates embed.FS
|
||||
|
||||
// initCmd represents the init command
|
||||
var initCmd = &cobra.Command{
|
||||
Use: "init",
|
||||
Short: "Project starter templates",
|
||||
Long: `Generate project templates`,
|
||||
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if project.IsDatabricksProject() {
|
||||
return fmt.Errorf("this path is already a Databricks project")
|
||||
}
|
||||
profileChoice, err := getConnectionProfile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wd, _ := os.Getwd()
|
||||
q := Questions{
|
||||
Text{"name", "Project name", func(res Results) string {
|
||||
return path.Base(wd)
|
||||
}, func(ans Answer, prj *project.Project, res Results) {
|
||||
prj.Name = ans.Value
|
||||
}},
|
||||
*profileChoice,
|
||||
Choice{"language", "Project language", Answers{
|
||||
{"Python", "Machine learning and data engineering focused projects", nil},
|
||||
{"Scala", "Data engineering focused projects with strong typing", nil},
|
||||
}},
|
||||
Choice{"isolation", "Deployment isolation", Answers{
|
||||
{"None", "Use shared Databricks workspace resources for all project team members", nil},
|
||||
{"Soft", "Prepend prefixes to each team member's deployment", func(
|
||||
ans Answer, prj *project.Project, res Results) {
|
||||
prj.Isolation = project.Soft
|
||||
}},
|
||||
}},
|
||||
// Choice{"cloud", "Cloud", Answers{
|
||||
// {"AWS", "Amazon Web Services", nil},
|
||||
// {"Azure", "Microsoft Azure Cloud", nil},
|
||||
// {"GCP", "Google Cloud Platform", nil},
|
||||
// }},
|
||||
// Choice{"ci", "Continuous Integration", Answers{
|
||||
// {"None", "Do not create continuous integration configuration", nil},
|
||||
// {"GitHub Actions", "Create .github/workflows/push.yml configuration", nil},
|
||||
// {"Azure DevOps", "Create basic build and test pipelines", nil},
|
||||
// }},
|
||||
// Choice{"ide", "Integrated Development Environment", Answers{
|
||||
// {"None", "Do not create templates for IDE", nil},
|
||||
// {"VSCode", "Create .devcontainer and other useful things", nil},
|
||||
// {"PyCharm", "Create project conf and other things", nil},
|
||||
// }},
|
||||
}
|
||||
res := Results{}
|
||||
err = q.Ask(res)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var prj project.Project
|
||||
for _, ans := range res {
|
||||
if ans.Callback == nil {
|
||||
continue
|
||||
}
|
||||
ans.Callback(ans, &prj, res)
|
||||
}
|
||||
raw, err := yaml.Marshal(prj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newConfig, err := os.Create(fmt.Sprintf("%s/%s", wd, project.ConfigFile))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = newConfig.Write(raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d, err := templates.ReadDir(".")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range d {
|
||||
cmd.Printf("template found: %v", v.Name())
|
||||
}
|
||||
cmd.Print("Config initialized!")
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
root.RootCmd.AddCommand(initCmd)
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package init
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/databricks/bricks/project"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
func loadCliProfiles() (profiles []Answer, err error) {
|
||||
file, err := homedir.Expand("~/.databrickscfg")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
gitConfig, err := ini.Load(file)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, v := range gitConfig.Sections() {
|
||||
host, err := v.GetKey("host")
|
||||
if err != nil {
|
||||
// invalid profile
|
||||
continue
|
||||
}
|
||||
profiles = append(profiles, Answer{
|
||||
Value: v.Name(),
|
||||
Details: fmt.Sprintf(`Connecting to "%s" workspace`, host),
|
||||
Callback: func(ans Answer, prj *project.Project, _ Results) {
|
||||
prj.Profile = ans.Value
|
||||
},
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getConnectionProfile() (*Choice, error) {
|
||||
profiles, err := loadCliProfiles()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO: propmt for password and create ~/.databrickscfg
|
||||
return &Choice{
|
||||
key: "profile",
|
||||
Label: "Databricks CLI profile",
|
||||
Answers: profiles,
|
||||
}, err
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package init
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/databricks/bricks/project"
|
||||
"github.com/manifoldco/promptui"
|
||||
)
|
||||
|
||||
type Results map[string]Answer
|
||||
|
||||
type Question interface {
|
||||
Ask(res Results) (key string, ans Answer, err error)
|
||||
}
|
||||
|
||||
type Questions []Question
|
||||
|
||||
func (qq Questions) Ask(res Results) error {
|
||||
for _, v := range qq {
|
||||
key, ans, err := v.Ask(res)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
res[key] = ans
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Text struct {
|
||||
key string
|
||||
Label string
|
||||
Default func(res Results) string
|
||||
Callback AnswerCallback
|
||||
}
|
||||
|
||||
func (t Text) Ask(res Results) (string, Answer, error) {
|
||||
def := ""
|
||||
if t.Default != nil {
|
||||
def = t.Default(res)
|
||||
}
|
||||
v, err := (&promptui.Prompt{
|
||||
Label: t.Label,
|
||||
Default: def,
|
||||
}).Run()
|
||||
return t.key, Answer{
|
||||
Value: v,
|
||||
Callback: t.Callback,
|
||||
}, err
|
||||
}
|
||||
|
||||
type Choice struct {
|
||||
key string
|
||||
Label string
|
||||
Answers []Answer
|
||||
}
|
||||
|
||||
func (q Choice) Ask(res Results) (string, Answer, error) {
|
||||
prompt := promptui.Select{
|
||||
Label: q.Label,
|
||||
Items: q.Answers,
|
||||
Templates: &promptui.SelectTemplates{
|
||||
Label: `{{ .Value }}`,
|
||||
Details: `{{ .Details | green }}`,
|
||||
Selected: fmt.Sprintf(`{{ "%s" | faint }}: {{ .Value | bold }}`, q.Label),
|
||||
},
|
||||
}
|
||||
i, _, err := prompt.Run()
|
||||
return q.key, q.Answers[i], err
|
||||
}
|
||||
|
||||
type Answers []Answer
|
||||
|
||||
type AnswerCallback func(ans Answer, prj *project.Project, res Results)
|
||||
|
||||
type Answer struct {
|
||||
Value string
|
||||
Details string
|
||||
Callback AnswerCallback
|
||||
}
|
||||
|
||||
func (a Answer) String() string {
|
||||
return a.Value
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
# Databricks notebook source
|
||||
|
||||
# this was automatically generated
|
||||
display(spark.tables())
|
Loading…
Reference in New Issue