// validateProjectConfig returns a slice containing a list of any errors // found in validating the given project configuration func (as *APIServer) validateProjectConfig(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() yamlBytes, err := ioutil.ReadAll(r.Body) if err != nil { as.WriteJSON(w, http.StatusBadRequest, fmt.Sprintf("Error reading request body: %v", err)) return } project := &model.Project{} validationErr := validator.ValidationError{} if err := model.LoadProjectInto(yamlBytes, "", project); err != nil { validationErr.Message = err.Error() as.WriteJSON(w, http.StatusBadRequest, []validator.ValidationError{validationErr}) return } syntaxErrs, err := validator.CheckProjectSyntax(project) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } semanticErrs := validator.CheckProjectSemantics(project) if len(syntaxErrs)+len(semanticErrs) != 0 { as.WriteJSON(w, http.StatusBadRequest, append(syntaxErrs, semanticErrs...)) return } as.WriteJSON(w, http.StatusOK, []validator.ValidationError{}) }
// validateProjectConfig returns a slice containing a list of any errors // found in validating the given project configuration func (as *APIServer) validateProjectConfig(w http.ResponseWriter, r *http.Request) { project := &model.Project{} validationErr := validator.ValidationError{} if err := util.ReadYAMLInto(r.Body, project); err != nil { validationErr.Message = err.Error() as.WriteJSON(w, http.StatusBadRequest, []validator.ValidationError{validationErr}) return } syntaxErrs := validator.CheckProjectSyntax(project) semanticErrs := validator.CheckProjectSemantics(project) if len(syntaxErrs)+len(semanticErrs) != 0 { as.WriteJSON(w, http.StatusBadRequest, append(syntaxErrs, semanticErrs...)) return } as.WriteJSON(w, http.StatusOK, []validator.ValidationError{}) }
// GetProjectConfig fetches the project configuration for a given repository // returning a remote config if the project references a remote repository // configuration file - via the Identifier. Otherwise it defaults to the local // project file func (repoTracker *RepoTracker) GetProjectConfig(revision string) ( project *model.Project, err error) { projectRef := repoTracker.ProjectRef if projectRef.LocalConfig != "" { // return the Local config from the project Ref. return model.FindProject("", projectRef) } project, err = repoTracker.GetRemoteConfig(revision) if err != nil { // Only create a stub version on API request errors that pertain // to actually fetching a config. Those errors currently include: // thirdparty.APIRequestError, thirdparty.FileNotFoundError and // thirdparty.YAMLFormatError _, apiReqErr := err.(thirdparty.APIRequestError) _, ymlFmtErr := err.(thirdparty.YAMLFormatError) _, noFileErr := err.(thirdparty.FileNotFoundError) if apiReqErr || noFileErr || ymlFmtErr { // If there's an error getting the remote config, e.g. because it // does not exist, we treat this the same as when the remote config // is invalid - but add a different error message message := fmt.Sprintf("error fetching project “%v” configuration "+ "data at revision “%v” (remote path=“%v”): %v", projectRef.Identifier, revision, projectRef.RemotePath, err) evergreen.Logger.Logf(slogger.ERROR, message) return nil, projectConfigError{[]string{message}} } // If we get here then we have an infrastructural error - e.g. // a thirdparty.APIUnmarshalError (indicating perhaps an API has // changed), a thirdparty.ResponseReadError(problem reading an // API response) or a thirdparty.APIResponseError (nil API // response) - or encountered a problem in fetching a local // configuration file. At any rate, this is bad enough that we // want to send a notification instead of just creating a stub // version. var lastRevision string repository, fErr := model.FindRepository(projectRef.Identifier) if fErr != nil || repository == nil { evergreen.Logger.Logf(slogger.ERROR, "error finding "+ "repository '%v': %v", projectRef.Identifier, fErr) } else { lastRevision = repository.LastRevision } repoTracker.sendFailureNotification(lastRevision, err) return nil, err } // check if project config is valid errs := validator.CheckProjectSyntax(project) if len(errs) != 0 { // We have syntax errors in the project. // Format them, as we need to store + display them to the user var message string var projectParseErrors []string for _, configError := range errs { message += fmt.Sprintf("\n\t=> %v", configError) projectParseErrors = append(projectParseErrors, configError.Error()) } evergreen.Logger.Logf(slogger.ERROR, "error validating project '%v' "+ "configuration at revision '%v': %v", projectRef.Identifier, revision, message) return nil, projectConfigError{projectParseErrors} } return project, nil }