mirror of https://github.com/databricks/cli.git
Define translation mode and options
This commit is contained in:
parent
aa9226446b
commit
9c8c85ddc1
|
@ -17,6 +17,34 @@ import (
|
||||||
"github.com/databricks/cli/libs/notebook"
|
"github.com/databricks/cli/libs/notebook"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TranslateMode specifies how a path should be translated.
|
||||||
|
type TranslateMode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// TranslateModeNotebook translates a path to a remote notebook.
|
||||||
|
TranslateModeNotebook TranslateMode = iota
|
||||||
|
|
||||||
|
// TranslateModeFile translates a path to a remote regular file.
|
||||||
|
TranslateModeFile
|
||||||
|
|
||||||
|
// TranslateModeDirectory translates a path to a remote directory.
|
||||||
|
TranslateModeDirectory
|
||||||
|
|
||||||
|
// TranslateModeRetainLocalAbsoluteFilePath translates a path to the local absolute file path.
|
||||||
|
TranslateModeRetainLocalAbsoluteFilePath
|
||||||
|
|
||||||
|
// TranslateModeNoOp does not translate the path.
|
||||||
|
TranslateModeNoOp
|
||||||
|
|
||||||
|
// TranslateModeNoOpWithPrefix does not translate the path, but adds a prefix to it.
|
||||||
|
TranslateModeNoOpWithPrefix
|
||||||
|
)
|
||||||
|
|
||||||
|
// translateOptions specifies how a path should be translated.
|
||||||
|
type translateOptions struct {
|
||||||
|
Mode TranslateMode
|
||||||
|
}
|
||||||
|
|
||||||
type ErrIsNotebook struct {
|
type ErrIsNotebook struct {
|
||||||
path string
|
path string
|
||||||
}
|
}
|
||||||
|
@ -44,8 +72,6 @@ func (m *translatePaths) Name() string {
|
||||||
return "TranslatePaths"
|
return "TranslatePaths"
|
||||||
}
|
}
|
||||||
|
|
||||||
type rewriteFunc func(ctx context.Context, literal, localFullPath, localRelPath, remotePath string) (string, error)
|
|
||||||
|
|
||||||
// translateContext is a context for rewriting paths in a config.
|
// translateContext is a context for rewriting paths in a config.
|
||||||
// It is freshly instantiated on every mutator apply call.
|
// It is freshly instantiated on every mutator apply call.
|
||||||
// It provides access to the underlying bundle object such that
|
// It provides access to the underlying bundle object such that
|
||||||
|
@ -64,8 +90,8 @@ type translateContext struct {
|
||||||
// - The context in which the function is called.
|
// - The context in which the function is called.
|
||||||
// - The argument `dir` is the directory relative to which the relative path should be interpreted.
|
// - The argument `dir` is the directory relative to which the relative path should be interpreted.
|
||||||
// - The argument `input` is the relative path to rewrite.
|
// - The argument `input` is the relative path to rewrite.
|
||||||
// - The argument `fn` is a function that performs the actual rewriting logic.
|
// - The argument `opts` is a struct that specifies how the path should be rewritten.
|
||||||
// This logic is different between regular files or notebooks.
|
// It contains a `Mode` field that specifies how the path should be rewritten.
|
||||||
//
|
//
|
||||||
// The function returns the rewritten path if successful, or an error if the path could not be rewritten.
|
// The function returns the rewritten path if successful, or an error if the path could not be rewritten.
|
||||||
// The returned path is an empty string if the path was not rewritten.
|
// The returned path is an empty string if the path was not rewritten.
|
||||||
|
@ -73,7 +99,7 @@ func (t *translateContext) rewritePath(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
dir string,
|
dir string,
|
||||||
input string,
|
input string,
|
||||||
fn rewriteFunc,
|
opts translateOptions,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
// We assume absolute paths point to a location in the workspace
|
// We assume absolute paths point to a location in the workspace
|
||||||
if path.IsAbs(input) {
|
if path.IsAbs(input) {
|
||||||
|
@ -115,7 +141,23 @@ func (t *translateContext) rewritePath(
|
||||||
remotePath := path.Join(workspacePath, filepath.ToSlash(localRelPath))
|
remotePath := path.Join(workspacePath, filepath.ToSlash(localRelPath))
|
||||||
|
|
||||||
// Convert local path into workspace path via specified function.
|
// Convert local path into workspace path via specified function.
|
||||||
interp, err := fn(ctx, input, localPath, localRelPath, remotePath)
|
var interp string
|
||||||
|
switch opts.Mode {
|
||||||
|
case TranslateModeNotebook:
|
||||||
|
interp, err = t.translateNotebookPath(ctx, input, localPath, localRelPath, remotePath)
|
||||||
|
case TranslateModeFile:
|
||||||
|
interp, err = t.translateFilePath(ctx, input, localPath, localRelPath, remotePath)
|
||||||
|
case TranslateModeDirectory:
|
||||||
|
interp, err = t.translateDirectoryPath(ctx, input, localPath, localRelPath, remotePath)
|
||||||
|
case TranslateModeRetainLocalAbsoluteFilePath:
|
||||||
|
interp, err = t.retainLocalAbsoluteFilePath(ctx, input, localPath, localRelPath, remotePath)
|
||||||
|
case TranslateModeNoOp:
|
||||||
|
interp, err = t.translateNoOp(ctx, input, localPath, localRelPath, remotePath)
|
||||||
|
case TranslateModeNoOpWithPrefix:
|
||||||
|
interp, err = t.translateNoOpWithPrefix(ctx, input, localPath, localRelPath, remotePath)
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("unsupported translate mode: %d", opts.Mode)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -191,10 +233,6 @@ func (t *translateContext) translateDirectoryPath(ctx context.Context, literal,
|
||||||
return remotePath, nil
|
return remotePath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *translateContext) translateNoOp(ctx context.Context, literal, localFullPath, localRelPath, remotePath string) (string, error) {
|
|
||||||
return localRelPath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *translateContext) retainLocalAbsoluteFilePath(ctx context.Context, literal, localFullPath, localRelPath, remotePath string) (string, error) {
|
func (t *translateContext) retainLocalAbsoluteFilePath(ctx context.Context, literal, localFullPath, localRelPath, remotePath string) (string, error) {
|
||||||
info, err := t.b.SyncRoot.Stat(filepath.ToSlash(localRelPath))
|
info, err := t.b.SyncRoot.Stat(filepath.ToSlash(localRelPath))
|
||||||
if errors.Is(err, fs.ErrNotExist) {
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
@ -209,6 +247,10 @@ func (t *translateContext) retainLocalAbsoluteFilePath(ctx context.Context, lite
|
||||||
return localFullPath, nil
|
return localFullPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *translateContext) translateNoOp(ctx context.Context, literal, localFullPath, localRelPath, remotePath string) (string, error) {
|
||||||
|
return localRelPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (t *translateContext) translateNoOpWithPrefix(ctx context.Context, literal, localFullPath, localRelPath, remotePath string) (string, error) {
|
func (t *translateContext) translateNoOpWithPrefix(ctx context.Context, literal, localFullPath, localRelPath, remotePath string) (string, error) {
|
||||||
if !strings.HasPrefix(localRelPath, ".") {
|
if !strings.HasPrefix(localRelPath, ".") {
|
||||||
localRelPath = "." + string(filepath.Separator) + localRelPath
|
localRelPath = "." + string(filepath.Separator) + localRelPath
|
||||||
|
@ -216,8 +258,8 @@ func (t *translateContext) translateNoOpWithPrefix(ctx context.Context, literal,
|
||||||
return localRelPath, nil
|
return localRelPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *translateContext) rewriteValue(ctx context.Context, p dyn.Path, v dyn.Value, fn rewriteFunc, dir string) (dyn.Value, error) {
|
func (t *translateContext) rewriteValue(ctx context.Context, p dyn.Path, v dyn.Value, dir string, opts translateOptions) (dyn.Value, error) {
|
||||||
out, err := t.rewritePath(ctx, dir, v.MustString(), fn)
|
out, err := t.rewritePath(ctx, dir, v.MustString(), opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if target := (&ErrIsNotebook{}); errors.As(err, target) {
|
if target := (&ErrIsNotebook{}); errors.As(err, target) {
|
||||||
return dyn.InvalidValue, fmt.Errorf(`expected a file for "%s" but got a notebook: %w`, p, target)
|
return dyn.InvalidValue, fmt.Errorf(`expected a file for "%s" but got a notebook: %w`, p, target)
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
type artifactRewritePattern struct {
|
type artifactRewritePattern struct {
|
||||||
pattern dyn.Pattern
|
pattern dyn.Pattern
|
||||||
fn rewriteFunc
|
opts translateOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *translateContext) artifactRewritePatterns() []artifactRewritePattern {
|
func (t *translateContext) artifactRewritePatterns() []artifactRewritePattern {
|
||||||
|
@ -23,7 +23,7 @@ func (t *translateContext) artifactRewritePatterns() []artifactRewritePattern {
|
||||||
return []artifactRewritePattern{
|
return []artifactRewritePattern{
|
||||||
{
|
{
|
||||||
base.Append(dyn.Key("path")),
|
base.Append(dyn.Key("path")),
|
||||||
t.translateNoOp,
|
translateOptions{Mode: TranslateModeNoOp},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ func (t *translateContext) applyArtifactTranslations(ctx context.Context, v dyn.
|
||||||
return dyn.InvalidValue, fmt.Errorf("unable to determine directory for artifact %s: %w", key, err)
|
return dyn.InvalidValue, fmt.Errorf("unable to determine directory for artifact %s: %w", key, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return t.rewriteValue(ctx, p, v, rewritePattern.fn, dir)
|
return t.rewriteValue(ctx, p, v, dir, rewritePattern.opts)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return dyn.InvalidValue, err
|
return dyn.InvalidValue, err
|
||||||
|
|
|
@ -17,6 +17,10 @@ func (t *translateContext) applyDashboardTranslations(ctx context.Context, v dyn
|
||||||
dyn.Key("file_path"),
|
dyn.Key("file_path"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
opts := translateOptions{
|
||||||
|
Mode: TranslateModeRetainLocalAbsoluteFilePath,
|
||||||
|
}
|
||||||
|
|
||||||
return dyn.MapByPattern(v, pattern, func(p dyn.Path, v dyn.Value) (dyn.Value, error) {
|
return dyn.MapByPattern(v, pattern, func(p dyn.Path, v dyn.Value) (dyn.Value, error) {
|
||||||
key := p[2].Key()
|
key := p[2].Key()
|
||||||
dir, err := v.Location().Directory()
|
dir, err := v.Location().Directory()
|
||||||
|
@ -24,6 +28,6 @@ func (t *translateContext) applyDashboardTranslations(ctx context.Context, v dyn
|
||||||
return dyn.InvalidValue, fmt.Errorf("unable to determine directory for dashboard %s: %w", key, err)
|
return dyn.InvalidValue, fmt.Errorf("unable to determine directory for dashboard %s: %w", key, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return t.rewriteValue(ctx, p, v, t.retainLocalAbsoluteFilePath, dir)
|
return t.rewriteValue(ctx, p, v, dir, opts)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,13 +39,17 @@ func (t *translateContext) applyJobTranslations(ctx context.Context, v dyn.Value
|
||||||
return dyn.InvalidValue, fmt.Errorf("unable to determine directory for job %s: %w", key, err)
|
return dyn.InvalidValue, fmt.Errorf("unable to determine directory for job %s: %w", key, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rewritePatternFn, err := t.getRewritePatternFn(kind)
|
mode, err := getJobTranslateMode(kind)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return dyn.InvalidValue, err
|
return dyn.InvalidValue, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opts := translateOptions{
|
||||||
|
Mode: mode,
|
||||||
|
}
|
||||||
|
|
||||||
// Try to rewrite the path relative to the directory of the configuration file where the value was defined.
|
// Try to rewrite the path relative to the directory of the configuration file where the value was defined.
|
||||||
nv, err := t.rewriteValue(ctx, p, v, rewritePatternFn, dir)
|
nv, err := t.rewriteValue(ctx, p, v, dir, opts)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nv, nil
|
return nv, nil
|
||||||
}
|
}
|
||||||
|
@ -53,7 +57,7 @@ func (t *translateContext) applyJobTranslations(ctx context.Context, v dyn.Value
|
||||||
// If we failed to rewrite the path, try to rewrite it relative to the fallback directory.
|
// If we failed to rewrite the path, try to rewrite it relative to the fallback directory.
|
||||||
// We only do this for jobs and pipelines because of the comment in [gatherFallbackPaths].
|
// We only do this for jobs and pipelines because of the comment in [gatherFallbackPaths].
|
||||||
if fallback[key] != "" {
|
if fallback[key] != "" {
|
||||||
nv, nerr := t.rewriteValue(ctx, p, v, rewritePatternFn, fallback[key])
|
nv, nerr := t.rewriteValue(ctx, p, v, fallback[key], opts)
|
||||||
if nerr == nil {
|
if nerr == nil {
|
||||||
// TODO: Emit a warning that this path should be rewritten.
|
// TODO: Emit a warning that this path should be rewritten.
|
||||||
return nv, nil
|
return nv, nil
|
||||||
|
@ -64,19 +68,19 @@ func (t *translateContext) applyJobTranslations(ctx context.Context, v dyn.Value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *translateContext) getRewritePatternFn(kind paths.PathKind) (rewriteFunc, error) {
|
func getJobTranslateMode(kind paths.PathKind) (TranslateMode, error) {
|
||||||
switch kind {
|
switch kind {
|
||||||
case paths.PathKindLibrary:
|
case paths.PathKindLibrary:
|
||||||
return t.translateNoOp, nil
|
return TranslateModeNoOp, nil
|
||||||
case paths.PathKindNotebook:
|
case paths.PathKindNotebook:
|
||||||
return t.translateNotebookPath, nil
|
return TranslateModeNotebook, nil
|
||||||
case paths.PathKindWorkspaceFile:
|
case paths.PathKindWorkspaceFile:
|
||||||
return t.translateFilePath, nil
|
return TranslateModeFile, nil
|
||||||
case paths.PathKindDirectory:
|
case paths.PathKindDirectory:
|
||||||
return t.translateDirectoryPath, nil
|
return TranslateModeDirectory, nil
|
||||||
case paths.PathKindWithPrefix:
|
case paths.PathKindWithPrefix:
|
||||||
return t.translateNoOpWithPrefix, nil
|
return TranslateModeNoOpWithPrefix, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("unsupported path kind: %d", kind)
|
return TranslateMode(0), fmt.Errorf("unsupported path kind: %d", kind)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
type pipelineRewritePattern struct {
|
type pipelineRewritePattern struct {
|
||||||
pattern dyn.Pattern
|
pattern dyn.Pattern
|
||||||
fn rewriteFunc
|
opts translateOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *translateContext) pipelineRewritePatterns() []pipelineRewritePattern {
|
func (t *translateContext) pipelineRewritePatterns() []pipelineRewritePattern {
|
||||||
|
@ -26,11 +26,11 @@ func (t *translateContext) pipelineRewritePatterns() []pipelineRewritePattern {
|
||||||
return []pipelineRewritePattern{
|
return []pipelineRewritePattern{
|
||||||
{
|
{
|
||||||
base.Append(dyn.Key("notebook"), dyn.Key("path")),
|
base.Append(dyn.Key("notebook"), dyn.Key("path")),
|
||||||
t.translateNotebookPath,
|
translateOptions{Mode: TranslateModeNotebook},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
base.Append(dyn.Key("file"), dyn.Key("path")),
|
base.Append(dyn.Key("file"), dyn.Key("path")),
|
||||||
t.translateFilePath,
|
translateOptions{Mode: TranslateModeFile},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ func (t *translateContext) applyPipelineTranslations(ctx context.Context, v dyn.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to rewrite the path relative to the directory of the configuration file where the value was defined.
|
// Try to rewrite the path relative to the directory of the configuration file where the value was defined.
|
||||||
nv, err := t.rewriteValue(ctx, p, v, rewritePattern.fn, dir)
|
nv, err := t.rewriteValue(ctx, p, v, dir, rewritePattern.opts)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nv, nil
|
return nv, nil
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ func (t *translateContext) applyPipelineTranslations(ctx context.Context, v dyn.
|
||||||
// If we failed to rewrite the path, try to rewrite it relative to the fallback directory.
|
// If we failed to rewrite the path, try to rewrite it relative to the fallback directory.
|
||||||
// We only do this for jobs and pipelines because of the comment in [gatherFallbackPaths].
|
// We only do this for jobs and pipelines because of the comment in [gatherFallbackPaths].
|
||||||
if fallback[key] != "" {
|
if fallback[key] != "" {
|
||||||
nv, nerr := t.rewriteValue(ctx, p, v, rewritePattern.fn, fallback[key])
|
nv, nerr := t.rewriteValue(ctx, p, v, fallback[key], rewritePattern.opts)
|
||||||
if nerr == nil {
|
if nerr == nil {
|
||||||
// TODO: Emit a warning that this path should be rewritten.
|
// TODO: Emit a warning that this path should be rewritten.
|
||||||
return nv, nil
|
return nv, nil
|
||||||
|
|
Loading…
Reference in New Issue