Skip to content

Commit 1dc97c8

Browse files
Add support for /workspace/import in testserver (#3192)
## Changes 1. Adds /worksapce/import to the default test server. 2. Add support for Python source notebooks to the test server. ## Why It's useful in converting generate unit tests to acceptance tests. PR: #3188 ## Tests Existing tests pass.
1 parent c17380c commit 1dc97c8

2 files changed

Lines changed: 62 additions & 8 deletions

File tree

acceptance/internal/handlers.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package internal
22

33
import (
4+
"encoding/base64"
45
"encoding/json"
56
"fmt"
67
"net/http"
@@ -113,6 +114,37 @@ func addDefaultHandlers(server *testserver.Server) {
113114
return ""
114115
})
115116

117+
server.Handle("POST", "/api/2.0/workspace/import", func(req testserver.Request) any {
118+
var request workspace.Import
119+
err := json.Unmarshal(req.Body, &request)
120+
if err != nil {
121+
return testserver.Response{
122+
Body: fmt.Sprintf("internal error: %s", err),
123+
StatusCode: http.StatusInternalServerError,
124+
}
125+
}
126+
127+
if request.Format != workspace.ImportFormatAuto {
128+
return testserver.Response{
129+
Body: "internal error: The test server only supports auto format.",
130+
StatusCode: http.StatusInternalServerError,
131+
}
132+
}
133+
134+
// The /workspace/import endpoint expects the content as base64 encoded string.
135+
// We need to decode it to get the actual content.
136+
decoded, err := base64.StdEncoding.DecodeString(request.Content)
137+
if err != nil {
138+
return testserver.Response{
139+
Body: fmt.Sprintf("internal error: %s", err),
140+
StatusCode: http.StatusInternalServerError,
141+
}
142+
}
143+
144+
req.Workspace.WorkspaceFilesImportFile(request.Path, decoded)
145+
return ""
146+
})
147+
116148
server.Handle("GET", "/api/2.0/workspace-files/{path:.*}", func(req testserver.Request) any {
117149
path := req.Vars["path"]
118150
return req.Workspace.WorkspaceFilesExportFile(path)

libs/testserver/fake_workspace.go

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"fmt"
77
"path"
8+
"path/filepath"
89
"sort"
910
"strconv"
1011
"strings"
@@ -179,17 +180,38 @@ func (s *FakeWorkspace) WorkspaceFilesImportFile(filePath string, body []byte) {
179180

180181
defer s.LockUnlock()()
181182

182-
s.files[filePath] = FileEntry{
183-
Info: workspace.ObjectInfo{
184-
ObjectType: "FILE",
185-
Path: filePath,
186-
Language: "SCALA",
187-
},
188-
Data: body,
183+
workspacePath := filePath
184+
185+
// Note: Files with .py, .scala, .r or .sql extension can
186+
// be notebooks if they contain a magical "Databricks notebook source"
187+
// header comment. We omit support non-python extensions for now for simplicity.
188+
extension := filepath.Ext(filePath)
189+
if extension == ".py" && strings.HasPrefix(string(body), "# Databricks notebook source") {
190+
// Notebooks are stripped of their extension by the workspace import API.
191+
workspacePath = strings.TrimSuffix(filePath, extension)
192+
s.files[workspacePath] = FileEntry{
193+
Info: workspace.ObjectInfo{
194+
ObjectType: "NOTEBOOK",
195+
Path: workspacePath,
196+
Language: "PYTHON",
197+
},
198+
Data: body,
199+
}
200+
} else {
201+
// The endpoint does not set language for files, so we omit that
202+
// here as well.
203+
// ref: https://docs.databricks.com/api/workspace/workspace/getstatus#language
204+
s.files[workspacePath] = FileEntry{
205+
Info: workspace.ObjectInfo{
206+
ObjectType: "FILE",
207+
Path: workspacePath,
208+
},
209+
Data: body,
210+
}
189211
}
190212

191213
// Add all directories in the path to the directories map
192-
for dir := path.Dir(filePath); dir != "/"; dir = path.Dir(dir) {
214+
for dir := path.Dir(workspacePath); dir != "/"; dir = path.Dir(dir) {
193215
s.directories[dir] = true
194216
}
195217
}

0 commit comments

Comments
 (0)