-
Notifications
You must be signed in to change notification settings - Fork 72
Added Upload and Download methods where applicable
#423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
dcc10fb
d3f16b5
3dacc0a
466ee91
7ce2fdd
e4397e7
6c4c4f6
c1a061d
da42b50
a93032e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,3 +25,4 @@ raw-specs/** | |
| out/** | ||
| *.log | ||
| .databricks/ | ||
| .DS_Store | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ import ( | |
| "context" | ||
| "encoding/base64" | ||
| "path/filepath" | ||
| "strings" | ||
| "testing" | ||
|
|
||
| "github.com/databricks/databricks-sdk-go" | ||
|
|
@@ -53,9 +54,8 @@ func TestAccWorkspaceIntegration(t *testing.T) { | |
|
|
||
| // Export the notebook and assert the contents | ||
| exportResponse, err := w.Workspace.Export(ctx, workspace.ExportRequest{ | ||
| DirectDownload: false, | ||
| Format: workspace.ExportFormatSource, | ||
| Path: notebook, | ||
| Format: workspace.ExportFormatSource, | ||
| Path: notebook, | ||
| }) | ||
| require.NoError(t, err) | ||
| assert.True(t, exportResponse.Content == base64.StdEncoding.EncodeToString([]byte("# Databricks notebook source\nprint('hello from job')"))) | ||
|
|
@@ -74,18 +74,92 @@ func TestAccWorkspaceIntegration(t *testing.T) { | |
| assert.Contains(t, paths, notebook) | ||
| } | ||
|
|
||
| func TestAccWorkspaceUploadNotebookWithFileExtensionNoTranspile(t *testing.T) { | ||
| // TODO: remove NoTranspile suffix once other languages get Upload/Donwload features | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. where?..
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Donwload |
||
| ctx, w := workspaceTest(t) | ||
|
|
||
| notebookPath := filepath.Join("/Users", me(t, w).UserName, RandomName("notebook-")+".py") | ||
|
|
||
| err := w.Workspace.Upload(ctx, notebookPath, strings.NewReader("print(1)")) | ||
| assert.NoError(t, err) | ||
|
pietern marked this conversation as resolved.
|
||
| t.Cleanup(func() { | ||
| err = w.Workspace.Delete(ctx, workspace.Delete{ | ||
| Path: notebookPath, | ||
| }) | ||
| require.NoError(t, err) | ||
| }) | ||
|
|
||
| info, err := w.Workspace.GetStatusByPath(ctx, notebookPath) | ||
| assert.NoError(t, err) | ||
| assert.Equal(t, workspace.LanguagePython, info.Language) | ||
| assert.Equal(t, workspace.ObjectTypeNotebook, info.ObjectType) | ||
|
|
||
| contents, err := w.Workspace.ReadFile(ctx, notebookPath) | ||
| assert.NoError(t, err) | ||
|
|
||
| assert.Equal(t, "# Databricks notebook source\nprint(1)", string(contents)) | ||
| } | ||
|
|
||
| func TestAccWorkspaceUploadNotebookWithFileNoExtensionNoTranspile(t *testing.T) { | ||
| // TODO: remove NoTranspile suffix once other languages get Upload/Donwload features | ||
| ctx, w := workspaceTest(t) | ||
|
|
||
| notebookPath := filepath.Join("/Users", me(t, w).UserName, RandomName("notebook-")) | ||
|
|
||
| err := w.Workspace.Upload(ctx, notebookPath, strings.NewReader("print(1)"), | ||
| workspace.UploadLanguage(workspace.LanguagePython)) | ||
| assert.NoError(t, err) | ||
| t.Cleanup(func() { | ||
| err = w.Workspace.Delete(ctx, workspace.Delete{ | ||
| Path: notebookPath, | ||
| }) | ||
| require.NoError(t, err) | ||
| }) | ||
|
|
||
| info, err := w.Workspace.GetStatusByPath(ctx, notebookPath) | ||
| assert.NoError(t, err) | ||
| assert.Equal(t, workspace.LanguagePython, info.Language) | ||
| assert.Equal(t, workspace.ObjectTypeNotebook, info.ObjectType) | ||
|
|
||
| contents, err := w.Workspace.ReadFile(ctx, notebookPath) | ||
| assert.NoError(t, err) | ||
|
|
||
| assert.Equal(t, "# Databricks notebook source\nprint(1)", string(contents)) | ||
| } | ||
|
|
||
| func TestAccWorkspaceUploadFileNoTranspile(t *testing.T) { | ||
| // TODO: remove NoTranspile suffix once other languages get Upload/Donwload features | ||
| ctx, w := workspaceTest(t) | ||
|
|
||
| txtPath := filepath.Join("/Users", me(t, w).UserName, RandomName("txt-")) | ||
|
|
||
| err := w.Workspace.Upload(ctx, txtPath, strings.NewReader("print(1)"), | ||
| workspace.UploadFormat(workspace.ExportFormatAuto)) | ||
| assert.NoError(t, err) | ||
| t.Cleanup(func() { | ||
| err = w.Workspace.Delete(ctx, workspace.Delete{ | ||
| Path: txtPath, | ||
| }) | ||
| require.NoError(t, err) | ||
| }) | ||
|
|
||
| info, err := w.Workspace.GetStatusByPath(ctx, txtPath) | ||
| assert.NoError(t, err) | ||
| assert.Equal(t, workspace.ObjectTypeFile, info.ObjectType) | ||
|
|
||
| contents, err := w.Workspace.ReadFile(ctx, txtPath) | ||
| assert.NoError(t, err) | ||
|
|
||
| assert.Equal(t, "print(1)", string(contents)) | ||
| } | ||
|
|
||
| func TestAccWorkspaceRecursiveListNoTranspile(t *testing.T) { | ||
| ctx, w := workspaceTest(t) | ||
| notebook := myNotebookPath(t, w) | ||
|
|
||
| // Import the test notebook | ||
| err := w.Workspace.Import(ctx, workspace.Import{ | ||
| Path: notebook, | ||
| Format: workspace.ExportFormatSource, | ||
| Language: workspace.LanguagePython, | ||
| Content: base64.StdEncoding.EncodeToString([]byte("# Databricks notebook source\nprint('hello from job')")), | ||
| Overwrite: true, | ||
| }) | ||
| err := w.Workspace.Upload(ctx, notebook, strings.NewReader("print(1)"), | ||
| workspace.UploadOverwrite()) | ||
| require.NoError(t, err) | ||
|
|
||
| allMyNotebooks, err := w.Workspace.RecursiveList(ctx, filepath.Join("/Users", me(t, w).UserName)) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| package files | ||
|
|
||
| import ( | ||
| "bytes" | ||
| "context" | ||
| "fmt" | ||
| "io" | ||
| "net/http" | ||
|
|
||
| "github.com/databricks/databricks-sdk-go/client" | ||
| ) | ||
|
|
||
| // BEGIN TODO: remove this once FilesAPI gets OpenAPI spec | ||
|
|
||
| func NewFiles(client *client.DatabricksClient) *FilesAPI { | ||
| return &FilesAPI{ | ||
| impl: &filesImpl{ | ||
| client: client, | ||
| }, | ||
| } | ||
| } | ||
|
|
||
| type FilesService interface{} | ||
|
|
||
| type FilesAPI struct { | ||
| impl FilesService | ||
| } | ||
|
|
||
| type filesImpl struct { | ||
| client *client.DatabricksClient | ||
| } | ||
|
|
||
| // END TODO: remove this once FilesAPI gets OpenAPI spec | ||
|
|
||
| func (a *FilesAPI) Upload(ctx context.Context, path string, r io.Reader) error { | ||
| impl, ok := a.impl.(*filesImpl) | ||
| if !ok { | ||
| return fmt.Errorf("wrong impl: %v", a.impl) | ||
| } | ||
| return impl.client.Do(ctx, "PUT", "/api/2.0/fs/files"+path, r, nil, | ||
| func(r *http.Request) error { | ||
| r.Header.Set("Content-Type", "application/octet-stream") | ||
| return nil | ||
| }) | ||
| } | ||
|
|
||
| // WriteFile is identical to [os.WriteFile] but for Files API. | ||
| func (a *FilesAPI) WriteFile(ctx context.Context, name string, data []byte) error { | ||
| return a.Upload(ctx, name, bytes.NewBuffer(data)) | ||
| } | ||
|
|
||
| func (a *FilesAPI) Download(ctx context.Context, path string) (io.ReadCloser, error) { | ||
| impl, ok := a.impl.(*filesImpl) | ||
| if !ok { | ||
| return nil, fmt.Errorf("wrong impl: %v", a.impl) | ||
| } | ||
| var buf bytes.Buffer | ||
| err := impl.client.Do(ctx, "GET", "/api/2.0/fs/files"+path, nil, &buf) | ||
|
nfx marked this conversation as resolved.
|
||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| // TODO: direclty call lower-level APIs to return raw HTTP response stream | ||
| return io.NopCloser(&buf), nil | ||
| } | ||
|
|
||
| // ReadFile is identical to [os.ReadFile] but for Files API. | ||
| func (a *FilesAPI) ReadFile(ctx context.Context, name string) ([]byte, error) { | ||
| b, err := a.Download(ctx, name) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| return io.ReadAll(b) | ||
| } | ||
|
|
||
| func (a *FilesAPI) Delete(ctx context.Context, path string) error { | ||
| impl, ok := a.impl.(*filesImpl) | ||
| if !ok { | ||
| return fmt.Errorf("wrong impl: %v", a.impl) | ||
| } | ||
| return impl.client.Do(ctx, "DELETE", "/api/2.0/fs/files"+path, nil, nil) | ||
| } | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this doesn't change behavior, but strictly speaking we only need to set this header on requests with a body. We can set the
Acceptheader on all of them as it pertains to the response.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we set the multipart header or octet-stream header in request visitors. multipart requests do require a Content-Type because of the multipart boundary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/databricks/databricks-sdk-go/blob/upload-download/service/workspace/utilities.go#L171-L175
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, not talking about why this change is done, I'm saying this header should not be set for GETs, or other requests without a request body.