func createArtifact(context *TaskContext, name string, req []byte) ([]byte, error) { par := queue.PostArtifactRequest(req) parsp, err := context.Queue().CreateArtifact( context.TaskID, strconv.Itoa(context.RunID), name, &par, ) if err != nil { return nil, err } return json.RawMessage(*parsp), nil }
func (task *TaskRun) uploadArtifact(artifact Artifact) *CommandExecutionError { log.Print("Uploading artifact: " + artifact.Base().CanonicalPath) task.Artifacts = append(task.Artifacts, artifact) payload, err := json.Marshal(artifact.RequestObject()) if err != nil { panic(err) } par := queue.PostArtifactRequest(json.RawMessage(payload)) parsp, err := task.Queue.CreateArtifact( task.TaskID, strconv.Itoa(int(task.RunID)), artifact.Base().CanonicalPath, &par, ) if err != nil { switch t := err.(type) { case *os.PathError: // artifact does not exist or is not readable... return Failure(err) case httpbackoff.BadHttpResponseCode: if t.HttpResponseCode/100 == 5 { return ResourceUnavailable(fmt.Errorf("TASK EXCEPTION due to response code %v from Queue when uploading artifact %v", t.HttpResponseCode, artifact)) } else { // if not a 5xx error, then either task cancelled, or a problem with the request == worker bug task.StatusManager.UpdateStatus() status := task.StatusManager.LastKnownStatus() if status == deadlineExceeded || status == cancelled { return nil } panic(fmt.Errorf("TASK FAIL due to response code %v from Queue when uploading artifact %v", t.HttpResponseCode, artifact)) } default: panic(fmt.Errorf("TASK EXCEPTION due to non-recoverable error when uploading artifact: %v", t)) } } // unmarshal response into object resp := artifact.ResponseObject() e := json.Unmarshal(json.RawMessage(*parsp), resp) if e != nil { panic(e) } // note: this only returns an error, if ProcessResponse returns an error... return ResourceUnavailable(artifact.ProcessResponse(resp)) }
func (task *TaskRun) uploadArtifact(artifact Artifact) error { // first check file exists! fileReader, err := os.Open(filepath.Join(TaskUser.HomeDir, artifact.CanonicalPath)) if err != nil { return err } task.Artifacts = append(task.Artifacts, artifact) debug("MimeType in queue request: %v", artifact.MimeType) par := queue.PostArtifactRequest(json.RawMessage(`{"storageType": "s3", "expires": "` + artifact.Expires.UTC().Format("2006-01-02T15:04:05.000Z0700") + `", "contentType": "` + artifact.MimeType + `"}`)) parsp, callSummary := Queue.CreateArtifact( task.TaskId, strconv.Itoa(int(task.RunId)), artifact.CanonicalPath, &par, ) if callSummary.Error != nil { debug("Could not upload artifact: %v", artifact) debug("%v", callSummary) debug("%v", parsp) debug("Request Headers") callSummary.HttpRequest.Header.Write(os.Stdout) debug("Request Body") debug(callSummary.HttpRequestBody) debug("Response Headers") callSummary.HttpResponse.Header.Write(os.Stdout) debug("Response Body") debug(callSummary.HttpResponseBody) return callSummary.Error } debug("Response body RAW") debug(callSummary.HttpResponseBody) debug("Response body INTERPRETED") debug(string(*parsp)) // unmarshal response into object resp := new(S3ArtifactResponse) err = json.Unmarshal(json.RawMessage(*parsp), resp) if err != nil { return err } httpClient := &http.Client{} httpCall := func() (*http.Response, error, error) { // instead of using fileReader, read it into memory and then use a // bytes.Reader since then http.NewRequest will properly set // Content-Length header for us, which is needed by the API we call requestPayload, err := ioutil.ReadAll(fileReader) if err != nil { return nil, nil, err } bytesReader := bytes.NewReader(requestPayload) // http.NewRequest automatically sets Content-Length correctly for bytes.Reader httpRequest, err := http.NewRequest("PUT", resp.PutURL, bytesReader) if err != nil { return nil, nil, err } debug("MimeType in put request: %v", artifact.MimeType) httpRequest.Header.Set("Content-Type", artifact.MimeType) // request body could be a) binary and b) massive, so don't show it... requestFull, dumpError := httputil.DumpRequestOut(httpRequest, false) if dumpError != nil { debug("Could not dump request, never mind...") } else { debug("Request") debug(string(requestFull)) } putResp, err := httpClient.Do(httpRequest) return putResp, err, nil } putResp, putAttempts, err := httpbackoff.Retry(httpCall) debug("%v put requests issued to %v", putAttempts, resp.PutURL) respBody, dumpError := httputil.DumpResponse(putResp, true) if dumpError != nil { debug("Could not dump response output, never mind...") } else { debug("Response") debug(string(respBody)) } return err }