blob: ce8f7c49bf43de681775f7e760c05682702d85c5 [file] [log] [blame]
package main
import (
"context"
"flag"
"net/http"
"cloud.google.com/go/datastore"
"github.com/go-chi/chi/v5"
"golang.org/x/oauth2/google"
"go.skia.org/infra/go/alogin"
"go.skia.org/infra/go/alogin/proxylogin"
"go.skia.org/infra/go/buildbucket"
"go.skia.org/infra/go/cleanup"
"go.skia.org/infra/go/common"
"go.skia.org/infra/go/httputils"
"go.skia.org/infra/go/roles"
"go.skia.org/infra/go/sklog"
"go.skia.org/infra/go/util"
"go.skia.org/infra/task_scheduler/go/db"
"go.skia.org/infra/task_scheduler/go/db/firestore"
"go.skia.org/infra/task_scheduler/go/job_creation/buildbucket_taskbackend"
)
const (
// APP_NAME is the name of this app.
APP_NAME = "task-scheduler-bbfe"
)
var (
// Task Scheduler database.
tsDb db.DBCloser
// Flags.
buildbucketTarget = flag.String("buildbucket_target", "", "Target name used by Buildbucket to address this Task Scheduler.")
host = flag.String("host", "localhost", "HTTP service host")
port = flag.String("port", ":8000", "HTTP service port for the web server (e.g., ':8000')")
firestoreInstance = flag.String("firestore_instance", "", "Firestore instance to use, eg. \"production\"")
local = flag.Bool("local", false, "Whether we're running on a dev machine vs in production.")
promPort = flag.String("prom_port", ":20000", "Metrics service address (e.g., ':10110')")
schedulerURL = flag.String("scheduler_url", "", "URL for the task scheduler frontend, if different from --host")
)
func runServer(serverURL string, bbHandler http.Handler, plogin alogin.Login) {
r := chi.NewRouter()
if bbHandler != nil {
r.Handle("/prpc/*", alogin.ForceRole(bbHandler, plogin, roles.Buildbucket))
}
h := httputils.LoggingRequestResponse(r)
h = httputils.XFrameOptionsDeny(h)
h = alogin.StatusMiddleware(plogin)(h)
if !*local {
h = httputils.HealthzAndHTTPS(h)
}
http.Handle("/", h)
sklog.Infof("Ready to serve on %s", serverURL)
sklog.Fatal(http.ListenAndServe(*port, nil))
}
func main() {
// Global init.
common.InitWithMust(
APP_NAME,
common.PrometheusOpt(promPort),
)
defer common.Defer()
ctx, cancelFn := context.WithCancel(context.Background())
cleanup.AtExit(cancelFn)
// Set up token source and authenticated API clients.
tokenSource, err := google.DefaultTokenSource(ctx, datastore.ScopeDatastore)
if err != nil {
sklog.Fatalf("Failed to create token source: %s", err)
}
// Initialize the database.
tsDb, err = firestore.NewDBWithParams(ctx, firestore.FIRESTORE_PROJECT, *firestoreInstance, tokenSource)
if err != nil {
sklog.Fatalf("Failed to create Firestore DB client: %s", err)
}
cleanup.AtExit(func() {
util.Close(tsDb)
})
serverURL := "https://" + *host
if *local {
serverURL = "http://" + *host + *port
}
// Initialize Buildbucket TaskBackend.
var bbHandler http.Handler
if *buildbucketTarget != "" {
httpClient := httputils.DefaultClientConfig().WithTokenSource(tokenSource).Client()
bb2 := buildbucket.NewClient(httpClient)
url := serverURL
if *schedulerURL != "" {
url = *schedulerURL
}
bbHandler = buildbucket_taskbackend.Handler(*buildbucketTarget, url, common.PROJECT_REPO_MAPPING, tsDb, bb2)
}
plogin := proxylogin.NewWithDefaults()
go runServer(serverURL, bbHandler, plogin)
// Run indefinitely, responding to HTTP requests.
select {}
}