From bec9c72bf4c12e77c0bc937ba217240b118f7573 Mon Sep 17 00:00:00 2001 From: monalisa Date: Wed, 15 Nov 2023 00:16:38 +0100 Subject: [PATCH 1/8] Add dropdown UI to select first party templates to bundle init --- cmd/bundle/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/bundle/init.go b/cmd/bundle/init.go index ccdc68591f..e1c5547d34 100644 --- a/cmd/bundle/init.go +++ b/cmd/bundle/init.go @@ -89,7 +89,7 @@ See https://docs.databricks.com/en/dev-tools/bundles/templates.html for more inf if !cmdio.IsOutTTY(ctx) || !cmdio.IsInTTY(ctx) { return errors.New("please specify a template") } - templatePath, err = cmdio.Ask(ctx, "Template to use", "default-python") + templatePath, err = cmdio.AskSelect(ctx, "Template to use", []string{"default-python", "mlops-stacks"}) if err != nil { return err } From f994c484e6d192409c0d76b6f3c9ca378ef5d6f1 Mon Sep 17 00:00:00 2001 From: monalisa Date: Wed, 22 Nov 2023 01:41:06 +0100 Subject: [PATCH 2/8] parameterise native templates --- cmd/bundle/init.go | 63 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/cmd/bundle/init.go b/cmd/bundle/init.go index e1c5547d34..c820b9442c 100644 --- a/cmd/bundle/init.go +++ b/cmd/bundle/init.go @@ -2,6 +2,7 @@ package bundle import ( "errors" + "fmt" "os" "path/filepath" "strings" @@ -23,6 +24,53 @@ var aliasedTemplates = map[string]string{ "mlops-stacks": "https://github.com/databricks/mlops-stacks", } +type nativeTemplate struct { + gitUrl string + description string + aliases []string +} + +var nativeTemplates = map[string]nativeTemplate{ + "default-python": { + description: "the default Python template", + }, + "mlops-stacks": { + gitUrl: "https://github.com/databricks/mlops-stacks", + description: "the MLOps Stacks template", + aliases: []string{"mlops-stack"}, + }, +} + +func nativeTemplateDescriptions() string { + var lines []string + for name, template := range nativeTemplates { + lines = append(lines, fmt.Sprintf("- %s: %s", name, template.description)) + } + return strings.Join(lines, "\n") +} + +func nativeTemplateOptions() []string { + var options []string + for name := range nativeTemplates { + options = append(options, name) + } + return options +} + +func getURLForNativeTemplate(name string) string { + for templateName, template := range nativeTemplates { + if templateName == name { + return template.gitUrl + } + for _, alias := range template.aliases { + if alias == name { + return template.gitUrl + } + } + } + return "" +} + func isRepoUrl(url string) bool { result := false for _, prefix := range gitUrlPrefixes { @@ -47,14 +95,14 @@ func newInitCommand() *cobra.Command { Use: "init [TEMPLATE_PATH]", Short: "Initialize using a bundle template", Args: cobra.MaximumNArgs(1), - Long: `Initialize using a bundle template. + Long: fmt.Sprintf(`Initialize using a bundle template. TEMPLATE_PATH optionally specifies which template to use. It can be one of the following: -- 'default-python' for the default Python template +%s - a local file system path with a template directory - a Git repository URL, e.g. https://github.com/my/repository -See https://docs.databricks.com/en/dev-tools/bundles/templates.html for more information on templates.`, +See https://docs.databricks.com/en/dev-tools/bundles/templates.html for more information on templates.`, nativeTemplateDescriptions()), } var configFile string @@ -89,15 +137,16 @@ See https://docs.databricks.com/en/dev-tools/bundles/templates.html for more inf if !cmdio.IsOutTTY(ctx) || !cmdio.IsInTTY(ctx) { return errors.New("please specify a template") } - templatePath, err = cmdio.AskSelect(ctx, "Template to use", []string{"default-python", "mlops-stacks"}) + templatePath, err = cmdio.AskSelect(ctx, "Template to use", nativeTemplateOptions()) if err != nil { return err } } - // Expand templatePath if it's an alias for a known template - if _, ok := aliasedTemplates[templatePath]; ok { - templatePath = aliasedTemplates[templatePath] + // Expand templatePath to a git URL if it's an alias for a known native template + // and we know it's git URL. + if gitUrl := getURLForNativeTemplate(templatePath); gitUrl != "" { + templatePath = gitUrl } if !isRepoUrl(templatePath) { From 57062ebb4f000704f940dfa68126a5d2b98144c1 Mon Sep 17 00:00:00 2001 From: monalisa Date: Wed, 22 Nov 2023 01:48:28 +0100 Subject: [PATCH 3/8] - --- cmd/bundle/init.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/cmd/bundle/init.go b/cmd/bundle/init.go index c820b9442c..c45ab8531a 100644 --- a/cmd/bundle/init.go +++ b/cmd/bundle/init.go @@ -19,11 +19,6 @@ var gitUrlPrefixes = []string{ "git@", } -var aliasedTemplates = map[string]string{ - "mlops-stack": "https://github.com/databricks/mlops-stacks", - "mlops-stacks": "https://github.com/databricks/mlops-stacks", -} - type nativeTemplate struct { gitUrl string description string @@ -32,11 +27,11 @@ type nativeTemplate struct { var nativeTemplates = map[string]nativeTemplate{ "default-python": { - description: "the default Python template", + description: "The default Python template", }, "mlops-stacks": { gitUrl: "https://github.com/databricks/mlops-stacks", - description: "the MLOps Stacks template", + description: "The Databricks MLOps Stacks template. More information can be found at: https://github.com/databricks/mlops-stacks", aliases: []string{"mlops-stack"}, }, } From 2cc7c3d2d1dfda7376b236443d47b7359c1b17d5 Mon Sep 17 00:00:00 2001 From: monalisa Date: Wed, 22 Nov 2023 01:59:24 +0100 Subject: [PATCH 4/8] add deterministic order for keys --- cmd/bundle/init.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cmd/bundle/init.go b/cmd/bundle/init.go index c45ab8531a..ba20686304 100644 --- a/cmd/bundle/init.go +++ b/cmd/bundle/init.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path/filepath" + "sort" "strings" "github.com/databricks/cli/cmd/root" @@ -45,11 +46,12 @@ func nativeTemplateDescriptions() string { } func nativeTemplateOptions() []string { - var options []string - for name := range nativeTemplates { - options = append(options, name) + keys := make([]string, 0, len(nativeTemplates)) + for k := range nativeTemplates { + keys = append(keys, k) } - return options + sort.Strings(keys) + return keys } func getURLForNativeTemplate(name string) string { From 52135bce0fbc463f48580df6cb89533cd2169fd9 Mon Sep 17 00:00:00 2001 From: monalisa Date: Thu, 23 Nov 2023 07:30:57 +0100 Subject: [PATCH 5/8] add tests --- cmd/bundle/init.go | 4 ++-- cmd/bundle/init_test.go | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/cmd/bundle/init.go b/cmd/bundle/init.go index ba20686304..0a3c10ced5 100644 --- a/cmd/bundle/init.go +++ b/cmd/bundle/init.go @@ -54,7 +54,7 @@ func nativeTemplateOptions() []string { return keys } -func getURLForNativeTemplate(name string) string { +func getUrlForNativeTemplate(name string) string { for templateName, template := range nativeTemplates { if templateName == name { return template.gitUrl @@ -142,7 +142,7 @@ See https://docs.databricks.com/en/dev-tools/bundles/templates.html for more inf // Expand templatePath to a git URL if it's an alias for a known native template // and we know it's git URL. - if gitUrl := getURLForNativeTemplate(templatePath); gitUrl != "" { + if gitUrl := getUrlForNativeTemplate(templatePath); gitUrl != "" { templatePath = gitUrl } diff --git a/cmd/bundle/init_test.go b/cmd/bundle/init_test.go index 4a795160eb..461a2c9604 100644 --- a/cmd/bundle/init_test.go +++ b/cmd/bundle/init_test.go @@ -25,3 +25,18 @@ func TestBundleInitRepoName(t *testing.T) { assert.Equal(t, "invalid-url", repoName("invalid-url")) assert.Equal(t, "www.github.com", repoName("https://www.github.com")) } + +func TestNativeTemplateOptions(t *testing.T) { + assert.Equal(t, []string{"default-python", "mlops-stacks"}, nativeTemplateOptions()) +} + +func TestNativeTemplateDescriptions(t *testing.T) { + assert.Equal(t, "- default-python: The default Python template\n- mlops-stacks: The Databricks MLOps Stacks template. More information can be found at: https://github.com/databricks/mlops-stacks", nativeTemplateDescriptions()) +} + +func TestGetUrlForNativeTemplate(t *testing.T) { + assert.Equal(t, "https://github.com/databricks/mlops-stacks", getUrlForNativeTemplate("mlops-stacks")) + assert.Equal(t, "https://github.com/databricks/mlops-stacks", getUrlForNativeTemplate("mlops-stack")) + assert.Equal(t, "", getUrlForNativeTemplate("default-python")) + assert.Equal(t, "", getUrlForNativeTemplate("invalid")) +} From 52b6353a8911f41aa2abadcb13e7f26781d459f9 Mon Sep 17 00:00:00 2001 From: monalisa Date: Thu, 23 Nov 2023 07:34:09 +0100 Subject: [PATCH 6/8] shorten help string --- cmd/bundle/init.go | 2 +- cmd/bundle/init_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/bundle/init.go b/cmd/bundle/init.go index 0a3c10ced5..43d0210abc 100644 --- a/cmd/bundle/init.go +++ b/cmd/bundle/init.go @@ -32,7 +32,7 @@ var nativeTemplates = map[string]nativeTemplate{ }, "mlops-stacks": { gitUrl: "https://github.com/databricks/mlops-stacks", - description: "The Databricks MLOps Stacks template. More information can be found at: https://github.com/databricks/mlops-stacks", + description: "The Databricks MLOps Stacks template (https://github.com/databricks/mlops-stacks)", aliases: []string{"mlops-stack"}, }, } diff --git a/cmd/bundle/init_test.go b/cmd/bundle/init_test.go index 461a2c9604..db4446bb1c 100644 --- a/cmd/bundle/init_test.go +++ b/cmd/bundle/init_test.go @@ -31,7 +31,7 @@ func TestNativeTemplateOptions(t *testing.T) { } func TestNativeTemplateDescriptions(t *testing.T) { - assert.Equal(t, "- default-python: The default Python template\n- mlops-stacks: The Databricks MLOps Stacks template. More information can be found at: https://github.com/databricks/mlops-stacks", nativeTemplateDescriptions()) + assert.Equal(t, "- default-python: The default Python template\n- mlops-stacks: The Databricks MLOps Stacks template (https://github.com/databricks/mlops-stacks)", nativeTemplateDescriptions()) } func TestGetUrlForNativeTemplate(t *testing.T) { From 0d1e876b05d63c7adb2a2b90e94ecb47b8bc1851 Mon Sep 17 00:00:00 2001 From: monalisa Date: Mon, 27 Nov 2023 16:07:59 +0100 Subject: [PATCH 7/8] use slices.Contains --- cmd/bundle/init.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cmd/bundle/init.go b/cmd/bundle/init.go index 43d0210abc..6b1a4a4371 100644 --- a/cmd/bundle/init.go +++ b/cmd/bundle/init.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path/filepath" + "slices" "sort" "strings" @@ -59,10 +60,8 @@ func getUrlForNativeTemplate(name string) string { if templateName == name { return template.gitUrl } - for _, alias := range template.aliases { - if alias == name { - return template.gitUrl - } + if slices.Contains(template.aliases, name) { + return template.gitUrl } } return "" From eddca42a662140c90d58fc447d480abc509e097e Mon Sep 17 00:00:00 2001 From: monalisa Date: Mon, 27 Nov 2023 17:05:46 +0100 Subject: [PATCH 8/8] convert map to array --- cmd/bundle/init.go | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/cmd/bundle/init.go b/cmd/bundle/init.go index 6b1a4a4371..ac6f49de38 100644 --- a/cmd/bundle/init.go +++ b/cmd/bundle/init.go @@ -6,7 +6,6 @@ import ( "os" "path/filepath" "slices" - "sort" "strings" "github.com/databricks/cli/cmd/root" @@ -22,16 +21,19 @@ var gitUrlPrefixes = []string{ } type nativeTemplate struct { + name string gitUrl string description string aliases []string } -var nativeTemplates = map[string]nativeTemplate{ - "default-python": { +var nativeTemplates = []nativeTemplate{ + { + name: "default-python", description: "The default Python template", }, - "mlops-stacks": { + { + name: "mlops-stacks", gitUrl: "https://github.com/databricks/mlops-stacks", description: "The Databricks MLOps Stacks template (https://github.com/databricks/mlops-stacks)", aliases: []string{"mlops-stack"}, @@ -40,24 +42,23 @@ var nativeTemplates = map[string]nativeTemplate{ func nativeTemplateDescriptions() string { var lines []string - for name, template := range nativeTemplates { - lines = append(lines, fmt.Sprintf("- %s: %s", name, template.description)) + for _, template := range nativeTemplates { + lines = append(lines, fmt.Sprintf("- %s: %s", template.name, template.description)) } return strings.Join(lines, "\n") } func nativeTemplateOptions() []string { - keys := make([]string, 0, len(nativeTemplates)) - for k := range nativeTemplates { - keys = append(keys, k) + names := make([]string, 0, len(nativeTemplates)) + for _, template := range nativeTemplates { + names = append(names, template.name) } - sort.Strings(keys) - return keys + return names } func getUrlForNativeTemplate(name string) string { - for templateName, template := range nativeTemplates { - if templateName == name { + for _, template := range nativeTemplates { + if template.name == name { return template.gitUrl } if slices.Contains(template.aliases, name) {