2014-06-04 21:25:38 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
|
|
|
"flag"
|
2014-09-07 21:55:37 +00:00
|
|
|
"fmt"
|
2014-06-04 21:25:38 +00:00
|
|
|
"net/http"
|
2014-06-21 21:22:38 +00:00
|
|
|
"strings"
|
2014-06-04 21:25:38 +00:00
|
|
|
|
2014-09-03 07:23:36 +00:00
|
|
|
"github.com/drone/config"
|
2014-06-04 21:25:38 +00:00
|
|
|
"github.com/drone/drone/server/handler"
|
2014-09-29 01:36:24 +00:00
|
|
|
"github.com/drone/drone/server/middleware"
|
2014-09-30 07:43:50 +00:00
|
|
|
"github.com/drone/drone/server/pubsub"
|
2014-06-12 19:44:19 +00:00
|
|
|
"github.com/drone/drone/shared/build/log"
|
2014-06-04 21:25:38 +00:00
|
|
|
|
2014-09-30 07:43:50 +00:00
|
|
|
"github.com/GeertJohan/go.rice"
|
2014-07-13 02:01:58 +00:00
|
|
|
|
2014-09-29 01:36:24 +00:00
|
|
|
"code.google.com/p/go.net/context"
|
|
|
|
webcontext "github.com/goji/context"
|
|
|
|
"github.com/zenazn/goji"
|
|
|
|
"github.com/zenazn/goji/web"
|
|
|
|
|
|
|
|
_ "github.com/drone/drone/plugin/notify/email"
|
2014-09-03 07:23:36 +00:00
|
|
|
"github.com/drone/drone/plugin/remote/bitbucket"
|
|
|
|
"github.com/drone/drone/plugin/remote/github"
|
|
|
|
"github.com/drone/drone/plugin/remote/gitlab"
|
2014-09-29 01:36:24 +00:00
|
|
|
"github.com/drone/drone/server/blobstore"
|
2014-10-01 16:41:57 +00:00
|
|
|
"github.com/drone/drone/server/capability"
|
2014-09-29 01:36:24 +00:00
|
|
|
"github.com/drone/drone/server/datastore"
|
|
|
|
"github.com/drone/drone/server/datastore/database"
|
2014-09-29 03:21:02 +00:00
|
|
|
"github.com/drone/drone/server/worker/director"
|
|
|
|
"github.com/drone/drone/server/worker/docker"
|
|
|
|
"github.com/drone/drone/server/worker/pool"
|
2014-06-04 21:25:38 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
// port the server will run on
|
|
|
|
port string
|
|
|
|
|
|
|
|
// database driver used to connect to the database
|
|
|
|
driver string
|
|
|
|
|
|
|
|
// driver specific connection information. In this
|
|
|
|
// case, it should be the location of the SQLite file
|
|
|
|
datasource string
|
|
|
|
|
|
|
|
// optional flags for tls listener
|
|
|
|
sslcert string
|
|
|
|
sslkey string
|
|
|
|
|
|
|
|
// commit sha for the current build.
|
2014-07-14 00:06:55 +00:00
|
|
|
version string = "0.3-dev"
|
2014-06-04 21:25:38 +00:00
|
|
|
revision string
|
2014-06-09 22:47:35 +00:00
|
|
|
|
2014-09-03 07:23:36 +00:00
|
|
|
conf string
|
|
|
|
prefix string
|
2014-09-05 03:53:32 +00:00
|
|
|
|
|
|
|
open bool
|
2014-09-07 21:55:37 +00:00
|
|
|
|
2014-09-29 03:21:02 +00:00
|
|
|
// worker pool
|
|
|
|
workers *pool.Pool
|
|
|
|
|
|
|
|
// director
|
|
|
|
worker *director.Director
|
|
|
|
|
2014-09-30 07:43:50 +00:00
|
|
|
pub *pubsub.PubSub
|
|
|
|
|
2014-09-07 21:55:37 +00:00
|
|
|
nodes StringArr
|
2014-09-29 01:36:24 +00:00
|
|
|
|
|
|
|
db *sql.DB
|
2014-10-01 16:41:57 +00:00
|
|
|
|
|
|
|
caps map[string]bool
|
2014-06-04 21:25:38 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
2014-06-12 19:44:19 +00:00
|
|
|
log.SetPriority(log.LOG_NOTICE)
|
|
|
|
|
2014-09-03 07:23:36 +00:00
|
|
|
flag.StringVar(&conf, "config", "", "")
|
|
|
|
flag.StringVar(&prefix, "prefix", "DRONE_", "")
|
2014-06-04 21:25:38 +00:00
|
|
|
flag.Parse()
|
|
|
|
|
2014-10-01 18:58:27 +00:00
|
|
|
config.StringVar(&datasource, "database-source", "drone.sqlite")
|
2014-10-01 06:30:42 +00:00
|
|
|
config.StringVar(&driver, "database-driver", "sqlite3")
|
2014-09-07 21:55:37 +00:00
|
|
|
config.Var(&nodes, "worker-nodes")
|
2014-09-05 03:53:32 +00:00
|
|
|
config.BoolVar(&open, "registration-open", false)
|
2014-09-03 07:23:36 +00:00
|
|
|
config.SetPrefix(prefix)
|
2014-09-07 21:55:37 +00:00
|
|
|
if err := config.Parse(conf); err != nil {
|
|
|
|
fmt.Println("Error parsing config", err)
|
|
|
|
}
|
2014-09-03 07:23:36 +00:00
|
|
|
|
|
|
|
// setup the remote services
|
|
|
|
bitbucket.Register()
|
|
|
|
github.Register()
|
|
|
|
gitlab.Register()
|
|
|
|
|
2014-10-01 16:41:57 +00:00
|
|
|
caps = map[string]bool{}
|
|
|
|
caps[capability.Registration] = open
|
|
|
|
|
2014-09-29 01:36:24 +00:00
|
|
|
// setup the database and cancel all pending
|
|
|
|
// commits in the system.
|
|
|
|
db = database.MustConnect(driver, datasource)
|
|
|
|
go database.NewCommitstore(db).KillCommits()
|
|
|
|
|
2014-09-29 03:21:02 +00:00
|
|
|
// Create the worker, director and builders
|
|
|
|
workers = pool.New()
|
|
|
|
worker = director.New()
|
|
|
|
|
2014-10-01 04:35:30 +00:00
|
|
|
if nodes == nil || len(nodes) == 0 {
|
|
|
|
workers.Allocate(docker.New())
|
|
|
|
workers.Allocate(docker.New())
|
|
|
|
} else {
|
|
|
|
for _, node := range nodes {
|
|
|
|
workers.Allocate(docker.NewHost(node))
|
2014-09-29 03:21:02 +00:00
|
|
|
}
|
2014-10-01 04:35:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub = pubsub.NewPubSub()
|
2014-09-29 03:21:02 +00:00
|
|
|
|
2014-09-30 07:43:50 +00:00
|
|
|
goji.Get("/api/logins", handler.GetLoginList)
|
2014-09-29 06:18:52 +00:00
|
|
|
goji.Get("/api/stream/stdout/:id", handler.WsConsole)
|
|
|
|
goji.Get("/api/stream/user", handler.WsUser)
|
2014-09-29 01:36:24 +00:00
|
|
|
goji.Get("/api/auth/:host", handler.GetLogin)
|
2014-10-02 14:39:00 +00:00
|
|
|
goji.Post("/api/auth/:host", handler.GetLogin)
|
2014-09-29 01:36:24 +00:00
|
|
|
goji.Get("/api/badge/:host/:owner/:name/status.svg", handler.GetBadge)
|
|
|
|
goji.Get("/api/badge/:host/:owner/:name/cc.xml", handler.GetCC)
|
2014-10-02 14:22:42 +00:00
|
|
|
goji.Get("/api/hook/:host", handler.PostHook)
|
|
|
|
goji.Put("/api/hook/:host", handler.PostHook)
|
|
|
|
goji.Post("/api/hook/:host", handler.PostHook)
|
2014-09-29 01:36:24 +00:00
|
|
|
|
|
|
|
repos := web.New()
|
|
|
|
repos.Use(middleware.SetRepo)
|
|
|
|
repos.Use(middleware.RequireRepoRead)
|
|
|
|
repos.Use(middleware.RequireRepoAdmin)
|
|
|
|
repos.Get("/api/repos/:host/:owner/:name/branches/:branch/commits/:commit/console", handler.GetOutput)
|
|
|
|
repos.Get("/api/repos/:host/:owner/:name/branches/:branch/commits/:commit", handler.GetCommit)
|
|
|
|
repos.Post("/api/repos/:host/:owner/:name/branches/:branch/commits/:commit", handler.PostCommit)
|
|
|
|
repos.Get("/api/repos/:host/:owner/:name/commits", handler.GetCommitList)
|
|
|
|
repos.Get("/api/repos/:host/:owner/:name", handler.GetRepo)
|
|
|
|
repos.Put("/api/repos/:host/:owner/:name", handler.PutRepo)
|
|
|
|
repos.Post("/api/repos/:host/:owner/:name", handler.PostRepo)
|
|
|
|
repos.Delete("/api/repos/:host/:owner/:name", handler.DelRepo)
|
|
|
|
goji.Handle("/api/repos/:host/:owner/:name*", repos)
|
|
|
|
|
|
|
|
users := web.New()
|
|
|
|
users.Use(middleware.RequireUserAdmin)
|
|
|
|
users.Get("/api/users/:host/:login", handler.GetUser)
|
|
|
|
users.Post("/api/users/:host/:login", handler.PostUser)
|
|
|
|
users.Delete("/api/users/:host/:login", handler.DelUser)
|
|
|
|
users.Get("/api/users", handler.GetUserList)
|
|
|
|
goji.Handle("/api/users*", users)
|
|
|
|
|
|
|
|
user := web.New()
|
|
|
|
user.Use(middleware.RequireUser)
|
|
|
|
user.Get("/api/user/feed", handler.GetUserFeed)
|
|
|
|
user.Get("/api/user/repos", handler.GetUserRepos)
|
|
|
|
user.Get("/api/user", handler.GetUserCurrent)
|
|
|
|
user.Put("/api/user", handler.PutUser)
|
|
|
|
goji.Handle("/api/user*", user)
|
|
|
|
|
2014-09-30 04:34:30 +00:00
|
|
|
work := web.New()
|
|
|
|
work.Use(middleware.RequireUserAdmin)
|
|
|
|
work.Get("/api/work/started", handler.GetWorkStarted)
|
|
|
|
work.Get("/api/work/pending", handler.GetWorkPending)
|
|
|
|
work.Get("/api/work/assignments", handler.GetWorkAssigned)
|
|
|
|
work.Get("/api/workers", handler.GetWorkers)
|
|
|
|
goji.Handle("/api/work*", work)
|
|
|
|
|
2014-09-30 07:43:50 +00:00
|
|
|
// Include static resources
|
|
|
|
assets := rice.MustFindBox("app").HTTPBox()
|
|
|
|
assetserve := http.FileServer(rice.MustFindBox("app").HTTPBox())
|
|
|
|
http.Handle("/static/", http.StripPrefix("/static", assetserve))
|
|
|
|
goji.Get("/*", func(c web.C, w http.ResponseWriter, r *http.Request) {
|
|
|
|
w.Write(assets.MustBytes("index.html"))
|
|
|
|
})
|
|
|
|
|
2014-09-29 01:36:24 +00:00
|
|
|
// Add middleware and serve
|
|
|
|
goji.Use(ContextMiddleware)
|
|
|
|
goji.Use(middleware.SetHeaders)
|
|
|
|
goji.Use(middleware.SetUser)
|
|
|
|
goji.Serve()
|
|
|
|
}
|
|
|
|
|
|
|
|
// ContextMiddleware creates a new go.net/context and
|
|
|
|
// injects into the current goji context.
|
|
|
|
func ContextMiddleware(c *web.C, h http.Handler) http.Handler {
|
|
|
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
var ctx = context.Background()
|
|
|
|
ctx = datastore.NewContext(ctx, database.NewDatastore(db))
|
|
|
|
ctx = blobstore.NewContext(ctx, database.NewBlobstore(db))
|
2014-09-29 03:21:02 +00:00
|
|
|
ctx = pool.NewContext(ctx, workers)
|
|
|
|
ctx = director.NewContext(ctx, worker)
|
2014-09-30 07:43:50 +00:00
|
|
|
ctx = pubsub.NewContext(ctx, pub)
|
2014-10-01 16:41:57 +00:00
|
|
|
ctx = capability.NewContext(ctx, caps)
|
2014-09-29 01:36:24 +00:00
|
|
|
|
|
|
|
// add the context to the goji web context
|
|
|
|
webcontext.Set(c, ctx)
|
|
|
|
h.ServeHTTP(w, r)
|
2014-06-04 21:25:38 +00:00
|
|
|
}
|
2014-09-29 01:36:24 +00:00
|
|
|
return http.HandlerFunc(fn)
|
2014-06-04 21:25:38 +00:00
|
|
|
}
|
2014-09-07 21:55:37 +00:00
|
|
|
|
|
|
|
type StringArr []string
|
|
|
|
|
|
|
|
func (s *StringArr) String() string {
|
|
|
|
return fmt.Sprint(*s)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *StringArr) Set(value string) error {
|
|
|
|
for _, str := range strings.Split(value, ",") {
|
|
|
|
str = strings.TrimSpace(str)
|
|
|
|
*s = append(*s, str)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|