blob: 285d63cac3116591479b7135c7eb13418c16abb1 [file] [log] [blame]
package catapult
import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
"go.skia.org/infra/go/auth"
"go.skia.org/infra/go/httputils"
"go.skia.org/infra/go/skerr"
pinpoint_proto "go.skia.org/infra/pinpoint/proto/v1"
"golang.org/x/oauth2/google"
)
const (
catapultBisectPostUrl = "https://pinpoint-dot-chromeperf.appspot.com/api/job"
catapultStagingPostUrl = "https://pinpoint-dot-chromeperf-stage.uc.r.appspot.com/api/job"
contentType = "application/protobuf"
)
type DatastoreResponse struct {
Kind string `json:"kind"`
// Pinpoint IDs are usually int, but now that we execute workflows with
// a UUID, Pinpoint stores the IDs as string and handles them.
ID string `json:"id"`
}
// CatapultClient contains an httpClient for writing to catpault
type CatapultClient struct {
httpClient *http.Client
url string
}
// NewCatapultClient creates a new CatapultClient
func NewCatapultClient(ctx context.Context, prod bool) (*CatapultClient, error) {
tokenSource, err := google.DefaultTokenSource(ctx, auth.ScopeUserinfoEmail)
if err != nil {
return nil, skerr.Wrapf(err, "Failed to create catapult client.")
}
client := httputils.DefaultClientConfig().WithTokenSource(tokenSource).Client()
if prod {
return &CatapultClient{
httpClient: client,
url: catapultBisectPostUrl,
}, nil
}
return &CatapultClient{
httpClient: client,
url: catapultStagingPostUrl,
}, nil
}
func (cc *CatapultClient) WriteBisectToCatapult(ctx context.Context, content *pinpoint_proto.LegacyJobResponse) (*DatastoreResponse, error) {
b, err := json.Marshal(content)
if err != nil {
return nil, skerr.Wrapf(err, "Failed to marshal content")
}
httpResponse, err := httputils.PostWithContext(ctx, cc.httpClient, cc.url, contentType, bytes.NewReader(b))
if err != nil {
return nil, skerr.Wrapf(err, "Failed to get Pinpoint response")
}
if httpResponse.Body == nil {
return nil, skerr.Wrap(err)
}
if httpResponse.StatusCode != http.StatusOK {
return nil, skerr.Fmt("The catapult post request failed with status code %d", httpResponse.StatusCode)
}
respBody, err := io.ReadAll(httpResponse.Body)
if err != nil {
return nil, skerr.Wrapf(err, "Failed to read body from datastore response.")
}
var dsResp DatastoreResponse
if err := json.Unmarshal(respBody, &dsResp); err != nil {
return nil, skerr.Wrapf(err, "Could not unmarshal response")
}
return &dsResp, nil
}