mirror of https://github.com/databricks/cli.git
merge
This commit is contained in:
commit
59a77bc842
|
@ -43,6 +43,6 @@ jobs:
|
|||
uses: goreleaser/goreleaser-action@v4
|
||||
with:
|
||||
version: latest
|
||||
args: release --rm-dist
|
||||
args: release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# Version changelog
|
||||
|
||||
## 0.0.30
|
||||
|
||||
* Initial preview release of the Bricks CLI.
|
2
Makefile
2
Makefile
|
@ -24,7 +24,7 @@ build: vendor
|
|||
|
||||
snapshot:
|
||||
@echo "✓ Building dev snapshot"
|
||||
@goreleaser build --snapshot --rm-dist --single-target
|
||||
@goreleaser build --snapshot --clean --single-target
|
||||
|
||||
vendor:
|
||||
@echo "✓ Filling vendor folder with library code ..."
|
||||
|
|
31
README.md
31
README.md
|
@ -1,28 +1,21 @@
|
|||
# Bricks CLI 🧱 [![build](https://github.com/databricks/bricks/workflows/build/badge.svg?branch=main)](https://github.com/databricks/bricks/actions?query=workflow%3Abuild+branch%3Amain)
|
||||
# Bricks CLI
|
||||
|
||||
_Where's "data"? Secured by the unity catalog. Projects build lifecycle is secured by `bricks` 🧱_
|
||||
[![build](https://github.com/databricks/bricks/workflows/build/badge.svg?branch=main)](https://github.com/databricks/bricks/actions?query=workflow%3Abuild+branch%3Amain)
|
||||
|
||||
This is an early PoC at this stage. `make build` (or [download the latest from releases page](https://github.com/databricks/bricks/releases)).
|
||||
This project is in private preview.
|
||||
|
||||
Reuses authentication from Databricks CLI. And terraform provider. See details here: https://registry.terraform.io/providers/databrickslabs/databricks/latest/docs#environment-variables
|
||||
Documentation is available at https://docs.databricks.com/dev-tools/cli/bricks-cli.html.
|
||||
|
||||
Supports:
|
||||
* Databricks CLI
|
||||
* Databricks CLI Profiles
|
||||
* Azure CLI Auth
|
||||
* Azure MSI Auth
|
||||
* Azure SPN Auth
|
||||
* Google OIDC Auth
|
||||
* Direct `DATABRICKS_HOST`, `DATABRICKS_TOKEN` or `DATABRICKS_USERNAME` + `DATABRICKS_PASSWORD` variables.
|
||||
## Installation
|
||||
|
||||
What works:
|
||||
This CLI is packaged as a dependency-free binary executable and may be located in any directory.
|
||||
|
||||
* `./bricks fs ls /`
|
||||
* `./bricks test`
|
||||
* `./bricks launch test.py`
|
||||
For convenient access, copy the `bricks` binary to any directory listed in `$PATH`.
|
||||
|
||||
What doesn't work:
|
||||
Confirm the binary works by executing `bricks version`.
|
||||
|
||||
* Everything else.
|
||||
## Authentication
|
||||
|
||||
This project reuses some code from Databricks Terraform Provider
|
||||
This CLI follows the Databricks Unified Authentication principles.
|
||||
|
||||
You can find a detailed description at https://github.com/databricks/databricks-sdk-go#authentication.
|
||||
|
|
|
@ -6,9 +6,12 @@ import (
|
|||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/databricks/bricks/bundle"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
const Delimiter = "."
|
||||
|
@ -63,7 +66,14 @@ func (s *stringField) interpolate(fns []LookupFunction, lookup map[string]string
|
|||
}
|
||||
|
||||
type accumulator struct {
|
||||
// all string fields in the bundle config
|
||||
strings map[string]*stringField
|
||||
|
||||
// contains path -> resolved_string mapping for string fields in the config
|
||||
// The resolved strings will NOT contain any variable references that could
|
||||
// have been resolved, however there might still be references that cannot
|
||||
// be resolved
|
||||
memo map[string]string
|
||||
}
|
||||
|
||||
// jsonFieldName returns the name in a field's `json` tag.
|
||||
|
@ -138,25 +148,7 @@ func (a *accumulator) walk(scope []string, rv reflect.Value, s setter) {
|
|||
}
|
||||
}
|
||||
|
||||
// Gathers the strings for a list of paths.
|
||||
// The fields in these paths may not depend on other fields,
|
||||
// as we don't support full DAG lookup yet (only single level).
|
||||
func (a *accumulator) gather(paths []string) (map[string]string, error) {
|
||||
var out = make(map[string]string)
|
||||
for _, path := range paths {
|
||||
f, ok := a.strings[path]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s is not defined", path)
|
||||
}
|
||||
deps := f.dependsOn()
|
||||
if len(deps) > 0 {
|
||||
return nil, fmt.Errorf("%s depends on %s", path, strings.Join(deps, ", "))
|
||||
}
|
||||
out[path] = f.Get()
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// walk and gather all string fields in the config
|
||||
func (a *accumulator) start(v any) {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Type().Kind() != reflect.Pointer {
|
||||
|
@ -168,25 +160,64 @@ func (a *accumulator) start(v any) {
|
|||
}
|
||||
|
||||
a.strings = make(map[string]*stringField)
|
||||
a.memo = make(map[string]string)
|
||||
a.walk([]string{}, rv, nilSetter{})
|
||||
}
|
||||
|
||||
func (a *accumulator) expand(fns ...LookupFunction) error {
|
||||
for path, v := range a.strings {
|
||||
ds := v.dependsOn()
|
||||
if len(ds) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Create map to be used for interpolation
|
||||
m, err := a.gather(ds)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot interpolate %s: %w", path, err)
|
||||
}
|
||||
|
||||
v.interpolate(fns, m)
|
||||
// recursively interpolate variables in a depth first manner
|
||||
func (a *accumulator) Resolve(path string, seenPaths []string, fns ...LookupFunction) error {
|
||||
// return early if the path is already resolved
|
||||
if _, ok := a.memo[path]; ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
// fetch the string node to resolve
|
||||
field, ok := a.strings[path]
|
||||
if !ok {
|
||||
return fmt.Errorf("could not find string field with path %s", path)
|
||||
}
|
||||
|
||||
// return early if the string field has no variables to interpolate
|
||||
if len(field.dependsOn()) == 0 {
|
||||
a.memo[path] = field.Get()
|
||||
return nil
|
||||
}
|
||||
|
||||
// resolve all variables refered in the root string field
|
||||
for _, childFieldPath := range field.dependsOn() {
|
||||
// error if there is a loop in variable interpolation
|
||||
if slices.Contains(seenPaths, childFieldPath) {
|
||||
return fmt.Errorf("cycle detected in field resolution: %s", strings.Join(append(seenPaths, childFieldPath), " -> "))
|
||||
}
|
||||
|
||||
// recursive resolve variables in the child fields
|
||||
err := a.Resolve(childFieldPath, append(seenPaths, childFieldPath), fns...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// interpolate root string once all variable references in it have been resolved
|
||||
field.interpolate(fns, a.memo)
|
||||
|
||||
// record interpolated string in memo
|
||||
a.memo[path] = field.Get()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Interpolate all string fields in the config
|
||||
func (a *accumulator) expand(fns ...LookupFunction) error {
|
||||
// sorting paths for stable order of iteration
|
||||
paths := maps.Keys(a.strings)
|
||||
sort.Strings(paths)
|
||||
|
||||
// iterate over paths for all strings fields in the config
|
||||
for _, path := range paths {
|
||||
err := a.Resolve(path, []string{path}, fns...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -97,3 +97,31 @@ func TestInterpolationWithMap(t *testing.T) {
|
|||
assert.Equal(t, "a", f.F["a"])
|
||||
assert.Equal(t, "a", f.F["b"])
|
||||
}
|
||||
|
||||
func TestInterpolationWithResursiveVariableReferences(t *testing.T) {
|
||||
f := foo{
|
||||
A: "a",
|
||||
B: "(${a})",
|
||||
C: "${a} ${b}",
|
||||
}
|
||||
|
||||
err := expand(&f)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, "a", f.A)
|
||||
assert.Equal(t, "(a)", f.B)
|
||||
assert.Equal(t, "a (a)", f.C)
|
||||
}
|
||||
|
||||
func TestInterpolationVariableLoopError(t *testing.T) {
|
||||
d := "${b}"
|
||||
f := foo{
|
||||
A: "a",
|
||||
B: "${c}",
|
||||
C: "${d}",
|
||||
D: &d,
|
||||
}
|
||||
|
||||
err := expand(&f)
|
||||
assert.ErrorContains(t, err, "cycle detected in field resolution: b -> c -> d -> b")
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/databricks/bricks/bundle"
|
||||
"github.com/databricks/bricks/bundle/config"
|
||||
"github.com/databricks/bricks/bundle/config/mutator"
|
||||
"github.com/databricks/databricks-sdk-go/service/scim"
|
||||
"github.com/databricks/databricks-sdk-go/service/iam"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -16,7 +16,7 @@ func TestExpandWorkspaceRoot(t *testing.T) {
|
|||
bundle := &bundle.Bundle{
|
||||
Config: config.Root{
|
||||
Workspace: config.Workspace{
|
||||
CurrentUser: &scim.User{
|
||||
CurrentUser: &iam.User{
|
||||
UserName: "jane@doe.com",
|
||||
},
|
||||
RootPath: "~/foo",
|
||||
|
@ -32,7 +32,7 @@ func TestExpandWorkspaceRootDoesNothing(t *testing.T) {
|
|||
bundle := &bundle.Bundle{
|
||||
Config: config.Root{
|
||||
Workspace: config.Workspace{
|
||||
CurrentUser: &scim.User{
|
||||
CurrentUser: &iam.User{
|
||||
UserName: "jane@doe.com",
|
||||
},
|
||||
RootPath: "/Users/charly@doe.com/foo",
|
||||
|
@ -48,7 +48,7 @@ func TestExpandWorkspaceRootWithoutRoot(t *testing.T) {
|
|||
bundle := &bundle.Bundle{
|
||||
Config: config.Root{
|
||||
Workspace: config.Workspace{
|
||||
CurrentUser: &scim.User{
|
||||
CurrentUser: &iam.User{
|
||||
UserName: "jane@doe.com",
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package resources
|
||||
|
||||
import "github.com/databricks/databricks-sdk-go/service/mlflow"
|
||||
import "github.com/databricks/databricks-sdk-go/service/ml"
|
||||
|
||||
type MlflowExperiment struct {
|
||||
Permissions []Permission `json:"permissions,omitempty"`
|
||||
|
||||
Paths
|
||||
|
||||
*mlflow.Experiment
|
||||
*ml.Experiment
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package resources
|
||||
|
||||
import "github.com/databricks/databricks-sdk-go/service/mlflow"
|
||||
import "github.com/databricks/databricks-sdk-go/service/ml"
|
||||
|
||||
type MlflowModel struct {
|
||||
Permissions []Permission `json:"permissions,omitempty"`
|
||||
|
||||
Paths
|
||||
|
||||
*mlflow.RegisteredModel
|
||||
*ml.Model
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/databricks/bricks/libs/databrickscfg"
|
||||
"github.com/databricks/databricks-sdk-go"
|
||||
"github.com/databricks/databricks-sdk-go/config"
|
||||
"github.com/databricks/databricks-sdk-go/service/scim"
|
||||
"github.com/databricks/databricks-sdk-go/service/iam"
|
||||
)
|
||||
|
||||
// Workspace defines configurables at the workspace level.
|
||||
|
@ -37,7 +37,7 @@ type Workspace struct {
|
|||
|
||||
// CurrentUser holds the current user.
|
||||
// This is set after configuration initialization.
|
||||
CurrentUser *scim.User `json:"current_user,omitempty" bundle:"readonly"`
|
||||
CurrentUser *iam.User `json:"current_user,omitempty" bundle:"readonly"`
|
||||
|
||||
// Remote workspace base path for deployment state, for artifacts, as synchronization target.
|
||||
// This defaults to "~/.bundle/${bundle.name}/${bundle.environment}" where "~" expands to
|
||||
|
|
|
@ -5,10 +5,9 @@ import (
|
|||
|
||||
"github.com/databricks/bricks/bundle/config"
|
||||
"github.com/databricks/bricks/bundle/config/resources"
|
||||
"github.com/databricks/databricks-sdk-go/service/clusters"
|
||||
"github.com/databricks/databricks-sdk-go/service/compute"
|
||||
"github.com/databricks/databricks-sdk-go/service/jobs"
|
||||
"github.com/databricks/databricks-sdk-go/service/libraries"
|
||||
"github.com/databricks/databricks-sdk-go/service/mlflow"
|
||||
"github.com/databricks/databricks-sdk-go/service/ml"
|
||||
"github.com/databricks/databricks-sdk-go/service/pipelines"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -21,7 +20,7 @@ func TestConvertJob(t *testing.T) {
|
|||
JobClusters: []jobs.JobCluster{
|
||||
{
|
||||
JobClusterKey: "key",
|
||||
NewCluster: &clusters.BaseClusterInfo{
|
||||
NewCluster: &compute.BaseClusterInfo{
|
||||
SparkVersion: "10.4.x-scala2.12",
|
||||
},
|
||||
},
|
||||
|
@ -82,9 +81,9 @@ func TestConvertJobTaskLibraries(t *testing.T) {
|
|||
Tasks: []jobs.JobTaskSettings{
|
||||
{
|
||||
TaskKey: "key",
|
||||
Libraries: []libraries.Library{
|
||||
Libraries: []compute.Library{
|
||||
{
|
||||
Pypi: &libraries.PythonPyPiLibrary{
|
||||
Pypi: &compute.PythonPyPiLibrary{
|
||||
Package: "mlflow",
|
||||
},
|
||||
},
|
||||
|
@ -171,10 +170,10 @@ func TestConvertPipelinePermissions(t *testing.T) {
|
|||
|
||||
func TestConvertModel(t *testing.T) {
|
||||
var src = resources.MlflowModel{
|
||||
RegisteredModel: &mlflow.RegisteredModel{
|
||||
Model: &ml.Model{
|
||||
Name: "name",
|
||||
Description: "description",
|
||||
Tags: []mlflow.RegisteredModelTag{
|
||||
Tags: []ml.ModelTag{
|
||||
{
|
||||
Key: "k1",
|
||||
Value: "v1",
|
||||
|
@ -235,7 +234,7 @@ func TestConvertModelPermissions(t *testing.T) {
|
|||
|
||||
func TestConvertExperiment(t *testing.T) {
|
||||
var src = resources.MlflowExperiment{
|
||||
Experiment: &mlflow.Experiment{
|
||||
Experiment: &ml.Experiment{
|
||||
Name: "name",
|
||||
},
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ func (r *jobRunner) logFailedTasks(ctx context.Context, runId int64) {
|
|||
red := color.New(color.FgRed).SprintFunc()
|
||||
green := color.New(color.FgGreen).SprintFunc()
|
||||
yellow := color.New(color.FgYellow).SprintFunc()
|
||||
run, err := w.Jobs.GetRun(ctx, jobs.GetRun{
|
||||
run, err := w.Jobs.GetRun(ctx, jobs.GetRunRequest{
|
||||
RunId: runId,
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -126,7 +126,7 @@ func (r *jobRunner) logFailedTasks(ctx context.Context, runId int64) {
|
|||
if isSuccess(task) {
|
||||
log.Infof(ctx, "task %s completed successfully", green(task.TaskKey))
|
||||
} else if isFailed(task) {
|
||||
taskInfo, err := w.Jobs.GetRunOutput(ctx, jobs.GetRunOutput{
|
||||
taskInfo, err := w.Jobs.GetRunOutput(ctx, jobs.GetRunOutputRequest{
|
||||
RunId: task.RunId,
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
@ -48,7 +48,7 @@ func (out *JobOutput) String() (string, error) {
|
|||
}
|
||||
|
||||
func GetJobOutput(ctx context.Context, w *databricks.WorkspaceClient, runId int64) (*JobOutput, error) {
|
||||
jobRun, err := w.Jobs.GetRun(ctx, jobs.GetRun{
|
||||
jobRun, err := w.Jobs.GetRun(ctx, jobs.GetRunRequest{
|
||||
RunId: runId,
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -58,7 +58,7 @@ func GetJobOutput(ctx context.Context, w *databricks.WorkspaceClient, runId int6
|
|||
TaskOutputs: make(map[string]RunOutput),
|
||||
}
|
||||
for _, task := range jobRun.Tasks {
|
||||
jobRunOutput, err := w.Jobs.GetRunOutput(ctx, jobs.GetRunOutput{
|
||||
jobRunOutput, err := w.Jobs.GetRunOutput(ctx, jobs.GetRunOutputRequest{
|
||||
RunId: task.RunId,
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
@ -54,7 +54,7 @@ func (r *pipelineRunner) logErrorEvent(ctx context.Context, pipelineId string, u
|
|||
// Otherwise for long lived pipelines, there can be a lot of unnecessary
|
||||
// latency due to multiple pagination API calls needed underneath the hood for
|
||||
// ListPipelineEventsAll
|
||||
res, err := w.Pipelines.Impl().ListPipelineEvents(ctx, pipelines.ListPipelineEvents{
|
||||
res, err := w.Pipelines.Impl().ListPipelineEvents(ctx, pipelines.ListPipelineEventsRequest{
|
||||
Filter: `level='ERROR'`,
|
||||
MaxResults: 100,
|
||||
PipelineId: pipelineId,
|
||||
|
|
|
@ -9,6 +9,15 @@ import (
|
|||
"github.com/databricks/databricks-sdk-go/service/pipelines"
|
||||
)
|
||||
|
||||
// The dlt backend computes events for pipeline runs which are accessable through
|
||||
// the 2.0/pipelines/{pipeline_id}/events API
|
||||
//
|
||||
// There are 4 levels for these events: ("ERROR", "WARN", "INFO", "METRICS")
|
||||
//
|
||||
// Here's short introduction to a few important events we display on the console:
|
||||
//
|
||||
// 1. `update_progress`: A state transition occured for the entire pipeline update
|
||||
// 2. `flow_progress`: A state transition occured for a single flow in the pipeine
|
||||
type ProgressEvent pipelines.PipelineEvent
|
||||
|
||||
func (event *ProgressEvent) String() string {
|
||||
|
@ -21,8 +30,8 @@ func (event *ProgressEvent) String() string {
|
|||
result.WriteString(event.Level.String() + " ")
|
||||
result.WriteString(fmt.Sprintf(`"%s"`, event.Message))
|
||||
|
||||
// construct error string
|
||||
if event.Error != nil {
|
||||
// construct error string if level=`Error`
|
||||
if event.Level == pipelines.EventLevelError && event.Error != nil {
|
||||
for _, exception := range event.Error.Exceptions {
|
||||
result.WriteString(fmt.Sprintf("\n%s", exception.Message))
|
||||
}
|
||||
|
@ -69,7 +78,7 @@ func (l *UpdateTracker) Events(ctx context.Context) ([]ProgressEvent, error) {
|
|||
}
|
||||
|
||||
// we only check the most recent 100 events for progress
|
||||
response, err := l.w.Pipelines.Impl().ListPipelineEvents(ctx, pipelines.ListPipelineEvents{
|
||||
response, err := l.w.Pipelines.Impl().ListPipelineEvents(ctx, pipelines.ListPipelineEventsRequest{
|
||||
PipelineId: l.PipelineId,
|
||||
MaxResults: 100,
|
||||
Filter: filter,
|
||||
|
|
|
@ -55,3 +55,24 @@ func TestUpdateErrorEventToString(t *testing.T) {
|
|||
}
|
||||
assert.Equal(t, "2023-03-27T23:30:36.122Z update_progress ERROR \"failed to update pipeline\"\nparsing error", event.String())
|
||||
}
|
||||
|
||||
func TestUpdateErrorIgnoredForWarnEvents(t *testing.T) {
|
||||
event := ProgressEvent{
|
||||
EventType: "update_progress",
|
||||
Message: "failed to update pipeline",
|
||||
Level: pipelines.EventLevelWarn,
|
||||
Origin: &pipelines.Origin{
|
||||
FlowName: "my_flow",
|
||||
PipelineName: "my_pipeline",
|
||||
},
|
||||
Timestamp: "2023-03-27T23:30:36.122Z",
|
||||
Error: &pipelines.ErrorDetail{
|
||||
Exceptions: []pipelines.SerializedException{
|
||||
{
|
||||
Message: "THIS IS IGNORED",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.Equal(t, "2023-03-27T23:30:36.122Z update_progress WARN \"failed to update pipeline\"", event.String())
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
bundle:
|
||||
name: foo ${workspace.profile}
|
||||
|
||||
workspace:
|
||||
profile: bar
|
||||
|
||||
resources:
|
||||
jobs:
|
||||
my_job:
|
||||
name: "${bundle.name} | ${workspace.profile}"
|
|
@ -0,0 +1,23 @@
|
|||
package config_tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/bricks/bundle"
|
||||
"github.com/databricks/bricks/bundle/config/interpolation"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestInterpolation(t *testing.T) {
|
||||
b := load(t, "./interpolation")
|
||||
err := bundle.Apply(context.Background(), b, []bundle.Mutator{
|
||||
interpolation.Interpolate(
|
||||
interpolation.IncludeLookupsInPath("bundle"),
|
||||
interpolation.IncludeLookupsInPath("workspace"),
|
||||
)})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "foo bar", b.Config.Bundle.Name)
|
||||
assert.Equal(t, "foo bar | bar", b.Config.Resources.Jobs["my_job"].Name)
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
package deploy
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/databricks/bricks/bundle/deployer"
|
||||
"github.com/databricks/bricks/cmd/bundle/debug"
|
||||
"github.com/databricks/bricks/libs/log"
|
||||
"github.com/databricks/databricks-sdk-go"
|
||||
"github.com/hashicorp/go-version"
|
||||
"github.com/hashicorp/hc-install/product"
|
||||
"github.com/hashicorp/hc-install/releases"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// TODO: will add integration test once terraform binary is bundled with bricks
|
||||
var deployTerraformCmd = &cobra.Command{
|
||||
Use: "deploy",
|
||||
Short: "deploys resources defined in a terraform config to a Databricks workspace",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
ctx := cmd.Context()
|
||||
|
||||
// default to cwd
|
||||
if *localRoot == "" {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*localRoot = cwd
|
||||
}
|
||||
|
||||
if *terraformBinaryPath == "" {
|
||||
installer := releases.ExactVersion{
|
||||
Product: product.Terraform,
|
||||
Version: version.Must(version.NewVersion("1.2.4")),
|
||||
}
|
||||
execPath, err := installer.Install(ctx)
|
||||
if err != nil {
|
||||
log.Errorf(ctx, "error installing Terraform: %s", err)
|
||||
}
|
||||
*terraformBinaryPath = execPath
|
||||
defer installer.Remove(ctx)
|
||||
}
|
||||
|
||||
// TODO: load bundle and get the workspace client from there once bundles
|
||||
// are stable
|
||||
wsc, err := databricks.NewWorkspaceClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d, err := deployer.Create(ctx, *env, *localRoot, *remoteRoot, wsc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if *terraformHcl == "" {
|
||||
*terraformHcl = filepath.Join(d.DefaultTerraformRoot())
|
||||
}
|
||||
|
||||
status, err := d.ApplyTerraformConfig(ctx, *terraformHcl, *terraformBinaryPath, *isForced)
|
||||
switch status {
|
||||
case deployer.Failed:
|
||||
log.Errorf(ctx, "failed to initiate deployment")
|
||||
case deployer.NoChanges:
|
||||
log.Infof(ctx, "no changes detected")
|
||||
case deployer.Partial:
|
||||
log.Errorf(ctx, "started deployment, but failed to complete")
|
||||
case deployer.PartialButUntracked:
|
||||
log.Errorf(ctx, "started deployment, but failed to complete. Any partially deployed resources in this run are untracked in the databricks workspace and might not be cleaned up on future deployments")
|
||||
case deployer.CompleteButUntracked:
|
||||
log.Errorf(ctx, "deployment complete. Failed to track deployed resources. Any deployed resources in this run are untracked in the databricks workspace and might not be cleaned up on future deployments")
|
||||
case deployer.Complete:
|
||||
log.Infof(ctx, "deployment complete")
|
||||
}
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
var remoteRoot *string
|
||||
var localRoot *string
|
||||
var env *string
|
||||
var isForced *bool
|
||||
|
||||
var terraformHcl *string
|
||||
|
||||
// TODO: remove this arguement once we package a terraform binary with the bricks cli
|
||||
var terraformBinaryPath *string
|
||||
|
||||
func init() {
|
||||
remoteRoot = deployTerraformCmd.Flags().String("remote-root", "", "workspace root of the project eg: /Repos/me@example.com/test-repo")
|
||||
localRoot = deployTerraformCmd.Flags().String("local-root", "", "path to the root directory of the DAB project. default: current working dir")
|
||||
terraformBinaryPath = deployTerraformCmd.Flags().String("terraform-cli-binary", "", "path to a terraform CLI executable binary")
|
||||
env = deployTerraformCmd.Flags().String("env", "development", "environment to deploy on. default: development")
|
||||
isForced = deployTerraformCmd.Flags().Bool("force", false, "force deploy your DAB to the workspace. default: false")
|
||||
terraformHcl = deployTerraformCmd.Flags().String("terraform-hcl", "", "path to the terraform config file from project root")
|
||||
|
||||
deployTerraformCmd.MarkFlagRequired("remote-root")
|
||||
debug.AddCommand(deployTerraformCmd)
|
||||
}
|
|
@ -8,7 +8,7 @@ import (
|
|||
// rootCmd represents the root command for the bundle subcommand.
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "bundle",
|
||||
Short: "Databricks Application Bundles",
|
||||
Short: "Databricks Asset Bundles",
|
||||
}
|
||||
|
||||
func AddCommand(cmd *cobra.Command) {
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/databricks/bricks/internal/build"
|
||||
"github.com/databricks/bricks/libs/cmdio"
|
||||
"github.com/databricks/bricks/libs/log"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/exp/slog"
|
||||
|
@ -15,8 +16,7 @@ import (
|
|||
// RootCmd represents the base command when called without any subcommands
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "bricks",
|
||||
Short: "Databricks project lifecycle management",
|
||||
Long: `Where's "data"? Secured by the unity catalog. Projects build lifecycle is secured by bricks`,
|
||||
Short: "Bricks CLI",
|
||||
|
||||
// Cobra prints the usage string to stderr if a command returns an error.
|
||||
// This usage string should only be displayed if an invalid combination of flags
|
||||
|
@ -24,6 +24,9 @@ var RootCmd = &cobra.Command{
|
|||
// The usage string is include in [flagErrorFunc] for flag errors only.
|
||||
SilenceUsage: true,
|
||||
|
||||
// Silence error printing by cobra. Errors are printed through cmdio.
|
||||
SilenceErrors: true,
|
||||
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
ctx := cmd.Context()
|
||||
|
||||
|
@ -65,6 +68,11 @@ func Execute() {
|
|||
|
||||
// Run the command
|
||||
cmd, err := RootCmd.ExecuteContextC(ctx)
|
||||
if err != nil {
|
||||
// If cmdio logger initialization succeeds, then this function logs with the
|
||||
// initialized cmdio logger, otherwise with the default cmdio logger
|
||||
cmdio.LogError(cmd.Context(), err)
|
||||
}
|
||||
|
||||
// Log exit status and error
|
||||
// We only log if logger initialization succeeded and is stored in command
|
||||
|
|
|
@ -18,7 +18,7 @@ func fetchDirs(ctx context.Context, wsc *databricks.WorkspaceClient, path string
|
|||
go func() {
|
||||
defer close(ch)
|
||||
|
||||
files, err := wsc.Workspace.ListAll(ctx, workspace.List{
|
||||
files, err := wsc.Workspace.ListAll(ctx, workspace.ListWorkspaceRequest{
|
||||
Path: path,
|
||||
})
|
||||
if err != nil {
|
||||
|
|
11
go.mod
11
go.mod
|
@ -3,7 +3,7 @@ module github.com/databricks/bricks
|
|||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/databricks/databricks-sdk-go v0.7.0
|
||||
github.com/databricks/databricks-sdk-go v0.8.0
|
||||
github.com/ghodss/yaml v1.0.0 // MIT + NOTICE
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // BSD-2-Clause
|
||||
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 // MIT
|
||||
|
@ -28,6 +28,7 @@ require (
|
|||
|
||||
require (
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
||||
github.com/google/s2a-go v0.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
|
@ -48,14 +49,14 @@ require (
|
|||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/oauth2 v0.6.0
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
golang.org/x/oauth2 v0.7.0
|
||||
golang.org/x/sys v0.7.0 // indirect
|
||||
golang.org/x/text v0.9.0
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
google.golang.org/api v0.115.0 // indirect
|
||||
google.golang.org/api v0.118.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd // indirect
|
||||
google.golang.org/grpc v1.54.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
|
|
63
go.sum
63
go.sum
|
@ -1,4 +1,5 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go/compute v1.19.0 h1:+9zda3WGgW1ZSTlVppLCYFIr48Pa35q1uG2N1itbCEQ=
|
||||
cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
|
@ -7,15 +8,22 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
|||
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA=
|
||||
github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.1.0 h1:bZgT/A+cikZnKIwn7xL2OBj012Bmvho/o6RpRvv3GKY=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/databricks/databricks-sdk-go v0.7.0 h1:eBVJ1QOzK2EW3VV/s0eit24Xv610KZMUgSzYmN35vI4=
|
||||
github.com/databricks/databricks-sdk-go v0.7.0/go.mod h1:I2aRssbBGMrwZ5iXakQAwK3I7VYono5tW3LxP7MYKeI=
|
||||
github.com/databricks/databricks-sdk-go v0.8.0 h1:LNWpcjDDFB9glT3aj6+Ie8Nlk3346TGCHUyUs3D5sU4=
|
||||
github.com/databricks/databricks-sdk-go v0.8.0/go.mod h1:aEMLe00mMlf5gvkD8PInqOM+dIAimeuAM6U+9eQN2yE=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
@ -23,6 +31,8 @@ github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc
|
|||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
|
@ -38,14 +48,17 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
|||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
|
@ -59,12 +72,15 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/s2a-go v0.1.0 h1:3Qm0liEiCErViKERO2Su5wp+9PfMRiuS6XB5FvpKnYQ=
|
||||
github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
|
||||
github.com/googleapis/gax-go/v2 v2.8.0 h1:UBtEZqx1bjXtOQ5BVTkuYghXrr3N4V123VKJK67vJZc=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
|
||||
|
@ -92,6 +108,7 @@ github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzL
|
|||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
|
||||
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
|
||||
|
@ -104,7 +121,9 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
|||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
|
@ -117,8 +136,10 @@ github.com/zclconf/go-cty v1.13.0 h1:It5dfKTTZHe9aeppbNOda3mN7Ag7sg6QkBNm6TkyFa0
|
|||
github.com/zclconf/go-cty v1.13.0/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
|
@ -131,34 +152,49 @@ golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
|||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw=
|
||||
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
|
||||
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
|
@ -169,22 +205,27 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
|
|||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.115.0 h1:6FFkVvStt4YqXSx3azKyzj7fXerGnVlLJ/eud01nBDE=
|
||||
google.golang.org/api v0.115.0/go.mod h1:9cD4/t6uvd9naoEJFA+M96d0IuB6BqFuyhpw68+mRGg=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.118.0 h1:FNfHq9Z2GKULxu7cEhCaB0wWQHg43UpomrrN+24ZRdE=
|
||||
google.golang.org/api v0.118.0/go.mod h1:76TtD3vkgmZ66zZzp72bUUklpmQmKlhh6sYtIjYK+5E=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633 h1:0BOZf6qNozI3pkN3fJLwNubheHJYHhMh91GRFOWWK08=
|
||||
google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
||||
google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd h1:sLpv7bNL1AsX3fdnWh9WVh7ejIzXdOc1RRHGeAmeStU=
|
||||
google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||
google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
|
||||
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
|
@ -205,6 +246,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
|||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
|
||||
lockpkg "github.com/databricks/bricks/libs/locker"
|
||||
"github.com/databricks/databricks-sdk-go"
|
||||
"github.com/databricks/databricks-sdk-go/service/repos"
|
||||
"github.com/databricks/databricks-sdk-go/service/workspace"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -26,7 +26,7 @@ func createRemoteTestProject(t *testing.T, projectNamePrefix string, wsc *databr
|
|||
assert.NoError(t, err)
|
||||
|
||||
remoteProjectRoot := fmt.Sprintf("/Repos/%s/%s", me.UserName, RandomName(projectNamePrefix))
|
||||
repoInfo, err := wsc.Repos.Create(ctx, repos.CreateRepo{
|
||||
repoInfo, err := wsc.Repos.Create(ctx, workspace.CreateRepo{
|
||||
Path: remoteProjectRoot,
|
||||
Url: EmptyRepoUrl,
|
||||
Provider: "gitHub",
|
||||
|
|
|
@ -19,7 +19,6 @@ import (
|
|||
"github.com/databricks/bricks/libs/testfile"
|
||||
"github.com/databricks/databricks-sdk-go"
|
||||
"github.com/databricks/databricks-sdk-go/client"
|
||||
"github.com/databricks/databricks-sdk-go/service/repos"
|
||||
"github.com/databricks/databricks-sdk-go/service/workspace"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -37,7 +36,7 @@ func setupRepo(t *testing.T, wsc *databricks.WorkspaceClient, ctx context.Contex
|
|||
require.NoError(t, err)
|
||||
repoPath := fmt.Sprintf("/Repos/%s/%s", me.UserName, RandomName("empty-repo-sync-integration-"))
|
||||
|
||||
repoInfo, err := wsc.Repos.Create(ctx, repos.CreateRepo{
|
||||
repoInfo, err := wsc.Repos.Create(ctx, workspace.CreateRepo{
|
||||
Path: repoPath,
|
||||
Url: repoUrl,
|
||||
Provider: "gitHub",
|
||||
|
@ -71,13 +70,13 @@ type assertSync struct {
|
|||
func (a *assertSync) remoteDirContent(ctx context.Context, relativeDir string, expectedFiles []string) {
|
||||
remoteDir := path.Join(a.remoteRoot, relativeDir)
|
||||
a.c.Eventually(func() bool {
|
||||
objects, err := a.w.Workspace.ListAll(ctx, workspace.List{
|
||||
objects, err := a.w.Workspace.ListAll(ctx, workspace.ListWorkspaceRequest{
|
||||
Path: remoteDir,
|
||||
})
|
||||
require.NoError(a.t, err)
|
||||
return len(objects) == len(expectedFiles)
|
||||
}, 30*time.Second, 5*time.Second)
|
||||
objects, err := a.w.Workspace.ListAll(ctx, workspace.List{
|
||||
objects, err := a.w.Workspace.ListAll(ctx, workspace.ListWorkspaceRequest{
|
||||
Path: remoteDir,
|
||||
})
|
||||
require.NoError(a.t, err)
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package cmdio
|
||||
|
||||
import "fmt"
|
||||
|
||||
type ErrorEvent struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
func (event *ErrorEvent) String() string {
|
||||
return fmt.Sprintf("Error: %s", event.Error)
|
||||
}
|
||||
|
||||
func (event *ErrorEvent) IsInplaceSupported() bool {
|
||||
return false
|
||||
}
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
|
@ -71,6 +72,16 @@ func LogNewline(ctx context.Context) {
|
|||
logger.Log(&NewlineEvent{})
|
||||
}
|
||||
|
||||
func LogError(ctx context.Context, err error) {
|
||||
logger, ok := FromContext(ctx)
|
||||
if !ok {
|
||||
logger = Default()
|
||||
}
|
||||
logger.Log(&ErrorEvent{
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
func Ask(ctx context.Context, question string) (bool, error) {
|
||||
logger, ok := FromContext(ctx)
|
||||
if !ok {
|
||||
|
@ -80,6 +91,10 @@ func Ask(ctx context.Context, question string) (bool, error) {
|
|||
}
|
||||
|
||||
func (l *Logger) Ask(question string) (bool, error) {
|
||||
if l.Mode == flags.ModeJson {
|
||||
return false, fmt.Errorf("question prompts are not supported in json mode")
|
||||
}
|
||||
|
||||
l.Writer.Write([]byte(question))
|
||||
ans, err := l.Reader.ReadString('\n')
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package cmdio
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/bricks/libs/flags"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAskFailedInJsonMode(t *testing.T) {
|
||||
l := NewLogger(flags.ModeJson)
|
||||
_, err := l.Ask("What is your spirit animal?")
|
||||
assert.ErrorContains(t, err, "question prompts are not supported in json mode")
|
||||
}
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/databricks/bricks/libs/log"
|
||||
"github.com/databricks/databricks-sdk-go"
|
||||
"github.com/databricks/databricks-sdk-go/apierr"
|
||||
"github.com/databricks/databricks-sdk-go/service/scim"
|
||||
"github.com/databricks/databricks-sdk-go/service/iam"
|
||||
"github.com/databricks/databricks-sdk-go/service/workspace"
|
||||
)
|
||||
|
||||
|
@ -29,7 +29,7 @@ func isPathNestedUnder(child, parent string) bool {
|
|||
}
|
||||
|
||||
// Check if the specified path is nested under one of the allowed base paths.
|
||||
func checkPathNestedUnderBasePaths(me *scim.User, p string) error {
|
||||
func checkPathNestedUnderBasePaths(me *iam.User, p string) error {
|
||||
validBasePaths := []string{
|
||||
path.Clean(fmt.Sprintf("/Users/%s", me.UserName)),
|
||||
path.Clean(fmt.Sprintf("/Repos/%s", me.UserName)),
|
||||
|
@ -49,7 +49,7 @@ func checkPathNestedUnderBasePaths(me *scim.User, p string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func repoPathForPath(me *scim.User, remotePath string) string {
|
||||
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 {
|
||||
|
|
|
@ -3,12 +3,12 @@ package sync
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/databricks-sdk-go/service/scim"
|
||||
"github.com/databricks/databricks-sdk-go/service/iam"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPathNestedUnderBasePaths(t *testing.T) {
|
||||
me := scim.User{
|
||||
me := iam.User{
|
||||
UserName: "jane@doe.com",
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ func TestPathNestedUnderBasePaths(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPathToRepoPath(t *testing.T) {
|
||||
me := scim.User{
|
||||
me := iam.User{
|
||||
UserName: "jane@doe.com",
|
||||
}
|
||||
|
||||
|
|
1
main.go
1
main.go
|
@ -5,7 +5,6 @@ import (
|
|||
_ "github.com/databricks/bricks/cmd/auth"
|
||||
_ "github.com/databricks/bricks/cmd/bundle"
|
||||
_ "github.com/databricks/bricks/cmd/bundle/debug"
|
||||
_ "github.com/databricks/bricks/cmd/bundle/debug/deploy"
|
||||
_ "github.com/databricks/bricks/cmd/fs"
|
||||
"github.com/databricks/bricks/cmd/root"
|
||||
_ "github.com/databricks/bricks/cmd/sync"
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
|
||||
"github.com/databricks/bricks/libs/log"
|
||||
"github.com/databricks/databricks-sdk-go"
|
||||
"github.com/databricks/databricks-sdk-go/service/dbfs"
|
||||
"github.com/databricks/databricks-sdk-go/service/files"
|
||||
)
|
||||
|
||||
func BuildWheel(ctx context.Context, dir string) (string, error) {
|
||||
|
@ -72,7 +72,7 @@ func UploadWheelToDBFSWithPEP503(ctx context.Context, dir string) (string, error
|
|||
return "", err
|
||||
}
|
||||
defer wf.Close()
|
||||
h, err := wsc.Dbfs.Open(ctx, dbfsLoc, dbfs.FileModeOverwrite|dbfs.FileModeWrite)
|
||||
h, err := wsc.Dbfs.Open(ctx, dbfsLoc, files.FileModeOverwrite|files.FileModeWrite)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
name: dev
|
||||
profile: demo
|
||||
isolation: none
|
||||
dev_cluster:
|
||||
cluster_name: Shared Autoscaling
|
|
@ -1 +0,0 @@
|
|||
spark.sql('show tables').show()
|
Loading…
Reference in New Issue