diff --git a/cmd/drone-agent/Dockerfile b/cmd/drone-agent/Dockerfile deleted file mode 100644 index db3abd9e..00000000 --- a/cmd/drone-agent/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -# Docker image for the Drone build agent -# -# CGO_ENABLED=0 go build -a -tags netgo -# docker build --rm=true -t drone/drone-agent . - -FROM gliderlabs/alpine:3.1 -RUN apk-install ca-certificates -ADD drone-agent /bin/ -ENTRYPOINT ["/bin/drone-agent"] diff --git a/cmd/drone-agent/main.go b/cmd/drone-agent/main.go deleted file mode 100644 index cccbb8e0..00000000 --- a/cmd/drone-agent/main.go +++ /dev/null @@ -1,154 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "io" - "os" - "time" - - log "github.com/drone/drone/Godeps/_workspace/src/github.com/Sirupsen/logrus" - "github.com/drone/drone/pkg/queue" - runner "github.com/drone/drone/pkg/runner/builtin" - - "github.com/drone/drone/Godeps/_workspace/src/github.com/gin-gonic/gin" - "github.com/drone/drone/Godeps/_workspace/src/github.com/samalba/dockerclient" -) - -var ( - // commit sha for the current build, set by - // the compile process. - version string - revision string -) - -var ( - // Defult docker host address - DefaultHost = "unix:///var/run/docker.sock" - - // Docker host address from environment variable - DockerHost = os.Getenv("DOCKER_HOST") -) - -var ( - addr string - token string -) - -func main() { - flag.StringVar(&addr, "addr", "http://localhost:8080", "") - flag.StringVar(&token, "token", "", "") - flag.Parse() - - if len(DockerHost) == 0 { - DockerHost = DefaultHost - } - - go func() { - for { - w, err := pull() - if err != nil { - log.Errorln(err) - time.Sleep(30 * time.Second) - continue - } - - log.Infof("Pulled and running build %s / %d", - w.Repo.FullName, w.Build.Number) - - updater := &updater{} - runner_ := runner.Runner{Updater: updater} - err = runner_.Run(w) - if err != nil { - log.Errorln(err) - } - } - }() - - s := gin.New() - s.GET("/stream/:id", stream) - s.GET("/ping", ping) - s.GET("/about", about) - s.Run(":1999") -} - -func pull() (*queue.Work, error) { - out := &queue.Work{} - err := send("POST", "/api/queue/pull", nil, out) - return out, err -} - -// ping handler returns a simple response to the -// caller indicating the server is running. This -// can be used for heartbeats. -func ping(c *gin.Context) { - c.String(200, "PONG") -} - -// about handler returns the version and revision -// information for this server. -func about(c *gin.Context) { - out := struct { - Version string - Revision string - }{version, revision} - c.JSON(200, out) -} - -// stream handler is a proxy that streams the Docker -// stdout and stderr for a running build to the caller. -func stream(c *gin.Context) { - if c.Request.FormValue("token") != token { - c.AbortWithStatus(401) - return - } - - client, err := dockerclient.NewDockerClient(DockerHost, nil) - if err != nil { - c.Fail(500, err) - return - } - cname := fmt.Sprintf("drone-%s", c.Params.ByName("id")) - - // finds the container by name - info, err := client.InspectContainer(cname) - if err != nil { - c.Fail(404, err) - return - } - - // verify the container is running. if not we'll - // do an exponential backoff and attempt to wait - if !info.State.Running { - for i := 0; ; i++ { - time.Sleep(1 * time.Second) - info, err = client.InspectContainer(info.Id) - if err != nil { - c.Fail(404, err) - return - } - if info.State.Running { - break - } - if i == 5 { - c.Fail(404, dockerclient.ErrNotFound) - return - } - } - } - - logs := &dockerclient.LogOptions{ - Follow: true, - Stdout: true, - Stderr: true, - } - - // directly streams the build output from the Docker - // daemon to the request. - rc, err := client.ContainerLogs(info.Id, logs) - if err != nil { - c.Fail(500, err) - return - } - io.Copy(c.Writer, rc) -} diff --git a/cmd/drone-agent/updater.go b/cmd/drone-agent/updater.go deleted file mode 100644 index 79e39117..00000000 --- a/cmd/drone-agent/updater.go +++ /dev/null @@ -1,119 +0,0 @@ -package main - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "strconv" - "time" - - logs "github.com/drone/drone/Godeps/_workspace/src/github.com/Sirupsen/logrus" - common "github.com/drone/drone/pkg/types" -) - -type updater struct{} - -func (u *updater) SetBuild(user *common.User, r *common.Repo, b *common.Build) error { - path := fmt.Sprintf("/api/queue/push/%s", r.FullName) - return sendBackoff("POST", path, b, nil) -} - -func (u *updater) SetJob(r *common.Repo, b *common.Build, j *common.Job) error { - path := fmt.Sprintf("/api/queue/push/%s/%v", r.FullName, b.Number) - return sendBackoff("POST", path, j, nil) -} - -func (u *updater) SetLogs(r *common.Repo, b *common.Build, j *common.Job, rc io.ReadCloser) error { - path := fmt.Sprintf("/api/queue/push/%s/%v/%v", r.FullName, b.Number, j.Number) - return sendBackoff("POST", path, rc, nil) -} - -func sendBackoff(method, path string, in, out interface{}) error { - var err error - var attempts int - for { - err = send(method, path, in, out) - if err == nil { - break - } - if attempts > 99 { - break - } - attempts++ - time.Sleep(time.Second * 30) - } - return err -} - -// do makes an http.Request and returns the response -func send(method, path string, in, out interface{}) error { - - // create the URI - uri, err := url.Parse(addr + path) - if err != nil { - return err - } - - if len(uri.Scheme) == 0 { - uri.Scheme = "http" - } - - params := uri.Query() - params.Add("token", token) - uri.RawQuery = params.Encode() - - // create the request - req, err := http.NewRequest(method, uri.String(), nil) - if err != nil { - return err - } - req.ProtoAtLeast(1, 1) - req.Close = true - req.ContentLength = 0 - - // If the data is a readCloser we can attach directly - // to the request body. - // - // Else we serialize the data input as JSON. - if rc, ok := in.(io.ReadCloser); ok { - req.Body = rc - - } else if in != nil { - inJson, err := json.Marshal(in) - if err != nil { - return err - } - - buf := bytes.NewBuffer(inJson) - req.Body = ioutil.NopCloser(buf) - - req.ContentLength = int64(len(inJson)) - req.Header.Set("Content-Length", strconv.Itoa(len(inJson))) - req.Header.Set("Content-Type", "application/json") - } - - // make the request using the default http client - resp, err := http.DefaultClient.Do(req) - if err != nil { - logs.Errorf("Error posting request. %s", err) - return err - } - defer resp.Body.Close() - - // Check for an http error status (ie not 200 StatusOK) - if resp.StatusCode > 300 { - logs.Errorf("Error status code %d", resp.StatusCode) - return fmt.Errorf(resp.Status) - } - - // Decode the JSON response - if out != nil { - err = json.NewDecoder(resp.Body).Decode(out) - } - - return err -} diff --git a/cmd/drone-server/drone.go b/cmd/drone-server/drone.go index fdf9ed58..eaf612cb 100644 --- a/cmd/drone-server/drone.go +++ b/cmd/drone-server/drone.go @@ -193,22 +193,6 @@ func main() { hooks.POST("", server.PostHook) } - queue := api.Group("/queue") - { - queue.Use(server.MustAgent()) - queue.Use(server.SetSettings(settings)) - queue.Use(server.SetUpdater(updater)) - queue.POST("/pull", server.PollBuild) - - push := queue.Group("/push/:owner/:name") - { - push.Use(server.SetRepo()) - push.POST("", server.PushCommit) - push.POST("/:commit", server.PushBuild) - push.POST("/:commit/:build/logs", server.PushLogs) - } - } - stream := api.Group("/stream") { stream.Use(server.SetRepo()) diff --git a/make.go b/make.go index 8c80aa02..7114b701 100644 --- a/make.go +++ b/make.go @@ -181,7 +181,6 @@ func build() error { output string }{ {"github.com/drone/drone/cmd/drone-server", "bin/drone"}, - {"github.com/drone/drone/cmd/drone-agent", "bin/drone-agent"}, } for _, bin := range bins { ldf := fmt.Sprintf("-X main.revision=%s -X main.version=%s", sha, version) @@ -223,7 +222,6 @@ func image() error { dir string name string }{ - {"./bin/drone-agent", "drone/drone-agent"}, {"./bin/drone-server", "drone/drone"}, } for _, image := range images { @@ -265,7 +263,6 @@ func clean() error { files := []string{ "bin/drone", - "bin/drone-agent", } for _, file := range files { diff --git a/pkg/server/queue.go b/pkg/server/queue.go index ea68285e..0a49be4a 100644 --- a/pkg/server/queue.go +++ b/pkg/server/queue.go @@ -1,150 +1,9 @@ package server import ( - "net" - "strconv" - "github.com/drone/drone/Godeps/_workspace/src/github.com/gin-gonic/gin" - "github.com/drone/drone/Godeps/_workspace/src/github.com/gin-gonic/gin/binding" - - log "github.com/drone/drone/Godeps/_workspace/src/github.com/Sirupsen/logrus" - common "github.com/drone/drone/pkg/types" ) -// GET /queue/pull -func PollBuild(c *gin.Context) { - queue := ToQueue(c) - store := ToDatastore(c) - - // extract the IP address from the agent that is - // polling for builds. - host := c.Request.RemoteAddr - addr, _, err := net.SplitHostPort(host) - if err != nil { - addr = host - } - addr = net.JoinHostPort(addr, "1999") - - log.Infof("agent connected and polling builds at %s", addr) - - // pull an item from the queue - work := queue.PullClose(c.Writer) - if work == nil { - c.AbortWithStatus(500) - return - } - - // persist the relationship between agent and commit. - err = store.SetAgent(work.Build, addr) - if err != nil { - // note the we are ignoring and just logging the error here. - // we consider this an acceptible failure because it doesn't - // impact anything other than live-streaming output. - log.Errorf("unable to store the agent address %s for build %s %v", - addr, work.Repo.FullName, work.Build.Number) - } - - c.JSON(200, work) - - // acknowledge work received by the client - queue.Ack(work) -} - -// POST /queue/push/:owner/:repo -func PushCommit(c *gin.Context) { - store := ToDatastore(c) - repo := ToRepo(c) - - in := &common.Build{} - if !c.BindWith(in, binding.JSON) { - return - } - user, err := store.User(repo.UserID) - if err != nil { - c.Fail(404, err) - return - } - build, err := store.BuildNumber(repo, in.Number) - if err != nil { - c.Fail(404, err) - return - } - - build.Started = in.Started - build.Finished = in.Finished - build.Status = in.Status - - updater := ToUpdater(c) - err = updater.SetBuild(user, repo, build) - if err != nil { - c.Fail(500, err) - return - } - c.Writer.WriteHeader(200) -} - -// POST /queue/push/:owner/:repo/:commit -func PushBuild(c *gin.Context) { - store := ToDatastore(c) - repo := ToRepo(c) - cnum, _ := strconv.Atoi(c.Params.ByName("commit")) - - in := &common.Job{} - if !c.BindWith(in, binding.JSON) { - return - } - - build, err := store.BuildNumber(repo, cnum) - if err != nil { - c.Fail(404, err) - return - } - job, err := store.JobNumber(build, in.Number) - if err != nil { - c.Fail(404, err) - return - } - - job.Started = in.Started - job.Finished = in.Finished - job.ExitCode = in.ExitCode - job.Status = in.Status - - updater := ToUpdater(c) - err = updater.SetJob(repo, build, job) - if err != nil { - c.Fail(500, err) - return - } - c.Writer.WriteHeader(200) -} - -// POST /queue/push/:owner/:repo/:comimt/:build/logs -func PushLogs(c *gin.Context) { - store := ToDatastore(c) - repo := ToRepo(c) - cnum, _ := strconv.Atoi(c.Params.ByName("commit")) - bnum, _ := strconv.Atoi(c.Params.ByName("build")) - - build, err := store.BuildNumber(repo, cnum) - if err != nil { - c.Fail(404, err) - return - } - job, err := store.JobNumber(build, bnum) - if err != nil { - c.Fail(404, err) - return - } - updater := ToUpdater(c) - err = updater.SetLogs(repo, build, job, c.Request.Body) - if err != nil { - c.Fail(500, err) - return - } - c.Writer.WriteHeader(200) -} - func GetQueue(c *gin.Context) { queue := ToQueue(c) items := queue.Items() diff --git a/pkg/server/server.go b/pkg/server/server.go index 2f19edf4..7d95e138 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -76,21 +76,6 @@ func SetRunner(r runner.Runner) gin.HandlerFunc { } } -func ToUpdater(c *gin.Context) runner.Updater { - v, ok := c.Get("updater") - if !ok { - return nil - } - return v.(runner.Updater) -} - -func SetUpdater(u runner.Updater) gin.HandlerFunc { - return func(c *gin.Context) { - c.Set("updater", u) - c.Next() - } -} - func ToSettings(c *gin.Context) *config.Config { v, ok := c.Get("config") if !ok { @@ -244,25 +229,6 @@ func MustAdmin() gin.HandlerFunc { } } -func MustAgent() gin.HandlerFunc { - return func(c *gin.Context) { - conf := ToSettings(c) - - // verify remote agents are enabled - if len(conf.Agents.Secret) == 0 { - c.AbortWithStatus(405) - return - } - // verify the agent token matches - token := c.Request.FormValue("token") - if token != conf.Agents.Secret { - c.AbortWithStatus(401) - return - } - c.Next() - } -} - func CheckPull() gin.HandlerFunc { return func(c *gin.Context) { u := ToUser(c)