diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2025-04-10 15:09:06 +0200 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2025-04-11 10:07:50 +0000 |
| commit | 4d9e57eb150fee8d24ff32fb4a8a414c77d246e6 (patch) | |
| tree | 9214e0b17c3aa833b9f812b52c5ecf7b28b4d741 /syz-cluster/pkg/controller | |
| parent | dfb5be349af98db984a0944f49896f454e4bc8a6 (diff) | |
syz-cluster: provide API for uploading artifacts archive
The archive would be a useful source of debugging information.
Provide an HTTP endpoint that accepts a multipart form request with
the archived data.
Provide an *api.Client method to encapsulate the encoding of the data.
Add a test.
Diffstat (limited to 'syz-cluster/pkg/controller')
| -rw-r--r-- | syz-cluster/pkg/controller/api.go | 31 | ||||
| -rw-r--r-- | syz-cluster/pkg/controller/api_test.go | 19 |
2 files changed, 50 insertions, 0 deletions
diff --git a/syz-cluster/pkg/controller/api.go b/syz-cluster/pkg/controller/api.go index bcab7813f..6dbdc4889 100644 --- a/syz-cluster/pkg/controller/api.go +++ b/syz-cluster/pkg/controller/api.go @@ -43,6 +43,7 @@ func (c APIServer) Mux() *http.ServeMux { mux.HandleFunc("/sessions/upload", c.uploadSession) mux.HandleFunc("/sessions/{session_id}/series", c.getSessionSeries) mux.HandleFunc("/sessions/{session_id}/skip", c.skipSession) + mux.HandleFunc("/tests/upload_artifacts", c.uploadTestArtifact) mux.HandleFunc("/tests/upload", c.uploadTest) mux.HandleFunc("/trees", c.getTrees) return mux @@ -116,6 +117,36 @@ func (c APIServer) uploadTest(w http.ResponseWriter, r *http.Request) { api.ReplyJSON[interface{}](w, nil) } +func (c APIServer) uploadTestArtifact(w http.ResponseWriter, r *http.Request) { + const maxMemory = 16 * 1000 * 1000 // 16 MB. + if err := r.ParseMultipartForm(maxMemory); err != nil { + http.Error(w, "could not parse the multipart form", http.StatusBadRequest) + return + } + defer r.MultipartForm.RemoveAll() + + file, _, err := r.FormFile("content") + if err != nil { + if err == http.ErrMissingFile { + http.Error(w, "the 'content' file must be present", http.StatusBadRequest) + return + } + http.Error(w, fmt.Sprintf("failed to query the file: %s", err), http.StatusInternalServerError) + return + } + defer file.Close() + + err = c.testService.SaveArtifacts(r.Context(), + r.FormValue("session"), + r.FormValue("test"), + file) + if err != nil { + http.Error(w, fmt.Sprint(err), http.StatusInternalServerError) + return + } + api.ReplyJSON[interface{}](w, nil) +} + func (c APIServer) uploadFinding(w http.ResponseWriter, r *http.Request) { req := api.ParseJSON[api.NewFinding](w, r) if req == nil { diff --git a/syz-cluster/pkg/controller/api_test.go b/syz-cluster/pkg/controller/api_test.go index 2b14fbe5d..fa8491208 100644 --- a/syz-cluster/pkg/controller/api_test.go +++ b/syz-cluster/pkg/controller/api_test.go @@ -4,6 +4,7 @@ package controller import ( + "bytes" "testing" "time" @@ -80,6 +81,24 @@ func TestAPISaveFinding(t *testing.T) { }) } +func TestAPIUploadTestArtifacts(t *testing.T) { + env, ctx := app.TestEnvironment(t) + client := TestServer(t, env) + + _, sessionID := UploadTestSeries(t, ctx, client, testSeries) + buildResp := UploadTestBuild(t, ctx, client, testBuild) + err := client.UploadTestResult(ctx, &api.TestResult{ + SessionID: sessionID, + BaseBuildID: buildResp.ID, + TestName: "test", + Result: api.TestRunning, + Log: []byte("some log"), + }) + assert.NoError(t, err) + err = client.UploadTestArtifacts(ctx, sessionID, "test", bytes.NewReader([]byte("artifacts content"))) + assert.NoError(t, err) +} + var testSeries = &api.Series{ ExtID: "ext-id", AuthorEmail: "some@email.com", |
