mirror of https://github.com/databricks/cli.git
87 lines
2.4 KiB
Go
87 lines
2.4 KiB
Go
package sync
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"path"
|
|
"strings"
|
|
|
|
"github.com/databricks/cli/libs/log"
|
|
"github.com/databricks/databricks-sdk-go"
|
|
"github.com/databricks/databricks-sdk-go/apierr"
|
|
"github.com/databricks/databricks-sdk-go/service/iam"
|
|
"github.com/databricks/databricks-sdk-go/service/workspace"
|
|
)
|
|
|
|
func repoPathForPath(me *iam.User, remotePath string) string {
|
|
base := path.Clean(fmt.Sprintf("/Repos/%s", me.UserName))
|
|
remotePath = path.Clean(remotePath)
|
|
for strings.HasPrefix(path.Dir(remotePath), base) && path.Dir(remotePath) != base {
|
|
remotePath = path.Dir(remotePath)
|
|
}
|
|
return remotePath
|
|
}
|
|
|
|
// EnsureRemotePathIsUsable checks if the specified path is nested under
|
|
// expected base paths and if it is a directory or repository.
|
|
func EnsureRemotePathIsUsable(ctx context.Context, wsc *databricks.WorkspaceClient, remotePath string, me *iam.User) error {
|
|
var err error
|
|
|
|
// TODO: we should cache CurrentUser.Me at the SDK level
|
|
// for now we let clients pass in any existing user they might already have
|
|
if me == nil {
|
|
me, err = wsc.CurrentUser.Me(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Ensure that the remote path exists.
|
|
// If it is a repo, it has to exist.
|
|
// If it is a workspace path, it may not exist.
|
|
info, err := wsc.Workspace.GetStatusByPath(ctx, remotePath)
|
|
if err != nil {
|
|
// We only deal with 404s below.
|
|
if !apierr.IsMissing(err) {
|
|
return err
|
|
}
|
|
|
|
// If the path is nested under a repo, the repo has to exist.
|
|
if strings.HasPrefix(remotePath, "/Repos/") {
|
|
repoPath := repoPathForPath(me, remotePath)
|
|
_, err = wsc.Workspace.GetStatusByPath(ctx, repoPath)
|
|
if err != nil && apierr.IsMissing(err) {
|
|
return fmt.Errorf("%s does not exist; please create it first", repoPath)
|
|
}
|
|
}
|
|
|
|
// The workspace path doesn't exist. Create it and try again.
|
|
err = wsc.Workspace.MkdirsByPath(ctx, remotePath)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to create directory at %s: %w", remotePath, err)
|
|
}
|
|
info, err = wsc.Workspace.GetStatusByPath(ctx, remotePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
log.Debugf(
|
|
ctx,
|
|
"Path %s has type %s (ID: %d)",
|
|
info.Path,
|
|
strings.ToLower(info.ObjectType.String()),
|
|
info.ObjectId,
|
|
)
|
|
|
|
// We expect the object at path to be a directory or a repo.
|
|
switch info.ObjectType {
|
|
case workspace.ObjectTypeDirectory:
|
|
return nil
|
|
case workspace.ObjectTypeRepo:
|
|
return nil
|
|
}
|
|
|
|
return fmt.Errorf("%s points to a %s", remotePath, strings.ToLower(info.ObjectType.String()))
|
|
}
|