purging agent code from 0.4 ... out of scope for 0.4 release
This commit is contained in:
parent
008a16f7e7
commit
c53e7173aa
7 changed files with 0 additions and 476 deletions
|
@ -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"]
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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())
|
||||
|
|
3
make.go
3
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 {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue