diff --git a/docs/arewefastyet_api.md b/docs/arewefastyet_api.md index fb0313b3b..95f044462 100644 --- a/docs/arewefastyet_api.md +++ b/docs/arewefastyet_api.md @@ -32,6 +32,7 @@ arewefastyet api [flags] --web-port string Port used for the HTTP server (default "8080") --web-pr-label-trigger string GitHub Pull Request label that will trigger the execution of new execution. (default "Benchmark me") --web-pr-label-trigger-planner-v3 string GitHub Pull Request label that will trigger the execution of new execution using the V3 planner. (default "Benchmark me (V3)") + --web-request-run-key string Key to authenticate requests for custom benchmark runs. --web-source-exclude-filter strings List of execution source to not execute. By default, all sources are ran. --web-source-filter strings List of execution source that should be run. By default, all sources are ran. --web-vitess-path string Absolute path where the vitess directory is located or where it should be cloned (default "/") diff --git a/go/server/api.go b/go/server/api.go index 645485d6b..9fa4b5c26 100644 --- a/go/server/api.go +++ b/go/server/api.go @@ -19,9 +19,11 @@ package server import ( + "fmt" "net/http" "sort" "strconv" + "strings" "time" "github.com/gin-gonic/gin" @@ -347,3 +349,67 @@ func (s *Server) getStatusStats(c *gin.Context) { } c.JSON(http.StatusOK, stats) } + +func (s *Server) requestRun(c *gin.Context) { + benchmarkType := c.Query("type") + sha := c.Query("sha") + pswd := c.Query("key") + v := c.Query("version") + + errStrFmt := "missing argument: %s" + if benchmarkType == "" { + errStr := fmt.Sprintf(errStrFmt, "type") + c.JSON(http.StatusBadRequest, &ErrorAPI{Error: errStr}) + slog.Error(errStr) + return + } + + if sha == "" { + errStr := fmt.Sprintf(errStrFmt, "sha") + c.JSON(http.StatusBadRequest, &ErrorAPI{Error: errStr}) + slog.Error(errStr) + return + } + + if v == "" { + errStr := fmt.Sprintf(errStrFmt, "version") + c.JSON(http.StatusBadRequest, &ErrorAPI{Error: errStr}) + slog.Error(errStr) + return + } + + // check request run key is correct + if pswd != s.requestRunKey { + errStr := "unauthorized, wrong key" + c.JSON(http.StatusUnauthorized, &ErrorAPI{Error: errStr}) + slog.Error(errStr) + return + } + + // get version from URL + version, err := strconv.Atoi(v) + if err != nil { + c.JSON(http.StatusInternalServerError, &ErrorAPI{Error: err.Error()}) + slog.Error(err) + return + } + currVersion := git.Version{Major: version} + + + configs := s.getConfigFiles() + cfg, ok := configs[strings.ToLower(benchmarkType)] + if !ok { + errMsg := "unknown benchmark type: " + strings.ToUpper(benchmarkType) + c.JSON(http.StatusBadRequest, &ErrorAPI{Error: errMsg}) + slog.Error(errMsg) + return + } + + // create execution element + elem := s.createSimpleExecutionQueueElement(cfg, "custom_run", sha, benchmarkType, "", false, 0, currVersion) + + // to new element to the queue + s.addToQueue(elem) + + c.JSON(http.StatusCreated, "created") +} diff --git a/go/server/server.go b/go/server/server.go index b5c9d4460..1fac8d0c8 100644 --- a/go/server/server.go +++ b/go/server/server.go @@ -50,6 +50,7 @@ const ( flagBenchmarkConfigPath = "web-benchmark-config-path" flagFilterBySource = "web-source-filter" flagExcludeFilterBySource = "web-source-exclude-filter" + flagRequestRunKey = "web-request-run-key" // keyMinimumVitessVersion is used to define on which minimum Vitess version a given // benchmark should be run. Only the major version is counted. This key/value is located @@ -94,6 +95,8 @@ type Server struct { ghApp *github.App + requestRunKey string + // Mode used to run the server. Mode } @@ -113,6 +116,7 @@ func (s *Server) AddToCommand(cmd *cobra.Command) { cmd.Flags().StringVar(&s.prLabelTriggerV3, flagPullRequestLabelTriggerWithPlannerV3, "Benchmark me (V3)", "GitHub Pull Request label that will trigger the execution of new execution using the V3 planner.") cmd.Flags().StringSliceVar(&s.sourceFilter, flagFilterBySource, nil, "List of execution source that should be run. By default, all sources are ran.") cmd.Flags().StringSliceVar(&s.excludeSourceFilter, flagExcludeFilterBySource, nil, "List of execution source to not execute. By default, all sources are ran.") + cmd.Flags().StringVar(&s.requestRunKey, flagRequestRunKey, "", "Key to authenticate requests for custom benchmark runs.") _ = viper.BindPFlag(flagPort, cmd.Flags().Lookup(flagPort)) _ = viper.BindPFlag(flagVitessPath, cmd.Flags().Lookup(flagVitessPath)) @@ -125,6 +129,7 @@ func (s *Server) AddToCommand(cmd *cobra.Command) { _ = viper.BindPFlag(flagPullRequestLabelTriggerWithPlannerV3, cmd.Flags().Lookup(flagPullRequestLabelTriggerWithPlannerV3)) _ = viper.BindPFlag(flagFilterBySource, cmd.Flags().Lookup(flagFilterBySource)) _ = viper.BindPFlag(flagExcludeFilterBySource, cmd.Flags().Lookup(flagExcludeFilterBySource)) + _ = viper.BindPFlag(flagRequestRunKey, cmd.Flags().Lookup(flagRequestRunKey)) s.slackConfig.AddToCommand(cmd) if s.dbCfg == nil { @@ -233,6 +238,7 @@ func (s *Server) Run() error { s.router.GET("/api/daily/summary", s.getDailySummary) s.router.GET("/api/daily", s.getDaily) s.router.GET("/api/status/stats", s.getStatusStats) + s.router.GET("/api/run/request", s.requestRun) return s.router.Run(":" + s.port) }