Merge pull request #129 from vito/nix-docker-queue-singletons
Remove docker client + queue singletons
This commit is contained in:
commit
9aa5f95e92
7 changed files with 38 additions and 36 deletions
|
@ -123,6 +123,8 @@ func vet(path string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(path string) {
|
func run(path string) {
|
||||||
|
dockerClient := docker.New()
|
||||||
|
|
||||||
// parse the Drone yml file
|
// parse the Drone yml file
|
||||||
s, err := script.ParseBuildFile(path)
|
s, err := script.ParseBuildFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -175,7 +177,7 @@ func run(path string) {
|
||||||
|
|
||||||
// loop through and create builders
|
// loop through and create builders
|
||||||
for _, b := range builds { //script.Builds {
|
for _, b := range builds { //script.Builds {
|
||||||
builder := build.New(docker.DefaultClient)
|
builder := build.New(dockerClient)
|
||||||
builder.Build = b
|
builder.Build = b
|
||||||
builder.Repo = &code
|
builder.Repo = &code
|
||||||
builder.Key = key
|
builder.Key = key
|
||||||
|
|
|
@ -5,7 +5,9 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"code.google.com/p/go.net/websocket"
|
"code.google.com/p/go.net/websocket"
|
||||||
"github.com/GeertJohan/go.rice"
|
"github.com/GeertJohan/go.rice"
|
||||||
|
@ -13,10 +15,12 @@ import (
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
"github.com/russross/meddler"
|
"github.com/russross/meddler"
|
||||||
|
|
||||||
|
"github.com/drone/drone/pkg/build/docker"
|
||||||
"github.com/drone/drone/pkg/channel"
|
"github.com/drone/drone/pkg/channel"
|
||||||
"github.com/drone/drone/pkg/database"
|
"github.com/drone/drone/pkg/database"
|
||||||
"github.com/drone/drone/pkg/database/migrate"
|
"github.com/drone/drone/pkg/database/migrate"
|
||||||
"github.com/drone/drone/pkg/handler"
|
"github.com/drone/drone/pkg/handler"
|
||||||
|
"github.com/drone/drone/pkg/queue"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -118,6 +122,11 @@ func setupStatic() {
|
||||||
|
|
||||||
// setup routes for serving dynamic content.
|
// setup routes for serving dynamic content.
|
||||||
func setupHandlers() {
|
func setupHandlers() {
|
||||||
|
queueRunner := queue.NewRunner(docker.New(), 300*time.Second)
|
||||||
|
queue := queue.Start(runtime.NumCPU(), queueRunner)
|
||||||
|
|
||||||
|
hookHandler := handler.NewHookHandler(queue)
|
||||||
|
|
||||||
m := pat.New()
|
m := pat.New()
|
||||||
m.Get("/login", handler.ErrorHandler(handler.Login))
|
m.Get("/login", handler.ErrorHandler(handler.Login))
|
||||||
m.Post("/login", handler.ErrorHandler(handler.Authorize))
|
m.Post("/login", handler.ErrorHandler(handler.Authorize))
|
||||||
|
@ -177,7 +186,7 @@ func setupHandlers() {
|
||||||
m.Get("/account/admin/users", handler.AdminHandler(handler.AdminUserList))
|
m.Get("/account/admin/users", handler.AdminHandler(handler.AdminUserList))
|
||||||
|
|
||||||
// handlers for GitHub post-commit hooks
|
// handlers for GitHub post-commit hooks
|
||||||
m.Post("/hook/github.com", handler.ErrorHandler(handler.Hook))
|
m.Post("/hook/github.com", handler.ErrorHandler(hookHandler.Hook))
|
||||||
|
|
||||||
// handlers for first-time installation
|
// handlers for first-time installation
|
||||||
m.Get("/install", handler.ErrorHandler(handler.Install))
|
m.Get("/install", handler.ErrorHandler(handler.Install))
|
||||||
|
|
|
@ -29,8 +29,6 @@ const (
|
||||||
// Enables verbose logging to the Terminal window
|
// Enables verbose logging to the Terminal window
|
||||||
var Logging = true
|
var Logging = true
|
||||||
|
|
||||||
var DefaultClient = New() // TEMPORARY; PLEASE CONSTRUCT/INJECT YOURSELF
|
|
||||||
|
|
||||||
// New creates an instance of the Docker Client
|
// New creates an instance of the Docker Client
|
||||||
func New() *Client {
|
func New() *Client {
|
||||||
c := &Client{}
|
c := &Client{}
|
||||||
|
|
|
@ -13,10 +13,19 @@ import (
|
||||||
"github.com/drone/go-github/github"
|
"github.com/drone/go-github/github"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type HookHandler struct {
|
||||||
|
queue *queue.Queue
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHookHandler(queue *queue.Queue) *HookHandler {
|
||||||
|
return &HookHandler{
|
||||||
|
queue: queue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Processes a generic POST-RECEIVE hook and
|
// Processes a generic POST-RECEIVE hook and
|
||||||
// attempts to trigger a build.
|
// attempts to trigger a build.
|
||||||
func Hook(w http.ResponseWriter, r *http.Request) error {
|
func (h *HookHandler) Hook(w http.ResponseWriter, r *http.Request) error {
|
||||||
|
|
||||||
// handle github ping
|
// handle github ping
|
||||||
if r.Header.Get("X-Github-Event") == "ping" {
|
if r.Header.Get("X-Github-Event") == "ping" {
|
||||||
return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
|
return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
|
||||||
|
@ -25,7 +34,7 @@ func Hook(w http.ResponseWriter, r *http.Request) error {
|
||||||
// if this is a pull request route
|
// if this is a pull request route
|
||||||
// to a different handler
|
// to a different handler
|
||||||
if r.Header.Get("X-Github-Event") == "pull_request" {
|
if r.Header.Get("X-Github-Event") == "pull_request" {
|
||||||
PullRequestHook(w, r)
|
h.PullRequestHook(w, r)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,14 +169,13 @@ func Hook(w http.ResponseWriter, r *http.Request) error {
|
||||||
//realtime.CommitPending(repo.UserID, repo.TeamID, repo.ID, commit.ID, repo.Private)
|
//realtime.CommitPending(repo.UserID, repo.TeamID, repo.ID, commit.ID, repo.Private)
|
||||||
//realtime.BuildPending(repo.UserID, repo.TeamID, repo.ID, commit.ID, build.ID, repo.Private)
|
//realtime.BuildPending(repo.UserID, repo.TeamID, repo.ID, commit.ID, build.ID, repo.Private)
|
||||||
|
|
||||||
queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript}) //Push(repo, commit, build, buildscript)
|
h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript}) //Push(repo, commit, build, buildscript)
|
||||||
|
|
||||||
// OK!
|
// OK!
|
||||||
return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
|
return RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func PullRequestHook(w http.ResponseWriter, r *http.Request) {
|
func (h *HookHandler) PullRequestHook(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// get the payload of the message
|
// get the payload of the message
|
||||||
// this should contain a json representation of the
|
// this should contain a json representation of the
|
||||||
// repository and commit details
|
// repository and commit details
|
||||||
|
@ -276,7 +284,7 @@ func PullRequestHook(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// notify websocket that a new build is pending
|
// notify websocket that a new build is pending
|
||||||
// TODO we should, for consistency, just put this inside Queue.Add()
|
// TODO we should, for consistency, just put this inside Queue.Add()
|
||||||
queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript})
|
h.queue.Add(&queue.BuildTask{Repo: repo, Commit: commit, Build: build, Script: buildscript})
|
||||||
|
|
||||||
// OK!
|
// OK!
|
||||||
RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
|
RenderText(w, http.StatusText(http.StatusOK), http.StatusOK)
|
||||||
|
|
|
@ -10,29 +10,29 @@ import (
|
||||||
"github.com/drone/drone/pkg/build/script"
|
"github.com/drone/drone/pkg/build/script"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Runner interface {
|
type BuildRunner interface {
|
||||||
Run(buildScript *script.Build, repo *repo.Repo, key []byte, buildOutput io.Writer) (success bool, err error)
|
Run(buildScript *script.Build, repo *repo.Repo, key []byte, buildOutput io.Writer) (success bool, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type runner struct {
|
type buildRunner struct {
|
||||||
dockerClient *docker.Client
|
dockerClient *docker.Client
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRunner(dockerClient *docker.Client, timeout time.Duration) *runner {
|
func NewBuildRunner(dockerClient *docker.Client, timeout time.Duration) BuildRunner {
|
||||||
return &runner{
|
return &buildRunner{
|
||||||
dockerClient: dockerClient,
|
dockerClient: dockerClient,
|
||||||
timeout: timeout,
|
timeout: timeout,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *runner) Run(buildScript *script.Build, repo *repo.Repo, key []byte, buildOutput io.Writer) (bool, error) {
|
func (runner *buildRunner) Run(buildScript *script.Build, repo *repo.Repo, key []byte, buildOutput io.Writer) (bool, error) {
|
||||||
builder := build.New(r.dockerClient)
|
builder := build.New(runner.dockerClient)
|
||||||
builder.Build = buildScript
|
builder.Build = buildScript
|
||||||
builder.Repo = repo
|
builder.Repo = repo
|
||||||
builder.Key = key
|
builder.Key = key
|
||||||
builder.Stdout = buildOutput
|
builder.Stdout = buildOutput
|
||||||
builder.Timeout = r.timeout
|
builder.Timeout = runner.timeout
|
||||||
|
|
||||||
err := builder.Run()
|
err := builder.Run()
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
package queue
|
package queue
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/drone/drone/pkg/build/docker"
|
|
||||||
"github.com/drone/drone/pkg/build/script"
|
"github.com/drone/drone/pkg/build/script"
|
||||||
. "github.com/drone/drone/pkg/model"
|
. "github.com/drone/drone/pkg/model"
|
||||||
"runtime"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Queue dispatches tasks to workers.
|
// A Queue dispatches tasks to workers.
|
||||||
|
@ -25,24 +22,12 @@ type BuildTask struct {
|
||||||
Script *script.Build
|
Script *script.Build
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultQueue = Start(runtime.NumCPU(), newRunner(docker.DefaultClient, 300*time.Second)) // TEMPORARY; INJECT PLEASE
|
// Start N workers with the given build runner.
|
||||||
|
func Start(workers int, runner BuildRunner) *Queue {
|
||||||
var Add = defaultQueue.Add // TEMPORARY; INJECT PLEASE
|
|
||||||
|
|
||||||
func Start(workers int, runner Runner) *Queue {
|
|
||||||
// get the number of CPUs. Since builds
|
|
||||||
// tend to be CPU-intensive we should only
|
|
||||||
// execute 1 build per CPU.
|
|
||||||
// must be at least 1
|
|
||||||
// if ncpu < 1 {
|
|
||||||
// ncpu = 1
|
|
||||||
// }
|
|
||||||
|
|
||||||
tasks := make(chan *BuildTask)
|
tasks := make(chan *BuildTask)
|
||||||
|
|
||||||
queue := &Queue{tasks: tasks}
|
queue := &Queue{tasks: tasks}
|
||||||
|
|
||||||
// spawn a worker for each CPU
|
|
||||||
for i := 0; i < workers; i++ {
|
for i := 0; i < workers; i++ {
|
||||||
worker := worker{
|
worker := worker{
|
||||||
runner: runner,
|
runner: runner,
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type worker struct {
|
type worker struct {
|
||||||
runner Runner
|
runner BuildRunner
|
||||||
}
|
}
|
||||||
|
|
||||||
// work is a function that will infinitely
|
// work is a function that will infinitely
|
||||||
|
|
Loading…
Reference in a new issue