Exemple #1
0
// IncKeyHandler increments the value stored in the given key, and returns it
func IncKeyHandler(w http.ResponseWriter, r *http.Request) {
	key := ""
	err := util.ReadJSONInto(r.Body, &key)
	if err != nil {
		evergreen.Logger.Logf(slogger.ERROR, "Error geting key: %v", err)
		plugin.WriteJSON(w, http.StatusInternalServerError, err.Error())
		return
	}

	change := mgo.Change{
		Update: bson.M{
			"$inc": bson.M{"value": 1},
		},
		ReturnNew: true,
		Upsert:    true,
	}

	keyVal := &KeyVal{}
	_, err = db.FindAndModify(KeyValCollection, bson.M{"_id": key}, nil, change, keyVal)
	if err != nil {
		evergreen.Logger.Logf(slogger.ERROR, "error doing findAndModify: %v", err)
		plugin.WriteJSON(w, http.StatusInternalServerError, err.Error())
		return
	}

	plugin.WriteJSON(w, http.StatusOK, keyVal)
}
Exemple #2
0
// Execute fetches the expansions from the API server
func (incCmd *IncCommand) Execute(pluginLogger plugin.Logger,
	pluginCom plugin.PluginCommunicator, conf *model.TaskConfig,
	stop chan bool) error {

	err := plugin.ExpandValues(incCmd, conf.Expansions)
	if err != nil {
		return err
	}

	keyVal := &KeyVal{}
	resp, err := pluginCom.TaskPostJSON(IncRoute, incCmd.Key)
	if err != nil {
		return err
	}
	if resp == nil {
		return fmt.Errorf("received nil response from inc API call")
	} else {
		defer resp.Body.Close()
	}
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("unexpected status code: %v", resp.StatusCode)
	}

	err = util.ReadJSONInto(resp.Body, keyVal)
	if err != nil {
		return fmt.Errorf("Failed to read JSON reply: %v", err)
	}

	conf.Expansions.Put(incCmd.Destination, fmt.Sprintf("%d", keyVal.Value))
	return nil
}
Exemple #3
0
func (mc *MockCommand) Execute(logger plugin.Logger,
	pluginCom plugin.PluginCommunicator, conf *model.TaskConfig, stop chan bool) error {
	resp, err := pluginCom.TaskGetJSON(fmt.Sprintf("blah/%s/%d", mc.Param1, mc.Param2))
	if resp != nil {
		defer resp.Body.Close()
	}

	if resp == nil {
		return fmt.Errorf("Received nil HTTP response from api server")
	}

	jsonReply := map[string]string{}
	err = util.ReadJSONInto(resp.Body, &jsonReply)
	if err != nil {
		return err
	}

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("Got bad status code from API response: %v, body: %v", resp.StatusCode, jsonReply)
	}

	expectedEchoReply := fmt.Sprintf("%v/%v/%v", mc.Param1, mc.Param2, conf.Task.Id)
	if jsonReply["echo"] != expectedEchoReply {
		return fmt.Errorf("Wrong echo reply! Wanted %v, got %v", expectedEchoReply, jsonReply["echo"])
	}
	return nil
}
Exemple #4
0
// getTasksForLatestVersion sends back the TaskJSON data associated with the latest version.
func getTasksForLatestVersion(w http.ResponseWriter, r *http.Request) {

	name := mux.Vars(r)["name"]
	var jsonTask TaskJSON

	projects := []string{}
	err := util.ReadJSONInto(r.Body, &projects)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	versionData := []VersionData{}
	for _, project := range projects {
		err := db.FindOneQ(collection, db.Query(bson.M{NameKey: name,
			ProjectIdKey: project}).Sort([]string{"-" + RevisionOrderNumberKey}).WithFields(VersionIdKey), &jsonTask)
		if err != nil {
			if err != mgo.ErrNotFound {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			http.Error(w, "{}", http.StatusNotFound)
			return
		}
		if jsonTask.VersionId == "" {
			http.Error(w, "{}", http.StatusNotFound)
		}
		jsonTasks, err := findTasksForVersion(jsonTask.VersionId, name)
		if jsonTasks == nil {
			http.Error(w, "{}", http.StatusNotFound)
			return
		}
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		// get the version commit info
		v, err := version.FindOne(version.ById(jsonTask.VersionId))
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		if v == nil {
			http.Error(w, "{}", http.StatusNotFound)
			return
		}

		commitInfo := CommitInfo{
			Author:     v.Author,
			Message:    v.Message,
			CreateTime: v.CreateTime,
			Revision:   v.Revision,
			VersionId:  jsonTask.VersionId,
		}

		versionData = append(versionData, VersionData{jsonTasks, commitInfo})
	}
	plugin.WriteJSON(w, http.StatusOK, versionData)
}
Exemple #5
0
// AttachFiles updates file mappings for a task or build
func (as *APIServer) AttachFiles(w http.ResponseWriter, r *http.Request) {
	task := MustHaveTask(r)
	evergreen.Logger.Logf(slogger.INFO, "Attaching files to task %v", task.Id)

	entry := &artifact.Entry{
		TaskId:          task.Id,
		TaskDisplayName: task.DisplayName,
		BuildId:         task.BuildId,
	}

	err := util.ReadJSONInto(r.Body, &entry.Files)
	if err != nil {
		message := fmt.Sprintf("Error reading file definitions for task  %v: %v", task.Id, err)
		evergreen.Logger.Errorf(slogger.ERROR, message)
		as.WriteJSON(w, http.StatusBadRequest, message)
		return
	}
	fmt.Printf("file entry is %#v\n", entry)

	if err := entry.Upsert(); err != nil {
		message := fmt.Sprintf("Error updating artifact file info for task %v: %v", task.Id, err)
		evergreen.Logger.Errorf(slogger.ERROR, message)
		as.WriteJSON(w, http.StatusInternalServerError, message)
		return
	}
	as.WriteJSON(w, http.StatusOK, fmt.Sprintf("Artifact files for task %v successfully attached", task.Id))
}
Exemple #6
0
// insertTask creates a TaskJSON document with the data sent in the request body.
func insertTask(w http.ResponseWriter, r *http.Request) {
	t := plugin.GetTask(r)
	if t == nil {
		http.Error(w, "task not found", http.StatusNotFound)
		return
	}
	name := mux.Vars(r)["name"]
	rawData := map[string]interface{}{}
	err := util.ReadJSONInto(r.Body, &rawData)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	jsonBlob := TaskJSON{
		TaskId:              t.Id,
		TaskName:            t.DisplayName,
		Name:                name,
		BuildId:             t.BuildId,
		Variant:             t.BuildVariant,
		ProjectId:           t.Project,
		VersionId:           t.Version,
		CreateTime:          t.CreateTime,
		Revision:            t.Revision,
		RevisionOrderNumber: t.RevisionOrderNumber,
		Data:                rawData,
		IsPatch:             t.Requester == evergreen.PatchVersionRequester,
	}
	_, err = db.Upsert(collection, bson.M{TaskIdKey: t.Id, NameKey: name}, jsonBlob)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	plugin.WriteJSON(w, http.StatusOK, "ok")
	return
}
Exemple #7
0
func (as *APIServer) getUserSession(w http.ResponseWriter, r *http.Request) {
	userCredentials := struct {
		Username string `json:"username"`
		Password string `json:"password"`
	}{}

	if err := util.ReadJSONInto(r.Body, &userCredentials); err != nil {
		as.LoggedError(w, r, http.StatusBadRequest, fmt.Errorf("Error reading user credentials: %v", err))
		return
	}
	userToken, err := as.UserManager.CreateUserToken(userCredentials.Username, userCredentials.Password)
	if err != nil {
		as.WriteJSON(w, http.StatusUnauthorized, err.Error())
		return
	}

	dataOut := struct {
		User struct {
			Name string `json:"name"`
		} `json:"user"`
		Token string `json:"token"`
	}{}
	dataOut.User.Name = userCredentials.Username
	dataOut.Token = userToken
	as.WriteJSON(w, http.StatusOK, dataOut)

}
//XXX remove this once the transition is complete...
//AttachResultsHandler is an API hook for receiving and updating test results
func AttachResultsHandler(w http.ResponseWriter, r *http.Request) {
	task := plugin.GetTask(r)
	if task == nil {
		message := "Cannot find task for attach results request"
		evergreen.Logger.Errorf(slogger.ERROR, message)
		http.Error(w, message, http.StatusBadRequest)
		return
	}
	results := &model.TestResults{}
	err := util.ReadJSONInto(r.Body, results)
	if err != nil {
		message := fmt.Sprintf("error reading test results: %v", err)
		evergreen.Logger.Errorf(slogger.ERROR, message)
		http.Error(w, message, http.StatusBadRequest)
		return
	}
	// set test result of task
	if err := task.SetResults(results.Results); err != nil {
		message := fmt.Sprintf("Error calling set results on task %v: %v", task.Id, err)
		evergreen.Logger.Errorf(slogger.ERROR, message)
		http.Error(w, message, http.StatusInternalServerError)
		return
	}
	plugin.WriteJSON(w, http.StatusOK, "Test results successfully attached")
}
Exemple #9
0
// GetProjectConfig loads the communicator's task's project from the API server.
func (h *HTTPCommunicator) GetProjectRef() (*model.ProjectRef, error) {
	projectRef := &model.ProjectRef{}
	retriableGet := util.RetriableFunc(
		func() error {
			resp, err := h.tryGet("project_ref")
			if resp != nil {
				defer resp.Body.Close()
			}
			if resp != nil && resp.StatusCode == http.StatusConflict {
				// Something very wrong, fail now with no retry.
				return fmt.Errorf("conflict - wrong secret!")
			}
			if err != nil {
				// Some generic error trying to connect - try again
				return util.RetriableError{err}
			}
			if resp == nil {
				return util.RetriableError{fmt.Errorf("empty response")}
			} else {
				err = util.ReadJSONInto(resp.Body, projectRef)
				if err != nil {
					return util.RetriableError{err}
				}
				return nil
			}
		},
	)

	retryFail, err := util.Retry(retriableGet, h.MaxAttempts, h.RetrySleep)
	if retryFail {
		return nil, fmt.Errorf("getting project ref failed after %v tries: %v", h.MaxAttempts, err)
	}
	return projectRef, nil
}
// AttachFilesHandler updates file mappings for a task or build
func AttachFilesHandler(w http.ResponseWriter, r *http.Request) {
	task := plugin.GetTask(r)
	evergreen.Logger.Logf(slogger.INFO, "Attaching files to task %v", task.Id)

	fileEntry := &artifact.Entry{}
	fileEntry.TaskId = task.Id
	fileEntry.TaskDisplayName = task.DisplayName
	fileEntry.BuildId = task.BuildId

	err := util.ReadJSONInto(r.Body, &fileEntry.Files)
	if err != nil {
		message := fmt.Sprintf("error reading file definitions: %v", err)
		evergreen.Logger.Errorf(slogger.ERROR, message)
		http.Error(w, message, http.StatusBadRequest)
		return
	}

	if err := fileEntry.Upsert(); err != nil {
		message := fmt.Sprintf("Error updating artifact file info: %v", err)
		evergreen.Logger.Errorf(slogger.ERROR, message)
		http.Error(w, message, http.StatusInternalServerError)
		return
	}

	plugin.WriteJSON(w, http.StatusOK, fmt.Sprintf("Artifact files for task %v successfully attached", task.Id))
}
Exemple #11
0
// Heartbeat sends a heartbeat to the API server. The server can respond with
// and "abort" response. This function returns true if the agent should abort.
func (h *HTTPCommunicator) Heartbeat() (bool, error) {
	h.Logger.Logf(slogger.INFO, "Sending heartbeat.")
	resp, err := h.tryPostJSON("heartbeat", "heartbeat")
	if resp != nil {
		defer resp.Body.Close()
	}
	if err != nil {
		h.Logger.Logf(slogger.ERROR, "Error sending heartbeat: %v", err)
		return false, err
	}
	if resp != nil && resp.StatusCode != http.StatusOK {
		return false, fmt.Errorf("unexpected status code doing heartbeat: %v",
			resp.StatusCode)
	}
	if resp != nil && resp.StatusCode == http.StatusConflict {
		h.Logger.Logf(slogger.ERROR, "wrong secret (409) sending heartbeat")
		h.SignalChan <- IncorrectSecret
		return false, fmt.Errorf("unauthorized - wrong secret")
	}

	heartbeatResponse := &apimodels.HeartbeatResponse{}
	if err = util.ReadJSONInto(resp.Body, heartbeatResponse); err != nil {
		h.Logger.Logf(slogger.ERROR, "Error unmarshaling heartbeat "+
			"response: %v", err)
		return false, err
	}
	return heartbeatResponse.Abort, nil
}
Exemple #12
0
// PutPatch submits a new patch for the given project to the API server. If successful, returns
// the patch object itself.
func (ac *APIClient) PutPatch(incomingPatch patchSubmission) (*patch.Patch, error) {
	authToken, err := generateTokenParam(ac.User, ac.APIKey)
	if err != nil {
		return nil, err
	}
	data := url.Values{}
	data.Set("id_token", authToken)
	data.Set("desc", incomingPatch.description)
	data.Set("project", incomingPatch.projectId)
	data.Set("patch", incomingPatch.patchData)
	data.Set("githash", incomingPatch.base)
	if incomingPatch.finalize {
		data.Set("buildvariants", incomingPatch.variants)
		data.Set("finalize", "true")
	} else {
		data.Set("buildvariants", "all")
	}
	resp, err := ac.put("patches/", bytes.NewBufferString(data.Encode()), true)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode != http.StatusCreated {
		return nil, NewAPIError(resp)
	}

	reply := struct {
		Patch *patch.Patch `json:"patch"`
	}{}

	if err := util.ReadJSONInto(resp.Body, &reply); err != nil {
		return nil, err
	}
	return reply.Patch, nil
}
Exemple #13
0
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
	}
}
Exemple #14
0
func (uis *UIServer) modifyHosts(w http.ResponseWriter, r *http.Request) {
	_ = MustHaveUser(r)

	opts := &uiParams{}
	err := util.ReadJSONInto(r.Body, opts)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	hostIds := opts.HostIds
	if len(hostIds) == 1 && strings.TrimSpace(hostIds[0]) == "" {
		http.Error(w, "No host ID's found in request", http.StatusBadRequest)
		return
	}

	// fetch all relevant hosts
	hosts, err := host.Find(host.ByIds(hostIds))

	if err != nil {
		uis.LoggedError(w, r, http.StatusInternalServerError, fmt.Errorf("Error finding hosts: %v", err))
		return
	}
	if len(hosts) == 0 {
		http.Error(w, "No matching hosts found.", http.StatusBadRequest)
		return
	}

	// determine what action needs to be taken
	switch opts.Action {
	case "updateStatus":
		newStatus := opts.Status
		if !util.SliceContains(validUpdateToStatuses, newStatus) {
			http.Error(w, fmt.Sprintf("Invalid status: %v", opts.Status), http.StatusBadRequest)
			return
		}
		numHostsUpdated := 0

		for _, host := range hosts {
			err := host.SetStatus(newStatus)
			if err != nil {
				uis.LoggedError(w, r, http.StatusInternalServerError, fmt.Errorf("Error updating host %v", err))
				return
			}
			numHostsUpdated += 1
		}
		msg := NewSuccessFlash(fmt.Sprintf("%v host(s) status successfully updated to '%v'",
			numHostsUpdated, newStatus))
		PushFlash(uis.CookieStore, r, w, msg)
		return
	default:
		http.Error(w, fmt.Sprintf("Unrecognized action: %v", opts.Action), http.StatusBadRequest)
		return
	}
}
Exemple #15
0
func (as *APIServer) StartTask(w http.ResponseWriter, r *http.Request) {
	task := MustHaveTask(r)

	if !getGlobalLock(r.RemoteAddr, task.Id) {
		as.LoggedError(w, r, http.StatusInternalServerError, ErrLockTimeout)
		return
	}
	defer releaseGlobalLock(r.RemoteAddr, task.Id)

	evergreen.Logger.Logf(slogger.INFO, "Marking task started: %v", task.Id)

	taskStartInfo := &apimodels.TaskStartRequest{}
	if err := util.ReadJSONInto(r.Body, taskStartInfo); err != nil {
		http.Error(w, fmt.Sprintf("Error reading task start request for %v: %v", task.Id, err), http.StatusBadRequest)
		return
	}

	if err := task.MarkStart(); err != nil {
		message := fmt.Errorf("Error marking task '%v' started: %v", task.Id, err)
		as.LoggedError(w, r, http.StatusInternalServerError, message)
		return
	}

	h, err := host.FindOne(host.ByRunningTaskId(task.Id))
	if err != nil {
		message := fmt.Errorf("Error finding host running task %v: %v", task.Id, err)
		as.LoggedError(w, r, http.StatusInternalServerError, message)
		return
	}

	// Fall back to checking host field on task doc
	if h == nil && len(task.HostId) > 0 {
		evergreen.Logger.Logf(slogger.DEBUG, "Falling back to host field of task: %v", task.Id)
		h, err = host.FindOne(host.ById(task.HostId))
		if err != nil {
			as.LoggedError(w, r, http.StatusInternalServerError, err)
			return
		}
		h.SetRunningTask(task.Id, h.AgentRevision, h.TaskDispatchTime)
	}

	if h == nil {
		message := fmt.Errorf("No host found running task %v", task.Id)
		as.LoggedError(w, r, http.StatusInternalServerError, message)
		return
	}

	if err := h.SetTaskPid(taskStartInfo.Pid); err != nil {
		message := fmt.Errorf("Error calling set pid on task %v : %v", task.Id, err)
		as.LoggedError(w, r, http.StatusInternalServerError, message)
		return
	}
	as.WriteJSON(w, http.StatusOK, fmt.Sprintf("Task %v started on host %v", task.Id, h.Id))
}
Exemple #16
0
func (as *APIServer) requestHost(w http.ResponseWriter, r *http.Request) {
	user := MustHaveUser(r)
	hostRequest := struct {
		Distro    string `json:"distro"`
		PublicKey string `json:"public_key"`
		UserData  string `json:"userdata"`
	}{}
	err := util.ReadJSONInto(r.Body, &hostRequest)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	if hostRequest.Distro == "" {
		http.Error(w, "distro may not be blank", http.StatusBadRequest)
		return
	}
	if hostRequest.PublicKey == "" {
		http.Error(w, "public key may not be blank", http.StatusBadRequest)
		return
	}

	opts := spawn.Options{
		Distro:    hostRequest.Distro,
		UserName:  user.Id,
		PublicKey: hostRequest.PublicKey,
		UserData:  hostRequest.UserData,
	}

	spawner := spawn.New(&as.Settings)
	err = spawner.Validate(opts)
	if err != nil {
		errCode := http.StatusBadRequest
		if _, ok := err.(spawn.BadOptionsErr); !ok {
			errCode = http.StatusInternalServerError
		}
		as.LoggedError(w, r, errCode, fmt.Errorf("Spawn request failed validation: %v", err))
		return
	}

	err = spawner.CreateHost(opts, user)
	if err != nil {
		evergreen.Logger.Logf(slogger.ERROR, err.Error())
		mailErr := notify.TrySendNotificationToUser(opts.UserName, "Spawning failed", err.Error(),
			notify.ConstructMailer(as.Settings.Notify))
		if mailErr != nil {
			evergreen.Logger.Logf(slogger.ERROR, "Failed to send notification: %v", mailErr)
		}
		return
	}

	as.WriteJSON(w, http.StatusOK, "")
}
Exemple #17
0
// UserMiddleware checks for session tokens on the request, then looks up and attaches a user
// for that token if one is found.
func UserMiddleware(um auth.UserManager) func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
	return func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
		err := r.ParseForm()
		if err != nil {
			http.Error(w, "can't parse form?", http.StatusBadRequest)
			return
		}
		// Note: at this point the "token" is actually a json object in string form,
		// containing both the username and token.
		token := r.FormValue("id_token")
		if len(token) == 0 {
			next(w, r)
			return
		}
		authData := struct {
			Name   string `json:"auth_user"`
			Token  string `json:"auth_token"`
			APIKey string `json:"api_key"`
		}{}
		if err := util.ReadJSONInto(ioutil.NopCloser(strings.NewReader(token)), &authData); err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}

		if len(authData.Token) > 0 { // legacy auth - token lookup
			authedUser, err := um.GetUserByToken(authData.Token)
			if err != nil {
				evergreen.Logger.Logf(slogger.ERROR, "Error getting user: %v", err)
			} else {
				// Get the user's full details from the DB or create them if they don't exists
				dbUser, err := model.GetOrCreateUser(authedUser.Username(),
					authedUser.DisplayName(), authedUser.Email())
				if err != nil {
					evergreen.Logger.Logf(slogger.ERROR, "Error looking up user %v: %v", authedUser.Username(), err)
				} else {
					context.Set(r, apiUserKey, dbUser)
				}
			}
		} else if len(authData.APIKey) > 0 {
			dbUser, err := user.FindOne(user.ById(authData.Name))
			if dbUser != nil && err == nil {
				if dbUser.APIKey != authData.APIKey {
					http.Error(w, "Unauthorized - invalid API key", http.StatusUnauthorized)
					return
				}
				context.Set(r, apiUserKey, dbUser)
			} else {
				evergreen.Logger.Logf(slogger.ERROR, "Error getting user: %v", err)
			}
		}
		next(w, r)
	}
}
Exemple #18
0
// FetchExpansionVars loads expansions for a communicator's task from the API server.
func (h *HTTPCommunicator) FetchExpansionVars() (*apimodels.ExpansionVars, error) {
	resultVars := &apimodels.ExpansionVars{}
	retriableGet := util.RetriableFunc(
		func() error {
			resp, err := h.tryGet("fetch_vars")
			if resp != nil {
				defer resp.Body.Close()
			}
			if err != nil {
				// Some generic error trying to connect - try again
				h.Logger.Logf(slogger.ERROR, "failed trying to call fetch GET: %v", err)
				return util.RetriableError{err}
			}
			if resp.StatusCode == http.StatusUnauthorized {
				err = fmt.Errorf("fetching expansions failed: got 'unauthorized' response.")
				h.Logger.Logf(slogger.ERROR, err.Error())
				return err
			}
			if resp.StatusCode != http.StatusOK {
				err = fmt.Errorf("failed trying fetch GET, got bad response code: %v", resp.StatusCode)
				h.Logger.Logf(slogger.ERROR, err.Error())
				return util.RetriableError{err}
			}
			if resp == nil {
				err = fmt.Errorf("empty response fetching expansions")
				h.Logger.Logf(slogger.ERROR, err.Error())
				return util.RetriableError{err}
			}

			// got here safely, so all is good - read the results
			err = util.ReadJSONInto(resp.Body, resultVars)
			if err != nil {
				err = fmt.Errorf("failed to read vars from response: %v", err)
				h.Logger.Logf(slogger.ERROR, err.Error())
				return err
			}
			return nil
		},
	)

	retryFail, err := util.Retry(retriableGet, 10, 1*time.Second)
	if err != nil {
		// stop trying to make fetch happen, it's not going to happen
		if retryFail {
			h.Logger.Logf(slogger.ERROR, "Fetching vars used up all retries.")
		}
		return nil, err
	}
	return resultVars, err
}
Exemple #19
0
// GetPatches requests a list of the user's patches from the API and returns them as a list
func (ac *APIClient) GetPatches(n int) ([]patch.Patch, error) {
	resp, err := ac.get(fmt.Sprintf("patches/mine?n=%v", n), nil)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, NewAPIError(resp)
	}
	patches := []patch.Patch{}
	if err := util.ReadJSONInto(resp.Body, &patches); err != nil {
		return nil, err
	}
	return patches, nil
}
func TestAttachResults(t *testing.T) {
	resetTasks(t)
	testConfig := evergreen.TestConfig()
	cwd := testutil.GetDirectoryOfFile()
	Convey("With attachResults plugin installed into plugin registry", t, func() {
		registry := plugin.NewSimpleRegistry()
		attachPlugin := &AttachPlugin{}
		err := registry.Register(attachPlugin)
		testutil.HandleTestingErr(err, t, "Couldn't register plugin: %v")

		server, err := service.CreateTestServer(testConfig, nil, plugin.APIPlugins, true)
		testutil.HandleTestingErr(err, t, "Couldn't set up testing server")
		httpCom := plugintest.TestAgentCommunicator("mocktaskid", "mocktasksecret", server.URL)
		configFile := filepath.Join(cwd, "testdata", "plugin_attach_results.yml")
		resultsLoc := filepath.Join(cwd, "testdata", "plugin_attach_results.json")
		taskConfig, err := plugintest.CreateTestConfig(configFile, t)
		testutil.HandleTestingErr(err, t, "failed to create test config: %v")
		taskConfig.WorkDir = "."
		sliceAppender := &evergreen.SliceAppender{[]*slogger.Log{}}
		logger := agentutil.NewTestLogger(sliceAppender)

		Convey("all commands in test project should execute successfully", func() {
			for _, projTask := range taskConfig.Project.Tasks {
				So(len(projTask.Commands), ShouldNotEqual, 0)
				for _, command := range projTask.Commands {
					pluginCmds, err := registry.GetCommands(command, taskConfig.Project.Functions)
					testutil.HandleTestingErr(err, t, "Couldn't get plugin command: %v")
					So(pluginCmds, ShouldNotBeNil)
					So(err, ShouldBeNil)
					pluginCom := &comm.TaskJSONCommunicator{pluginCmds[0].Plugin(), httpCom}
					err = pluginCmds[0].Execute(logger, pluginCom, taskConfig, make(chan bool))
					So(err, ShouldBeNil)
					testTask, err := task.FindOne(task.ById(httpCom.TaskId))
					testutil.HandleTestingErr(err, t, "Couldn't find task")
					So(testTask, ShouldNotBeNil)
					// ensure test results are exactly as expected
					// attempt to open the file
					reportFile, err := os.Open(resultsLoc)
					testutil.HandleTestingErr(err, t, "Couldn't open report file: '%v'", err)
					results := &task.TestResults{}
					err = util.ReadJSONInto(reportFile, results)
					testutil.HandleTestingErr(err, t, "Couldn't read report file: '%v'", err)
					testResults := *results
					So(testTask.TestResults, ShouldResemble, testResults.Results)
					testutil.HandleTestingErr(err, t, "Couldn't clean up test temp dir")
				}
			}
		})
	})
}
Exemple #21
0
// GetPatch fetches the config requests project details from the API server for a given project ID.
func (ac *APIClient) GetPatch(patchId string) (*service.RestPatch, error) {
	resp, err := ac.get(fmt.Sprintf("patches/%v", patchId), nil)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, NewAPIError(resp)
	}
	ref := &service.RestPatch{}
	if err := util.ReadJSONInto(resp.Body, ref); err != nil {
		return nil, err
	}
	return ref, nil
}
Exemple #22
0
// GetProjectRef requests project details from the API server for a given project ID.
func (ac *APIClient) GetProjectRef(projectId string) (*model.ProjectRef, error) {
	resp, err := ac.get(fmt.Sprintf("/ref/%s", projectId), nil)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, NewAPIError(resp)
	}
	ref := &model.ProjectRef{}
	if err := util.ReadJSONInto(resp.Body, ref); err != nil {
		return nil, err
	}
	return ref, nil
}
Exemple #23
0
func (ac *APIClient) ListProjects() ([]model.ProjectRef, error) {
	resp, err := ac.get("projects", nil)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, NewAPIError(resp)
	}
	projs := []model.ProjectRef{}
	if err := util.ReadJSONInto(resp.Body, &projs); err != nil {
		return nil, err
	}
	return projs, nil
}
Exemple #24
0
func (ac *APIClient) ListTasks(project string) ([]model.ProjectTask, error) {
	resp, err := ac.get(fmt.Sprintf("tasks/%v", project), nil)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, NewAPIError(resp)
	}
	tasks := []model.ProjectTask{}
	if err := util.ReadJSONInto(resp.Body, &tasks); err != nil {
		return nil, err
	}
	return tasks, nil
}
Exemple #25
0
func (ac *APIClient) ListVariants(project string) ([]model.BuildVariant, error) {
	resp, err := ac.get(fmt.Sprintf("variants/%v", project), nil)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, NewAPIError(resp)
	}
	variants := []model.BuildVariant{}
	if err := util.ReadJSONInto(resp.Body, &variants); err != nil {
		return nil, err
	}
	return variants, nil
}
Exemple #26
0
// PutPatch submits a new patch for the given project to the API server. If successful, returns
// the patch object itself.
func (ac *APIClient) PutPatch(incomingPatch patchSubmission) (*patch.Patch, error) {
	data := struct {
		Description string `json:"desc"`
		Project     string `json:"project"`
		Patch       string `json:"patch"`
		Githash     string `json:"githash"`
		Variants    string `json:"buildvariants"`
		Finalize    bool   `json:"finalize"`
	}{
		incomingPatch.description,
		incomingPatch.projectId,
		incomingPatch.patchData,
		incomingPatch.base,
		"all",
		false,
	}

	if incomingPatch.finalize {
		data.Variants = incomingPatch.variants
		data.Finalize = true
	}

	rPipe, wPipe := io.Pipe()
	encoder := json.NewEncoder(wPipe)
	go func() {
		encoder.Encode(data)
		wPipe.Close()
	}()
	defer rPipe.Close()

	resp, err := ac.put("patches/", rPipe)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode != http.StatusCreated {
		return nil, NewAPIError(resp)
	}

	reply := struct {
		Patch *patch.Patch `json:"patch"`
	}{}

	if err := util.ReadJSONInto(resp.Body, &reply); err != nil {
		return nil, err
	}

	return reply.Patch, nil
}
Exemple #27
0
// AttachResults attaches the received results to the task in the database.
func (as *APIServer) AttachResults(w http.ResponseWriter, r *http.Request) {
	task := MustHaveTask(r)
	results := &model.TestResults{}
	err := util.ReadJSONInto(r.Body, results)
	if err != nil {
		as.LoggedError(w, r, http.StatusBadRequest, err)
		return
	}
	// set test result of task
	if err := task.SetResults(results.Results); err != nil {
		as.LoggedError(w, r, http.StatusInternalServerError, err)
		return
	}
	as.WriteJSON(w, http.StatusOK, "test results successfully attached")
}
Exemple #28
0
// CheckUpdates fetches information about available updates to client binaries from the server.
func (ac *APIClient) CheckUpdates() (*evergreen.ClientConfig, error) {
	resp, err := ac.get("update", nil)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode != http.StatusOK {
		return nil, NewAPIError(resp)
	}

	reply := evergreen.ClientConfig{}
	if err := util.ReadJSONInto(resp.Body, &reply); err != nil {
		return nil, err
	}
	return &reply, nil
}
Exemple #29
0
func (uis *UIServer) userSettingsModify(w http.ResponseWriter, r *http.Request) {
	currentUser := MustHaveUser(r)
	userSettings := user.UserSettings{}

	if err := util.ReadJSONInto(r.Body, &userSettings); err != nil {
		uis.LoggedError(w, r, http.StatusBadRequest, err)
		return
	}

	if err := model.SaveUserSettings(currentUser.Username(), userSettings); err != nil {
		uis.LoggedError(w, r, http.StatusInternalServerError, fmt.Errorf("Error saving user settings: %v", err))
		return
	}

	PushFlash(uis.CookieStore, r, w, NewSuccessFlash("Settings were saved."))
	uis.WriteJSON(w, http.StatusOK, "Updated user settings successfully")
}
Exemple #30
0
// GetProjectConfig loads the communicator's task's project from the API server.
func (h *HTTPCommunicator) GetProjectConfig() (*model.Project, error) {
	projectConfig := &model.Project{}
	retriableGet := util.RetriableFunc(
		func() error {
			resp, err := h.tryGet("version")
			if resp != nil {
				defer resp.Body.Close()
			}
			if resp != nil && resp.StatusCode == http.StatusConflict {
				// Something very wrong, fail now with no retry.
				return fmt.Errorf("conflict - wrong secret!")
			}
			if err != nil {
				// Some generic error trying to connect - try again
				return util.RetriableError{err}
			}
			if resp == nil {
				return util.RetriableError{fmt.Errorf("empty response")}
			} else {
				v := &version.Version{}
				err = util.ReadJSONInto(resp.Body, v)
				if err != nil {
					h.Logger.Errorf(slogger.ERROR,
						"unable to read project version response: %v\n", err)
					return util.RetriableError{fmt.Errorf("unable to read "+
						"project version response: %v\n", err)}
				}
				err = model.LoadProjectInto([]byte(v.Config), v.Project, projectConfig)
				if err != nil {
					h.Logger.Errorf(slogger.ERROR,
						"unable to unmarshal project config: %v\n", err)
					return util.RetriableError{fmt.Errorf("unable to "+
						"unmarshall project config: %v\n", err)}
				}
				return nil
			}
		},
	)

	retryFail, err := util.Retry(retriableGet, h.MaxAttempts, h.RetrySleep)
	if retryFail {
		return nil, fmt.Errorf("getting project configuration failed after %v "+
			"tries: %v", h.MaxAttempts, err)
	}
	return projectConfig, nil
}