mirror of https://github.com/databricks/cli.git
Add function to opportunistically load a bundle (#180)
It is not an error if a bundle cannot be found for this category. This sets the stage for using bundle configuration in non-bundle commands.
This commit is contained in:
parent
035fb6514d
commit
9a1d908f79
|
@ -41,8 +41,10 @@ func Load(path string) (*Bundle, error) {
|
||||||
return bundle, nil
|
return bundle, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadFromRoot() (*Bundle, error) {
|
// MustLoad returns a bundle configuration.
|
||||||
root, err := getRoot()
|
// It returns an error if a bundle was not found or could not be loaded.
|
||||||
|
func MustLoad() (*Bundle, error) {
|
||||||
|
root, err := mustGetRoot()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -50,6 +52,23 @@ func LoadFromRoot() (*Bundle, error) {
|
||||||
return Load(root)
|
return Load(root)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TryLoad returns a bundle configuration if there is one, but doesn't fail if there isn't one.
|
||||||
|
// It returns an error if a bundle was found but could not be loaded.
|
||||||
|
// It returns a `nil` bundle if a bundle was not found.
|
||||||
|
func TryLoad() (*Bundle, error) {
|
||||||
|
root, err := tryGetRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// No root is fine in this function.
|
||||||
|
if root == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return Load(root)
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Bundle) WorkspaceClient() *databricks.WorkspaceClient {
|
func (b *Bundle) WorkspaceClient() *databricks.WorkspaceClient {
|
||||||
b.clientOnce.Do(func() {
|
b.clientOnce.Do(func() {
|
||||||
var err error
|
var err error
|
||||||
|
|
|
@ -39,3 +39,42 @@ func TestBundleCacheDir(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, strings.HasPrefix(cacheDir, projectDir))
|
assert.True(t, strings.HasPrefix(cacheDir, projectDir))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBundleMustLoadSuccess(t *testing.T) {
|
||||||
|
t.Setenv(envBundleRoot, "./tests/basic")
|
||||||
|
b, err := MustLoad()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "./tests/basic", b.Config.Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBundleMustLoadFailureWithEnv(t *testing.T) {
|
||||||
|
t.Setenv(envBundleRoot, "./tests/doesntexist")
|
||||||
|
_, err := MustLoad()
|
||||||
|
require.Error(t, err, "not a directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBundleMustLoadFailureIfNotFound(t *testing.T) {
|
||||||
|
chdir(t, t.TempDir())
|
||||||
|
_, err := MustLoad()
|
||||||
|
require.Error(t, err, "unable to find bundle root")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBundleTryLoadSuccess(t *testing.T) {
|
||||||
|
t.Setenv(envBundleRoot, "./tests/basic")
|
||||||
|
b, err := TryLoad()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "./tests/basic", b.Config.Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBundleTryLoadFailureWithEnv(t *testing.T) {
|
||||||
|
t.Setenv(envBundleRoot, "./tests/doesntexist")
|
||||||
|
_, err := TryLoad()
|
||||||
|
require.Error(t, err, "not a directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBundleTryLoadOkIfNotFound(t *testing.T) {
|
||||||
|
chdir(t, t.TempDir())
|
||||||
|
b, err := TryLoad()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Nil(t, b)
|
||||||
|
}
|
||||||
|
|
|
@ -10,29 +10,56 @@ import (
|
||||||
|
|
||||||
const envBundleRoot = "BUNDLE_ROOT"
|
const envBundleRoot = "BUNDLE_ROOT"
|
||||||
|
|
||||||
// getRoot returns the bundle root.
|
// getRootEnv returns the value of the `BUNDLE_ROOT` environment variable
|
||||||
// If the `BUNDLE_ROOT` environment variable is set, we assume its value
|
// if it set and is a directory. If the environment variable is set but
|
||||||
// to be a valid bundle root. Otherwise we try to find it by traversing
|
// is not a directory, it returns an error. If the environment variable is
|
||||||
// the path and looking for a project configuration file.
|
// not set, it returns an empty string.
|
||||||
func getRoot() (string, error) {
|
func getRootEnv() (string, error) {
|
||||||
path, ok := os.LookupEnv(envBundleRoot)
|
path, ok := os.LookupEnv(envBundleRoot)
|
||||||
if ok {
|
if !ok {
|
||||||
stat, err := os.Stat(path)
|
return "", nil
|
||||||
if err == nil && !stat.IsDir() {
|
|
||||||
err = fmt.Errorf("not a directory")
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf(`invalid bundle root %s="%s": %w`, envBundleRoot, path, err)
|
|
||||||
}
|
|
||||||
return path, nil
|
|
||||||
}
|
}
|
||||||
|
stat, err := os.Stat(path)
|
||||||
|
if err == nil && !stat.IsDir() {
|
||||||
|
err = fmt.Errorf("not a directory")
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf(`invalid bundle root %s="%s": %w`, envBundleRoot, path, err)
|
||||||
|
}
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getRootWithTraversal returns the bundle root by traversing the filesystem
|
||||||
|
// from the working directory to the root looking for a configuration file.
|
||||||
|
func getRootWithTraversal() (string, error) {
|
||||||
wd, err := os.Getwd()
|
wd, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
path, err = folders.FindDirWithLeaf(wd, config.FileName)
|
path, err := folders.FindDirWithLeaf(wd, config.FileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf(`unable to locate bundle root`)
|
return "", fmt.Errorf(`unable to locate bundle root: %s not found`, config.FileName)
|
||||||
}
|
}
|
||||||
return path, nil
|
return path, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mustGetRoot returns a bundle root or an error if one cannot be found.
|
||||||
|
func mustGetRoot() (string, error) {
|
||||||
|
path, err := getRootEnv()
|
||||||
|
if path != "" || err != nil {
|
||||||
|
return path, err
|
||||||
|
}
|
||||||
|
return getRootWithTraversal()
|
||||||
|
}
|
||||||
|
|
||||||
|
// tryGetRoot returns a bundle root or an empty string if one cannot be found.
|
||||||
|
func tryGetRoot() (string, error) {
|
||||||
|
// Note: an invalid value in the environment variable is still an error.
|
||||||
|
path, err := getRootEnv()
|
||||||
|
if path != "" || err != nil {
|
||||||
|
return path, err
|
||||||
|
}
|
||||||
|
// Note: traversal failing means the bundle root cannot be found.
|
||||||
|
path, _ = getRootWithTraversal()
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ func TestRootFromEnv(t *testing.T) {
|
||||||
t.Setenv(envBundleRoot, dir)
|
t.Setenv(envBundleRoot, dir)
|
||||||
|
|
||||||
// It should pull the root from the environment variable.
|
// It should pull the root from the environment variable.
|
||||||
root, err := getRoot()
|
root, err := mustGetRoot()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, root, dir)
|
require.Equal(t, root, dir)
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ func TestRootFromEnvDoesntExist(t *testing.T) {
|
||||||
t.Setenv(envBundleRoot, filepath.Join(dir, "doesntexist"))
|
t.Setenv(envBundleRoot, filepath.Join(dir, "doesntexist"))
|
||||||
|
|
||||||
// It should pull the root from the environment variable.
|
// It should pull the root from the environment variable.
|
||||||
_, err := getRoot()
|
_, err := mustGetRoot()
|
||||||
require.Errorf(t, err, "invalid bundle root")
|
require.Errorf(t, err, "invalid bundle root")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ func TestRootFromEnvIsFile(t *testing.T) {
|
||||||
t.Setenv(envBundleRoot, f.Name())
|
t.Setenv(envBundleRoot, f.Name())
|
||||||
|
|
||||||
// It should pull the root from the environment variable.
|
// It should pull the root from the environment variable.
|
||||||
_, err = getRoot()
|
_, err = mustGetRoot()
|
||||||
require.Errorf(t, err, "invalid bundle root")
|
require.Errorf(t, err, "invalid bundle root")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ func TestRootIfEnvIsEmpty(t *testing.T) {
|
||||||
t.Setenv(envBundleRoot, dir)
|
t.Setenv(envBundleRoot, dir)
|
||||||
|
|
||||||
// It should pull the root from the environment variable.
|
// It should pull the root from the environment variable.
|
||||||
_, err := getRoot()
|
_, err := mustGetRoot()
|
||||||
require.Errorf(t, err, "invalid bundle root")
|
require.Errorf(t, err, "invalid bundle root")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ func TestRootLookup(t *testing.T) {
|
||||||
|
|
||||||
// It should find the project root from $PWD.
|
// It should find the project root from $PWD.
|
||||||
wd := chdir(t, "./a/b/c")
|
wd := chdir(t, "./a/b/c")
|
||||||
root, err := getRoot()
|
root, err := mustGetRoot()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, wd, root)
|
require.Equal(t, wd, root)
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,6 @@ func TestRootLookupError(t *testing.T) {
|
||||||
|
|
||||||
// It can't find a project root from a temporary directory.
|
// It can't find a project root from a temporary directory.
|
||||||
_ = chdir(t, t.TempDir())
|
_ = chdir(t, t.TempDir())
|
||||||
_, err := getRoot()
|
_, err := mustGetRoot()
|
||||||
require.ErrorContains(t, err, "unable to locate bundle root")
|
require.ErrorContains(t, err, "unable to locate bundle root")
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ var rootCmd = &cobra.Command{
|
||||||
// and configures it on the command's context.
|
// and configures it on the command's context.
|
||||||
func ConfigureBundle(cmd *cobra.Command, args []string) error {
|
func ConfigureBundle(cmd *cobra.Command, args []string) error {
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
b, err := bundle.LoadFromRoot()
|
b, err := bundle.MustLoad()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue