databricks-cli/project/config.go

138 lines
4.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package project
import (
"errors"
"fmt"
"io"
"os"
"path/filepath"
"reflect"
"github.com/databricks/bricks/folders"
"github.com/databricks/databricks-sdk-go/service/clusters"
"github.com/ghodss/yaml"
)
type Isolation string
const (
None Isolation = ""
Soft Isolation = "soft"
)
// ConfigFile is the name of project configuration file
const ConfigFile = "databricks.yml"
type Assertions struct {
Groups []string `json:"groups,omitempty"`
Secrets []string `json:"secrets,omitempty"`
ServicePrincipals []string `json:"service_principals,omitempty"`
}
type Config struct {
Name string `json:"name"` // or do default from folder name?..
Isolation Isolation `json:"isolation,omitempty"`
// development-time vs deployment-time resources
DevCluster *clusters.ClusterInfo `json:"dev_cluster,omitempty"`
// Assertions defines a list of configurations expected to be applied
// to the workspace by a higher-privileged user (or service principal)
// in order for the deploy command to work, as individual project teams
// in almost all the cases dont have admin privileges on Databricks
// workspaces.
//
// This configuration simplifies the flexibility of individual project
// teams, make jobs deployment easier and portable across environments.
// This configuration block would contain the following entities to be
// created by administrator users or admin-level automation, like Terraform
// and/or SCIM provisioning.
Assertions *Assertions `json:"assertions,omitempty"`
// Environments contain this project's defined environments.
// They can be used to differentiate settings and resources between
// development, staging, production, etc.
// If not specified, the code below initializes this field with a
// single default-initialized environment called "development".
Environments map[string]Environment `json:"environments"`
}
func (c Config) IsDevClusterDefined() bool {
return reflect.ValueOf(c.DevCluster).IsZero()
}
// IsDevClusterJustReference denotes reference-only clusters.
// This conflicts with Soft isolation. Happens for cost-restricted projects,
// where there's only a single Shared Autoscaling cluster per workspace and
// general users have no ability to create other iteractive clusters.
func (c *Config) IsDevClusterJustReference() bool {
if c.DevCluster.ClusterName == "" {
return false
}
return reflect.DeepEqual(c.DevCluster, &clusters.ClusterInfo{
ClusterName: c.DevCluster.ClusterName,
})
}
// IsDatabricksProject returns true for folders with `databricks.yml`
// in the parent tree
func IsDatabricksProject() bool {
_, err := findProjectRoot()
return err == nil
}
func loadProjectConf(root string) (c Config, err error) {
configFilePath := filepath.Join(root, ConfigFile)
if _, err := os.Stat(configFilePath); errors.Is(err, os.ErrNotExist) {
baseDir := filepath.Base(root)
// If bricks config file is missing we assume the project root dir name
// as the name of the project
return validateAndApplyProjectDefaults(Config{Name: baseDir})
}
config, err := os.Open(configFilePath)
if err != nil {
return
}
defer config.Close()
raw, err := io.ReadAll(config)
if err != nil {
return
}
err = yaml.Unmarshal(raw, &c)
if err != nil {
return
}
return validateAndApplyProjectDefaults(c)
}
func validateAndApplyProjectDefaults(c Config) (Config, error) {
// If no environments are specified, define default environment under default name.
if c.Environments == nil {
c.Environments = make(map[string]Environment)
c.Environments[DefaultEnvironment] = Environment{}
}
// defaultCluster := clusters.ClusterInfo{
// NodeTypeID: "smallest",
// SparkVersion: "latest",
// AutoterminationMinutes: 30,
// }
return c, nil
}
func findProjectRoot() (string, error) {
wd, err := os.Getwd()
if err != nil {
return "", err
}
dir, err := folders.FindDirWithLeaf(wd, ConfigFile)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return "", fmt.Errorf("cannot find %s anywhere", ConfigFile)
}
}
return dir, nil
}