2023-07-21 08:59:02 +00:00
|
|
|
package template
|
|
|
|
|
|
|
|
import (
|
2023-08-25 09:03:42 +00:00
|
|
|
"context"
|
|
|
|
"errors"
|
2023-07-21 08:59:02 +00:00
|
|
|
"fmt"
|
2023-07-27 09:51:31 +00:00
|
|
|
"net/url"
|
2023-10-19 07:08:36 +00:00
|
|
|
"os"
|
2023-07-25 14:42:53 +00:00
|
|
|
"regexp"
|
2023-07-21 08:59:02 +00:00
|
|
|
"text/template"
|
2023-08-25 09:03:42 +00:00
|
|
|
|
|
|
|
"github.com/databricks/cli/cmd/root"
|
|
|
|
"github.com/databricks/cli/libs/auth"
|
2024-02-19 09:15:17 +00:00
|
|
|
"github.com/databricks/databricks-sdk-go/apierr"
|
2023-08-25 09:03:42 +00:00
|
|
|
"github.com/databricks/databricks-sdk-go/service/iam"
|
2023-07-21 08:59:02 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type ErrFail struct {
|
|
|
|
msg string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (err ErrFail) Error() string {
|
|
|
|
return err.msg
|
|
|
|
}
|
|
|
|
|
2023-08-15 16:07:22 +00:00
|
|
|
type pair struct {
|
|
|
|
k string
|
|
|
|
v any
|
|
|
|
}
|
|
|
|
|
2023-09-06 09:52:31 +00:00
|
|
|
var cachedUser *iam.User
|
|
|
|
var cachedIsServicePrincipal *bool
|
2024-02-19 09:15:17 +00:00
|
|
|
var cachedCatalog *string
|
2023-09-06 09:52:31 +00:00
|
|
|
|
2023-08-25 09:03:42 +00:00
|
|
|
func loadHelpers(ctx context.Context) template.FuncMap {
|
|
|
|
w := root.WorkspaceClient(ctx)
|
|
|
|
return template.FuncMap{
|
|
|
|
"fail": func(format string, args ...any) (any, error) {
|
|
|
|
return nil, ErrFail{fmt.Sprintf(format, args...)}
|
|
|
|
},
|
|
|
|
// Alias for https://pkg.go.dev/net/url#Parse. Allows usage of all methods of url.URL
|
|
|
|
"url": func(rawUrl string) (*url.URL, error) {
|
|
|
|
return url.Parse(rawUrl)
|
|
|
|
},
|
|
|
|
// Alias for https://pkg.go.dev/regexp#Compile. Allows usage of all methods of regexp.Regexp
|
|
|
|
"regexp": func(expr string) (*regexp.Regexp, error) {
|
|
|
|
return regexp.Compile(expr)
|
|
|
|
},
|
|
|
|
// A key value pair. This is used with the map function to generate maps
|
|
|
|
// to use inside a template
|
|
|
|
"pair": func(k string, v any) pair {
|
|
|
|
return pair{k, v}
|
|
|
|
},
|
|
|
|
// map converts a list of pairs to a map object. This is useful to pass multiple
|
|
|
|
// objects to templates defined in the library directory. Go text template
|
|
|
|
// syntax for invoking a template only allows specifying a single argument,
|
|
|
|
// this function can be used to workaround that limitation.
|
|
|
|
//
|
|
|
|
// For example: {{template "my_template" (map (pair "foo" $arg1) (pair "bar" $arg2))}}
|
|
|
|
// $arg1 and $arg2 can be referred from inside "my_template" as ".foo" and ".bar"
|
|
|
|
"map": func(pairs ...pair) map[string]any {
|
|
|
|
result := make(map[string]any, 0)
|
|
|
|
for _, p := range pairs {
|
|
|
|
result[p.k] = p.v
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
},
|
|
|
|
// Get smallest node type (follows Terraform's GetSmallestNodeType)
|
|
|
|
"smallest_node_type": func() (string, error) {
|
|
|
|
if w.Config.Host == "" {
|
2023-10-19 07:08:36 +00:00
|
|
|
return "", errors.New("cannot determine target workspace, please first setup a configuration profile using 'databricks configure'")
|
2023-08-25 09:03:42 +00:00
|
|
|
}
|
|
|
|
if w.Config.IsAzure() {
|
|
|
|
return "Standard_D3_v2", nil
|
|
|
|
} else if w.Config.IsGcp() {
|
|
|
|
return "n1-standard-4", nil
|
|
|
|
}
|
|
|
|
return "i3.xlarge", nil
|
|
|
|
},
|
2023-10-19 07:08:36 +00:00
|
|
|
"path_separator": func() string {
|
|
|
|
return string(os.PathSeparator)
|
|
|
|
},
|
2023-08-25 09:03:42 +00:00
|
|
|
"workspace_host": func() (string, error) {
|
|
|
|
if w.Config.Host == "" {
|
2023-10-19 07:08:36 +00:00
|
|
|
return "", errors.New("cannot determine target workspace, please first setup a configuration profile using 'databricks configure'")
|
2023-08-25 09:03:42 +00:00
|
|
|
}
|
|
|
|
return w.Config.Host, nil
|
|
|
|
},
|
|
|
|
"user_name": func() (string, error) {
|
2023-09-06 09:52:31 +00:00
|
|
|
if cachedUser == nil {
|
2023-08-25 09:03:42 +00:00
|
|
|
var err error
|
2023-09-06 09:52:31 +00:00
|
|
|
cachedUser, err = w.CurrentUser.Me(ctx)
|
2023-08-25 09:03:42 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
}
|
2023-09-06 09:52:31 +00:00
|
|
|
result := cachedUser.UserName
|
2023-08-25 09:03:42 +00:00
|
|
|
if result == "" {
|
2023-09-06 09:52:31 +00:00
|
|
|
result = cachedUser.Id
|
2023-08-25 09:03:42 +00:00
|
|
|
}
|
|
|
|
return result, nil
|
|
|
|
},
|
2024-02-01 16:46:07 +00:00
|
|
|
"short_name": func() (string, error) {
|
|
|
|
if cachedUser == nil {
|
|
|
|
var err error
|
|
|
|
cachedUser, err = w.CurrentUser.Me(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return auth.GetShortUserName(cachedUser.UserName), nil
|
|
|
|
},
|
2024-02-19 09:15:17 +00:00
|
|
|
// Get the default workspace catalog. If there is no default, or if
|
|
|
|
// Unity Catalog is not enabled, return an empty string.
|
|
|
|
"default_catalog": func() (string, error) {
|
|
|
|
if cachedCatalog == nil {
|
|
|
|
metastore, err := w.Metastores.Current(ctx)
|
|
|
|
if err != nil {
|
|
|
|
var aerr *apierr.APIError
|
|
|
|
if errors.As(err, &aerr) && aerr.ErrorCode == "METASTORE_DOES_NOT_EXIST" {
|
|
|
|
// Workspace doesn't have a metastore assigned, ignore error
|
|
|
|
empty_default := ""
|
|
|
|
cachedCatalog = &empty_default
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
cachedCatalog = &metastore.DefaultCatalogName
|
|
|
|
}
|
|
|
|
return *cachedCatalog, nil
|
|
|
|
},
|
2023-08-25 09:03:42 +00:00
|
|
|
"is_service_principal": func() (bool, error) {
|
2023-09-06 09:52:31 +00:00
|
|
|
if cachedIsServicePrincipal != nil {
|
|
|
|
return *cachedIsServicePrincipal, nil
|
2023-08-25 09:03:42 +00:00
|
|
|
}
|
2023-09-06 09:52:31 +00:00
|
|
|
if cachedUser == nil {
|
2023-08-25 09:03:42 +00:00
|
|
|
var err error
|
2023-09-06 09:52:31 +00:00
|
|
|
cachedUser, err = w.CurrentUser.Me(ctx)
|
2023-08-25 09:03:42 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
}
|
2023-09-06 09:52:31 +00:00
|
|
|
result := auth.IsServicePrincipal(cachedUser.Id)
|
|
|
|
cachedIsServicePrincipal = &result
|
2023-08-25 09:03:42 +00:00
|
|
|
return result, nil
|
|
|
|
},
|
|
|
|
}
|
2023-07-21 08:59:02 +00:00
|
|
|
}
|