From ea2666e0c00c430b3be2ba0ebdbb189a14e5d0b4 Mon Sep 17 00:00:00 2001 From: Alexander Egorenkov Date: Fri, 30 Oct 2020 15:53:52 +0100 Subject: syz-ci: support HTTP PUT method to upload coverage reports The syz-ci's configuration parameter *cover_upload_path* contains a protocol-specific path now. Currently, only two protocols for uploading of manager's coverage reports are supported: * Google Cloud Storage (GCS) * HTTP PUT - A path which starts with "gcs://" shall be interpreted as a GCS path with gs:// prefix stripped. - For a path which starts with http:// or https:// the HTTP PUT method shall be used for uploading. - If the given path contains no supported protocol prefix, then syz-ci shall assume that it is a GCS path. Signed-off-by: Alexander Egorenkov --- syz-ci/manager.go | 48 +++++++++++++++++++++++++++++++++++++++--------- syz-ci/syz-ci.go | 3 ++- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/syz-ci/manager.go b/syz-ci/manager.go index 59dc6bf21..fcf0bf7f6 100644 --- a/syz-ci/manager.go +++ b/syz-ci/manager.go @@ -10,6 +10,7 @@ import ( "net/http" "os" "path/filepath" + "strings" "time" "github.com/google/syzkaller/dashboard/dashapi" @@ -612,11 +613,7 @@ func (mgr *Manager) pollCommits(buildCommit string) ([]string, []dashapi.Commit, } func (mgr *Manager) uploadCoverReport() error { - GCS, err := gcs.NewClient() - if err != nil { - return fmt.Errorf("failed to create GCS client: %v", err) - } - defer GCS.Close() + // Get coverage report from manager. addr := mgr.managercfg.HTTP if addr != "" && addr[0] == ':' { addr = "127.0.0.1" + addr // in case addr is ":port" @@ -626,19 +623,52 @@ func (mgr *Manager) uploadCoverReport() error { return fmt.Errorf("failed to get report: %v", err) } defer resp.Body.Close() - gcsPath := filepath.Join(mgr.cfg.CoverUploadPath, mgr.name+".html") - gcsWriter, err := GCS.FileWriter(gcsPath) + // Upload coverage report. + coverUploadURL := filepath.Join(mgr.cfg.CoverUploadPath, mgr.name+".html") + if strings.HasPrefix(coverUploadURL, "gs://") { + return uploadCoverReportGCS(strings.TrimPrefix(coverUploadURL, "gs://"), resp.Body) + } else if strings.HasPrefix(coverUploadURL, "http://") || strings.HasPrefix(coverUploadURL, "https://") { + return uploadCoverReportHTTPPut(coverUploadURL, resp.Body) + } else { // Use GCS as default to maintain backwards compatibility. + return uploadCoverReportGCS(coverUploadURL, resp.Body) + } +} + +func uploadCoverReportGCS(coverUploadURL string, coverReport io.Reader) error { + GCS, err := gcs.NewClient() + if err != nil { + return fmt.Errorf("failed to create GCS client: %v", err) + } + defer GCS.Close() + gcsWriter, err := GCS.FileWriter(coverUploadURL) if err != nil { return fmt.Errorf("failed to create GCS writer: %v", err) } - if _, err := io.Copy(gcsWriter, resp.Body); err != nil { + if _, err := io.Copy(gcsWriter, coverReport); err != nil { gcsWriter.Close() return fmt.Errorf("failed to copy report: %v", err) } if err := gcsWriter.Close(); err != nil { return fmt.Errorf("failed to close gcs writer: %v", err) } - return GCS.Publish(gcsPath) + return GCS.Publish(coverUploadURL) +} + +func uploadCoverReportHTTPPut(coverUploadURL string, coverReport io.Reader) error { + req, err := http.NewRequest(http.MethodPut, coverUploadURL, coverReport) + if err != nil { + return fmt.Errorf("failed to create HTTP PUT request: %v", err) + } + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("failed to perform HTTP PUT request: %v", err) + } + defer resp.Body.Close() + if !(resp.StatusCode >= 200 && resp.StatusCode <= 299) { + return fmt.Errorf("HTTP PUT failed with status code: %v", err) + } + return nil } // Errorf logs non-fatal error and sends it to dashboard. diff --git a/syz-ci/syz-ci.go b/syz-ci/syz-ci.go index 0467449ee..fe7a7dde4 100644 --- a/syz-ci/syz-ci.go +++ b/syz-ci/syz-ci.go @@ -91,7 +91,8 @@ type Config struct { SyzkallerBranch string `json:"syzkaller_branch"` // Defaults to "master". // Dir with additional syscall descriptions (.txt and .const files). SyzkallerDescriptions string `json:"syzkaller_descriptions"` - // GCS path to upload coverage reports from managers (optional). + // Protocol-specific path to upload coverage reports from managers (optional). + // Supported protocols: GCS (gs://) and HTTP PUT (http:// or https://). CoverUploadPath string `json:"cover_upload_path"` BisectBinDir string `json:"bisect_bin_dir"` Ccache string `json:"ccache"` -- cgit mrf-deployment