initial work to enable grpc

This commit is contained in:
Brad Rydzewski 2017-06-28 13:21:22 -04:00
parent f604d592bc
commit aed567a71e
20 changed files with 1571 additions and 961 deletions

View file

@ -46,7 +46,7 @@ pipeline:
image: plugins/docker
repo: drone/drone
secrets: [ docker_username, docker_password ]
tag: [ 0.7, 0.7.3 ]
tag: [ 0.8, 0.8.0, 0.8.0-rc.1 ]
when:
event: tag

View file

@ -1,7 +1,7 @@
# docker build --rm -t drone/drone .
FROM centurylink/ca-certs
EXPOSE 8000 80 443
EXPOSE 8000 9000 80 443
ENV DATABASE_DRIVER=sqlite3
ENV DATABASE_CONFIG=/var/lib/drone/drone.sqlite

View file

@ -6,19 +6,18 @@ import (
"io"
"io/ioutil"
"log"
"math"
"net/url"
"strconv"
"sync"
"time"
"google.golang.org/grpc"
"github.com/cncd/pipeline/pipeline"
"github.com/cncd/pipeline/pipeline/backend"
"github.com/cncd/pipeline/pipeline/backend/docker"
"github.com/cncd/pipeline/pipeline/interrupt"
"github.com/cncd/pipeline/pipeline/multipart"
"github.com/cncd/pipeline/pipeline/rpc"
"github.com/drone/drone/version"
"github.com/tevino/abool"
"github.com/urfave/cli"
@ -31,83 +30,60 @@ var Command = cli.Command{
Action: loop,
Flags: []cli.Flag{
cli.StringFlag{
EnvVar: "DRONE_SERVER,DRONE_ENDPOINT",
Name: "drone-server",
EnvVar: "DRONE_SERVER",
Name: "server",
Usage: "drone server address",
Value: "ws://localhost:8000/ws/broker",
Value: "localhost:9000",
},
cli.StringFlag{
EnvVar: "DRONE_SECRET,DRONE_AGENT_SECRET",
Name: "drone-secret",
EnvVar: "DRONE_SECRET",
Name: "secret",
Usage: "drone agent secret",
},
cli.DurationFlag{
EnvVar: "DRONE_BACKOFF",
Name: "backoff",
Usage: "drone server backoff interval",
Value: time.Second * 15,
},
cli.IntFlag{
Name: "retry-limit",
EnvVar: "DRONE_RETRY_LIMIT",
Value: math.MaxInt32,
},
cli.BoolFlag{
EnvVar: "DRONE_DEBUG",
Name: "debug",
Usage: "start the agent in debug mode",
},
cli.StringFlag{
EnvVar: "DRONE_FILTER",
Name: "filter",
Usage: "filter jobs processed by this agent",
EnvVar: "DRONE_PLATFORM",
Name: "platform",
Value: "linux/amd64",
},
cli.IntFlag{
Name: "max-procs",
EnvVar: "DRONE_MAX_PROCS",
Name: "max-procs",
Value: 1,
},
cli.StringFlag{
Name: "platform",
EnvVar: "DRONE_PLATFORM",
Value: "linux/amd64",
},
},
}
func loop(c *cli.Context) error {
endpoint, err := url.Parse(
c.String("drone-server"),
)
if err != nil {
return err
}
// endpoint, err := url.Parse(
// c.String("drone-server"),
// )
// if err != nil {
// return err
// }
filter := rpc.Filter{
Labels: map[string]string{
"platform": c.String("platform"),
},
}
client, err := rpc.NewClient(
endpoint.String(),
rpc.WithRetryLimit(
c.Int("retry-limit"),
),
rpc.WithBackoff(
c.Duration("backoff"),
),
rpc.WithToken(
c.String("drone-secret"),
),
rpc.WithHeader(
"X-Drone-Version",
version.Version.String(),
),
// TODO pass version information to grpc server
// TODO authenticate to grpc server
conn, err := grpc.Dial(
c.String("server"),
grpc.WithInsecure(),
)
if err != nil {
return err
}
defer client.Close()
defer conn.Close()
client := rpc.NewGrpcClient(conn)
sigterm := abool.New()
ctx := context.Background()

View file

@ -2,19 +2,24 @@ package server
import (
"context"
"net"
"net/http"
"net/url"
"strings"
"time"
"google.golang.org/grpc"
"golang.org/x/crypto/acme/autocert"
"golang.org/x/sync/errgroup"
"github.com/cncd/logging"
"github.com/cncd/pipeline/pipeline/rpc/proto"
"github.com/cncd/pubsub"
"github.com/drone/drone/plugins/registry"
"github.com/drone/drone/plugins/secrets"
"github.com/drone/drone/plugins/sender"
"github.com/drone/drone/remote"
"github.com/drone/drone/router"
"github.com/drone/drone/router/middleware"
droneserver "github.com/drone/drone/server"
@ -395,8 +400,13 @@ func server(c *cli.Context) error {
logrus.SetLevel(logrus.WarnLevel)
}
s := setupStore(c)
setupEvilGlobals(c, s)
remote_, err := setupRemote(c)
if err != nil {
logrus.Fatal(err)
}
store_ := setupStore(c)
setupEvilGlobals(c, store_, remote_)
// setup the server and start the listener
handler := router.Load(
@ -404,10 +414,38 @@ func server(c *cli.Context) error {
middleware.Version,
middleware.Config(c),
middleware.Cache(c),
middleware.Store(c, s),
middleware.Remote(c),
middleware.Store(c, store_),
middleware.Remote(remote_),
)
var g errgroup.Group
// start the grpc server
g.Go(func() error {
lis, err := net.Listen("tcp", ":9000")
if err != nil {
logrus.Error(err)
return err
}
s := grpc.NewServer()
ss := new(droneserver.DroneServer)
ss.Queue = droneserver.Config.Services.Queue
ss.Logger = droneserver.Config.Services.Logs
ss.Pubsub = droneserver.Config.Services.Pubsub
ss.Remote = remote_
ss.Store = store_
ss.Host = droneserver.Config.Server.Host
proto.RegisterDroneServer(s, ss)
err = s.Serve(lis)
if err != nil {
logrus.Error(err)
return err
}
return nil
})
// start the server with tls enabled
if c.String("server-cert") != "" {
return http.ListenAndServeTLS(
@ -428,7 +466,6 @@ func server(c *cli.Context) error {
// start the server with lets encrypt enabled
// listen on ports 443 and 80
var g errgroup.Group
g.Go(func() error {
return http.ListenAndServe(":http", handler)
})
@ -449,7 +486,7 @@ func server(c *cli.Context) error {
// in the gin.Context to storing them in a struct. We are also moving away
// from gin to gorilla. We will temporarily use global during our refactoring
// which will be removing in the final implementation.
func setupEvilGlobals(c *cli.Context, v store.Store) {
func setupEvilGlobals(c *cli.Context, v store.Store, r remote.Remote) {
// storage
droneserver.Config.Storage.Files = v
@ -463,6 +500,7 @@ func setupEvilGlobals(c *cli.Context, v store.Store) {
droneserver.Config.Services.Registries = setupRegistryService(c, v)
droneserver.Config.Services.Secrets = setupSecretService(c, v)
droneserver.Config.Services.Senders = sender.New(v, v)
if endpoint := c.String("registry-service"); endpoint != "" {
droneserver.Config.Services.Registries = registry.NewRemote(endpoint)
}

View file

@ -3,10 +3,19 @@
package server
import (
"fmt"
"github.com/cncd/queue"
"github.com/drone/drone/model"
"github.com/drone/drone/plugins/registry"
"github.com/drone/drone/plugins/secrets"
"github.com/drone/drone/remote"
"github.com/drone/drone/remote/bitbucket"
"github.com/drone/drone/remote/bitbucketserver"
"github.com/drone/drone/remote/gitea"
"github.com/drone/drone/remote/github"
"github.com/drone/drone/remote/gitlab"
"github.com/drone/drone/remote/gogs"
"github.com/drone/drone/store"
"github.com/drone/drone/store/datastore"
@ -35,3 +44,95 @@ func setupRegistryService(c *cli.Context, s store.Store) model.RegistryService {
func setupPubsub(c *cli.Context) {}
func setupStream(c *cli.Command) {}
func setupGatingService(c *cli.Command) {}
// helper function to setup the remote from the CLI arguments.
func setupRemote(c *cli.Context) (remote.Remote, error) {
switch {
case c.Bool("github"):
return setupGithub(c)
case c.Bool("gitlab"):
return setupGitlab(c)
case c.Bool("bitbucket"):
return setupBitbucket(c)
case c.Bool("stash"):
return setupStash(c)
case c.Bool("gogs"):
return setupGogs(c)
case c.Bool("gitea"):
return setupGitea(c)
default:
return nil, fmt.Errorf("version control system not configured")
}
}
// helper function to setup the Bitbucket remote from the CLI arguments.
func setupBitbucket(c *cli.Context) (remote.Remote, error) {
return bitbucket.New(
c.String("bitbucket-client"),
c.String("bitbucket-secret"),
), nil
}
// helper function to setup the Gogs remote from the CLI arguments.
func setupGogs(c *cli.Context) (remote.Remote, error) {
return gogs.New(gogs.Opts{
URL: c.String("gogs-server"),
Username: c.String("gogs-git-username"),
Password: c.String("gogs-git-password"),
PrivateMode: c.Bool("gogs-private-mode"),
SkipVerify: c.Bool("gogs-skip-verify"),
})
}
// helper function to setup the Gitea remote from the CLI arguments.
func setupGitea(c *cli.Context) (remote.Remote, error) {
return gitea.New(gitea.Opts{
URL: c.String("gitea-server"),
Username: c.String("gitea-git-username"),
Password: c.String("gitea-git-password"),
PrivateMode: c.Bool("gitea-private-mode"),
SkipVerify: c.Bool("gitea-skip-verify"),
})
}
// helper function to setup the Stash remote from the CLI arguments.
func setupStash(c *cli.Context) (remote.Remote, error) {
return bitbucketserver.New(bitbucketserver.Opts{
URL: c.String("stash-server"),
Username: c.String("stash-git-username"),
Password: c.String("stash-git-password"),
ConsumerKey: c.String("stash-consumer-key"),
ConsumerRSA: c.String("stash-consumer-rsa"),
ConsumerRSAString: c.String("stash-consumer-rsa-string"),
SkipVerify: c.Bool("stash-skip-verify"),
})
}
// helper function to setup the Gitlab remote from the CLI arguments.
func setupGitlab(c *cli.Context) (remote.Remote, error) {
return gitlab.New(gitlab.Opts{
URL: c.String("gitlab-server"),
Client: c.String("gitlab-client"),
Secret: c.String("gitlab-secret"),
Username: c.String("gitlab-git-username"),
Password: c.String("gitlab-git-password"),
PrivateMode: c.Bool("gitlab-private-mode"),
SkipVerify: c.Bool("gitlab-skip-verify"),
})
}
// helper function to setup the GitHub remote from the CLI arguments.
func setupGithub(c *cli.Context) (remote.Remote, error) {
return github.New(github.Opts{
URL: c.String("github-server"),
Context: c.String("github-context"),
Client: c.String("github-client"),
Secret: c.String("github-secret"),
Scopes: c.StringSlice("github-scope"),
Username: c.String("github-git-username"),
Password: c.String("github-git-password"),
PrivateMode: c.Bool("github-private-mode"),
SkipVerify: c.Bool("github-skip-verify"),
MergeRef: c.BoolT("github-merge-ref"),
})
}

View file

@ -62,7 +62,7 @@ func (q *persistentQueue) Poll(c context.Context, f queue.Filter) (*queue.Task,
if derr := q.store.TaskDelete(task.ID); derr != nil {
logrus.Errorf("pull queue item: %s: failed to remove from backup: %s", task.ID, derr)
} else {
logrus.Errorf("pull queue item: %s: successfully removed from backup", task.ID)
logrus.Debugf("pull queue item: %s: successfully removed from backup", task.ID)
}
}
return task, err

View file

@ -1,120 +1,14 @@
package middleware
import (
"fmt"
"github.com/Sirupsen/logrus"
"github.com/drone/drone/remote"
"github.com/drone/drone/remote/bitbucket"
"github.com/drone/drone/remote/bitbucketserver"
"github.com/drone/drone/remote/gitea"
"github.com/drone/drone/remote/github"
"github.com/drone/drone/remote/gitlab"
"github.com/drone/drone/remote/gogs"
"github.com/gin-gonic/gin"
"github.com/urfave/cli"
)
// Remote is a middleware function that initializes the Remote and attaches to
// the context of every http.Request.
func Remote(c *cli.Context) gin.HandlerFunc {
v, err := setupRemote(c)
if err != nil {
logrus.Fatalln(err)
}
func Remote(v remote.Remote) gin.HandlerFunc {
return func(c *gin.Context) {
remote.ToContext(c, v)
}
}
// helper function to setup the remote from the CLI arguments.
func setupRemote(c *cli.Context) (remote.Remote, error) {
switch {
case c.Bool("github"):
return setupGithub(c)
case c.Bool("gitlab"):
return setupGitlab(c)
case c.Bool("bitbucket"):
return setupBitbucket(c)
case c.Bool("stash"):
return setupStash(c)
case c.Bool("gogs"):
return setupGogs(c)
case c.Bool("gitea"):
return setupGitea(c)
default:
return nil, fmt.Errorf("version control system not configured")
}
}
// helper function to setup the Bitbucket remote from the CLI arguments.
func setupBitbucket(c *cli.Context) (remote.Remote, error) {
return bitbucket.New(
c.String("bitbucket-client"),
c.String("bitbucket-secret"),
), nil
}
// helper function to setup the Gogs remote from the CLI arguments.
func setupGogs(c *cli.Context) (remote.Remote, error) {
return gogs.New(gogs.Opts{
URL: c.String("gogs-server"),
Username: c.String("gogs-git-username"),
Password: c.String("gogs-git-password"),
PrivateMode: c.Bool("gogs-private-mode"),
SkipVerify: c.Bool("gogs-skip-verify"),
})
}
// helper function to setup the Gitea remote from the CLI arguments.
func setupGitea(c *cli.Context) (remote.Remote, error) {
return gitea.New(gitea.Opts{
URL: c.String("gitea-server"),
Username: c.String("gitea-git-username"),
Password: c.String("gitea-git-password"),
PrivateMode: c.Bool("gitea-private-mode"),
SkipVerify: c.Bool("gitea-skip-verify"),
})
}
// helper function to setup the Stash remote from the CLI arguments.
func setupStash(c *cli.Context) (remote.Remote, error) {
return bitbucketserver.New(bitbucketserver.Opts{
URL: c.String("stash-server"),
Username: c.String("stash-git-username"),
Password: c.String("stash-git-password"),
ConsumerKey: c.String("stash-consumer-key"),
ConsumerRSA: c.String("stash-consumer-rsa"),
ConsumerRSAString: c.String("stash-consumer-rsa-string"),
SkipVerify: c.Bool("stash-skip-verify"),
})
}
// helper function to setup the Gitlab remote from the CLI arguments.
func setupGitlab(c *cli.Context) (remote.Remote, error) {
return gitlab.New(gitlab.Opts{
URL: c.String("gitlab-server"),
Client: c.String("gitlab-client"),
Secret: c.String("gitlab-secret"),
Username: c.String("gitlab-git-username"),
Password: c.String("gitlab-git-password"),
PrivateMode: c.Bool("gitlab-private-mode"),
SkipVerify: c.Bool("gitlab-skip-verify"),
})
}
// helper function to setup the GitHub remote from the CLI arguments.
func setupGithub(c *cli.Context) (remote.Remote, error) {
return github.New(github.Opts{
URL: c.String("github-server"),
Context: c.String("github-context"),
Client: c.String("github-client"),
Secret: c.String("github-secret"),
Scopes: c.StringSlice("github-scope"),
Username: c.String("github-git-username"),
Password: c.String("github-git-password"),
PrivateMode: c.Bool("github-private-mode"),
SkipVerify: c.Bool("github-skip-verify"),
MergeRef: c.BoolT("github-merge-ref"),
})
}

View file

@ -80,7 +80,6 @@ func Load(middleware ...gin.HandlerFunc) http.Handler {
repo.GET("/builds", server.GetBuilds)
repo.GET("/builds/:number", server.GetBuild)
repo.GET("/logs/:number/:ppid/:proc", server.GetBuildLogs)
repo.POST("/sign", session.MustPush, server.Sign)
// requires push permissions
repo.GET("/secrets", session.MustPush, server.GetSecretList)
@ -120,8 +119,6 @@ func Load(middleware ...gin.HandlerFunc) http.Handler {
ws := e.Group("/ws")
{
ws.GET("/broker", server.RPCHandler)
ws.GET("/rpc", server.RPCHandler)
ws.GET("/feed", server.EventStream)
ws.GET("/logs/:owner/:name/:build/:number",
session.SetRepo(),

View file

@ -8,18 +8,18 @@ import (
"log"
"strconv"
oldcontext "golang.org/x/net/context"
"github.com/Sirupsen/logrus"
"github.com/cncd/logging"
"github.com/cncd/pipeline/pipeline/rpc"
"github.com/cncd/pipeline/pipeline/rpc/proto"
"github.com/cncd/pubsub"
"github.com/cncd/queue"
"github.com/coreos/go-semver/semver"
"github.com/gin-gonic/gin"
"github.com/drone/drone/model"
"github.com/drone/drone/remote"
"github.com/drone/drone/store"
"github.com/drone/drone/version"
)
// This file is a complete disaster because I'm trying to wedge in some
@ -66,64 +66,6 @@ var Config = struct {
}
}{}
// var config = struct {
// pubsub pubsub.Publisher
// queue queue.Queue
// logger logging.Log
// secret string
// host string
// }{
// pubsub.New(),
// queue.New(),
// logging.New(),
// os.Getenv("DRONE_SECRET"),
// os.Getenv("DRONE_HOST"),
// }
// func SetupRPC() gin.HandlerFunc {
// return func(c *gin.Context) {
// c.Next()
// }
// }
func RPCHandler(c *gin.Context) {
if secret := c.Request.Header.Get("Authorization"); secret != "Bearer "+Config.Server.Pass {
log.Printf("Unable to connect agent. Invalid authorization token %q does not match %q", secret, Config.Server.Pass)
c.String(401, "Unable to connect agent. Invalid authorization token")
return
}
agent := semver.New(
c.Request.Header.Get("X-Drone-Version"),
)
logrus.Debugf("agent connected: ip address %s: version %s", c.ClientIP(), agent)
// if agent.LessThan(version.Version) {
// logrus.Warnf("Version mismatch. Agent version %s < Server version %s", agent, version.Version)
// c.String(409, "Version mismatch. Agent version %s < Server version %s", agent, version.Version)
// return
// }
switch agent.Minor {
case 6, 7:
// these versions are ok
default:
logrus.Warnf("Version mismatch. Agent version %s < Server version %s", agent, version.Version)
c.String(409, "Version mismatch. Agent version %s < Server version %s", agent, version.Version)
return
}
peer := RPC{
remote: remote.FromContext(c),
store: store.FromContext(c),
queue: Config.Services.Queue,
pubsub: Config.Services.Pubsub,
logger: Config.Services.Logs,
host: Config.Server.Host,
}
rpc.NewServer(&peer).ServeHTTP(c.Writer, c.Request)
}
type RPC struct {
remote remote.Remote
queue queue.Queue
@ -470,3 +412,219 @@ func (s *RPC) checkCancelled(pipeline *rpc.Pipeline) (bool, error) {
}
return false, err
}
//
//
//
// DroneServer is a grpc server implementation.
type DroneServer struct {
Remote remote.Remote
Queue queue.Queue
Pubsub pubsub.Publisher
Logger logging.Log
Store store.Store
Host string
}
func (s *DroneServer) Next(c oldcontext.Context, req *proto.NextRequest) (*proto.NextReply, error) {
peer := RPC{
remote: s.Remote,
store: s.Store,
queue: s.Queue,
pubsub: s.Pubsub,
logger: s.Logger,
host: s.Host,
}
filter := rpc.Filter{
Labels: req.GetFilter().GetLabels(),
}
res := new(proto.NextReply)
pipeline, err := peer.Next(c, filter)
if err != nil {
return res, err
}
if pipeline == nil {
return res, err
}
res.Pipeline = new(proto.Pipeline)
res.Pipeline.Id = pipeline.ID
res.Pipeline.Timeout = pipeline.Timeout
res.Pipeline.Payload, _ = json.Marshal(pipeline.Config)
return res, err
// fn := func(task *queue.Task) bool {
// for k, v := range req.GetFilter().Labels {
// if task.Labels[k] != v {
// return false
// }
// }
// return true
// }
// task, err := s.Queue.Poll(c, fn)
// if err != nil {
// return nil, err
// } else if task == nil {
// return nil, nil
// }
//
// pipeline := new(rpc.Pipeline)
// json.Unmarshal(task.Data, pipeline)
//
// res := new(proto.NextReply)
// res.Pipeline = new(proto.Pipeline)
// res.Pipeline.Id = pipeline.ID
// res.Pipeline.Timeout = pipeline.Timeout
// res.Pipeline.Payload, _ = json.Marshal(pipeline.Config)
//
// // check if the process was previously cancelled
// // cancelled, _ := s.checkCancelled(pipeline)
// // if cancelled {
// // logrus.Debugf("ignore pid %v: cancelled by user", pipeline.ID)
// // if derr := s.queue.Done(c, pipeline.ID); derr != nil {
// // logrus.Errorf("error: done: cannot ack proc_id %v: %s", pipeline.ID, err)
// // }
// // return nil, nil
// // }
//
// return res, nil
}
func (s *DroneServer) Init(c oldcontext.Context, req *proto.InitRequest) (*proto.Empty, error) {
peer := RPC{
remote: s.Remote,
store: s.Store,
queue: s.Queue,
pubsub: s.Pubsub,
logger: s.Logger,
host: s.Host,
}
state := rpc.State{
Error: req.GetState().GetError(),
ExitCode: int(req.GetState().GetExitCode()),
Finished: req.GetState().GetFinished(),
Started: req.GetState().GetStarted(),
Proc: req.GetState().GetName(),
Exited: req.GetState().GetExited(),
}
res := new(proto.Empty)
err := peer.Init(c, req.GetId(), state)
return res, err
}
func (s *DroneServer) Update(c oldcontext.Context, req *proto.UpdateRequest) (*proto.Empty, error) {
peer := RPC{
remote: s.Remote,
store: s.Store,
queue: s.Queue,
pubsub: s.Pubsub,
logger: s.Logger,
host: s.Host,
}
state := rpc.State{
Error: req.GetState().GetError(),
ExitCode: int(req.GetState().GetExitCode()),
Finished: req.GetState().GetFinished(),
Started: req.GetState().GetStarted(),
Proc: req.GetState().GetName(),
Exited: req.GetState().GetExited(),
}
res := new(proto.Empty)
err := peer.Update(c, req.GetId(), state)
return res, err
}
func (s *DroneServer) Upload(c oldcontext.Context, req *proto.UploadRequest) (*proto.Empty, error) {
peer := RPC{
remote: s.Remote,
store: s.Store,
queue: s.Queue,
pubsub: s.Pubsub,
logger: s.Logger,
host: s.Host,
}
file := &rpc.File{
Data: req.GetFile().GetData(),
Mime: req.GetFile().GetMime(),
Name: req.GetFile().GetName(),
Proc: req.GetFile().GetProc(),
Size: int(req.GetFile().GetSize()),
Time: req.GetFile().GetTime(),
}
res := new(proto.Empty)
err := peer.Upload(c, req.GetId(), file)
return res, err
}
func (s *DroneServer) Done(c oldcontext.Context, req *proto.DoneRequest) (*proto.Empty, error) {
peer := RPC{
remote: s.Remote,
store: s.Store,
queue: s.Queue,
pubsub: s.Pubsub,
logger: s.Logger,
host: s.Host,
}
state := rpc.State{
Error: req.GetState().GetError(),
ExitCode: int(req.GetState().GetExitCode()),
Finished: req.GetState().GetFinished(),
Started: req.GetState().GetStarted(),
Proc: req.GetState().GetName(),
Exited: req.GetState().GetExited(),
}
res := new(proto.Empty)
err := peer.Done(c, req.GetId(), state)
return res, err
}
func (s *DroneServer) Wait(c oldcontext.Context, req *proto.WaitRequest) (*proto.Empty, error) {
peer := RPC{
remote: s.Remote,
store: s.Store,
queue: s.Queue,
pubsub: s.Pubsub,
logger: s.Logger,
host: s.Host,
}
res := new(proto.Empty)
err := peer.Wait(c, req.GetId())
return res, err
}
func (s *DroneServer) Extend(c oldcontext.Context, req *proto.ExtendRequest) (*proto.Empty, error) {
peer := RPC{
remote: s.Remote,
store: s.Store,
queue: s.Queue,
pubsub: s.Pubsub,
logger: s.Logger,
host: s.Host,
}
res := new(proto.Empty)
err := peer.Extend(c, req.GetId())
return res, err
}
func (s *DroneServer) Log(c oldcontext.Context, req *proto.LogRequest) (*proto.Empty, error) {
peer := RPC{
remote: s.Remote,
store: s.Store,
queue: s.Queue,
pubsub: s.Pubsub,
logger: s.Logger,
host: s.Host,
}
line := &rpc.Line{
Out: req.GetLine().GetOut(),
Pos: int(req.GetLine().GetPos()),
Time: req.GetLine().GetTime(),
Proc: req.GetLine().GetProc(),
}
res := new(proto.Empty)
err := peer.Log(c, req.GetId(), line)
return res, err
}

View file

@ -1,40 +0,0 @@
package server
import (
"io/ioutil"
"github.com/drone/drone/router/middleware/session"
"github.com/gin-gonic/gin"
"github.com/square/go-jose"
)
func Sign(c *gin.Context) {
repo := session.Repo(c)
in, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
c.String(400, "Unable to read request body. %s.", err.Error())
return
}
signer, err := jose.NewSigner(jose.HS256, []byte(repo.Hash))
if err != nil {
c.String(500, "Unable to create the signer. %s.", err.Error())
return
}
signed, err := signer.Sign(in)
if err != nil {
c.String(500, "Unable to sign input. %s", err.Error())
return
}
out, err := signed.CompactSerialize()
if err != nil {
c.String(500, "Unable to serialize signature. %s", err.Error())
return
}
c.String(200, out)
}

View file

@ -1,29 +0,0 @@
BSD 3-Clause License
Copyright (c) 2017, Brad Rydzewski
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,230 @@
package rpc
import (
"context"
"encoding/json"
"time"
"github.com/cncd/pipeline/pipeline/backend"
"github.com/cncd/pipeline/pipeline/rpc/proto"
"google.golang.org/grpc"
)
type client struct {
client proto.DroneClient
conn *grpc.ClientConn
}
// NewGrpcClient returns a new grpc Client.
func NewGrpcClient(conn *grpc.ClientConn) Peer {
client := new(client)
client.client = proto.NewDroneClient(conn)
client.conn = conn
return client
}
func (c *client) Close() error {
return c.conn.Close()
}
// Next returns the next pipeline in the queue.
func (c *client) Next(ctx context.Context, f Filter) (*Pipeline, error) {
var res *proto.NextReply
var err error
req := new(proto.NextRequest)
req.Filter = new(proto.Filter)
req.Filter.Expr = f.Expr
req.Filter.Labels = f.Labels
for {
res, err = c.client.Next(ctx, req)
//
// TODO error type
//
if err == nil {
break
}
println("error getting next execution. retry. " + err.Error())
select {
case <-time.After(1 * time.Second):
}
}
if res.GetPipeline() == nil {
return nil, nil
}
p := new(Pipeline)
p.ID = res.GetPipeline().GetId()
p.Timeout = res.GetPipeline().GetTimeout()
p.Config = new(backend.Config)
json.Unmarshal(res.GetPipeline().GetPayload(), p.Config)
return p, nil
}
// Wait blocks until the pipeline is complete.
func (c *client) Wait(ctx context.Context, id string) (err error) {
req := new(proto.WaitRequest)
req.Id = id
for {
_, err = c.client.Wait(ctx, req)
//
// TODO error type
//
if err == nil {
break
}
select {
case <-time.After(1 * time.Second):
}
}
return nil
}
// Init signals the pipeline is initialized.
func (c *client) Init(ctx context.Context, id string, state State) (err error) {
req := new(proto.InitRequest)
req.Id = id
req.State = new(proto.State)
req.State.Error = state.Error
req.State.ExitCode = int32(state.ExitCode)
req.State.Exited = state.Exited
req.State.Finished = state.Finished
req.State.Started = state.Started
req.State.Name = state.Proc
for {
_, err = c.client.Init(ctx, req)
//
// TODO error type
//
if err == nil {
break
}
select {
case <-time.After(1 * time.Second):
}
}
return nil
}
// Done signals the pipeline is complete.
func (c *client) Done(ctx context.Context, id string, state State) (err error) {
req := new(proto.DoneRequest)
req.Id = id
req.State = new(proto.State)
req.State.Error = state.Error
req.State.ExitCode = int32(state.ExitCode)
req.State.Exited = state.Exited
req.State.Finished = state.Finished
req.State.Started = state.Started
req.State.Name = state.Proc
for {
_, err = c.client.Done(ctx, req)
//
// TODO error type
//
if err == nil {
break
}
select {
case <-time.After(1 * time.Second):
}
}
return nil
}
// Extend extends the pipeline deadline
func (c *client) Extend(ctx context.Context, id string) (err error) {
req := new(proto.ExtendRequest)
req.Id = id
for {
_, err = c.client.Extend(ctx, req)
//
// TODO error type
//
if err == nil {
break
}
select {
case <-time.After(1 * time.Second):
}
}
return nil
}
// Update updates the pipeline state.
func (c *client) Update(ctx context.Context, id string, state State) (err error) {
req := new(proto.UpdateRequest)
req.Id = id
req.State = new(proto.State)
req.State.Error = state.Error
req.State.ExitCode = int32(state.ExitCode)
req.State.Exited = state.Exited
req.State.Finished = state.Finished
req.State.Started = state.Started
req.State.Name = state.Proc
for {
_, err = c.client.Update(ctx, req)
//
// TODO error type
//
if err == nil {
break
}
select {
case <-time.After(1 * time.Second):
}
}
return nil
}
// Upload uploads the pipeline artifact.
func (c *client) Upload(ctx context.Context, id string, file *File) (err error) {
req := new(proto.UploadRequest)
req.Id = id
req.File = new(proto.File)
req.File.Name = file.Name
req.File.Mime = file.Mime
req.File.Proc = file.Proc
req.File.Size = int32(file.Size)
req.File.Time = file.Time
req.File.Data = file.Data
for {
_, err = c.client.Upload(ctx, req)
//
// TODO error type
//
if err == nil {
break
}
select {
case <-time.After(1 * time.Second):
}
}
return nil
}
// Log writes the pipeline log entry.
func (c *client) Log(ctx context.Context, id string, line *Line) (err error) {
req := new(proto.LogRequest)
req.Id = id
req.Line = new(proto.Line)
req.Line.Out = line.Out
req.Line.Pos = int32(line.Pos)
req.Line.Proc = line.Proc
req.Line.Time = line.Time
for {
_, err = c.client.Log(ctx, req)
//
// TODO error type
//
if err == nil {
break
}
select {
case <-time.After(1 * time.Second):
}
}
return nil
}

View file

@ -0,0 +1,814 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: drone.proto
/*
Package proto is a generated protocol buffer package.
It is generated from these files:
drone.proto
It has these top-level messages:
File
State
Line
Filter
Pipeline
NextRequest
NextReply
InitRequest
WaitRequest
DoneRequest
ExtendRequest
UploadRequest
UpdateRequest
LogRequest
Empty
*/
package proto
import proto1 "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto1.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto1.ProtoPackageIsVersion2 // please upgrade the proto package
type File struct {
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
Proc string `protobuf:"bytes,2,opt,name=proc" json:"proc,omitempty"`
Mime string `protobuf:"bytes,3,opt,name=mime" json:"mime,omitempty"`
Time int64 `protobuf:"varint,4,opt,name=time" json:"time,omitempty"`
Size int32 `protobuf:"varint,5,opt,name=size" json:"size,omitempty"`
Data []byte `protobuf:"bytes,6,opt,name=data,proto3" json:"data,omitempty"`
}
func (m *File) Reset() { *m = File{} }
func (m *File) String() string { return proto1.CompactTextString(m) }
func (*File) ProtoMessage() {}
func (*File) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *File) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *File) GetProc() string {
if m != nil {
return m.Proc
}
return ""
}
func (m *File) GetMime() string {
if m != nil {
return m.Mime
}
return ""
}
func (m *File) GetTime() int64 {
if m != nil {
return m.Time
}
return 0
}
func (m *File) GetSize() int32 {
if m != nil {
return m.Size
}
return 0
}
func (m *File) GetData() []byte {
if m != nil {
return m.Data
}
return nil
}
type State struct {
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
Exited bool `protobuf:"varint,2,opt,name=exited" json:"exited,omitempty"`
ExitCode int32 `protobuf:"varint,3,opt,name=exit_code,json=exitCode" json:"exit_code,omitempty"`
Started int64 `protobuf:"varint,4,opt,name=started" json:"started,omitempty"`
Finished int64 `protobuf:"varint,5,opt,name=finished" json:"finished,omitempty"`
Error string `protobuf:"bytes,6,opt,name=error" json:"error,omitempty"`
}
func (m *State) Reset() { *m = State{} }
func (m *State) String() string { return proto1.CompactTextString(m) }
func (*State) ProtoMessage() {}
func (*State) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *State) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *State) GetExited() bool {
if m != nil {
return m.Exited
}
return false
}
func (m *State) GetExitCode() int32 {
if m != nil {
return m.ExitCode
}
return 0
}
func (m *State) GetStarted() int64 {
if m != nil {
return m.Started
}
return 0
}
func (m *State) GetFinished() int64 {
if m != nil {
return m.Finished
}
return 0
}
func (m *State) GetError() string {
if m != nil {
return m.Error
}
return ""
}
type Line struct {
Proc string `protobuf:"bytes,1,opt,name=proc" json:"proc,omitempty"`
Time int64 `protobuf:"varint,2,opt,name=time" json:"time,omitempty"`
Pos int32 `protobuf:"varint,3,opt,name=pos" json:"pos,omitempty"`
Out string `protobuf:"bytes,4,opt,name=out" json:"out,omitempty"`
}
func (m *Line) Reset() { *m = Line{} }
func (m *Line) String() string { return proto1.CompactTextString(m) }
func (*Line) ProtoMessage() {}
func (*Line) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
func (m *Line) GetProc() string {
if m != nil {
return m.Proc
}
return ""
}
func (m *Line) GetTime() int64 {
if m != nil {
return m.Time
}
return 0
}
func (m *Line) GetPos() int32 {
if m != nil {
return m.Pos
}
return 0
}
func (m *Line) GetOut() string {
if m != nil {
return m.Out
}
return ""
}
type Filter struct {
Labels map[string]string `protobuf:"bytes,1,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
Expr string `protobuf:"bytes,2,opt,name=expr" json:"expr,omitempty"`
}
func (m *Filter) Reset() { *m = Filter{} }
func (m *Filter) String() string { return proto1.CompactTextString(m) }
func (*Filter) ProtoMessage() {}
func (*Filter) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (m *Filter) GetLabels() map[string]string {
if m != nil {
return m.Labels
}
return nil
}
func (m *Filter) GetExpr() string {
if m != nil {
return m.Expr
}
return ""
}
type Pipeline struct {
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
Timeout int64 `protobuf:"varint,2,opt,name=timeout" json:"timeout,omitempty"`
Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
}
func (m *Pipeline) Reset() { *m = Pipeline{} }
func (m *Pipeline) String() string { return proto1.CompactTextString(m) }
func (*Pipeline) ProtoMessage() {}
func (*Pipeline) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
func (m *Pipeline) GetId() string {
if m != nil {
return m.Id
}
return ""
}
func (m *Pipeline) GetTimeout() int64 {
if m != nil {
return m.Timeout
}
return 0
}
func (m *Pipeline) GetPayload() []byte {
if m != nil {
return m.Payload
}
return nil
}
type NextRequest struct {
Filter *Filter `protobuf:"bytes,1,opt,name=filter" json:"filter,omitempty"`
}
func (m *NextRequest) Reset() { *m = NextRequest{} }
func (m *NextRequest) String() string { return proto1.CompactTextString(m) }
func (*NextRequest) ProtoMessage() {}
func (*NextRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
func (m *NextRequest) GetFilter() *Filter {
if m != nil {
return m.Filter
}
return nil
}
type NextReply struct {
Pipeline *Pipeline `protobuf:"bytes,1,opt,name=pipeline" json:"pipeline,omitempty"`
}
func (m *NextReply) Reset() { *m = NextReply{} }
func (m *NextReply) String() string { return proto1.CompactTextString(m) }
func (*NextReply) ProtoMessage() {}
func (*NextReply) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
func (m *NextReply) GetPipeline() *Pipeline {
if m != nil {
return m.Pipeline
}
return nil
}
type InitRequest struct {
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
State *State `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"`
}
func (m *InitRequest) Reset() { *m = InitRequest{} }
func (m *InitRequest) String() string { return proto1.CompactTextString(m) }
func (*InitRequest) ProtoMessage() {}
func (*InitRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
func (m *InitRequest) GetId() string {
if m != nil {
return m.Id
}
return ""
}
func (m *InitRequest) GetState() *State {
if m != nil {
return m.State
}
return nil
}
type WaitRequest struct {
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
}
func (m *WaitRequest) Reset() { *m = WaitRequest{} }
func (m *WaitRequest) String() string { return proto1.CompactTextString(m) }
func (*WaitRequest) ProtoMessage() {}
func (*WaitRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
func (m *WaitRequest) GetId() string {
if m != nil {
return m.Id
}
return ""
}
type DoneRequest struct {
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
State *State `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"`
}
func (m *DoneRequest) Reset() { *m = DoneRequest{} }
func (m *DoneRequest) String() string { return proto1.CompactTextString(m) }
func (*DoneRequest) ProtoMessage() {}
func (*DoneRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
func (m *DoneRequest) GetId() string {
if m != nil {
return m.Id
}
return ""
}
func (m *DoneRequest) GetState() *State {
if m != nil {
return m.State
}
return nil
}
type ExtendRequest struct {
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
}
func (m *ExtendRequest) Reset() { *m = ExtendRequest{} }
func (m *ExtendRequest) String() string { return proto1.CompactTextString(m) }
func (*ExtendRequest) ProtoMessage() {}
func (*ExtendRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
func (m *ExtendRequest) GetId() string {
if m != nil {
return m.Id
}
return ""
}
type UploadRequest struct {
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
File *File `protobuf:"bytes,2,opt,name=file" json:"file,omitempty"`
}
func (m *UploadRequest) Reset() { *m = UploadRequest{} }
func (m *UploadRequest) String() string { return proto1.CompactTextString(m) }
func (*UploadRequest) ProtoMessage() {}
func (*UploadRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
func (m *UploadRequest) GetId() string {
if m != nil {
return m.Id
}
return ""
}
func (m *UploadRequest) GetFile() *File {
if m != nil {
return m.File
}
return nil
}
type UpdateRequest struct {
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
State *State `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"`
}
func (m *UpdateRequest) Reset() { *m = UpdateRequest{} }
func (m *UpdateRequest) String() string { return proto1.CompactTextString(m) }
func (*UpdateRequest) ProtoMessage() {}
func (*UpdateRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
func (m *UpdateRequest) GetId() string {
if m != nil {
return m.Id
}
return ""
}
func (m *UpdateRequest) GetState() *State {
if m != nil {
return m.State
}
return nil
}
type LogRequest struct {
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
Line *Line `protobuf:"bytes,2,opt,name=line" json:"line,omitempty"`
}
func (m *LogRequest) Reset() { *m = LogRequest{} }
func (m *LogRequest) String() string { return proto1.CompactTextString(m) }
func (*LogRequest) ProtoMessage() {}
func (*LogRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
func (m *LogRequest) GetId() string {
if m != nil {
return m.Id
}
return ""
}
func (m *LogRequest) GetLine() *Line {
if m != nil {
return m.Line
}
return nil
}
type Empty struct {
}
func (m *Empty) Reset() { *m = Empty{} }
func (m *Empty) String() string { return proto1.CompactTextString(m) }
func (*Empty) ProtoMessage() {}
func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
func init() {
proto1.RegisterType((*File)(nil), "proto.File")
proto1.RegisterType((*State)(nil), "proto.State")
proto1.RegisterType((*Line)(nil), "proto.Line")
proto1.RegisterType((*Filter)(nil), "proto.Filter")
proto1.RegisterType((*Pipeline)(nil), "proto.Pipeline")
proto1.RegisterType((*NextRequest)(nil), "proto.NextRequest")
proto1.RegisterType((*NextReply)(nil), "proto.NextReply")
proto1.RegisterType((*InitRequest)(nil), "proto.InitRequest")
proto1.RegisterType((*WaitRequest)(nil), "proto.WaitRequest")
proto1.RegisterType((*DoneRequest)(nil), "proto.DoneRequest")
proto1.RegisterType((*ExtendRequest)(nil), "proto.ExtendRequest")
proto1.RegisterType((*UploadRequest)(nil), "proto.UploadRequest")
proto1.RegisterType((*UpdateRequest)(nil), "proto.UpdateRequest")
proto1.RegisterType((*LogRequest)(nil), "proto.LogRequest")
proto1.RegisterType((*Empty)(nil), "proto.Empty")
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// Client API for Drone service
type DroneClient interface {
Next(ctx context.Context, in *NextRequest, opts ...grpc.CallOption) (*NextReply, error)
Init(ctx context.Context, in *InitRequest, opts ...grpc.CallOption) (*Empty, error)
Wait(ctx context.Context, in *WaitRequest, opts ...grpc.CallOption) (*Empty, error)
Done(ctx context.Context, in *DoneRequest, opts ...grpc.CallOption) (*Empty, error)
Extend(ctx context.Context, in *ExtendRequest, opts ...grpc.CallOption) (*Empty, error)
Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*Empty, error)
Upload(ctx context.Context, in *UploadRequest, opts ...grpc.CallOption) (*Empty, error)
Log(ctx context.Context, in *LogRequest, opts ...grpc.CallOption) (*Empty, error)
}
type droneClient struct {
cc *grpc.ClientConn
}
func NewDroneClient(cc *grpc.ClientConn) DroneClient {
return &droneClient{cc}
}
func (c *droneClient) Next(ctx context.Context, in *NextRequest, opts ...grpc.CallOption) (*NextReply, error) {
out := new(NextReply)
err := grpc.Invoke(ctx, "/proto.Drone/Next", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *droneClient) Init(ctx context.Context, in *InitRequest, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := grpc.Invoke(ctx, "/proto.Drone/Init", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *droneClient) Wait(ctx context.Context, in *WaitRequest, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := grpc.Invoke(ctx, "/proto.Drone/Wait", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *droneClient) Done(ctx context.Context, in *DoneRequest, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := grpc.Invoke(ctx, "/proto.Drone/Done", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *droneClient) Extend(ctx context.Context, in *ExtendRequest, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := grpc.Invoke(ctx, "/proto.Drone/Extend", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *droneClient) Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := grpc.Invoke(ctx, "/proto.Drone/Update", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *droneClient) Upload(ctx context.Context, in *UploadRequest, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := grpc.Invoke(ctx, "/proto.Drone/Upload", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *droneClient) Log(ctx context.Context, in *LogRequest, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := grpc.Invoke(ctx, "/proto.Drone/Log", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for Drone service
type DroneServer interface {
Next(context.Context, *NextRequest) (*NextReply, error)
Init(context.Context, *InitRequest) (*Empty, error)
Wait(context.Context, *WaitRequest) (*Empty, error)
Done(context.Context, *DoneRequest) (*Empty, error)
Extend(context.Context, *ExtendRequest) (*Empty, error)
Update(context.Context, *UpdateRequest) (*Empty, error)
Upload(context.Context, *UploadRequest) (*Empty, error)
Log(context.Context, *LogRequest) (*Empty, error)
}
func RegisterDroneServer(s *grpc.Server, srv DroneServer) {
s.RegisterService(&_Drone_serviceDesc, srv)
}
func _Drone_Next_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(NextRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DroneServer).Next(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/proto.Drone/Next",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DroneServer).Next(ctx, req.(*NextRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Drone_Init_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(InitRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DroneServer).Init(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/proto.Drone/Init",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DroneServer).Init(ctx, req.(*InitRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Drone_Wait_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(WaitRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DroneServer).Wait(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/proto.Drone/Wait",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DroneServer).Wait(ctx, req.(*WaitRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Drone_Done_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DoneRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DroneServer).Done(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/proto.Drone/Done",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DroneServer).Done(ctx, req.(*DoneRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Drone_Extend_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ExtendRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DroneServer).Extend(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/proto.Drone/Extend",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DroneServer).Extend(ctx, req.(*ExtendRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Drone_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DroneServer).Update(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/proto.Drone/Update",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DroneServer).Update(ctx, req.(*UpdateRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Drone_Upload_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UploadRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DroneServer).Upload(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/proto.Drone/Upload",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DroneServer).Upload(ctx, req.(*UploadRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Drone_Log_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LogRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DroneServer).Log(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/proto.Drone/Log",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DroneServer).Log(ctx, req.(*LogRequest))
}
return interceptor(ctx, in, info, handler)
}
var _Drone_serviceDesc = grpc.ServiceDesc{
ServiceName: "proto.Drone",
HandlerType: (*DroneServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Next",
Handler: _Drone_Next_Handler,
},
{
MethodName: "Init",
Handler: _Drone_Init_Handler,
},
{
MethodName: "Wait",
Handler: _Drone_Wait_Handler,
},
{
MethodName: "Done",
Handler: _Drone_Done_Handler,
},
{
MethodName: "Extend",
Handler: _Drone_Extend_Handler,
},
{
MethodName: "Update",
Handler: _Drone_Update_Handler,
},
{
MethodName: "Upload",
Handler: _Drone_Upload_Handler,
},
{
MethodName: "Log",
Handler: _Drone_Log_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "drone.proto",
}
func init() { proto1.RegisterFile("drone.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 625 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x5d, 0x6b, 0xd4, 0x40,
0x14, 0x35, 0x9f, 0xdd, 0xbd, 0x69, 0xb5, 0x0e, 0x45, 0xe2, 0x8a, 0x74, 0x19, 0x10, 0x82, 0xc2,
0x82, 0xab, 0x0f, 0x55, 0x10, 0x94, 0x7e, 0x80, 0xb0, 0x14, 0x19, 0x11, 0x1f, 0x25, 0x6d, 0xa6,
0x75, 0x30, 0x9b, 0x89, 0xc9, 0xac, 0x6c, 0x7c, 0xf0, 0x07, 0xf8, 0x1b, 0xfc, 0x9b, 0xbe, 0xcb,
0x9d, 0x99, 0xa4, 0xd9, 0x76, 0xd7, 0x97, 0x3e, 0xf5, 0x7e, 0x9c, 0x3b, 0xf7, 0x9c, 0x7b, 0xd2,
0x85, 0x28, 0xab, 0x64, 0xc1, 0x27, 0x65, 0x25, 0x95, 0x24, 0x81, 0xfe, 0x43, 0x7f, 0x81, 0x7f,
0x22, 0x72, 0x4e, 0x08, 0xf8, 0x45, 0x3a, 0xe7, 0xb1, 0x33, 0x76, 0x92, 0x21, 0xd3, 0x31, 0xd6,
0xca, 0x4a, 0x9e, 0xc7, 0xae, 0xa9, 0x61, 0x8c, 0xb5, 0xb9, 0x98, 0xf3, 0xd8, 0x33, 0x35, 0x8c,
0xb1, 0xa6, 0xb0, 0xe6, 0x8f, 0x9d, 0xc4, 0x63, 0x3a, 0xc6, 0x5a, 0x2d, 0x7e, 0xf2, 0x38, 0x18,
0x3b, 0x49, 0xc0, 0x74, 0x8c, 0xb5, 0x2c, 0x55, 0x69, 0x1c, 0x8e, 0x9d, 0x64, 0x9b, 0xe9, 0x98,
0xfe, 0x71, 0x20, 0xf8, 0xa8, 0x52, 0xb5, 0x9e, 0xc1, 0x03, 0x08, 0xf9, 0x52, 0x28, 0x9e, 0x69,
0x0e, 0x03, 0x66, 0x33, 0xf2, 0x08, 0x86, 0x18, 0x7d, 0x39, 0x97, 0x99, 0xa1, 0x12, 0xb0, 0x01,
0x16, 0x0e, 0x65, 0xc6, 0x49, 0x0c, 0x5b, 0xb5, 0x4a, 0x2b, 0x9c, 0x32, 0x8c, 0xda, 0x94, 0x8c,
0x60, 0x70, 0x21, 0x0a, 0x51, 0x7f, 0xe5, 0x99, 0x26, 0xe6, 0xb1, 0x2e, 0x27, 0x7b, 0x10, 0xf0,
0xaa, 0x92, 0x95, 0x66, 0x37, 0x64, 0x26, 0xa1, 0x0c, 0xfc, 0x99, 0x28, 0xae, 0x4e, 0xe1, 0xac,
0x9e, 0x42, 0xcb, 0x76, 0x7b, 0xb2, 0x77, 0xc1, 0x2b, 0x65, 0x6d, 0x29, 0x61, 0x88, 0x15, 0xb9,
0x50, 0x9a, 0xc9, 0x90, 0x61, 0x48, 0x7f, 0x3b, 0x10, 0x9e, 0x88, 0x5c, 0xf1, 0x8a, 0x3c, 0x87,
0x30, 0x4f, 0xcf, 0x78, 0x5e, 0xc7, 0xce, 0xd8, 0x4b, 0xa2, 0xe9, 0x43, 0x63, 0xce, 0xc4, 0xb4,
0x27, 0x33, 0xdd, 0x3b, 0x2e, 0x54, 0xd5, 0x30, 0x0b, 0xc4, 0xad, 0x7c, 0x59, 0x56, 0xad, 0x29,
0x18, 0x8f, 0x5e, 0x41, 0xd4, 0x83, 0xe2, 0xca, 0x6f, 0xbc, 0xb1, 0x5c, 0x31, 0x44, 0x71, 0x3f,
0xd2, 0x7c, 0xc1, 0xed, 0x94, 0x49, 0x5e, 0xbb, 0x07, 0x0e, 0x3d, 0x85, 0xc1, 0x07, 0x51, 0xf2,
0x1c, 0x45, 0xde, 0x05, 0x57, 0x64, 0x76, 0xcc, 0x15, 0x19, 0x1e, 0x12, 0x45, 0x21, 0x7d, 0xa3,
0xb1, 0x4d, 0xb1, 0x53, 0xa6, 0x4d, 0x2e, 0xd3, 0x4c, 0x4b, 0xdd, 0x66, 0x6d, 0x4a, 0x5f, 0x42,
0x74, 0xca, 0x97, 0x8a, 0xf1, 0xef, 0x0b, 0x5e, 0x2b, 0xf2, 0x04, 0xc2, 0x0b, 0xad, 0x45, 0x3f,
0x1b, 0x4d, 0x77, 0x56, 0x04, 0x32, 0xdb, 0xa4, 0x07, 0x30, 0x34, 0x53, 0x65, 0xde, 0x90, 0x67,
0x30, 0x28, 0x2d, 0x25, 0x3b, 0x75, 0xcf, 0x4e, 0xb5, 0x4c, 0x59, 0x07, 0xa0, 0xef, 0x20, 0x7a,
0x5f, 0x88, 0x6e, 0xdf, 0x75, 0x09, 0x14, 0x82, 0x1a, 0xbf, 0x2e, 0x2d, 0x20, 0x9a, 0x6e, 0xdb,
0x87, 0xf4, 0x17, 0xc7, 0x4c, 0x8b, 0x3e, 0x86, 0xe8, 0x73, 0xba, 0xf1, 0x09, 0xdc, 0x70, 0x24,
0x0b, 0x7e, 0x9b, 0x0d, 0xfb, 0xb0, 0x73, 0xbc, 0x54, 0xbc, 0xc8, 0x36, 0xed, 0x78, 0x0b, 0x3b,
0x9f, 0x4a, 0xbc, 0xdf, 0xa6, 0x2d, 0xfb, 0xe0, 0x5f, 0x88, 0xbc, 0x5d, 0x12, 0x5d, 0x5d, 0x91,
0x33, 0xdd, 0xa0, 0x87, 0xf8, 0x42, 0x86, 0x3b, 0x6f, 0xc1, 0xf3, 0x0d, 0xc0, 0x4c, 0x5e, 0xfe,
0x87, 0x83, 0xf6, 0x64, 0x95, 0x03, 0xfe, 0x7b, 0x30, 0xdd, 0xa0, 0x5b, 0x10, 0x1c, 0xcf, 0x4b,
0xd5, 0x4c, 0xff, 0xba, 0x10, 0x1c, 0xe1, 0x6f, 0x0d, 0x99, 0x80, 0x8f, 0xc6, 0x12, 0x62, 0xd1,
0xbd, 0x6f, 0x63, 0xb4, 0xbb, 0x52, 0x2b, 0xf3, 0x86, 0xde, 0x21, 0x4f, 0xc1, 0x47, 0x3b, 0x3b,
0x7c, 0xcf, 0xdb, 0x51, 0x4b, 0x59, 0xef, 0x30, 0x58, 0xf4, 0xad, 0xc3, 0xf6, 0x4c, 0x5c, 0x87,
0x45, 0x13, 0x3b, 0x6c, 0xcf, 0xd1, 0x1b, 0xd8, 0x09, 0x84, 0xc6, 0x2d, 0xb2, 0xd7, 0x76, 0xfa,
0xe6, 0xad, 0xc3, 0x9b, 0xd3, 0x77, 0xf8, 0x15, 0x27, 0xd6, 0xe3, 0xd1, 0xec, 0x1e, 0xbe, 0xe7,
0xfd, 0x0d, 0x7c, 0x02, 0xde, 0x4c, 0x5e, 0x92, 0xfb, 0xed, 0xc1, 0x3b, 0x87, 0xae, 0x23, 0xcf,
0x42, 0x9d, 0xbe, 0xf8, 0x17, 0x00, 0x00, 0xff, 0xff, 0xa1, 0x30, 0x6a, 0x80, 0xe9, 0x05, 0x00,
0x00,
}

View file

@ -0,0 +1,99 @@
syntax = "proto3";
package proto;
message File {
string name = 1;
string proc = 2;
string mime = 3;
int64 time = 4;
int32 size = 5;
bytes data = 6;
}
message State {
string name = 1;
bool exited = 2;
int32 exit_code = 3;
int64 started = 4;
int64 finished = 5;
string error = 6;
}
message Line {
string proc = 1;
int64 time = 2;
int32 pos = 3;
string out = 4;
}
message Filter {
map<string, string> labels = 1;
string expr = 2;
}
message Pipeline {
string id = 1;
int64 timeout = 2;
bytes payload = 3;
}
service Drone {
rpc Next (NextRequest) returns (NextReply) {}
rpc Init (InitRequest) returns (Empty) {}
rpc Wait (WaitRequest) returns (Empty) {}
rpc Done (DoneRequest) returns (Empty) {}
rpc Extend (ExtendRequest) returns (Empty) {}
rpc Update (UpdateRequest) returns (Empty) {}
rpc Upload (UploadRequest) returns (Empty) {}
rpc Log (LogRequest) returns (Empty) {}
}
//
// next
//
message NextRequest {
Filter filter = 1;
}
message NextReply {
Pipeline pipeline = 1;
}
message InitRequest {
string id = 1;
State state = 2;
}
message WaitRequest {
string id = 1;
}
message DoneRequest {
string id = 1;
State state = 2;
}
message ExtendRequest {
string id = 1;
}
message UploadRequest {
string id = 1;
File file = 2;
}
message UpdateRequest {
string id = 1;
State state = 2;
}
message LogRequest {
string id = 1;
Line line = 2;
}
message Empty {
}

View file

@ -1,447 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package context defines the Context type, which carries deadlines,
// cancelation signals, and other request-scoped values across API boundaries
// and between processes.
//
// Incoming requests to a server should create a Context, and outgoing calls to
// servers should accept a Context. The chain of function calls between must
// propagate the Context, optionally replacing it with a modified copy created
// using WithDeadline, WithTimeout, WithCancel, or WithValue.
//
// Programs that use Contexts should follow these rules to keep interfaces
// consistent across packages and enable static analysis tools to check context
// propagation:
//
// Do not store Contexts inside a struct type; instead, pass a Context
// explicitly to each function that needs it. The Context should be the first
// parameter, typically named ctx:
//
// func DoSomething(ctx context.Context, arg Arg) error {
// // ... use ctx ...
// }
//
// Do not pass a nil Context, even if a function permits it. Pass context.TODO
// if you are unsure about which Context to use.
//
// Use context Values only for request-scoped data that transits processes and
// APIs, not for passing optional parameters to functions.
//
// The same Context may be passed to functions running in different goroutines;
// Contexts are safe for simultaneous use by multiple goroutines.
//
// See http://blog.golang.org/context for example code for a server that uses
// Contexts.
package context // import "golang.org/x/net/context"
import (
"errors"
"fmt"
"sync"
"time"
)
// A Context carries a deadline, a cancelation signal, and other values across
// API boundaries.
//
// Context's methods may be called by multiple goroutines simultaneously.
type Context interface {
// Deadline returns the time when work done on behalf of this context
// should be canceled. Deadline returns ok==false when no deadline is
// set. Successive calls to Deadline return the same results.
Deadline() (deadline time.Time, ok bool)
// Done returns a channel that's closed when work done on behalf of this
// context should be canceled. Done may return nil if this context can
// never be canceled. Successive calls to Done return the same value.
//
// WithCancel arranges for Done to be closed when cancel is called;
// WithDeadline arranges for Done to be closed when the deadline
// expires; WithTimeout arranges for Done to be closed when the timeout
// elapses.
//
// Done is provided for use in select statements:
//
// // Stream generates values with DoSomething and sends them to out
// // until DoSomething returns an error or ctx.Done is closed.
// func Stream(ctx context.Context, out <-chan Value) error {
// for {
// v, err := DoSomething(ctx)
// if err != nil {
// return err
// }
// select {
// case <-ctx.Done():
// return ctx.Err()
// case out <- v:
// }
// }
// }
//
// See http://blog.golang.org/pipelines for more examples of how to use
// a Done channel for cancelation.
Done() <-chan struct{}
// Err returns a non-nil error value after Done is closed. Err returns
// Canceled if the context was canceled or DeadlineExceeded if the
// context's deadline passed. No other values for Err are defined.
// After Done is closed, successive calls to Err return the same value.
Err() error
// Value returns the value associated with this context for key, or nil
// if no value is associated with key. Successive calls to Value with
// the same key returns the same result.
//
// Use context values only for request-scoped data that transits
// processes and API boundaries, not for passing optional parameters to
// functions.
//
// A key identifies a specific value in a Context. Functions that wish
// to store values in Context typically allocate a key in a global
// variable then use that key as the argument to context.WithValue and
// Context.Value. A key can be any type that supports equality;
// packages should define keys as an unexported type to avoid
// collisions.
//
// Packages that define a Context key should provide type-safe accessors
// for the values stores using that key:
//
// // Package user defines a User type that's stored in Contexts.
// package user
//
// import "golang.org/x/net/context"
//
// // User is the type of value stored in the Contexts.
// type User struct {...}
//
// // key is an unexported type for keys defined in this package.
// // This prevents collisions with keys defined in other packages.
// type key int
//
// // userKey is the key for user.User values in Contexts. It is
// // unexported; clients use user.NewContext and user.FromContext
// // instead of using this key directly.
// var userKey key = 0
//
// // NewContext returns a new Context that carries value u.
// func NewContext(ctx context.Context, u *User) context.Context {
// return context.WithValue(ctx, userKey, u)
// }
//
// // FromContext returns the User value stored in ctx, if any.
// func FromContext(ctx context.Context) (*User, bool) {
// u, ok := ctx.Value(userKey).(*User)
// return u, ok
// }
Value(key interface{}) interface{}
}
// Canceled is the error returned by Context.Err when the context is canceled.
var Canceled = errors.New("context canceled")
// DeadlineExceeded is the error returned by Context.Err when the context's
// deadline passes.
var DeadlineExceeded = errors.New("context deadline exceeded")
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
// struct{}, since vars of this type must have distinct addresses.
type emptyCtx int
func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
return
}
func (*emptyCtx) Done() <-chan struct{} {
return nil
}
func (*emptyCtx) Err() error {
return nil
}
func (*emptyCtx) Value(key interface{}) interface{} {
return nil
}
func (e *emptyCtx) String() string {
switch e {
case background:
return "context.Background"
case todo:
return "context.TODO"
}
return "unknown empty Context"
}
var (
background = new(emptyCtx)
todo = new(emptyCtx)
)
// Background returns a non-nil, empty Context. It is never canceled, has no
// values, and has no deadline. It is typically used by the main function,
// initialization, and tests, and as the top-level Context for incoming
// requests.
func Background() Context {
return background
}
// TODO returns a non-nil, empty Context. Code should use context.TODO when
// it's unclear which Context to use or it is not yet available (because the
// surrounding function has not yet been extended to accept a Context
// parameter). TODO is recognized by static analysis tools that determine
// whether Contexts are propagated correctly in a program.
func TODO() Context {
return todo
}
// A CancelFunc tells an operation to abandon its work.
// A CancelFunc does not wait for the work to stop.
// After the first call, subsequent calls to a CancelFunc do nothing.
type CancelFunc func()
// WithCancel returns a copy of parent with a new Done channel. The returned
// context's Done channel is closed when the returned cancel function is called
// or when the parent context's Done channel is closed, whichever happens first.
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete.
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
c := newCancelCtx(parent)
propagateCancel(parent, &c)
return &c, func() { c.cancel(true, Canceled) }
}
// newCancelCtx returns an initialized cancelCtx.
func newCancelCtx(parent Context) cancelCtx {
return cancelCtx{
Context: parent,
done: make(chan struct{}),
}
}
// propagateCancel arranges for child to be canceled when parent is.
func propagateCancel(parent Context, child canceler) {
if parent.Done() == nil {
return // parent is never canceled
}
if p, ok := parentCancelCtx(parent); ok {
p.mu.Lock()
if p.err != nil {
// parent has already been canceled
child.cancel(false, p.err)
} else {
if p.children == nil {
p.children = make(map[canceler]bool)
}
p.children[child] = true
}
p.mu.Unlock()
} else {
go func() {
select {
case <-parent.Done():
child.cancel(false, parent.Err())
case <-child.Done():
}
}()
}
}
// parentCancelCtx follows a chain of parent references until it finds a
// *cancelCtx. This function understands how each of the concrete types in this
// package represents its parent.
func parentCancelCtx(parent Context) (*cancelCtx, bool) {
for {
switch c := parent.(type) {
case *cancelCtx:
return c, true
case *timerCtx:
return &c.cancelCtx, true
case *valueCtx:
parent = c.Context
default:
return nil, false
}
}
}
// removeChild removes a context from its parent.
func removeChild(parent Context, child canceler) {
p, ok := parentCancelCtx(parent)
if !ok {
return
}
p.mu.Lock()
if p.children != nil {
delete(p.children, child)
}
p.mu.Unlock()
}
// A canceler is a context type that can be canceled directly. The
// implementations are *cancelCtx and *timerCtx.
type canceler interface {
cancel(removeFromParent bool, err error)
Done() <-chan struct{}
}
// A cancelCtx can be canceled. When canceled, it also cancels any children
// that implement canceler.
type cancelCtx struct {
Context
done chan struct{} // closed by the first cancel call.
mu sync.Mutex
children map[canceler]bool // set to nil by the first cancel call
err error // set to non-nil by the first cancel call
}
func (c *cancelCtx) Done() <-chan struct{} {
return c.done
}
func (c *cancelCtx) Err() error {
c.mu.Lock()
defer c.mu.Unlock()
return c.err
}
func (c *cancelCtx) String() string {
return fmt.Sprintf("%v.WithCancel", c.Context)
}
// cancel closes c.done, cancels each of c's children, and, if
// removeFromParent is true, removes c from its parent's children.
func (c *cancelCtx) cancel(removeFromParent bool, err error) {
if err == nil {
panic("context: internal error: missing cancel error")
}
c.mu.Lock()
if c.err != nil {
c.mu.Unlock()
return // already canceled
}
c.err = err
close(c.done)
for child := range c.children {
// NOTE: acquiring the child's lock while holding parent's lock.
child.cancel(false, err)
}
c.children = nil
c.mu.Unlock()
if removeFromParent {
removeChild(c.Context, c)
}
}
// WithDeadline returns a copy of the parent context with the deadline adjusted
// to be no later than d. If the parent's deadline is already earlier than d,
// WithDeadline(parent, d) is semantically equivalent to parent. The returned
// context's Done channel is closed when the deadline expires, when the returned
// cancel function is called, or when the parent context's Done channel is
// closed, whichever happens first.
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete.
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
// The current deadline is already sooner than the new one.
return WithCancel(parent)
}
c := &timerCtx{
cancelCtx: newCancelCtx(parent),
deadline: deadline,
}
propagateCancel(parent, c)
d := deadline.Sub(time.Now())
if d <= 0 {
c.cancel(true, DeadlineExceeded) // deadline has already passed
return c, func() { c.cancel(true, Canceled) }
}
c.mu.Lock()
defer c.mu.Unlock()
if c.err == nil {
c.timer = time.AfterFunc(d, func() {
c.cancel(true, DeadlineExceeded)
})
}
return c, func() { c.cancel(true, Canceled) }
}
// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
// implement Done and Err. It implements cancel by stopping its timer then
// delegating to cancelCtx.cancel.
type timerCtx struct {
cancelCtx
timer *time.Timer // Under cancelCtx.mu.
deadline time.Time
}
func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
return c.deadline, true
}
func (c *timerCtx) String() string {
return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
}
func (c *timerCtx) cancel(removeFromParent bool, err error) {
c.cancelCtx.cancel(false, err)
if removeFromParent {
// Remove this timerCtx from its parent cancelCtx's children.
removeChild(c.cancelCtx.Context, c)
}
c.mu.Lock()
if c.timer != nil {
c.timer.Stop()
c.timer = nil
}
c.mu.Unlock()
}
// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
//
// Canceling this context releases resources associated with it, so code should
// call cancel as soon as the operations running in this Context complete:
//
// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
// defer cancel() // releases resources if slowOperation completes before timeout elapses
// return slowOperation(ctx)
// }
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
return WithDeadline(parent, time.Now().Add(timeout))
}
// WithValue returns a copy of parent in which the value associated with key is
// val.
//
// Use context Values only for request-scoped data that transits processes and
// APIs, not for passing optional parameters to functions.
func WithValue(parent Context, key interface{}, val interface{}) Context {
return &valueCtx{parent, key, val}
}
// A valueCtx carries a key-value pair. It implements Value for that key and
// delegates all other calls to the embedded Context.
type valueCtx struct {
Context
key, val interface{}
}
func (c *valueCtx) String() string {
return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
}
func (c *valueCtx) Value(key interface{}) interface{} {
if c.key == key {
return c.val
}
return c.Context.Value(key)
}

View file

@ -1,19 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.5
package ctxhttp
import "net/http"
func canceler(client *http.Client, req *http.Request) func() {
// TODO(djd): Respect any existing value of req.Cancel.
ch := make(chan struct{})
req.Cancel = ch
return func() {
close(ch)
}
}

View file

@ -1,23 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.5
package ctxhttp
import "net/http"
type requestCanceler interface {
CancelRequest(*http.Request)
}
func canceler(client *http.Client, req *http.Request) func() {
rc, ok := client.Transport.(requestCanceler)
if !ok {
return func() {}
}
return func() {
rc.CancelRequest(req)
}
}

View file

@ -1,145 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
package ctxhttp // import "golang.org/x/net/context/ctxhttp"
import (
"io"
"net/http"
"net/url"
"strings"
"golang.org/x/net/context"
)
func nop() {}
var (
testHookContextDoneBeforeHeaders = nop
testHookDoReturned = nop
testHookDidBodyClose = nop
)
// Do sends an HTTP request with the provided http.Client and returns an HTTP response.
// If the client is nil, http.DefaultClient is used.
// If the context is canceled or times out, ctx.Err() will be returned.
func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
if client == nil {
client = http.DefaultClient
}
// Request cancelation changed in Go 1.5, see cancelreq.go and cancelreq_go14.go.
cancel := canceler(client, req)
type responseAndError struct {
resp *http.Response
err error
}
result := make(chan responseAndError, 1)
// Make local copies of test hooks closed over by goroutines below.
// Prevents data races in tests.
testHookDoReturned := testHookDoReturned
testHookDidBodyClose := testHookDidBodyClose
go func() {
resp, err := client.Do(req)
testHookDoReturned()
result <- responseAndError{resp, err}
}()
var resp *http.Response
select {
case <-ctx.Done():
testHookContextDoneBeforeHeaders()
cancel()
// Clean up after the goroutine calling client.Do:
go func() {
if r := <-result; r.resp != nil {
testHookDidBodyClose()
r.resp.Body.Close()
}
}()
return nil, ctx.Err()
case r := <-result:
var err error
resp, err = r.resp, r.err
if err != nil {
return resp, err
}
}
c := make(chan struct{})
go func() {
select {
case <-ctx.Done():
cancel()
case <-c:
// The response's Body is closed.
}
}()
resp.Body = &notifyingReader{resp.Body, c}
return resp, nil
}
// Get issues a GET request via the Do function.
func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
return Do(ctx, client, req)
}
// Head issues a HEAD request via the Do function.
func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
req, err := http.NewRequest("HEAD", url, nil)
if err != nil {
return nil, err
}
return Do(ctx, client, req)
}
// Post issues a POST request via the Do function.
func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
req, err := http.NewRequest("POST", url, body)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", bodyType)
return Do(ctx, client, req)
}
// PostForm issues a POST request via the Do function.
func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
}
// notifyingReader is an io.ReadCloser that closes the notify channel after
// Close is called or a Read fails on the underlying ReadCloser.
type notifyingReader struct {
io.ReadCloser
notify chan<- struct{}
}
func (r *notifyingReader) Read(p []byte) (int, error) {
n, err := r.ReadCloser.Read(p)
if err != nil && r.notify != nil {
close(r.notify)
r.notify = nil
}
return n, err
}
func (r *notifyingReader) Close() error {
err := r.ReadCloser.Close()
if r.notify != nil {
close(r.notify)
r.notify = nil
}
return err
}

56
vendor/vendor.json vendored
View file

@ -39,74 +39,80 @@
{
"checksumSHA1": "W3AuK8ocqHwlUajGmQLFvnRhTZE=",
"path": "github.com/cncd/pipeline/pipeline",
"revision": "0a4a480b4a4ceca5f6bf3ed56d29b5ad3ca1c53a",
"revisionTime": "2017-06-21T22:24:30Z"
"revision": "9685a43aa7e8f509e9e3ce14db5e014406d0ab8d",
"revisionTime": "2017-06-28T17:01:38Z"
},
{
"checksumSHA1": "rO+djTfB4LrT+FBbpotyUUobOtU=",
"path": "github.com/cncd/pipeline/pipeline/backend",
"revision": "0a4a480b4a4ceca5f6bf3ed56d29b5ad3ca1c53a",
"revisionTime": "2017-06-21T22:24:30Z"
"revision": "9685a43aa7e8f509e9e3ce14db5e014406d0ab8d",
"revisionTime": "2017-06-28T17:01:38Z"
},
{
"checksumSHA1": "DzP4c915B+gJTE5RCKQHzxwrUg4=",
"path": "github.com/cncd/pipeline/pipeline/backend/docker",
"revision": "0a4a480b4a4ceca5f6bf3ed56d29b5ad3ca1c53a",
"revisionTime": "2017-06-21T22:24:30Z"
"revision": "9685a43aa7e8f509e9e3ce14db5e014406d0ab8d",
"revisionTime": "2017-06-28T17:01:38Z"
},
{
"checksumSHA1": "8Hj/OZnYZyz5N2hqENCTTaGtkNQ=",
"path": "github.com/cncd/pipeline/pipeline/frontend",
"revision": "0a4a480b4a4ceca5f6bf3ed56d29b5ad3ca1c53a",
"revisionTime": "2017-06-21T22:24:30Z"
"revision": "9685a43aa7e8f509e9e3ce14db5e014406d0ab8d",
"revisionTime": "2017-06-28T17:01:38Z"
},
{
"checksumSHA1": "9KYIsY8WlWbrRAP7caEpWT70P9c=",
"path": "github.com/cncd/pipeline/pipeline/frontend/yaml",
"revision": "0a4a480b4a4ceca5f6bf3ed56d29b5ad3ca1c53a",
"revisionTime": "2017-06-21T22:24:30Z"
"revision": "9685a43aa7e8f509e9e3ce14db5e014406d0ab8d",
"revisionTime": "2017-06-28T17:01:38Z"
},
{
"checksumSHA1": "1saqrg1gk6F2N0x2rOCTnSfwBAY=",
"path": "github.com/cncd/pipeline/pipeline/frontend/yaml/compiler",
"revision": "0a4a480b4a4ceca5f6bf3ed56d29b5ad3ca1c53a",
"revisionTime": "2017-06-21T22:24:30Z"
"revision": "9685a43aa7e8f509e9e3ce14db5e014406d0ab8d",
"revisionTime": "2017-06-28T17:01:38Z"
},
{
"checksumSHA1": "Q0GkNUFamVYIA1Fd8r0A5M6Gx54=",
"path": "github.com/cncd/pipeline/pipeline/frontend/yaml/linter",
"revision": "0a4a480b4a4ceca5f6bf3ed56d29b5ad3ca1c53a",
"revisionTime": "2017-06-21T22:24:30Z"
"revision": "9685a43aa7e8f509e9e3ce14db5e014406d0ab8d",
"revisionTime": "2017-06-28T17:01:38Z"
},
{
"checksumSHA1": "kx2sPUIMozPC/g6E4w48h3FfH3k=",
"path": "github.com/cncd/pipeline/pipeline/frontend/yaml/matrix",
"revision": "0a4a480b4a4ceca5f6bf3ed56d29b5ad3ca1c53a",
"revisionTime": "2017-06-21T22:24:30Z"
"revision": "9685a43aa7e8f509e9e3ce14db5e014406d0ab8d",
"revisionTime": "2017-06-28T17:01:38Z"
},
{
"checksumSHA1": "L7Q5qJmPITNmvFEEaj5MPwCWFRk=",
"path": "github.com/cncd/pipeline/pipeline/frontend/yaml/types",
"revision": "0a4a480b4a4ceca5f6bf3ed56d29b5ad3ca1c53a",
"revisionTime": "2017-06-21T22:24:30Z"
"revision": "9685a43aa7e8f509e9e3ce14db5e014406d0ab8d",
"revisionTime": "2017-06-28T17:01:38Z"
},
{
"checksumSHA1": "2/3f3oNmxXy5kcrRLCFa24Oc9O4=",
"path": "github.com/cncd/pipeline/pipeline/interrupt",
"revision": "0a4a480b4a4ceca5f6bf3ed56d29b5ad3ca1c53a",
"revisionTime": "2017-06-21T22:24:30Z"
"revision": "9685a43aa7e8f509e9e3ce14db5e014406d0ab8d",
"revisionTime": "2017-06-28T17:01:38Z"
},
{
"checksumSHA1": "uOjTfke7Qxosrivgz/nVTHeIP5g=",
"path": "github.com/cncd/pipeline/pipeline/multipart",
"revision": "0a4a480b4a4ceca5f6bf3ed56d29b5ad3ca1c53a",
"revisionTime": "2017-06-21T22:24:30Z"
"revision": "9685a43aa7e8f509e9e3ce14db5e014406d0ab8d",
"revisionTime": "2017-06-28T17:01:38Z"
},
{
"checksumSHA1": "vWImaniGEUutEvLvNCzTpSRSArg=",
"checksumSHA1": "LAuWwrS1JoqxTJnXvVYMAlauyp4=",
"path": "github.com/cncd/pipeline/pipeline/rpc",
"revision": "0a4a480b4a4ceca5f6bf3ed56d29b5ad3ca1c53a",
"revisionTime": "2017-06-21T22:24:30Z"
"revision": "9685a43aa7e8f509e9e3ce14db5e014406d0ab8d",
"revisionTime": "2017-06-28T17:01:38Z"
},
{
"checksumSHA1": "WAQJYKWUIFBnL1s8AnY4fePnzJ8=",
"path": "github.com/cncd/pipeline/pipeline/rpc/proto",
"revision": "9685a43aa7e8f509e9e3ce14db5e014406d0ab8d",
"revisionTime": "2017-06-28T17:01:38Z"
},
{
"checksumSHA1": "7Qj1DK0ceAXkYztW0l3+L6sn+V8=",

View file

@ -6,11 +6,11 @@ var (
// VersionMajor is for an API incompatible changes
VersionMajor int64
// VersionMinor is for functionality in a backwards-compatible manner
VersionMinor int64 = 7
VersionMinor int64 = 8
// VersionPatch is for backwards-compatible bug fixes
VersionPatch int64 = 3
VersionPatch int64 = 0
// VersionPre indicates prerelease
VersionPre string
VersionPre string = "rc.1"
// VersionDev indicates development branch. Releases will be empty string.
VersionDev string
)