示例#1
0
func New(session *mgo.Session, opts Options) *logKeeper {
	if session == nil {
		panic("session must not be nil")
	}
	session.SetSocketTimeout(0)

	render := render.New(render.Options{
		Directory: "templates",
		Funcs: template.FuncMap{
			"MutableVar": func() interface{} {
				return &MutableVar{""}
			},
			"ColorSet": func() *ColorSet {
				return NewColorSet()
			},
			"DateFormat": func(when time.Time, layout string) string {
				return when.Format(layout)
			},
		},
	})

	// Set default values for options
	if opts.DB == "" {
		opts.DB = "logkeeper"
	}
	db := session.DB(opts.DB)

	return &logKeeper{db, render, opts}
}
示例#2
0
func main() {
	settings := evergreen.GetSettingsOrExit()
	if settings.Ui.LogFile != "" {
		evergreen.SetLogger(settings.Ui.LogFile)
	}
	db.SetGlobalSessionProvider(db.SessionFactoryFromConfig(settings))

	home := evergreen.FindEvergreenHome()

	userManager, err := auth.LoadUserManager(settings.AuthConfig)
	if err != nil {
		fmt.Println("Failed to create user manager:", err)
		os.Exit(1)
	}

	cookieStore := sessions.NewCookieStore([]byte(settings.Ui.Secret))

	uis := ui.UIServer{
		nil,             // render
		settings.Ui.Url, // RootURL
		userManager,     // User Manager
		*settings,       // mci settings
		cookieStore,     // cookiestore
		nil,             // plugin panel manager
	}
	router, err := uis.NewRouter()
	if err != nil {
		fmt.Println("Failed to create router:", err)
		os.Exit(1)
	}

	webHome := filepath.Join(home, "public")

	functionOptions := ui.FuncOptions{webHome, settings.Ui.HelpUrl, true, router}

	functions, err := ui.MakeTemplateFuncs(functionOptions, settings.SuperUsers)
	if err != nil {
		fmt.Println("Failed to create template function map:", err)
		os.Exit(1)
	}

	uis.Render = render.New(render.Options{
		Directory:    filepath.Join(home, ui.WebRootPath, ui.Templates),
		DisableCache: !settings.Ui.CacheTemplates,
		Funcs:        functions,
	})
	err = uis.InitPlugins()
	if err != nil {
		fmt.Println("WARNING: Error initializing plugins:", err)
	}

	n := negroni.New()
	n.Use(negroni.NewStatic(http.Dir(webHome)))
	n.Use(ui.NewLogger())
	n.Use(negroni.HandlerFunc(ui.UserMiddleware(userManager)))
	n.UseHandler(router)
	graceful.Run(settings.Ui.HttpListenAddr, requestTimeout, n)
	evergreen.Logger.Logf(slogger.INFO, "UI server cleanly terminated")
}
示例#3
0
// New returns an APIServer initialized with the given settings and plugins.
func New(settings *evergreen.Settings, plugins []plugin.APIPlugin) (*APIServer, error) {
	authManager, err := auth.LoadUserManager(settings.AuthConfig)
	if err != nil {
		return nil, err
	}

	return &APIServer{render.New(render.Options{}), authManager, *settings, plugins}, nil
}
示例#4
0
// Run loops while there are any unprocessed alerts and attempts to deliver them.
func (qp *QueueProcessor) Run(config *evergreen.Settings) error {
	evergreen.Logger.Logf(slogger.INFO, "Starting alert queue processor run")
	home := evergreen.FindEvergreenHome()
	qp.config = config
	qp.render = render.New(render.Options{
		Directory:    filepath.Join(home, "alerts", "templates"),
		DisableCache: !config.Ui.CacheTemplates,
		TextFuncs:    nil,
		HtmlFuncs:    nil,
	})

	if len(qp.config.SuperUsers) == 0 {
		evergreen.Logger.Logf(slogger.WARN, "WARNING: No superusers configured, some alerts may have no recipient")
	}
	superUsers, err := user.Find(user.ByIds(qp.config.SuperUsers...))
	if err != nil {
		evergreen.Logger.Logf(slogger.ERROR, "Error getting superuser list: %v", err)
		return err
	}
	qp.superUsersConfigs = []model.AlertConfig{}
	for _, u := range superUsers {
		qp.superUsersConfigs = append(qp.superUsersConfigs, model.AlertConfig{"email", bson.M{"rcpt": u.Email()}})
	}
	evergreen.Logger.Logf(slogger.INFO, "Super-users config for outgoing alerts is: %#v", qp.superUsersConfigs)

	evergreen.Logger.Logf(slogger.INFO, "Running alert queue processing")
	for {
		nextAlert, err := alert.DequeueAlertRequest()

		if err != nil {
			evergreen.Logger.Logf(slogger.ERROR, "Failed to dequeue alert request: %v", err)
			return err
		}
		if nextAlert == nil {
			evergreen.Logger.Logf(slogger.INFO, "Reached end of queue items - stopping.")
			break
		}

		evergreen.Logger.Logf(slogger.DEBUG, "Processing queue item %v", nextAlert.Id.Hex())

		alertContext, err := qp.loadAlertContext(nextAlert)
		if err != nil {
			evergreen.Logger.Logf(slogger.ERROR, "Failed to load alert context: %v", err)
			return err
		}

		evergreen.Logger.Logf(slogger.DEBUG, "Delivering queue item %v", nextAlert.Id.Hex())
		err = qp.Deliver(nextAlert, alertContext)
		if err != nil {
			evergreen.Logger.Logf(slogger.ERROR, "Got error delivering message: %v", err)
		}

	}
	evergreen.Logger.Logf(slogger.INFO, "Finished alert queue processor run.")
	return nil
}
示例#5
0
文件: hw.go 项目: tychoish/evergreen
func (hwp *HelloWorldPlugin) GetUIHandler() http.Handler {
	renderer := render.New(render.Options{})
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// this handler returns the Id of the current user, as a sanity check that
		// proves plugins have access to user information.
		userId := "Not Logged In"
		u := plugin.GetUser(r)
		if u != nil {
			userId = u.Id
		}
		renderer.WriteJSON(w, http.StatusOK, struct {
			UserId string
		}{userId})
	})
}
示例#6
0
文件: ui.go 项目: tychoish/evergreen
func main() {

	settings := evergreen.GetSettingsOrExit()
	home := evergreen.FindEvergreenHome()
	uis, err := ui.New(settings, home)
	if err != nil {
		fmt.Println("Failed to create ui server: %v", err)
		os.Exit(1)
	}
	router, err := uis.NewRouter()
	if err != nil {
		fmt.Println("Failed to create router:", err)
		os.Exit(1)
	}

	webHome := filepath.Join(uis.Home, "public")

	functionOptions := ui.FuncOptions{webHome, uis.Settings.Ui.HelpUrl, true, router}

	functions, err := ui.MakeTemplateFuncs(functionOptions, uis.Settings.SuperUsers)
	htmlFunctions := htmlTemplate.FuncMap(functions)
	textFunctions := textTemplate.FuncMap(functions)

	if err != nil {
		fmt.Println("Failed to create template function map:", err)
		os.Exit(1)
	}

	uis.Render = render.New(render.Options{
		Directory:    filepath.Join(uis.Home, ui.WebRootPath, ui.Templates),
		DisableCache: !uis.Settings.Ui.CacheTemplates,
		HtmlFuncs:    htmlFunctions,
		TextFuncs:    textFunctions,
	})
	err = uis.InitPlugins()
	if err != nil {
		fmt.Println("WARNING: Error initializing plugins:", err)
	}

	n := negroni.New()
	n.Use(negroni.NewStatic(http.Dir(webHome)))
	n.Use(ui.NewLogger())
	n.Use(negroni.HandlerFunc(ui.UserMiddleware(uis.UserManager)))
	n.UseHandler(router)
	graceful.Run(uis.Settings.Ui.HttpListenAddr, requestTimeout, n)
	evergreen.Logger.Logf(slogger.INFO, "UI server cleanly terminated")
}
示例#7
0
func TestGetTaskInfo(t *testing.T) {

	userManager, err := auth.LoadUserManager(taskTestConfig.AuthConfig)
	testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config")

	uis := UIServer{
		RootURL:     taskTestConfig.Ui.Url,
		Settings:    *taskTestConfig,
		UserManager: userManager,
	}

	home := evergreen.FindEvergreenHome()

	uis.Render = render.New(render.Options{
		Directory:    filepath.Join(home, WebRootPath, Templates),
		DisableCache: true,
		Funcs:        nil,
	})

	router, err := uis.NewRouter()
	testutil.HandleTestingErr(err, t, "Failure in uis.NewRouter()")

	Convey("When finding info on a particular task", t, func() {
		testutil.HandleTestingErr(db.Clear(model.TasksCollection), t,
			"Error clearing '%v' collection", model.TasksCollection)

		taskId := "my-task"
		versionId := "my-version"
		projectName := "project_test"

		testResult := model.TestResult{
			Status:    "success",
			TestFile:  "some-test",
			URL:       "some-url",
			StartTime: float64(time.Now().Add(-9 * time.Minute).Unix()),
			EndTime:   float64(time.Now().Add(-1 * time.Minute).Unix()),
		}
		task := &model.Task{
			Id:                  taskId,
			CreateTime:          time.Now().Add(-20 * time.Minute),
			ScheduledTime:       time.Now().Add(-15 * time.Minute),
			DispatchTime:        time.Now().Add(-14 * time.Minute),
			StartTime:           time.Now().Add(-10 * time.Minute),
			FinishTime:          time.Now().Add(-5 * time.Second),
			PushTime:            time.Now().Add(-1 * time.Millisecond),
			Version:             versionId,
			Project:             projectName,
			Revision:            fmt.Sprintf("%x", rand.Int()),
			Priority:            10,
			LastHeartbeat:       time.Now(),
			Activated:           false,
			BuildId:             "some-build-id",
			DistroId:            "some-distro-id",
			BuildVariant:        "some-build-variant",
			DependsOn:           []model.Dependency{{"some-other-task", ""}},
			DisplayName:         "My task",
			HostId:              "some-host-id",
			Restarts:            0,
			Execution:           0,
			Archived:            false,
			RevisionOrderNumber: 42,
			Requester:           evergreen.RepotrackerVersionRequester,
			Status:              "success",
			Details: apimodels.TaskEndDetail{
				TimedOut:    false,
				Description: "some-stage",
			},
			Aborted:          false,
			TimeTaken:        time.Duration(100 * time.Millisecond),
			ExpectedDuration: time.Duration(99 * time.Millisecond),
			TestResults:      []model.TestResult{testResult},
			MinQueuePos:      0,
		}
		So(task.Insert(), ShouldBeNil)

		file := artifact.File{
			Name: "Some Artifact",
			Link: "some-url",
		}
		artifact := artifact.Entry{
			TaskId: taskId,
			Files:  []artifact.File{file},
		}
		So(artifact.Upsert(), ShouldBeNil)

		url, err := router.Get("task_info").URL("task_id", taskId)
		So(err, ShouldBeNil)

		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		// Need match variables to be set so can call mux.Vars(request)
		// in the actual handler function
		router.ServeHTTP(response, request)

		So(response.Code, ShouldEqual, http.StatusOK)

		Convey("response should match contents of database", func() {
			var jsonBody map[string]interface{}
			err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
			So(err, ShouldBeNil)
			Println(string(response.Body.Bytes()))

			var rawJsonBody map[string]*json.RawMessage
			err = json.Unmarshal(response.Body.Bytes(), &rawJsonBody)
			So(err, ShouldBeNil)

			So(jsonBody["id"], ShouldEqual, task.Id)

			var createTime time.Time
			err = json.Unmarshal(*rawJsonBody["create_time"], &createTime)
			So(err, ShouldBeNil)
			So(createTime, ShouldHappenWithin, rest.TimePrecision, task.CreateTime)

			var scheduledTime time.Time
			err = json.Unmarshal(*rawJsonBody["scheduled_time"], &scheduledTime)
			So(err, ShouldBeNil)
			So(scheduledTime, ShouldHappenWithin, rest.TimePrecision, task.ScheduledTime)

			var dispatchTime time.Time
			err = json.Unmarshal(*rawJsonBody["dispatch_time"], &dispatchTime)
			So(err, ShouldBeNil)
			So(dispatchTime, ShouldHappenWithin, rest.TimePrecision, task.DispatchTime)

			var startTime time.Time
			err = json.Unmarshal(*rawJsonBody["start_time"], &startTime)
			So(err, ShouldBeNil)
			So(startTime, ShouldHappenWithin, rest.TimePrecision, task.StartTime)

			var finishTime time.Time
			err = json.Unmarshal(*rawJsonBody["finish_time"], &finishTime)
			So(err, ShouldBeNil)
			So(finishTime, ShouldHappenWithin, rest.TimePrecision, task.FinishTime)

			var pushTime time.Time
			err = json.Unmarshal(*rawJsonBody["push_time"], &pushTime)
			So(err, ShouldBeNil)
			So(pushTime, ShouldHappenWithin, rest.TimePrecision, task.PushTime)

			So(jsonBody["version"], ShouldEqual, task.Version)
			So(jsonBody["project"], ShouldEqual, task.Project)
			So(jsonBody["revision"], ShouldEqual, task.Revision)
			So(jsonBody["priority"], ShouldEqual, task.Priority)

			var lastHeartbeat time.Time
			err = json.Unmarshal(*rawJsonBody["last_heartbeat"], &lastHeartbeat)
			So(err, ShouldBeNil)
			So(lastHeartbeat, ShouldHappenWithin, rest.TimePrecision, task.LastHeartbeat)

			So(jsonBody["activated"], ShouldEqual, task.Activated)
			So(jsonBody["build_id"], ShouldEqual, task.BuildId)
			So(jsonBody["distro"], ShouldEqual, task.DistroId)
			So(jsonBody["build_variant"], ShouldEqual, task.BuildVariant)

			var dependsOn []model.Dependency
			So(rawJsonBody["depends_on"], ShouldNotBeNil)
			err = json.Unmarshal(*rawJsonBody["depends_on"], &dependsOn)
			So(err, ShouldBeNil)
			So(dependsOn, ShouldResemble, task.DependsOn)

			So(jsonBody["display_name"], ShouldEqual, task.DisplayName)
			So(jsonBody["host_id"], ShouldEqual, task.HostId)
			So(jsonBody["restarts"], ShouldEqual, task.Restarts)
			So(jsonBody["execution"], ShouldEqual, task.Execution)
			So(jsonBody["archived"], ShouldEqual, task.Archived)
			So(jsonBody["order"], ShouldEqual, task.RevisionOrderNumber)
			So(jsonBody["requester"], ShouldEqual, task.Requester)
			So(jsonBody["status"], ShouldEqual, task.Status)

			_jsonStatusDetails, ok := jsonBody["status_details"]
			So(ok, ShouldBeTrue)
			jsonStatusDetails, ok := _jsonStatusDetails.(map[string]interface{})
			So(ok, ShouldBeTrue)

			So(jsonStatusDetails["timed_out"], ShouldEqual, task.Details.TimedOut)
			So(jsonStatusDetails["timeout_stage"], ShouldEqual, task.Details.Description)

			So(jsonBody["aborted"], ShouldEqual, task.Aborted)
			So(jsonBody["time_taken"], ShouldEqual, task.TimeTaken)
			So(jsonBody["expected_duration"], ShouldEqual, task.ExpectedDuration)

			_jsonTestResults, ok := jsonBody["test_results"]
			So(ok, ShouldBeTrue)
			jsonTestResults, ok := _jsonTestResults.(map[string]interface{})
			So(ok, ShouldBeTrue)
			So(len(jsonTestResults), ShouldEqual, 1)

			_jsonTestResult, ok := jsonTestResults[testResult.TestFile]
			So(ok, ShouldBeTrue)
			jsonTestResult, ok := _jsonTestResult.(map[string]interface{})
			So(ok, ShouldBeTrue)

			So(jsonTestResult["status"], ShouldEqual, testResult.Status)
			So(jsonTestResult["time_taken"], ShouldNotBeNil) // value correctness is unchecked

			_jsonTestResultLogs, ok := jsonTestResult["logs"]
			So(ok, ShouldBeTrue)
			jsonTestResultLogs, ok := _jsonTestResultLogs.(map[string]interface{})
			So(ok, ShouldBeTrue)

			So(jsonTestResultLogs["url"], ShouldEqual, testResult.URL)

			So(jsonBody["min_queue_pos"], ShouldEqual, task.MinQueuePos)

			var jsonFiles []map[string]interface{}
			err = json.Unmarshal(*rawJsonBody["files"], &jsonFiles)
			So(err, ShouldBeNil)
			So(len(jsonFiles), ShouldEqual, 1)

			jsonFile := jsonFiles[0]
			So(jsonFile["name"], ShouldEqual, file.Name)
			So(jsonFile["url"], ShouldEqual, file.Link)
		})
	})

	Convey("When finding info on a nonexistent task", t, func() {
		taskId := "not-present"

		url, err := router.Get("task_info").URL("task_id", taskId)
		So(err, ShouldBeNil)

		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		// Need match variables to be set so can call mux.Vars(request)
		// in the actual handler function
		router.ServeHTTP(response, request)

		So(response.Code, ShouldEqual, http.StatusNotFound)

		Convey("response should contain a sensible error message", func() {
			var jsonBody map[string]interface{}
			err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
			So(err, ShouldBeNil)

			So(jsonBody["message"], ShouldEqual,
				fmt.Sprintf("Error finding task '%v'", taskId))
		})
	})
}
示例#8
0
func TestGetTaskStatus(t *testing.T) {

	userManager, err := auth.LoadUserManager(taskTestConfig.AuthConfig)
	testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config")

	uis := UIServer{
		RootURL:     taskTestConfig.Ui.Url,
		Settings:    *taskTestConfig,
		UserManager: userManager,
	}

	home := evergreen.FindEvergreenHome()

	uis.Render = render.New(render.Options{
		Directory:    filepath.Join(home, WebRootPath, Templates),
		DisableCache: true,
		Funcs:        nil,
	})

	router, err := uis.NewRouter()
	testutil.HandleTestingErr(err, t, "Failure in uis.NewRouter()")

	Convey("When finding the status of a particular task", t, func() {
		testutil.HandleTestingErr(db.Clear(model.TasksCollection), t,
			"Error clearing '%v' collection", model.TasksCollection)

		taskId := "my-task"

		testResult := model.TestResult{
			Status:    "success",
			TestFile:  "some-test",
			URL:       "some-url",
			StartTime: float64(time.Now().Add(-9 * time.Minute).Unix()),
			EndTime:   float64(time.Now().Add(-1 * time.Minute).Unix()),
		}
		task := &model.Task{
			Id:          taskId,
			DisplayName: "My task",
			Status:      "success",
			Details: apimodels.TaskEndDetail{
				TimedOut:    false,
				Description: "some-stage",
			},
			TestResults: []model.TestResult{testResult},
		}
		So(task.Insert(), ShouldBeNil)

		url, err := router.Get("task_status").URL("task_id", taskId)
		So(err, ShouldBeNil)

		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		// Need match variables to be set so can call mux.Vars(request)
		// in the actual handler function
		router.ServeHTTP(response, request)

		So(response.Code, ShouldEqual, http.StatusOK)

		Convey("response should match contents of database", func() {
			var jsonBody map[string]interface{}
			err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
			So(err, ShouldBeNil)

			var rawJsonBody map[string]*json.RawMessage
			err = json.Unmarshal(response.Body.Bytes(), &rawJsonBody)
			So(err, ShouldBeNil)

			So(jsonBody["task_id"], ShouldEqual, task.Id)
			So(jsonBody["task_name"], ShouldEqual, task.DisplayName)
			So(jsonBody["status"], ShouldEqual, task.Status)

			_jsonStatusDetails, ok := jsonBody["status_details"]
			So(ok, ShouldBeTrue)
			jsonStatusDetails, ok := _jsonStatusDetails.(map[string]interface{})
			So(ok, ShouldBeTrue)

			So(jsonStatusDetails["timed_out"], ShouldEqual, task.Details.TimedOut)
			So(jsonStatusDetails["timeout_stage"], ShouldEqual, task.Details.Description)

			_jsonTestResults, ok := jsonBody["tests"]
			So(ok, ShouldBeTrue)
			jsonTestResults, ok := _jsonTestResults.(map[string]interface{})
			So(ok, ShouldBeTrue)
			So(len(jsonTestResults), ShouldEqual, 1)

			_jsonTestResult, ok := jsonTestResults[testResult.TestFile]
			So(ok, ShouldBeTrue)
			jsonTestResult, ok := _jsonTestResult.(map[string]interface{})
			So(ok, ShouldBeTrue)

			So(jsonTestResult["status"], ShouldEqual, testResult.Status)
			So(jsonTestResult["time_taken"], ShouldNotBeNil) // value correctness is unchecked

			_jsonTestResultLogs, ok := jsonTestResult["logs"]
			So(ok, ShouldBeTrue)
			jsonTestResultLogs, ok := _jsonTestResultLogs.(map[string]interface{})
			So(ok, ShouldBeTrue)

			So(jsonTestResultLogs["url"], ShouldEqual, testResult.URL)
		})
	})

	Convey("When finding the status of a nonexistent task", t, func() {
		taskId := "not-present"

		url, err := router.Get("task_status").URL("task_id", taskId)
		So(err, ShouldBeNil)

		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		// Need match variables to be set so can call mux.Vars(request)
		// in the actual handler function
		router.ServeHTTP(response, request)

		So(response.Code, ShouldEqual, http.StatusNotFound)

		Convey("response should contain a sensible error message", func() {
			var jsonBody map[string]interface{}
			err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
			So(err, ShouldBeNil)

			So(jsonBody["message"], ShouldEqual,
				fmt.Sprintf("Error finding task '%v'", taskId))
		})
	})
}
示例#9
0
func TestGetBuildInfo(t *testing.T) {

	userManager, err := auth.LoadUserManager(buildTestConfig.AuthConfig)
	testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config")

	uis := UIServer{
		RootURL:     buildTestConfig.Ui.Url,
		Settings:    *buildTestConfig,
		UserManager: userManager,
	}
	uis.InitPlugins()

	home := evergreen.FindEvergreenHome()

	uis.Render = render.New(render.Options{
		Directory:    filepath.Join(home, WebRootPath, Templates),
		DisableCache: true,
	})

	router, err := uis.NewRouter()
	testutil.HandleTestingErr(err, t, "Failed to create ui server router")

	Convey("When finding info on a particular build", t, func() {
		testutil.HandleTestingErr(db.Clear(build.Collection), t,
			"Error clearing '%v' collection", build.Collection)

		buildId := "my-build"
		versionId := "my-version"
		projectName := "mci-test"

		err := modelutil.CreateTestLocalConfig(buildTestConfig, "mci-test", "")
		So(err, ShouldBeNil)

		err = modelutil.CreateTestLocalConfig(buildTestConfig, "render", "")
		So(err, ShouldBeNil)

		err = modelutil.CreateTestLocalConfig(buildTestConfig, "project_test", "")

		task := build.TaskCache{
			Id:          "some-task-id",
			DisplayName: "some-task-name",
			Status:      "success",
			TimeTaken:   time.Duration(100 * time.Millisecond),
		}
		build := &build.Build{
			Id:                  buildId,
			CreateTime:          time.Now().Add(-20 * time.Minute),
			StartTime:           time.Now().Add(-10 * time.Minute),
			FinishTime:          time.Now().Add(-5 * time.Second),
			PushTime:            time.Now().Add(-1 * time.Millisecond),
			Version:             versionId,
			Project:             projectName,
			Revision:            fmt.Sprintf("%x", rand.Int()),
			BuildVariant:        "some-build-variant",
			BuildNumber:         "42",
			Status:              "success",
			Activated:           true,
			ActivatedTime:       time.Now().Add(-15 * time.Minute),
			RevisionOrderNumber: rand.Int(),
			Tasks:               []build.TaskCache{task},
			TimeTaken:           time.Duration(10 * time.Minute),
			DisplayName:         "My build",
			Requester:           evergreen.RepotrackerVersionRequester,
		}
		So(build.Insert(), ShouldBeNil)

		url, err := router.Get("build_info").URL("build_id", buildId)
		So(err, ShouldBeNil)

		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		// Need match variables to be set so can call mux.Vars(request)
		// in the actual handler function
		router.ServeHTTP(response, request)

		So(response.Code, ShouldEqual, http.StatusOK)

		Convey("response should match contents of database", func() {
			var jsonBody map[string]interface{}
			err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
			So(err, ShouldBeNil)

			var rawJsonBody map[string]*json.RawMessage
			err = json.Unmarshal(response.Body.Bytes(), &rawJsonBody)
			So(err, ShouldBeNil)

			So(jsonBody["id"], ShouldEqual, build.Id)

			var createTime time.Time
			err = json.Unmarshal(*rawJsonBody["create_time"], &createTime)
			So(err, ShouldBeNil)
			So(createTime, ShouldHappenWithin, TimePrecision, build.CreateTime)

			var startTime time.Time
			err = json.Unmarshal(*rawJsonBody["start_time"], &startTime)
			So(err, ShouldBeNil)
			So(startTime, ShouldHappenWithin, TimePrecision, build.StartTime)

			var finishTime time.Time
			err = json.Unmarshal(*rawJsonBody["finish_time"], &finishTime)
			So(err, ShouldBeNil)
			So(finishTime, ShouldHappenWithin, TimePrecision, build.FinishTime)

			var pushTime time.Time
			err = json.Unmarshal(*rawJsonBody["push_time"], &pushTime)
			So(err, ShouldBeNil)
			So(pushTime, ShouldHappenWithin, TimePrecision, build.PushTime)

			So(jsonBody["version"], ShouldEqual, build.Version)
			So(jsonBody["project"], ShouldEqual, build.Project)
			So(jsonBody["revision"], ShouldEqual, build.Revision)
			So(jsonBody["variant"], ShouldEqual, build.BuildVariant)
			So(jsonBody["number"], ShouldEqual, build.BuildNumber)
			So(jsonBody["status"], ShouldEqual, build.Status)
			So(jsonBody["activated"], ShouldEqual, build.Activated)

			var activatedTime time.Time
			err = json.Unmarshal(*rawJsonBody["activated_time"], &activatedTime)
			So(err, ShouldBeNil)
			So(activatedTime, ShouldHappenWithin, TimePrecision, build.ActivatedTime)

			So(jsonBody["order"], ShouldEqual, build.RevisionOrderNumber)

			_jsonTasks, ok := jsonBody["tasks"]
			So(ok, ShouldBeTrue)
			jsonTasks, ok := _jsonTasks.(map[string]interface{})
			So(ok, ShouldBeTrue)
			So(len(jsonTasks), ShouldEqual, 1)

			_jsonTask, ok := jsonTasks[task.DisplayName]
			So(ok, ShouldBeTrue)
			jsonTask, ok := _jsonTask.(map[string]interface{})
			So(ok, ShouldBeTrue)

			So(jsonTask["task_id"], ShouldEqual, task.Id)
			So(jsonTask["status"], ShouldEqual, task.Status)
			So(jsonTask["time_taken"], ShouldEqual, task.TimeTaken)

			So(jsonBody["time_taken"], ShouldEqual, build.TimeTaken)
			So(jsonBody["name"], ShouldEqual, build.DisplayName)
			So(jsonBody["requester"], ShouldEqual, build.Requester)
		})
	})

	Convey("When finding info on a nonexistent build", t, func() {
		buildId := "not-present"

		url, err := router.Get("build_info").URL("build_id", buildId)
		So(err, ShouldBeNil)

		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		// Need match variables to be set so can call mux.Vars(request)
		// in the actual handler function
		router.ServeHTTP(response, request)

		So(response.Code, ShouldEqual, http.StatusNotFound)

		Convey("response should contain a sensible error message", func() {
			var jsonBody map[string]interface{}
			err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
			So(err, ShouldBeNil)
			So(len(jsonBody["message"].(string)), ShouldBeGreaterThan, 0)
		})
	})
}
示例#10
0
func TestGetBuildStatus(t *testing.T) {

	userManager, err := auth.LoadUserManager(buildTestConfig.AuthConfig)
	testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config")

	uis := UIServer{
		RootURL:     buildTestConfig.Ui.Url,
		Settings:    *buildTestConfig,
		UserManager: userManager,
	}

	home := evergreen.FindEvergreenHome()

	uis.Render = render.New(render.Options{
		Directory:    filepath.Join(home, WebRootPath, Templates),
		DisableCache: true,
	})
	uis.InitPlugins()

	router, err := uis.NewRouter()
	testutil.HandleTestingErr(err, t, "Failed to create ui server router")

	Convey("When finding the status of a particular build", t, func() {
		testutil.HandleTestingErr(db.Clear(build.Collection), t,
			"Error clearing '%v' collection", build.Collection)

		buildId := "my-build"
		versionId := "my-version"

		task := build.TaskCache{
			Id:          "some-task-id",
			DisplayName: "some-task-name",
			Status:      "success",
			TimeTaken:   time.Duration(100 * time.Millisecond),
		}
		build := &build.Build{
			Id:           buildId,
			Version:      versionId,
			BuildVariant: "some-build-variant",
			DisplayName:  "Some Build Variant",
			Tasks:        []build.TaskCache{task},
		}
		So(build.Insert(), ShouldBeNil)

		url, err := router.Get("build_status").URL("build_id", buildId)
		So(err, ShouldBeNil)

		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		// Need match variables to be set so can call mux.Vars(request)
		// in the actual handler function
		router.ServeHTTP(response, request)

		So(response.Code, ShouldEqual, http.StatusOK)

		Convey("response should match contents of database", func() {
			var jsonBody map[string]interface{}
			err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
			So(err, ShouldBeNil)

			var rawJsonBody map[string]*json.RawMessage
			err = json.Unmarshal(response.Body.Bytes(), &rawJsonBody)
			So(err, ShouldBeNil)

			So(jsonBody["build_id"], ShouldEqual, build.Id)
			So(jsonBody["build_variant"], ShouldEqual, build.BuildVariant)

			_jsonTasks, ok := jsonBody["tasks"]
			So(ok, ShouldBeTrue)
			jsonTasks, ok := _jsonTasks.(map[string]interface{})
			So(ok, ShouldBeTrue)
			So(len(jsonTasks), ShouldEqual, 1)

			_jsonTask, ok := jsonTasks[task.DisplayName]
			So(ok, ShouldBeTrue)
			jsonTask, ok := _jsonTask.(map[string]interface{})
			So(ok, ShouldBeTrue)

			So(jsonTask["task_id"], ShouldEqual, task.Id)
			So(jsonTask["status"], ShouldEqual, task.Status)
			So(jsonTask["time_taken"], ShouldEqual, task.TimeTaken)
		})
	})

	Convey("When finding the status of a nonexistent build", t, func() {
		buildId := "not-present"

		url, err := router.Get("build_status").URL("build_id", buildId)
		So(err, ShouldBeNil)

		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		// Need match variables to be set so can call mux.Vars(request)
		// in the actual handler function
		router.ServeHTTP(response, request)

		So(response.Code, ShouldEqual, http.StatusNotFound)

		Convey("response should contain a sensible error message", func() {
			var jsonBody map[string]interface{}
			err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
			So(err, ShouldBeNil)
			So(len(jsonBody["message"].(string)), ShouldBeGreaterThan, 0)
		})
	})
}
func TestGetVersionStatus(t *testing.T) {

	userManager, err := auth.LoadUserManager(versionTestConfig.AuthConfig)
	testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config")

	uis := UIServer{
		RootURL:     versionTestConfig.Ui.Url,
		Settings:    *versionTestConfig,
		UserManager: userManager,
	}

	home := evergreen.FindEvergreenHome()

	uis.Render = render.New(render.Options{
		Directory:    filepath.Join(home, WebRootPath, Templates),
		DisableCache: true,
		Funcs:        nil,
	})

	router, err := uis.NewRouter()
	testutil.HandleTestingErr(err, t, "Failure in uis.NewRouter()")

	Convey("When finding the status of a particular version", t, func() {
		testutil.HandleTestingErr(db.Clear(build.Collection), t,
			"Error clearing '%v' collection", build.Collection)

		versionId := "my-version"

		task := build.TaskCache{
			Id:          "some-task-id",
			DisplayName: "some-task-name",
			Status:      "success",
			TimeTaken:   time.Duration(100 * time.Millisecond),
		}
		build := &build.Build{
			Id:           "some-build-id",
			Version:      versionId,
			BuildVariant: "some-build-variant",
			DisplayName:  "Some Build Variant",
			Tasks:        []build.TaskCache{task},
		}
		So(build.Insert(), ShouldBeNil)

		Convey("grouped by tasks", func() {
			groupBy := "tasks"

			url, err := router.Get("version_status").URL("version_id", versionId)
			So(err, ShouldBeNil)

			query := url.Query()
			query.Set("groupby", groupBy)
			url.RawQuery = query.Encode()

			request, err := http.NewRequest("GET", url.String(), nil)
			So(err, ShouldBeNil)

			response := httptest.NewRecorder()
			// Need match variables to be set so can call mux.Vars(request)
			// in the actual handler function
			router.ServeHTTP(response, request)

			So(response.Code, ShouldEqual, http.StatusOK)

			Convey("response should match contents of database", func() {
				var jsonBody map[string]interface{}
				err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
				So(err, ShouldBeNil)

				So(jsonBody["version_id"], ShouldEqual, versionId)

				_jsonTasks, ok := jsonBody["tasks"]
				So(ok, ShouldBeTrue)
				jsonTasks, ok := _jsonTasks.(map[string]interface{})
				So(ok, ShouldBeTrue)
				So(len(jsonTasks), ShouldEqual, 1)

				_jsonTask, ok := jsonTasks[task.DisplayName]
				So(ok, ShouldBeTrue)
				jsonTask, ok := _jsonTask.(map[string]interface{})
				So(ok, ShouldBeTrue)

				_jsonBuild, ok := jsonTask[build.BuildVariant]
				So(ok, ShouldBeTrue)
				jsonBuild, ok := _jsonBuild.(map[string]interface{})
				So(ok, ShouldBeTrue)

				So(jsonBuild["task_id"], ShouldEqual, task.Id)
				So(jsonBuild["status"], ShouldEqual, task.Status)
				So(jsonBuild["time_taken"], ShouldEqual, task.TimeTaken)
			})

			Convey("is the default option", func() {
				url, err := router.Get("version_status").URL("version_id", versionId)
				So(err, ShouldBeNil)

				request, err := http.NewRequest("GET", url.String(), nil)
				So(err, ShouldBeNil)

				_response := httptest.NewRecorder()
				// Need match variables to be set so can call mux.Vars(request)
				// in the actual handler function
				router.ServeHTTP(_response, request)

				So(_response, ShouldResemble, response)
			})
		})

		Convey("grouped by builds", func() {
			groupBy := "builds"

			url, err := router.Get("version_status").URL("version_id", versionId)
			So(err, ShouldBeNil)

			query := url.Query()
			query.Set("groupby", groupBy)
			url.RawQuery = query.Encode()

			request, err := http.NewRequest("GET", url.String(), nil)
			So(err, ShouldBeNil)

			response := httptest.NewRecorder()
			// Need match variables to be set so can call mux.Vars(request)
			// in the actual handler function
			router.ServeHTTP(response, request)

			So(response.Code, ShouldEqual, http.StatusOK)

			Convey("response should match contents of database", func() {
				var jsonBody map[string]interface{}
				err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
				So(err, ShouldBeNil)

				So(jsonBody["version_id"], ShouldEqual, versionId)

				_jsonBuilds, ok := jsonBody["builds"]
				So(ok, ShouldBeTrue)
				jsonBuilds, ok := _jsonBuilds.(map[string]interface{})
				So(ok, ShouldBeTrue)
				So(len(jsonBuilds), ShouldEqual, 1)

				_jsonBuild, ok := jsonBuilds[build.BuildVariant]
				So(ok, ShouldBeTrue)
				jsonBuild, ok := _jsonBuild.(map[string]interface{})
				So(ok, ShouldBeTrue)

				_jsonTask, ok := jsonBuild[task.DisplayName]
				So(ok, ShouldBeTrue)
				jsonTask, ok := _jsonTask.(map[string]interface{})
				So(ok, ShouldBeTrue)

				So(jsonTask["task_id"], ShouldEqual, task.Id)
				So(jsonTask["status"], ShouldEqual, task.Status)
				So(jsonTask["time_taken"], ShouldEqual, task.TimeTaken)
			})
		})

		Convey("grouped by an invalid option", func() {
			groupBy := "invalidOption"

			url, err := router.Get("version_status").URL("version_id", versionId)
			So(err, ShouldBeNil)

			query := url.Query()
			query.Set("groupby", groupBy)
			url.RawQuery = query.Encode()

			request, err := http.NewRequest("GET", url.String(), nil)
			So(err, ShouldBeNil)

			response := httptest.NewRecorder()
			// Need match variables to be set so can call mux.Vars(request)
			// in the actual handler function
			router.ServeHTTP(response, request)

			So(response.Code, ShouldEqual, http.StatusBadRequest)

			var jsonBody map[string]interface{}
			err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
			So(err, ShouldBeNil)

			So(jsonBody["message"], ShouldEqual,
				fmt.Sprintf("Invalid groupby parameter '%v'", groupBy))
		})
	})

	Convey("When finding the status of a nonexistent version", t, func() {
		versionId := "not-present"

		Convey("grouped by tasks", func() {
			groupBy := "tasks"

			url, err := router.Get("version_status").URL("version_id", versionId)
			So(err, ShouldBeNil)

			query := url.Query()
			query.Set("groupby", groupBy)
			url.RawQuery = query.Encode()

			request, err := http.NewRequest("GET", url.String(), nil)
			So(err, ShouldBeNil)

			response := httptest.NewRecorder()
			// Need match variables to be set so can call mux.Vars(request)
			// in the actual handler function
			router.ServeHTTP(response, request)

			So(response.Code, ShouldEqual, http.StatusOK)

			Convey("response should contain a sensible error message", func() {
				var jsonBody map[string]interface{}
				err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
				So(err, ShouldBeNil)

				_jsonTasks, ok := jsonBody["tasks"]
				So(ok, ShouldBeTrue)
				jsonTasks, ok := _jsonTasks.(map[string]interface{})
				So(ok, ShouldBeTrue)
				So(jsonTasks, ShouldBeEmpty)
			})
		})

		Convey("grouped by builds", func() {
			versionId := "not-present"
			groupBy := "builds"

			url, err := router.Get("version_status").URL("version_id", versionId)
			So(err, ShouldBeNil)

			query := url.Query()
			query.Set("groupby", groupBy)
			url.RawQuery = query.Encode()

			request, err := http.NewRequest("GET", url.String(), nil)
			So(err, ShouldBeNil)

			response := httptest.NewRecorder()
			// Need match variables to be set so can call mux.Vars(request)
			// in the actual handler function
			router.ServeHTTP(response, request)

			So(response.Code, ShouldEqual, http.StatusOK)

			Convey("response should contain a sensible error message", func() {
				var jsonBody map[string]interface{}
				err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
				So(err, ShouldBeNil)

				_jsonBuilds, ok := jsonBody["builds"]
				So(ok, ShouldBeTrue)
				jsonBuilds, ok := _jsonBuilds.(map[string]interface{})
				So(ok, ShouldBeTrue)
				So(jsonBuilds, ShouldBeEmpty)
			})
		})
	})
}
func TestActivateVersion(t *testing.T) {

	userManager, err := auth.LoadUserManager(versionTestConfig.AuthConfig)
	testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config")

	uis := UIServer{
		RootURL:     versionTestConfig.Ui.Url,
		Settings:    *versionTestConfig,
		UserManager: userManager,
	}

	home := evergreen.FindEvergreenHome()

	uis.Render = render.New(render.Options{
		Directory:    filepath.Join(home, WebRootPath, Templates),
		DisableCache: true,
		Funcs:        nil,
	})

	router, err := uis.NewRouter()
	testutil.HandleTestingErr(err, t, "Failure in uis.NewRouter()")

	Convey("When marking a particular version as active", t, func() {
		testutil.HandleTestingErr(db.Clear(version.Collection), t,
			"Error clearing '%v' collection", version.Collection)

		versionId := "my-version"
		projectName := "project_test"

		build := &build.Build{
			Id:           "some-build-id",
			BuildVariant: "some-build-variant",
		}
		So(build.Insert(), ShouldBeNil)

		v := &version.Version{
			Id:                  versionId,
			CreateTime:          time.Now().Add(-20 * time.Minute),
			StartTime:           time.Now().Add(-10 * time.Minute),
			FinishTime:          time.Now().Add(-5 * time.Second),
			Revision:            fmt.Sprintf("%x", rand.Int()),
			Author:              "some-author",
			AuthorEmail:         "some-email",
			Message:             "some-message",
			Status:              "success",
			BuildIds:            []string{build.Id},
			BuildVariants:       []version.BuildStatus{{"some-build-variant", true, time.Now().Add(-20 * time.Minute), "some-build-id"}},
			RevisionOrderNumber: rand.Int(),
			Owner:               "some-owner",
			Repo:                "some-repo",
			Branch:              "some-branch",
			RepoKind:            "github",
			Identifier:          projectName,
			Remote:              false,
			RemotePath:          "",
			Requester:           evergreen.RepotrackerVersionRequester,
		}
		So(v.Insert(), ShouldBeNil)

		url, err := router.Get("version_info").URL("version_id", versionId)
		So(err, ShouldBeNil)

		var body = map[string]interface{}{
			"activated": true,
		}
		jsonBytes, err := json.Marshal(body)
		So(err, ShouldBeNil)
		bodyReader := bytes.NewReader(jsonBytes)

		request, err := http.NewRequest("PATCH", url.String(), bodyReader)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		// Need match variables to be set so can call mux.Vars(request)
		// in the actual handler function
		router.ServeHTTP(response, request)

		So(response.Code, ShouldEqual, http.StatusOK)

		validateVersionInfo(v, response)
	})

	Convey("When marking a nonexistent version as active", t, func() {
		versionId := "not-present"

		url, err := router.Get("version_info").URL("version_id", versionId)
		So(err, ShouldBeNil)

		var body = map[string]interface{}{
			"activated": true,
		}
		jsonBytes, err := json.Marshal(body)
		So(err, ShouldBeNil)
		bodyReader := bytes.NewReader(jsonBytes)

		request, err := http.NewRequest("PATCH", url.String(), bodyReader)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		// Need match variables to be set so can call mux.Vars(request)
		// in the actual handler function
		router.ServeHTTP(response, request)

		So(response.Code, ShouldEqual, http.StatusNotFound)

		Convey("response should contain a sensible error message", func() {
			var jsonBody map[string]interface{}
			err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
			So(err, ShouldBeNil)

			So(jsonBody["message"], ShouldEqual,
				fmt.Sprintf("Error finding version '%v'", versionId))
		})
	})
}
func TestGetRecentVersions(t *testing.T) {

	userManager, err := auth.LoadUserManager(versionTestConfig.AuthConfig)
	testutil.HandleTestingErr(err, t, "Failure in loading UserManager from config")

	uis := UIServer{
		RootURL:     versionTestConfig.Ui.Url,
		Settings:    *versionTestConfig,
		UserManager: userManager,
	}

	home := evergreen.FindEvergreenHome()

	uis.Render = render.New(render.Options{
		Directory:    filepath.Join(home, WebRootPath, Templates),
		DisableCache: true,
		Funcs:        nil,
	})

	router, err := uis.NewRouter()
	testutil.HandleTestingErr(err, t, "Failure in uis.NewRouter()")

	err = testutil.CreateTestLocalConfig(buildTestConfig, "mci-test", "")
	testutil.HandleTestingErr(err, t, "Error loading local config mci-test")

	err = testutil.CreateTestLocalConfig(buildTestConfig, "render", "")
	testutil.HandleTestingErr(err, t, "Error loading local config render")

	Convey("When finding recent versions", t, func() {
		testutil.HandleTestingErr(db.ClearCollections(version.Collection, build.Collection), t,
			"Error clearing '%v' collection", version.Collection)

		projectName := "project_test"

		err = testutil.CreateTestLocalConfig(buildTestConfig, projectName, "")
		So(err, ShouldBeNil)
		otherProjectName := "my-other-project"
		So(projectName, ShouldNotEqual, otherProjectName) // sanity-check

		buildIdPreface := "build-id-for-version%v"

		So(rest.NumRecentVersions, ShouldBeGreaterThan, 0)
		versions := make([]*version.Version, 0, rest.NumRecentVersions)

		// Insert a bunch of versions into the database
		for i := 0; i < rest.NumRecentVersions; i++ {
			v := &version.Version{
				Id:                  fmt.Sprintf("version%v", i),
				Identifier:          projectName,
				Author:              fmt.Sprintf("author%v", i),
				Revision:            fmt.Sprintf("%x", rand.Int()),
				Message:             fmt.Sprintf("message%v", i),
				RevisionOrderNumber: i + 1,
				Requester:           evergreen.RepotrackerVersionRequester,
			}
			So(v.Insert(), ShouldBeNil)
			versions = append(versions, v)
		}

		// Construct a version that should not be present in the response
		// since the length of the build ids slice is different than that
		// of the build variants slice
		earlyVersion := &version.Version{
			Id:                  "some-id",
			Identifier:          projectName,
			Author:              "some-author",
			Revision:            fmt.Sprintf("%x", rand.Int()),
			Message:             "some-message",
			RevisionOrderNumber: 0,
			Requester:           evergreen.RepotrackerVersionRequester,
		}
		So(earlyVersion.Insert(), ShouldBeNil)

		// Construct a version that should not be present in the response
		// since it belongs to a different project
		otherVersion := &version.Version{
			Id:                  "some-other-id",
			Identifier:          otherProjectName,
			Author:              "some-other-author",
			Revision:            fmt.Sprintf("%x", rand.Int()),
			Message:             "some-other-message",
			RevisionOrderNumber: rest.NumRecentVersions + 1,
			Requester:           evergreen.RepotrackerVersionRequester,
		}
		So(otherVersion.Insert(), ShouldBeNil)

		builds := make([]*build.Build, 0, rest.NumRecentVersions)
		task := build.TaskCache{
			Id:          "some-task-id",
			DisplayName: "some-task-name",
			Status:      "success",
			TimeTaken:   time.Duration(100 * time.Millisecond),
		}

		for i := 0; i < rest.NumRecentVersions; i++ {
			build := &build.Build{
				Id:           fmt.Sprintf(buildIdPreface, i),
				Version:      versions[i].Id,
				BuildVariant: "some-build-variant",
				DisplayName:  "Some Build Variant",
				Tasks:        []build.TaskCache{task},
			}
			So(build.Insert(), ShouldBeNil)
			builds = append(builds, build)
		}

		url, err := router.Get("recent_versions").URL("project_id", projectName)
		So(err, ShouldBeNil)

		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		// Need match variables to be set so can call mux.Vars(request)
		// in the actual handler function
		router.ServeHTTP(response, request)

		So(response.Code, ShouldEqual, http.StatusOK)

		Convey("response should match contents of database", func() {
			var jsonBody map[string]interface{}
			err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
			So(err, ShouldBeNil)

			var rawJsonBody map[string]*json.RawMessage
			err = json.Unmarshal(response.Body.Bytes(), &rawJsonBody)
			So(err, ShouldBeNil)

			So(jsonBody["project"], ShouldEqual, projectName)

			var jsonVersions []map[string]interface{}
			err = json.Unmarshal(*rawJsonBody["versions"], &jsonVersions)
			So(err, ShouldBeNil)
			So(len(jsonVersions), ShouldEqual, len(versions))

			for i, v := range versions {
				jsonVersion := jsonVersions[len(jsonVersions)-i-1] // reverse order

				So(jsonVersion["version_id"], ShouldEqual, v.Id)
				So(jsonVersion["author"], ShouldEqual, v.Author)
				So(jsonVersion["revision"], ShouldEqual, v.Revision)
				So(jsonVersion["message"], ShouldEqual, v.Message)

				_jsonBuilds, ok := jsonVersion["builds"]
				So(ok, ShouldBeTrue)
				jsonBuilds, ok := _jsonBuilds.(map[string]interface{})
				So(ok, ShouldBeTrue)
				So(len(jsonBuilds), ShouldEqual, 1)

				_jsonBuild, ok := jsonBuilds[builds[i].BuildVariant]
				So(ok, ShouldBeTrue)
				jsonBuild, ok := _jsonBuild.(map[string]interface{})
				So(ok, ShouldBeTrue)

				So(jsonBuild["build_id"], ShouldEqual, builds[i].Id)
				So(jsonBuild["name"], ShouldEqual, builds[i].DisplayName)

				_jsonTasks, ok := jsonBuild["tasks"]
				So(ok, ShouldBeTrue)
				jsonTasks, ok := _jsonTasks.(map[string]interface{})
				So(ok, ShouldBeTrue)
				So(len(jsonTasks), ShouldEqual, 1)

				_jsonTask, ok := jsonTasks[task.DisplayName]
				So(ok, ShouldBeTrue)
				jsonTask, ok := _jsonTask.(map[string]interface{})
				So(ok, ShouldBeTrue)

				So(jsonTask["task_id"], ShouldEqual, task.Id)
				So(jsonTask["status"], ShouldEqual, task.Status)
				So(jsonTask["time_taken"], ShouldEqual, task.TimeTaken)
			}
		})
	})

	Convey("When finding recent versions for a nonexistent project", t, func() {
		projectName := "not-present"

		url, err := router.Get("recent_versions").URL("project_id", projectName)
		So(err, ShouldBeNil)

		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		// Need match variables to be set so can call mux.Vars(request)
		// in the actual handler function
		router.ServeHTTP(response, request)

		So(response.Code, ShouldEqual, http.StatusOK)

		Convey("response should contain no versions", func() {
			var jsonBody map[string]interface{}
			err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
			So(err, ShouldBeNil)

			var rawJsonBody map[string]*json.RawMessage
			err = json.Unmarshal(response.Body.Bytes(), &rawJsonBody)
			So(err, ShouldBeNil)

			So(jsonBody["project"], ShouldEqual, projectName)

			var jsonVersions []map[string]interface{}
			err = json.Unmarshal(*rawJsonBody["versions"], &jsonVersions)
			So(err, ShouldBeNil)
			So(jsonVersions, ShouldBeEmpty)
		})
	})
}
示例#14
0
func TestGetProjectInfo(t *testing.T) {
	uis := UIServer{
		RootURL:     projectTestConfig.Ui.Url,
		Settings:    *projectTestConfig,
		UserManager: testutil.MockUserManager{},
	}
	home := evergreen.FindEvergreenHome()
	uis.Render = render.New(render.Options{
		Directory:    filepath.Join(home, WebRootPath, Templates),
		DisableCache: true,
		Funcs:        nil,
	})
	router, err := uis.NewRouter()
	testutil.HandleTestingErr(err, t, "error setting up router")
	n := negroni.New()
	n.Use(negroni.HandlerFunc(UserMiddleware(uis.UserManager)))
	n.UseHandler(router)

	Convey("When loading a public project, it should be found", t, func() {
		testutil.HandleTestingErr(db.Clear(model.ProjectRefCollection), t,
			"Error clearing '%v' collection", model.ProjectRefCollection)

		publicId := "pub"
		public := &model.ProjectRef{
			Identifier:  publicId,
			Repo:        "repo1",
			LocalConfig: "buildvariants:\n - name: ubuntu",
		}
		So(public.Insert(), ShouldBeNil)

		url, err := router.Get("project_info").URL("project_id", publicId)
		So(err, ShouldBeNil)
		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()

		Convey("by a public user", func() {
			n.ServeHTTP(response, request)
			outRef := &model.ProjectRef{}
			So(response.Code, ShouldEqual, http.StatusOK)
			So(json.Unmarshal(response.Body.Bytes(), outRef), ShouldBeNil)
			So(outRef, ShouldResemble, public)
		})
		Convey("and a logged-in user", func() {
			request.AddCookie(&http.Cookie{Name: evergreen.AuthTokenCookie, Value: "token"})
			n.ServeHTTP(response, request)
			outRef := &model.ProjectRef{}
			So(response.Code, ShouldEqual, http.StatusOK)
			So(json.Unmarshal(response.Body.Bytes(), outRef), ShouldBeNil)
			So(outRef, ShouldResemble, public)
		})
	})

	Convey("When loading a private project", t, func() {
		testutil.HandleTestingErr(db.Clear(model.ProjectRefCollection), t,
			"Error clearing '%v' collection", model.ProjectRefCollection)

		privateId := "priv"
		private := &model.ProjectRef{
			Identifier: privateId,
			Private:    true,
			Repo:       "repo1",
		}
		So(private.Insert(), ShouldBeNil)

		Convey("users who are not logged in should be denied with a 302", func() {
			url, err := router.Get("project_info").URL("project_id", privateId)
			So(err, ShouldBeNil)
			request, err := http.NewRequest("GET", url.String(), nil)
			So(err, ShouldBeNil)
			response := httptest.NewRecorder()
			n.ServeHTTP(response, request)

			So(response.Code, ShouldEqual, http.StatusFound)
		})

		Convey("users who are logged in should be able to access the project", func() {
			url, err := router.Get("project_info").URL("project_id", privateId)
			So(err, ShouldBeNil)
			request, err := http.NewRequest("GET", url.String(), nil)
			So(err, ShouldBeNil)
			// add auth cookie--this can be anything if we are using a MockUserManager
			request.AddCookie(&http.Cookie{Name: evergreen.AuthTokenCookie, Value: "token"})
			response := httptest.NewRecorder()
			n.ServeHTTP(response, request)

			outRef := &model.ProjectRef{}
			So(response.Code, ShouldEqual, http.StatusOK)
			So(json.Unmarshal(response.Body.Bytes(), outRef), ShouldBeNil)
			So(outRef, ShouldResemble, private)
		})
	})

	Convey("When finding info on a nonexistent project", t, func() {
		url, err := router.Get("project_info").URL("project_id", "nope")
		So(err, ShouldBeNil)

		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)
		response := httptest.NewRecorder()

		Convey("response should contain a sensible error message", func() {
			Convey("for a public user", func() {
				n.ServeHTTP(response, request)
				So(response.Code, ShouldEqual, http.StatusNotFound)
				var jsonBody map[string]interface{}
				err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
				So(err, ShouldBeNil)
				So(len(jsonBody["message"].(string)), ShouldBeGreaterThan, 0)
			})
			Convey("and a logged-in user", func() {
				request.AddCookie(&http.Cookie{Name: evergreen.AuthTokenCookie, Value: "token"})
				n.ServeHTTP(response, request)
				So(response.Code, ShouldEqual, http.StatusNotFound)
				var jsonBody map[string]interface{}
				err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
				So(err, ShouldBeNil)
				So(len(jsonBody["message"].(string)), ShouldBeGreaterThan, 0)
			})
		})
	})
}
示例#15
0
func TestGetVersionInfo(t *testing.T) {

	uis := UIServer{
		RootURL:     versionTestConfig.Ui.Url,
		Settings:    *versionTestConfig,
		UserManager: testutil.MockUserManager{},
	}
	home := evergreen.FindEvergreenHome()

	uis.Render = render.New(render.Options{
		Directory:    filepath.Join(home, WebRootPath, Templates),
		DisableCache: true,
	})

	router, err := uis.NewRouter()
	testutil.HandleTestingErr(err, t, "Failure in uis.NewRouter()")

	err = testutil.CreateTestLocalConfig(buildTestConfig, "mci-test", "")
	testutil.HandleTestingErr(err, t, "Error loading local config mci-test")

	err = testutil.CreateTestLocalConfig(buildTestConfig, "render", "")
	testutil.HandleTestingErr(err, t, "Error loading local config render")

	Convey("When finding info on a particular version", t, func() {
		testutil.HandleTestingErr(db.Clear(version.Collection), t,
			"Error clearing '%v' collection", version.Collection)

		versionId := "my-version"
		projectName := "project_test"

		err = testutil.CreateTestLocalConfig(buildTestConfig, projectName, "")
		So(err, ShouldBeNil)

		v := &version.Version{
			Id:                  versionId,
			CreateTime:          time.Now().Add(-20 * time.Minute),
			StartTime:           time.Now().Add(-10 * time.Minute),
			FinishTime:          time.Now().Add(-5 * time.Second),
			Revision:            fmt.Sprintf("%x", rand.Int()),
			Author:              "some-author",
			AuthorEmail:         "some-email",
			Message:             "some-message",
			Status:              "success",
			BuildIds:            []string{"some-build-id"},
			BuildVariants:       []version.BuildStatus{{"some-build-variant", true, time.Now().Add(-20 * time.Minute), "some-build-id"}},
			RevisionOrderNumber: rand.Int(),
			Owner:               "some-owner",
			Repo:                "some-repo",
			Branch:              "some-branch",
			RepoKind:            "github",
			Identifier:          versionId,
			Remote:              false,
			RemotePath:          "",
			Requester:           evergreen.RepotrackerVersionRequester,
		}
		So(v.Insert(), ShouldBeNil)

		url, err := router.Get("version_info").URL("version_id", versionId)
		So(err, ShouldBeNil)

		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		// Need match variables to be set so can call mux.Vars(request)
		// in the actual handler function
		router.ServeHTTP(response, request)

		Println(response.Body)

		So(response.Code, ShouldEqual, http.StatusOK)
		validateVersionInfo(v, response)
	})

	Convey("When finding info on a nonexistent version", t, func() {
		versionId := "not-present"

		url, err := router.Get("version_info").URL("version_id", versionId)
		So(err, ShouldBeNil)

		request, err := http.NewRequest("GET", url.String(), nil)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		// Need match variables to be set so can call mux.Vars(request)
		// in the actual handler function
		router.ServeHTTP(response, request)

		So(response.Code, ShouldEqual, http.StatusNotFound)

		Convey("response should contain a sensible error message", func() {
			var jsonBody map[string]interface{}
			err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
			So(err, ShouldBeNil)
			So(len(jsonBody["message"].(string)), ShouldBeGreaterThan, 0)
		})
	})
}
示例#16
0
func TestActivateVersion(t *testing.T) {

	uis := UIServer{
		RootURL:     versionTestConfig.Ui.Url,
		Settings:    *versionTestConfig,
		UserManager: MockUserManager{},
	}

	home := evergreen.FindEvergreenHome()

	uis.Render = render.New(render.Options{
		Directory:    filepath.Join(home, WebRootPath, Templates),
		DisableCache: true,
	})
	uis.InitPlugins()

	router, err := uis.NewRouter()
	testutil.HandleTestingErr(err, t, "Failed to create ui server router")

	n := negroni.New()
	n.Use(negroni.HandlerFunc(UserMiddleware(uis.UserManager)))
	n.UseHandler(router)

	Convey("When marking a particular version as active", t, func() {
		testutil.HandleTestingErr(db.ClearCollections(version.Collection, build.Collection), t,
			"Error clearing collections")

		versionId := "my-version"
		projectName := "project_test"

		build := &build.Build{
			Id:           "some-build-id",
			BuildVariant: "some-build-variant",
		}
		So(build.Insert(), ShouldBeNil)

		v := &version.Version{
			Id:                  versionId,
			CreateTime:          time.Now().Add(-20 * time.Minute),
			StartTime:           time.Now().Add(-10 * time.Minute),
			FinishTime:          time.Now().Add(-5 * time.Second),
			Revision:            fmt.Sprintf("%x", rand.Int()),
			Author:              "some-author",
			AuthorEmail:         "some-email",
			Message:             "some-message",
			Status:              "success",
			BuildIds:            []string{build.Id},
			BuildVariants:       []version.BuildStatus{{"some-build-variant", true, time.Now().Add(-20 * time.Minute), "some-build-id"}},
			RevisionOrderNumber: rand.Int(),
			Owner:               "some-owner",
			Repo:                "some-repo",
			Branch:              "some-branch",
			RepoKind:            "github",
			Identifier:          projectName,
			Remote:              false,
			RemotePath:          "",
			Requester:           evergreen.RepotrackerVersionRequester,
		}
		So(v.Insert(), ShouldBeNil)

		url, err := router.Get("version_info").URL("version_id", versionId)
		So(err, ShouldBeNil)

		var body = map[string]interface{}{
			"activated": true,
		}
		jsonBytes, err := json.Marshal(body)
		So(err, ShouldBeNil)
		bodyReader := bytes.NewReader(jsonBytes)

		request, err := http.NewRequest("PATCH", url.String(), bodyReader)
		So(err, ShouldBeNil)
		// add auth cookie--this can be anything if we are using a MockUserManager
		request.AddCookie(&http.Cookie{Name: evergreen.AuthTokenCookie, Value: "token"})

		response := httptest.NewRecorder()
		// Need match variables to be set so can call mux.Vars(request)
		// in the actual handler function
		n.ServeHTTP(response, request)

		So(response.Code, ShouldEqual, http.StatusOK)

		validateVersionInfo(v, response)
	})

	Convey("When marking a nonexistent version as active", t, func() {
		versionId := "not-present"

		url, err := router.Get("version_info").URL("version_id", versionId)
		So(err, ShouldBeNil)

		var body = map[string]interface{}{
			"activated": true,
		}
		jsonBytes, err := json.Marshal(body)
		So(err, ShouldBeNil)
		bodyReader := bytes.NewReader(jsonBytes)

		request, err := http.NewRequest("PATCH", url.String(), bodyReader)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		// add auth cookie--this can be anything if we are using a MockUserManager
		request.AddCookie(&http.Cookie{Name: evergreen.AuthTokenCookie, Value: "token"})
		n.ServeHTTP(response, request)

		So(response.Code, ShouldEqual, http.StatusNotFound)

		Convey("response should contain a sensible error message", func() {
			var jsonBody map[string]interface{}
			err = json.Unmarshal(response.Body.Bytes(), &jsonBody)
			So(err, ShouldBeNil)
			So(len(jsonBody["message"].(string)), ShouldBeGreaterThan, 0)
		})
	})

	Convey("When modifying a version without credentials", t, func() {
		versionId := "not-present"

		url, err := router.Get("version_info").URL("version_id", versionId)
		So(err, ShouldBeNil)

		var body = map[string]interface{}{
			"activated": true,
		}
		jsonBytes, err := json.Marshal(body)
		So(err, ShouldBeNil)
		bodyReader := bytes.NewReader(jsonBytes)

		request, err := http.NewRequest("PATCH", url.String(), bodyReader)
		So(err, ShouldBeNil)

		response := httptest.NewRecorder()
		n.ServeHTTP(response, request)

		Convey("response should indicate a permission error", func() {
			So(response.Code, ShouldEqual, http.StatusUnauthorized)
		})
	})
}