// Execute carries out the S3CopyCommand command - this is required // to satisfy the 'Command' interface func (scc *S3CopyCommand) Execute(pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, taskConfig *model.TaskConfig, stop chan bool) error { // expand the S3 copy parameters before running the task if err := plugin.ExpandValues(scc, taskConfig.Expansions); err != nil { return err } // validate the S3 copy parameters before running the task if err := scc.validateS3CopyParams(); err != nil { return err } errChan := make(chan error) go func() { errChan <- scc.S3Copy(taskConfig, pluginLogger, pluginCom) }() select { case err := <-errChan: return err case <-stop: pluginLogger.LogExecution(slogger.INFO, "Received signal to terminate"+ " execution of S3 copy command") return nil } }
// ParseTestOutputFiles parses all of the files that are passed in, and returns the // test logs and test results found within. func ParseTestOutputFiles(outputFiles []string, stop chan bool, pluginLogger plugin.Logger, taskConfig *model.TaskConfig) ([]model.TestLog, [][]TestResult, error) { var results [][]TestResult var logs []model.TestLog // now, open all the files, and parse the test results for _, outputFile := range outputFiles { // kill the execution if API server requests select { case <-stop: return nil, nil, fmt.Errorf("command was stopped") default: // no stop signal } // assume that the name of the file, stripping off the ".suite" extension if present, // is the name of the suite being tested _, suiteName := filepath.Split(outputFile) suiteName = strings.TrimSuffix(suiteName, ".suite") // open the file fileReader, err := os.Open(outputFile) if err != nil { // don't bomb out on a single bad file pluginLogger.LogTask(slogger.ERROR, "Unable to open file '%v' for parsing: %v", outputFile, err) continue } defer fileReader.Close() // parse the output logs parser := &VanillaParser{Suite: suiteName} if err := parser.Parse(fileReader); err != nil { // continue on error pluginLogger.LogTask(slogger.ERROR, "Error parsing file '%v': %v", outputFile, err) continue } // build up the test logs logLines := parser.Logs() testLog := model.TestLog{ Name: suiteName, Task: taskConfig.Task.Id, TaskExecution: taskConfig.Task.Execution, Lines: logLines, } // save the results results = append(results, parser.Results()) logs = append(logs, testLog) } return logs, results, nil }
// AttachTaskFiles is responsible for sending the // specified file to the API Server func (c *S3CopyCommand) AttachTaskFiles(pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, request S3CopyRequest) error { remotePath := filepath.ToSlash(request.S3DestinationPath) fileLink := s3baseURL + request.S3DestinationBucket + "/" + remotePath displayName := request.S3DisplayName if displayName == "" { displayName = filepath.Base(request.S3SourcePath) } pluginLogger.LogExecution(slogger.INFO, "attaching file with name %v", displayName) file := artifact.File{ Name: displayName, Link: fileLink, } files := []*artifact.File{&file} err := pluginCom.PostTaskFiles(files) if err != nil { return fmt.Errorf("Attach files failed: %v", err) } pluginLogger.LogExecution(slogger.INFO, "API attach files call succeeded") return nil }
// Execute builds the archive. func (self *TarGzPackCommand) Execute(pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, conf *model.TaskConfig, stop chan bool) error { // if the source dir is a relative path, join it to the working dir if !filepath.IsAbs(self.SourceDir) { self.SourceDir = filepath.Join(conf.WorkDir, self.SourceDir) } // if the target is a relative path, join it to the working dir if !filepath.IsAbs(self.Target) { self.Target = filepath.Join(conf.WorkDir, self.Target) } errChan := make(chan error) go func() { errChan <- self.BuildArchive(conf.WorkDir, pluginLogger) }() select { case err := <-errChan: return err case <-stop: pluginLogger.LogExecution(slogger.INFO, "Received signal to terminate"+ " execution of targz pack command") return nil } }
// Execute fetches the expansions from the API server func (self *FetchVarsCommand) Execute(pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, conf *model.TaskConfig, stop chan bool) error { pluginLogger.LogTask(slogger.ERROR, "Expansions.fetch deprecated") return nil }
func (jgc *JSONHistoryCommand) Execute(log plugin.Logger, com plugin.PluginCommunicator, conf *model.TaskConfig, stop chan bool) error { err := plugin.ExpandValues(jgc, conf.Expansions) if err != nil { return err } if jgc.File == "" { return fmt.Errorf("'file' param must not be blank") } if jgc.DataName == "" { return fmt.Errorf("'name' param must not be blank") } if jgc.TaskName == "" { return fmt.Errorf("'task' param must not be blank") } if jgc.File != "" && !filepath.IsAbs(jgc.File) { jgc.File = filepath.Join(conf.WorkDir, jgc.File) } endpoint := fmt.Sprintf("history/%s/%s", jgc.TaskName, jgc.DataName) if jgc.Tags { endpoint = fmt.Sprintf("tags/%s/%s", jgc.TaskName, jgc.DataName) } retriableGet := util.RetriableFunc( func() error { resp, err := com.TaskGetJSON(endpoint) if resp != nil { defer resp.Body.Close() } if err != nil { //Some generic error trying to connect - try again log.LogExecution(slogger.WARN, "Error connecting to API server: %v", err) return util.RetriableError{err} } if resp.StatusCode == http.StatusOK { jsonBytes, err := ioutil.ReadAll(resp.Body) if err != nil { return err } return ioutil.WriteFile(jgc.File, jsonBytes, 0755) } if resp.StatusCode != http.StatusOK { if resp.StatusCode == http.StatusNotFound { return fmt.Errorf("No JSON data found") } return util.RetriableError{fmt.Errorf("unexpected status code %v", resp.StatusCode)} } return nil }, ) _, err = util.Retry(retriableGet, 10, 3*time.Second) return err }
// SendJSONLogs is responsible for sending the specified logs // to the API Server. If successful, it returns a log ID that can be used // to refer to the log object in test results. func SendJSONLogs(taskConfig *model.TaskConfig, pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, logs *model.TestLog) (string, error) { pluginLogger.LogExecution(slogger.INFO, "Attaching test logs for %v", logs.Name) logId, err := pluginCom.TaskPostTestLog(logs) if err != nil { return "", err } pluginLogger.LogTask(slogger.INFO, "Attach test logs succeeded") return logId, nil }
func (self *AttachXUnitResultsCommand) parseAndUploadResults( taskConfig *model.TaskConfig, pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator) error { tests := []model.TestResult{} logs := []*model.TestLog{} logIdxToTestIdx := []int{} reportFilePaths, err := getFilePaths(taskConfig.WorkDir, self.File) if err != nil { return err } for _, reportFileLoc := range reportFilePaths { file, err := os.Open(reportFileLoc) if err != nil { return fmt.Errorf("couldn't open xunit file: '%v'", err) } testSuites, err := xunit.ParseXMLResults(file) if err != nil { return fmt.Errorf("error parsing xunit file: '%v'", err) } err = file.Close() if err != nil { return fmt.Errorf("error closing xunit file: '%v'", err) } // go through all the tests for _, suite := range testSuites { for _, tc := range suite.TestCases { // logs are only created when a test case does not succeed test, log := tc.ToModelTestResultAndLog(taskConfig.Task) if log != nil { logs = append(logs, log) logIdxToTestIdx = append(logIdxToTestIdx, len(tests)) } tests = append(tests, test) } } } for i, log := range logs { logId, err := SendJSONLogs(taskConfig, pluginLogger, pluginCom, log) if err != nil { pluginLogger.LogTask(slogger.WARN, "Error uploading logs for %v", log.Name) continue } tests[logIdxToTestIdx[i]].LogId = logId tests[logIdxToTestIdx[i]].LineNum = 1 } return SendJSONResults(taskConfig, pluginLogger, pluginCom, &model.TestResults{tests}) }
// SendJSONResults is responsible for sending the // specified file to the API Server func SendJSONResults(taskConfig *model.TaskConfig, pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, results *model.TestResults) error { pluginLogger.LogExecution(slogger.INFO, "Attaching test results") err := pluginCom.TaskPostResults(results) if err != nil { return err } pluginLogger.LogTask(slogger.INFO, "Attach test results succeeded") return nil }
// Execute pulls the task's patch and then applies it func (gapc *GitApplyPatchCommand) Execute(pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, conf *model.TaskConfig, stop chan bool) error { //Apply patches only if necessary if conf.Task.Requester == evergreen.PatchVersionRequester { pluginLogger.LogExecution(slogger.INFO, "Fetching patch.") patch, err := gapc.GetPatch(conf, pluginCom, pluginLogger) if err != nil { pluginLogger.LogExecution(slogger.ERROR, "Failed to get patch: %v", err) return fmt.Errorf("Failed to get patch: %v", err) } err = gapc.getPatchContents(conf, pluginCom, pluginLogger, patch) if err != nil { pluginLogger.LogExecution(slogger.ERROR, "Failed to get patch contents: %v", err) return fmt.Errorf("Failed to get patch contents: %v", err) } err = gapc.applyPatch(conf, patch, pluginLogger) if err != nil { pluginLogger.LogExecution(slogger.INFO, "Failed to apply patch: %v", err) return fmt.Errorf("Failed to apply patch: %v", err) } } return nil }
// Execute carries out the AttachResultsCommand command - this is required // to satisfy the 'Command' interface func (self *AttachTaskFilesCommand) Execute(pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, taskConfig *model.TaskConfig, stop chan bool) error { if err := self.expandAttachTaskFilesCommand(taskConfig); err != nil { msg := fmt.Sprintf("error expanding params: %v", err) pluginLogger.LogTask(slogger.ERROR, "Error updating task files: %v", msg) return fmt.Errorf(msg) } pluginLogger.LogTask(slogger.INFO, "Sending task file links to server") return self.SendTaskFiles(taskConfig, pluginLogger, pluginCom) }
// S3Copy is responsible for carrying out the core of the S3CopyPlugin's // function - it makes an API calls to copy a given staged file to it's final // production destination func (scc *S3CopyCommand) S3Copy(taskConfig *model.TaskConfig, pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator) error { for _, s3CopyFile := range scc.S3CopyFiles { if len(s3CopyFile.BuildVariants) > 0 && !util.SliceContains( s3CopyFile.BuildVariants, taskConfig.BuildVariant.Name) { continue } pluginLogger.LogExecution(slogger.INFO, "Making API push copy call to "+ "transfer %v/%v => %v/%v", s3CopyFile.Source.Bucket, s3CopyFile.Source.Path, s3CopyFile.Destination.Bucket, s3CopyFile.Destination.Path) s3CopyReq := S3CopyRequest{ AwsKey: scc.AwsKey, AwsSecret: scc.AwsSecret, S3SourceBucket: s3CopyFile.Source.Bucket, S3SourcePath: s3CopyFile.Source.Path, S3DestinationBucket: s3CopyFile.Destination.Bucket, S3DestinationPath: s3CopyFile.Destination.Path, S3DisplayName: s3CopyFile.DisplayName, } resp, err := pluginCom.TaskPostJSON(s3CopyAPIEndpoint, s3CopyReq) if resp != nil { defer resp.Body.Close() } if resp != nil && resp.StatusCode != http.StatusOK { body, _ := ioutil.ReadAll(resp.Body) return fmt.Errorf("S3 push copy failed (%v): %v", resp.StatusCode, string(body)) } if err != nil { body, _ := ioutil.ReadAll(resp.Body) return fmt.Errorf("S3 push copy failed (%v): %v", resp.StatusCode, string(body)) } pluginLogger.LogExecution(slogger.INFO, "API push copy call succeeded") err = scc.AttachTaskFiles(pluginLogger, pluginCom, s3CopyReq) if err != nil { body, readAllErr := ioutil.ReadAll(resp.Body) if readAllErr != nil { return fmt.Errorf("Error: %v", err) } return fmt.Errorf("Error: %v, (%v): %v", resp.StatusCode, err, string(body)) } } return nil }
// Execute builds the archive. func (self *TarGzPackCommand) Execute(pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, conf *model.TaskConfig, stop chan bool) error { if err := plugin.ExpandValues(self, conf.Expansions); err != nil { return fmt.Errorf("error expanding params: %v", err) } // if the source dir is a relative path, join it to the working dir if !filepath.IsAbs(self.SourceDir) { self.SourceDir = filepath.Join(conf.WorkDir, self.SourceDir) } // if the target is a relative path, join it to the working dir if !filepath.IsAbs(self.Target) { self.Target = filepath.Join(conf.WorkDir, self.Target) } errChan := make(chan error) filesArchived := -1 go func() { var err error filesArchived, err = self.BuildArchive(conf.WorkDir, pluginLogger) errChan <- err }() select { case err := <-errChan: if err != nil { return err } if filesArchived == 0 { deleteErr := os.Remove(self.Target) if deleteErr != nil { pluginLogger.LogExecution(slogger.INFO, "Error deleting empty archive: %v", deleteErr) } } return nil case <-stop: pluginLogger.LogExecution(slogger.INFO, "Received signal to terminate"+ " execution of targz pack command") return nil } }
// cleanup() has a windows-specific implementation which finds the job object associated with the // given task key, and if it exists, terminates it. This will guarantee that any shell processes // started throughout the task run are destroyed, as long as they were captured in trackProcess. func cleanup(key string, log plugin.Logger) error { jobsMutex.Lock() defer jobsMutex.Unlock() job, hasKey := jobsMapping[key] if !hasKey { return nil } err := job.Terminate(0) if err != nil { log.LogSystem(slogger.ERROR, "terminating job object failed: %v", err) return err } delete(jobsMapping, key) defer job.Close() return nil }
// Implementation of Execute. Expands the parameters, and then fetches the // resource from s3. func (self *S3GetCommand) Execute(pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, conf *model.TaskConfig, stop chan bool) error { // expand necessary params if err := self.expandParams(conf); err != nil { return err } // validate the params if err := self.validateParams(); err != nil { return fmt.Errorf("expanded params are not valid: %v", err) } if !self.shouldRunForVariant(conf.BuildVariant.Name) { pluginLogger.LogTask(slogger.INFO, "Skipping S3 get of remote file %v for variant %v", self.RemoteFile, conf.BuildVariant.Name) return nil } // if the local file or extract_to is a relative path, join it to the // working dir if self.LocalFile != "" && !filepath.IsAbs(self.LocalFile) { self.LocalFile = filepath.Join(conf.WorkDir, self.LocalFile) } if self.ExtractTo != "" && !filepath.IsAbs(self.ExtractTo) { self.ExtractTo = filepath.Join(conf.WorkDir, self.ExtractTo) } errChan := make(chan error) go func() { errChan <- self.GetWithRetry(pluginLogger) }() select { case err := <-errChan: return err case <-stop: pluginLogger.LogExecution(slogger.INFO, "Received signal to terminate"+ " execution of S3 Get Command") return nil } }
// Execute updates the expansions. Fulfills Command interface. func (self *UpdateCommand) Execute(pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, conf *model.TaskConfig, stop chan bool) error { err := self.ExecuteUpdates(conf) if err != nil { return err } if self.YamlFile != "" { pluginLogger.LogTask(slogger.INFO, "Updating expansions with keys from file: %v", self.YamlFile) filename := filepath.Join(conf.WorkDir, self.YamlFile) err := conf.Expansions.UpdateFromYaml(filename) if err != nil { return err } } return nil }
// Implementation of Execute. func (mfc *ManifestLoadCommand) Execute(pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, conf *model.TaskConfig, stop chan bool) error { errChan := make(chan error) go func() { errChan <- mfc.Load(pluginLogger, pluginCom, conf) }() select { case err := <-errChan: return err case <-stop: pluginLogger.LogExecution(slogger.INFO, "Received signal to terminate"+ " execution of manifest load command") return nil } }
// Implementation of Execute, to unpack the archive. func (self *TarGzUnpackCommand) Execute(pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, conf *model.TaskConfig, stop chan bool) error { errChan := make(chan error) go func() { errChan <- self.UnpackArchive() }() select { case err := <-errChan: return err case <-stop: pluginLogger.LogExecution(slogger.INFO, "Received signal to terminate"+ " execution of targz unpack command") return nil } }
// Execute starts the shell with its given parameters. func (cc *CleanupCommand) Execute(pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, conf *model.TaskConfig, stop chan bool) error { defer func() { trackedTask = "" }() if trackedTask == "" && trackedTask != conf.Task.Id { pluginLogger.LogExecution(slogger.WARN, "Process tracking was not enabled for task, skipping cleanup.") return nil } pluginLogger.LogExecution(slogger.INFO, "Running process cleanup...") // Clean up all shell processes spawned during the execution of this task by this agent, // by calling the platform-specific "cleanup" function cleanup(conf.Task.Id, pluginLogger) return nil }
// Wrapper around the Put() function to retry it func (s3pc *S3PutCommand) PutWithRetry(log plugin.Logger, com plugin.PluginCommunicator) error { retriablePut := util.RetriableFunc( func() error { err := s3pc.Put() if err != nil { if err == errSkippedFile { return err } log.LogExecution(slogger.ERROR, "Error putting to s3 bucket: %v", err) return util.RetriableError{err} } return nil }, ) retryFail, err := util.RetryArithmeticBackoff(retriablePut, maxS3PutAttempts, s3PutSleep) if err == errSkippedFile { log.LogExecution(slogger.INFO, "S3 put skipped optional missing file.") return nil } if retryFail { log.LogExecution(slogger.ERROR, "S3 put failed with error: %v", err) return err } return s3pc.AttachTaskFiles(log, com) }
// Execute carries out the AttachResultsCommand command - this is required // to satisfy the 'Command' interface func (self *AttachResultsCommand) Execute(pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, taskConfig *model.TaskConfig, stop chan bool) error { if err := self.expandAttachResultsParams(taskConfig); err != nil { return err } errChan := make(chan error) go func() { // attempt to open the file reportFileLoc := filepath.Join(taskConfig.WorkDir, self.FileLoc) reportFile, err := os.Open(reportFileLoc) if err != nil { errChan <- fmt.Errorf("Couldn't open report file: '%v'", err) return } results := &task.TestResults{} if err = util.ReadJSONInto(reportFile, results); err != nil { errChan <- fmt.Errorf("Couldn't read report file: '%v'", err) return } if err := reportFile.Close(); err != nil { pluginLogger.LogExecution(slogger.INFO, "Error closing file: %v", err) } errChan <- SendJSONResults(taskConfig, pluginLogger, pluginCom, results) }() select { case err := <-errChan: return err case <-stop: pluginLogger.LogExecution(slogger.INFO, "Received signal to terminate"+ " execution of attach results command") return nil } }
// Implementation of Execute, to unpack the archive. func (self *TarGzUnpackCommand) Execute(pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, conf *model.TaskConfig, stop chan bool) error { if err := plugin.ExpandValues(self, conf.Expansions); err != nil { return fmt.Errorf("error expanding params: %v", err) } errChan := make(chan error) go func() { errChan <- self.UnpackArchive() }() select { case err := <-errChan: return err case <-stop: pluginLogger.LogExecution(slogger.INFO, "Received signal to terminate"+ " execution of targz unpack command") return nil } }
// Wrapper around the Put() function to retry it func (self *S3PutCommand) PutWithRetry(pluginLogger plugin.Logger, pluginComm plugin.PluginCommunicator) error { retriablePut := util.RetriableFunc( func() error { err := self.Put() if err != nil { pluginLogger.LogExecution(slogger.ERROR, "Error putting to s3"+ " bucket: %v", err) return util.RetriableError{err} } return nil }, ) retryFail, err := util.RetryArithmeticBackoff(retriablePut, maxS3PutAttempts, s3PutSleep) if retryFail { pluginLogger.LogExecution(slogger.ERROR, "S3 put failed with error: %v", err) return err } return self.AttachTaskFiles(pluginLogger, pluginComm) }
// Execute carries out the AttachResultsCommand command - this is required // to satisfy the 'Command' interface func (self *AttachXUnitResultsCommand) Execute(pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, taskConfig *model.TaskConfig, stop chan bool) error { if err := self.expandParams(taskConfig); err != nil { return err } errChan := make(chan error) go func() { errChan <- self.parseAndUploadResults(taskConfig, pluginLogger, pluginCom) }() select { case err := <-errChan: return err case <-stop: pluginLogger.LogExecution(slogger.INFO, "Received signal to terminate"+ " execution of attach xunit results command") return nil } }
// AttachTaskFiles is responsible for sending the // specified file to the API Server func (s3pc *S3PutCommand) AttachTaskFiles(log plugin.Logger, com plugin.PluginCommunicator) error { remoteFile := filepath.ToSlash(s3pc.RemoteFile) fileLink := s3baseURL + s3pc.Bucket + "/" + remoteFile displayName := s3pc.DisplayName if displayName == "" { displayName = filepath.Base(s3pc.LocalFile) } file := &artifact.File{ Name: displayName, Link: fileLink, Visibility: s3pc.Visibility, } err := com.PostTaskFiles([]*artifact.File{file}) if err != nil { return fmt.Errorf("Attach files failed: %v", err) } log.LogExecution(slogger.INFO, "API attach files call succeeded") return nil }
func (jsc *JSONSendCommand) Execute(log plugin.Logger, com plugin.PluginCommunicator, conf *model.TaskConfig, stop chan bool) error { if jsc.File == "" { return fmt.Errorf("'file' param must not be blank") } if jsc.DataName == "" { return fmt.Errorf("'name' param must not be blank") } errChan := make(chan error) go func() { // attempt to open the file fileLoc := filepath.Join(conf.WorkDir, jsc.File) jsonFile, err := os.Open(fileLoc) if err != nil { errChan <- fmt.Errorf("Couldn't open json file: '%v'", err) return } jsonData := map[string]interface{}{} err = util.ReadJSONInto(jsonFile, &jsonData) if err != nil { errChan <- fmt.Errorf("File contained invalid json: %v", err) return } retriablePost := util.RetriableFunc( func() error { log.LogTask(slogger.INFO, "Posting JSON") resp, err := com.TaskPostJSON(fmt.Sprintf("data/%v", jsc.DataName), jsonData) if resp != nil { defer resp.Body.Close() } if err != nil { return util.RetriableError{err} } if resp.StatusCode != http.StatusOK { return util.RetriableError{fmt.Errorf("unexpected status code %v", resp.StatusCode)} } return nil }, ) _, err = util.Retry(retriablePost, 10, 3*time.Second) errChan <- err }() select { case err := <-errChan: if err != nil { log.LogTask(slogger.ERROR, "Sending json data failed: %v", err) } return err case <-stop: log.LogExecution(slogger.INFO, "Received abort signal, stopping.") return nil } }
// Implementation of Execute. Expands the parameters, and then puts the // resource to s3. func (s3pc *S3PutCommand) Execute(log plugin.Logger, com plugin.PluginCommunicator, conf *model.TaskConfig, stop chan bool) error { // expand necessary params if err := s3pc.expandParams(conf); err != nil { return err } // validate the params if err := s3pc.validateParams(); err != nil { return fmt.Errorf("expanded params are not valid: %v", err) } if !s3pc.shouldRunForVariant(conf.BuildVariant.Name) { log.LogTask(slogger.INFO, "Skipping S3 put of local file %v for variant %v", s3pc.LocalFile, conf.BuildVariant.Name) return nil } if s3pc.isMulti() { log.LogTask(slogger.INFO, "Putting files matching filter %v into path %v in s3 bucket %v", s3pc.LocalFilesIncludeFilter, s3pc.RemoteFile, s3pc.Bucket) } else { if !filepath.IsAbs(s3pc.LocalFile) { s3pc.LocalFile = filepath.Join(conf.WorkDir, s3pc.LocalFile) } log.LogTask(slogger.INFO, "Putting %v into path %v in s3 bucket %v", s3pc.LocalFile, s3pc.RemoteFile, s3pc.Bucket) } errChan := make(chan error) go func() { errChan <- s3pc.PutWithRetry(log, com) }() select { case err := <-errChan: return err case <-stop: log.LogExecution(slogger.INFO, "Received signal to terminate execution of S3 Put Command") return nil } }
func cleanup(key string, log plugin.Logger) error { pids, err := listProc() if err != nil { return err } pidMarker := fmt.Sprintf("EVR_AGENT_PID=%v", os.Getpid()) taskMarker := fmt.Sprintf("EVR_TASK_ID=%v", key) for _, pid := range pids { env, err := getEnv(pid) if err != nil { continue } if envHasMarkers(env, pidMarker, taskMarker) { p := os.Process{} p.Pid = pid if err := p.Kill(); err != nil { log.LogSystem(slogger.INFO, "Cleanup killing %v failed: %v", pid, err) } else { log.LogTask(slogger.INFO, "Cleanup killed process %v", pid) } } } return nil }
// Load performs a GET on /manifest/load func (mfc *ManifestLoadCommand) Load(log plugin.Logger, pluginCom plugin.PluginCommunicator, conf *model.TaskConfig) error { var loadedManifest *manifest.Manifest var err error retriableGet := util.RetriableFunc( func() error { resp, err := pluginCom.TaskGetJSON(ManifestLoadAPIEndpoint) if resp != nil { defer resp.Body.Close() } if err != nil { //Some generic error trying to connect - try again log.LogExecution(slogger.WARN, "Error connecting to API server: %v", err) return util.RetriableError{err} } if resp != nil && resp.StatusCode != http.StatusOK { log.LogExecution(slogger.WARN, "Unexpected status code %v, retrying", resp.StatusCode) return util.RetriableError{fmt.Errorf("Unexpected status code %v", resp.StatusCode)} } err = util.ReadJSONInto(resp.Body, &loadedManifest) if err != nil { return err } return nil }) _, err = util.RetryArithmeticBackoff(retriableGet, 5, 5*time.Second) if err != nil { return err } if loadedManifest == nil { return fmt.Errorf("Manifest is empty") } mfc.updateExpansions(loadedManifest, conf) return nil }
// SendJSONResults is responsible for sending the // specified file to the API Server func SendJSONResults(taskConfig *model.TaskConfig, pluginLogger plugin.Logger, pluginCom plugin.PluginCommunicator, results *task.TestResults) error { for i, res := range results.Results { if res.LogRaw != "" { pluginLogger.LogExecution(slogger.INFO, "Attaching raw test logs") testLogs := &model.TestLog{ Name: res.TestFile, Task: taskConfig.Task.Id, TaskExecution: taskConfig.Task.Execution, Lines: []string{res.LogRaw}, } id, err := pluginCom.TaskPostTestLog(testLogs) if err != nil { pluginLogger.LogExecution(slogger.ERROR, "Error posting raw logs from results: %v", err) } else { results.Results[i].LogId = id } // clear the logs from the TestResult struct after it has been saved in the test logs. Since they are // being saved in the test_logs collection, we can clear them to prevent them from being saved in the task // collection. results.Results[i].LogRaw = "" } } pluginLogger.LogExecution(slogger.INFO, "Attaching test results") err := pluginCom.TaskPostResults(results) if err != nil { return err } pluginLogger.LogTask(slogger.INFO, "Attach test results succeeded") return nil }