Skip to content

Commit

Permalink
simplify the custom template code
Browse files Browse the repository at this point in the history
  • Loading branch information
shreyas-goenka committed Jan 17, 2025
1 parent eb6fc09 commit f7557bf
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 29 deletions.
27 changes: 21 additions & 6 deletions libs/template/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ type Resolver struct {
Branch string
}

// ErrCustomSelected is returned when the user selects the "custom..." option
// in the prompt UI when they run `databricks bundle init`. This error signals
// the upstream callsite to show documentation to the user on how to use a custom
// template.
var ErrCustomSelected = errors.New("custom template selected")

// Configures the reader and the writer for template and returns
Expand Down Expand Up @@ -83,12 +87,25 @@ func (r Resolver) Resolve(ctx context.Context) (*Template, error) {
return nil, ErrCustomSelected
}

tmpl := Get(templateName)
tmpl := GetDatabricksTemplate(templateName)

// If the user directory provided a template path or URL that is not a built-in template,
// then configure a reader for the template.
// If we could not find a databricks template with the name provided by the user,
// then we assume that the user provided us with a reference to a custom template.
//
// This reference could be one of:
// 1. Path to a local template directory.
// 2. URL to a Git repository containing a template.
//
// We resolve the appropriate reader according to the reference provided by the user.
if tmpl == nil {
tmpl = Get(Custom)
tmpl = &Template{
name: Custom,
// We use a writer that does not log verbose telemetry for custom templates.
// This is important because template definitions can contain PII that we
// do not want to centralize.
Writer: &defaultWriter{},
}

if isRepoUrl(r.TemplatePathOrUrl) {
tmpl.Reader = &gitReader{
gitUrl: r.TemplatePathOrUrl,
Expand All @@ -101,9 +118,7 @@ func (r Resolver) Resolve(ctx context.Context) (*Template, error) {
path: r.TemplatePathOrUrl,
}
}

}

err = tmpl.Writer.Configure(ctx, r.ConfigFile, r.OutputDir)
if err != nil {
return nil, err
Expand Down
38 changes: 19 additions & 19 deletions libs/template/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,10 @@ const (
DbtSql TemplateName = "dbt-sql"
MlopsStacks TemplateName = "mlops-stacks"
DefaultPydabs TemplateName = "default-pydabs"

// Custom represents any template that is not one of the above default
// templates. It's a catch all for any custom templates that customers provide
// as a path or URL argument.
Custom TemplateName = "custom..."
Custom TemplateName = "custom"
)

var allTemplates = []Template{
var databricksTemplates = []Template{
{
name: DefaultPython,
description: "The default Python template for Notebooks / Delta Live Tables / Workflows",
Expand Down Expand Up @@ -69,28 +65,23 @@ var allTemplates = []Template{
Reader: &gitReader{gitUrl: "https://databricks.github.io/workflows-authoring-toolkit/pydabs-template.git", cloneFunc: git.Clone},
Writer: &writerWithFullTelemetry{},
},
{
name: Custom,
description: "Bring your own template",
// Reader is determined at runtime based on the user input.
Reader: nil,
Writer: &defaultWriter{},
},
}

func HelpDescriptions() string {
var lines []string
for _, template := range allTemplates {
for _, template := range databricksTemplates {
if template.name != Custom && !template.hidden {
lines = append(lines, fmt.Sprintf("- %s: %s", template.name, template.description))
}
}
return strings.Join(lines, "\n")
}

var customTemplateDescription = "Bring your own template"

func options() []cmdio.Tuple {
names := make([]cmdio.Tuple, 0, len(allTemplates))
for _, template := range allTemplates {
names := make([]cmdio.Tuple, 0, len(databricksTemplates))
for _, template := range databricksTemplates {
if template.hidden {
continue
}
Expand All @@ -100,6 +91,11 @@ func options() []cmdio.Tuple {
}
names = append(names, tuple)
}

names = append(names, cmdio.Tuple{
Name: "custom...",
Id: customTemplateDescription,
})
return names
}

Expand All @@ -112,7 +108,11 @@ func SelectTemplate(ctx context.Context) (TemplateName, error) {
return "", err
}

for _, template := range allTemplates {
if description == customTemplateDescription {
return TemplateName(""), ErrCustomSelected
}

for _, template := range databricksTemplates {
if template.description == description {
return template.name, nil
}
Expand All @@ -121,8 +121,8 @@ func SelectTemplate(ctx context.Context) (TemplateName, error) {
panic("this should never happen - template not found")
}

func Get(name TemplateName) *Template {
for _, template := range allTemplates {
func GetDatabricksTemplate(name TemplateName) *Template {
for _, template := range databricksTemplates {
if template.name == name || slices.Contains(template.aliases, string(name)) {
return &template
}
Expand Down
8 changes: 4 additions & 4 deletions libs/template/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestBundleInitRepoName(t *testing.T) {
}

func TestTemplateTelemetryIsCapturedForAllDefaultTemplates(t *testing.T) {
for _, tmpl := range allTemplates {
for _, tmpl := range databricksTemplates {
w := tmpl.Writer

if tmpl.name == Custom {
Expand All @@ -64,7 +64,7 @@ func TestTemplateGet(t *testing.T) {
}

for _, name := range names {
tmpl := Get(name)
tmpl := GetDatabricksTemplate(name)
assert.Equal(t, tmpl.name, name)
}

Expand All @@ -75,10 +75,10 @@ func TestTemplateGet(t *testing.T) {
}

for _, name := range notExist {
tmpl := Get(TemplateName(name))
tmpl := GetDatabricksTemplate(TemplateName(name))
assert.Nil(t, tmpl)
}

// Assert the alias works.
assert.Equal(t, MlopsStacks, Get(TemplateName("mlops-stack")).name)
assert.Equal(t, MlopsStacks, GetDatabricksTemplate(TemplateName("mlops-stack")).name)
}
6 changes: 6 additions & 0 deletions libs/template/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ const (
)

type Writer interface {
// Configure the writer with:
// 1. The path to the config file (if any) that contains input values for the
// template.
// 2. The output directory where the template will be materialized.
Configure(ctx context.Context, configPath, outputDir string) error

// Materialize the template to the local file system.
Materialize(ctx context.Context, r Reader) error
}

Expand Down

0 comments on commit f7557bf

Please sign in to comment.