From 2f67f5f70680c162108f370f5911b65370dd76fd Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Wed, 12 Apr 2017 13:04:39 +0200 Subject: [PATCH] compare server and agent version for compatibility --- drone/agent/agent.go | 2 +- drone/main.go | 2 +- plugins/internal/http.go | 27 ++++++++++++++++++++++++--- plugins/sender/plugin.go | 5 ++--- router/middleware/header/header.go | 2 +- router/middleware/version.go | 2 +- server/pages.go | 4 ++++ server/rpc.go | 14 ++++++++++++++ server/template/files/error.html | 17 +++++++++++++++++ version/version.go | 18 +++++++++++------- 10 files changed, 76 insertions(+), 17 deletions(-) create mode 100644 server/template/files/error.html diff --git a/drone/agent/agent.go b/drone/agent/agent.go index 4d1342220..33493b6eb 100644 --- a/drone/agent/agent.go +++ b/drone/agent/agent.go @@ -101,7 +101,7 @@ func loop(c *cli.Context) error { ), rpc.WithHeader( "X-Drone-Version", - version.Version, + version.Version.String(), ), ) if err != nil { diff --git a/drone/main.go b/drone/main.go index 27c9d74b2..a39074ce9 100644 --- a/drone/main.go +++ b/drone/main.go @@ -17,7 +17,7 @@ func main() { app := cli.NewApp() app.Name = "drone" - app.Version = version.Version + app.Version = version.Version.String() app.Usage = "command line utility" app.Flags = []cli.Flag{ cli.StringFlag{ diff --git a/plugins/internal/http.go b/plugins/internal/http.go index 2ae958d14..938bf3116 100644 --- a/plugins/internal/http.go +++ b/plugins/internal/http.go @@ -3,7 +3,6 @@ package internal import ( "bytes" "encoding/json" - "errors" "io" "io/ioutil" "net/http" @@ -47,8 +46,14 @@ func Send(method, path string, in, out interface{}) error { // if an error is encountered, parse and return the // error response. if resp.StatusCode > http.StatusPartialContent { - out, _ := ioutil.ReadAll(resp.Body) - return errors.New(string(out)) + out, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + return &Error{ + code: resp.StatusCode, + text: string(out), + } } // if a json response is expected, parse and return @@ -59,3 +64,19 @@ func Send(method, path string, in, out interface{}) error { return nil } + +// Error represents a http error. +type Error struct { + code int + text string +} + +// Code returns the http error code. +func (e *Error) Code() int { + return e.code +} + +// Error returns the error message in string format. +func (e *Error) Error() string { + return e.text +} diff --git a/plugins/sender/plugin.go b/plugins/sender/plugin.go index 446ea9bc3..38d1e3ba0 100644 --- a/plugins/sender/plugin.go +++ b/plugins/sender/plugin.go @@ -18,12 +18,11 @@ func NewRemote(endpoint string) model.SenderService { func (p *plugin) SenderAllowed(user *model.User, repo *model.Repo, build *model.Build) (bool, error) { path := fmt.Sprintf("%s/sender/%s/%s/%s", p.endpoint, repo.Owner, repo.Name, build.Sender) - out := new(model.Sender) - err := internal.Send("POST", path, build, out) + err := internal.Send("POST", path, build, nil) if err != nil { return false, err } - return out.Allow, nil + return true, err } func (p *plugin) SenderCreate(repo *model.Repo, sender *model.Sender) error { diff --git a/router/middleware/header/header.go b/router/middleware/header/header.go index d259431c7..7b82154ab 100644 --- a/router/middleware/header/header.go +++ b/router/middleware/header/header.go @@ -52,6 +52,6 @@ func Secure(c *gin.Context) { // version information to the HTTP response. This is intended // for debugging and troubleshooting. func Version(c *gin.Context) { - c.Header("X-DRONE-VERSION", version.Version) + c.Header("X-DRONE-VERSION", version.Version.String()) c.Next() } diff --git a/router/middleware/version.go b/router/middleware/version.go index 20466d8ec..87170010a 100644 --- a/router/middleware/version.go +++ b/router/middleware/version.go @@ -8,5 +8,5 @@ import ( // Version is a middleware function that appends the Drone version information // to the HTTP response. This is intended for debugging and troubleshooting. func Version(c *gin.Context) { - c.Header("X-DRONE-VERSION", version.Version) + c.Header("X-DRONE-VERSION", version.Version.String()) } diff --git a/server/pages.go b/server/pages.go index 74a73c206..e301fa47d 100644 --- a/server/pages.go +++ b/server/pages.go @@ -28,6 +28,10 @@ func ShowIndex(c *gin.Context) { // ShowLogin is a legacy endpoint that now redirects to // initiliaze the oauth flow func ShowLogin(c *gin.Context) { + if err := c.Query("error"); err != "" { + c.HTML(500, "error.html", gin.H{"error": err}) + return + } c.Redirect(303, "/authorize") } diff --git a/server/rpc.go b/server/rpc.go index ff1896f34..de0d8932a 100644 --- a/server/rpc.go +++ b/server/rpc.go @@ -7,15 +7,18 @@ import ( "log" "strconv" + "github.com/Sirupsen/logrus" "github.com/cncd/logging" "github.com/cncd/pipeline/pipeline/rpc" "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 @@ -86,6 +89,17 @@ func RPCHandler(c *gin.Context) { 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 + } + peer := RPC{ remote: remote.FromContext(c), store: store.FromContext(c), diff --git a/server/template/files/error.html b/server/template/files/error.html new file mode 100644 index 000000000..018c45c8f --- /dev/null +++ b/server/template/files/error.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + error | drone + + + {{ .error }} + + diff --git a/version/version.go b/version/version.go index 329bfbd0a..36758ec04 100644 --- a/version/version.go +++ b/version/version.go @@ -1,19 +1,23 @@ package version -import "fmt" +import "github.com/coreos/go-semver/semver" var ( // VersionMajor is for an API incompatible changes - VersionMajor = 0 + VersionMajor int64 = 0 // VersionMinor is for functionality in a backwards-compatible manner - VersionMinor = 6 + VersionMinor int64 = 6 // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 0 + VersionPatch int64 = 0 // VersionDev indicates development branch. Releases will be empty string. - VersionDev = "dev" + VersionDev string ) // Version is the specification version that the package types support. -var Version = fmt.Sprintf("%d.%d.%d+%s", - VersionMajor, VersionMinor, VersionPatch, VersionDev) +var Version = semver.Version{ + Major: VersionMajor, + Minor: VersionMinor, + Patch: VersionPatch, + Metadata: VersionDev, +}