aboutsummaryrefslogtreecommitdiffstats
path: root/syz-cluster/pkg/service
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2025-04-10 15:09:06 +0200
committerAleksandr Nogikh <nogikh@google.com>2025-04-11 10:07:50 +0000
commit4d9e57eb150fee8d24ff32fb4a8a414c77d246e6 (patch)
tree9214e0b17c3aa833b9f812b52c5ecf7b28b4d741 /syz-cluster/pkg/service
parentdfb5be349af98db984a0944f49896f454e4bc8a6 (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/service')
-rw-r--r--syz-cluster/pkg/service/sessiontest.go45
1 files changed, 36 insertions, 9 deletions
diff --git a/syz-cluster/pkg/service/sessiontest.go b/syz-cluster/pkg/service/sessiontest.go
index 0e4e56761..a59126860 100644
--- a/syz-cluster/pkg/service/sessiontest.go
+++ b/syz-cluster/pkg/service/sessiontest.go
@@ -7,6 +7,7 @@ import (
"bytes"
"context"
"fmt"
+ "io"
"time"
"cloud.google.com/go/spanner"
@@ -46,18 +47,44 @@ func (s *SessionTestService) Save(ctx context.Context, req *api.TestResult) erro
if req.PatchedBuildID != "" {
entity.PatchedBuildID = spanner.NullString{StringVal: req.PatchedBuildID, Valid: true}
}
- if entity.LogURI != "" {
- err := s.blobStorage.Update(entity.LogURI, bytes.NewReader(req.Log))
+ // TODO: the code does not really handle simultaneous requests.
+ if len(req.Log) > 0 {
+ entity.LogURI, err = s.uploadOrUpdate(ctx, entity.LogURI, bytes.NewReader(req.Log))
if err != nil {
- return fmt.Errorf("failed to update the log: %w", err)
+ return fmt.Errorf("failed to save the log: %w", err)
}
- } else if len(req.Log) > 0 {
- // TODO: it will leak if we fail to save the entity.
- uri, err := s.blobStorage.Store(bytes.NewReader(req.Log))
+ }
+ return s.testRepo.InsertOrUpdate(ctx, entity)
+}
+
+// TODO: this function has the same problems as Save().
+func (s *SessionTestService) SaveArtifacts(ctx context.Context, sessionID, testName string, reader io.Reader) error {
+ entity, err := s.testRepo.Get(ctx, sessionID, testName)
+ if err != nil {
+ return fmt.Errorf("failed to query the test: %w", err)
+ } else if entity == nil {
+ return fmt.Errorf("the test has not been submitted yet")
+ }
+ newArchiveURI, err := s.uploadOrUpdate(ctx, entity.ArtifactsArchiveURI, reader)
+ if err != nil {
+ return fmt.Errorf("failed to save the artifacts archive: %w", err)
+ }
+ entity.ArtifactsArchiveURI = newArchiveURI
+ return s.testRepo.InsertOrUpdate(ctx, entity)
+}
+
+func (s *SessionTestService) uploadOrUpdate(ctx context.Context, uri string, reader io.Reader) (string, error) {
+ if uri != "" {
+ err := s.blobStorage.Update(uri, reader)
if err != nil {
- return fmt.Errorf("failed to save the log: %w", err)
+ return "", fmt.Errorf("failed to update: %w", err)
}
- entity.LogURI = uri
+ return uri, nil
+ }
+ // TODO: it will leak if we fail to save the entity.
+ uri, err := s.blobStorage.Store(reader)
+ if err != nil {
+ return "", fmt.Errorf("failed to save: %w", err)
}
- return s.testRepo.InsertOrUpdate(context.Background(), entity)
+ return uri, nil
}