harness-drone/cmd/drone-server/main.go
2020-06-04 22:15:30 -04:00

193 lines
5 KiB
Go

// Copyright 2019 Drone IO, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"context"
"flag"
"fmt"
"github.com/drone/drone/cmd/drone-server/bootstrap"
"github.com/drone/drone/cmd/drone-server/config"
"github.com/drone/drone/core"
"github.com/drone/drone/metric/sink"
"github.com/drone/drone/operator/runner"
"github.com/drone/drone/service/canceler/reaper"
"github.com/drone/drone/server"
"github.com/drone/drone/trigger/cron"
"github.com/drone/signal"
"github.com/joho/godotenv"
"github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
_ "github.com/go-sql-driver/mysql"
_ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
)
func main() {
var envfile string
flag.StringVar(&envfile, "env-file", ".env", "Read in a file of environment variables")
flag.Parse()
godotenv.Load(envfile)
config, err := config.Environ()
if err != nil {
logger := logrus.WithError(err)
logger.Fatalln("main: invalid configuration")
}
initLogging(config)
ctx := signal.WithContext(
context.Background(),
)
// if trace level logging is enabled, output the
// configuration parameters.
if logrus.IsLevelEnabled(logrus.TraceLevel) {
fmt.Println(config.String())
}
app, err := InitializeApplication(config)
if err != nil {
logger := logrus.WithError(err)
logger.Fatalln("main: cannot initialize server")
}
// optionally bootstrap the system with administrative or
// machine users configured in the environment.
err = bootstrap.New(app.users).Bootstrap(ctx, &core.User{
Login: config.Users.Create.Username,
Machine: config.Users.Create.Machine,
Admin: config.Users.Create.Admin,
Hash: config.Users.Create.Token,
})
if err != nil {
logger := logrus.WithError(err)
logger.Fatalln("cannot bootstrap user account")
}
g := errgroup.Group{}
g.Go(func() error {
logrus.WithFields(
logrus.Fields{
"proto": config.Server.Proto,
"host": config.Server.Host,
"port": config.Server.Port,
"url": config.Server.Addr,
"acme": config.Server.Acme,
},
).Infoln("starting the http server")
return app.server.ListenAndServe(ctx)
})
// launches the datadog sink in a goroutine. If the sink
// is disabled, the goroutine exits immediately without error.
g.Go(func() (err error) {
if !config.Datadog.Enabled {
return nil
}
return app.sink.Start(ctx)
})
// launches the cron runner in a goroutine. If the cron
// runner is disabled, the goroutine exits immediately
// without error.
g.Go(func() (err error) {
if config.Cron.Disabled {
return nil
}
logrus.WithField("interval", config.Cron.Interval.String()).
Infoln("starting the cron scheduler")
return app.cron.Start(ctx, config.Cron.Interval)
})
// launches the reaper in a goroutine. If the reaper
// is disabled, the goroutine exits immediately
// without error.
g.Go(func() (err error) {
if config.Cleanup.Disabled {
return nil
}
logrus.WithField("interval", config.Cleanup.Interval.String()).
Infoln("starting the zombie build reaper")
return app.reaper.Start(ctx, config.Cleanup.Interval)
})
// launches the build runner in a goroutine. If the local
// runner is disabled (because nomad or kubernetes is enabled)
// then the goroutine exits immediately without error.
g.Go(func() (err error) {
if app.runner == nil {
return nil
}
logrus.WithField("threads", config.Runner.Capacity).
Infoln("main: starting the local build runner")
return app.runner.Start(ctx, config.Runner.Capacity)
})
if err := g.Wait(); err != nil {
logrus.WithError(err).Fatalln("program terminated")
}
}
// helper function configures the logging.
func initLogging(c config.Config) {
if c.Logging.Debug {
logrus.SetLevel(logrus.DebugLevel)
}
if c.Logging.Trace {
logrus.SetLevel(logrus.TraceLevel)
}
if c.Logging.Text {
logrus.SetFormatter(&logrus.TextFormatter{
ForceColors: c.Logging.Color,
DisableColors: !c.Logging.Color,
})
} else {
logrus.SetFormatter(&logrus.JSONFormatter{
PrettyPrint: c.Logging.Pretty,
})
}
}
// application is the main struct for the Drone server.
type application struct {
cron *cron.Scheduler
reaper *reaper.Reaper
sink *sink.Datadog
runner *runner.Runner
server *server.Server
users core.UserStore
}
// newApplication creates a new application struct.
func newApplication(
cron *cron.Scheduler,
reaper *reaper.Reaper,
sink *sink.Datadog,
runner *runner.Runner,
server *server.Server,
users core.UserStore) application {
return application{
users: users,
cron: cron,
sink: sink,
server: server,
runner: runner,
reaper: reaper,
}
}