compare server and agent version for compatibility

This commit is contained in:
Brad Rydzewski 2017-04-12 13:04:39 +02:00
parent b86fa5fc16
commit 2f67f5f706
10 changed files with 76 additions and 17 deletions

View file

@ -101,7 +101,7 @@ func loop(c *cli.Context) error {
), ),
rpc.WithHeader( rpc.WithHeader(
"X-Drone-Version", "X-Drone-Version",
version.Version, version.Version.String(),
), ),
) )
if err != nil { if err != nil {

View file

@ -17,7 +17,7 @@ func main() {
app := cli.NewApp() app := cli.NewApp()
app.Name = "drone" app.Name = "drone"
app.Version = version.Version app.Version = version.Version.String()
app.Usage = "command line utility" app.Usage = "command line utility"
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
cli.StringFlag{ cli.StringFlag{

View file

@ -3,7 +3,6 @@ package internal
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"errors"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
@ -47,8 +46,14 @@ func Send(method, path string, in, out interface{}) error {
// if an error is encountered, parse and return the // if an error is encountered, parse and return the
// error response. // error response.
if resp.StatusCode > http.StatusPartialContent { if resp.StatusCode > http.StatusPartialContent {
out, _ := ioutil.ReadAll(resp.Body) out, err := ioutil.ReadAll(resp.Body)
return errors.New(string(out)) if err != nil {
return err
}
return &Error{
code: resp.StatusCode,
text: string(out),
}
} }
// if a json response is expected, parse and return // if a json response is expected, parse and return
@ -59,3 +64,19 @@ func Send(method, path string, in, out interface{}) error {
return nil 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
}

View file

@ -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) { 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) 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, nil)
err := internal.Send("POST", path, build, out)
if err != nil { if err != nil {
return false, err return false, err
} }
return out.Allow, nil return true, err
} }
func (p *plugin) SenderCreate(repo *model.Repo, sender *model.Sender) error { func (p *plugin) SenderCreate(repo *model.Repo, sender *model.Sender) error {

View file

@ -52,6 +52,6 @@ func Secure(c *gin.Context) {
// version information to the HTTP response. This is intended // version information to the HTTP response. This is intended
// for debugging and troubleshooting. // for debugging and troubleshooting.
func Version(c *gin.Context) { func Version(c *gin.Context) {
c.Header("X-DRONE-VERSION", version.Version) c.Header("X-DRONE-VERSION", version.Version.String())
c.Next() c.Next()
} }

View file

@ -8,5 +8,5 @@ import (
// Version is a middleware function that appends the Drone version information // Version is a middleware function that appends the Drone version information
// to the HTTP response. This is intended for debugging and troubleshooting. // to the HTTP response. This is intended for debugging and troubleshooting.
func Version(c *gin.Context) { func Version(c *gin.Context) {
c.Header("X-DRONE-VERSION", version.Version) c.Header("X-DRONE-VERSION", version.Version.String())
} }

View file

@ -28,6 +28,10 @@ func ShowIndex(c *gin.Context) {
// ShowLogin is a legacy endpoint that now redirects to // ShowLogin is a legacy endpoint that now redirects to
// initiliaze the oauth flow // initiliaze the oauth flow
func ShowLogin(c *gin.Context) { 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") c.Redirect(303, "/authorize")
} }

View file

@ -7,15 +7,18 @@ import (
"log" "log"
"strconv" "strconv"
"github.com/Sirupsen/logrus"
"github.com/cncd/logging" "github.com/cncd/logging"
"github.com/cncd/pipeline/pipeline/rpc" "github.com/cncd/pipeline/pipeline/rpc"
"github.com/cncd/pubsub" "github.com/cncd/pubsub"
"github.com/cncd/queue" "github.com/cncd/queue"
"github.com/coreos/go-semver/semver"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/drone/drone/model" "github.com/drone/drone/model"
"github.com/drone/drone/remote" "github.com/drone/drone/remote"
"github.com/drone/drone/store" "github.com/drone/drone/store"
"github.com/drone/drone/version"
) )
// This file is a complete disaster because I'm trying to wedge in some // 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") c.String(401, "Unable to connect agent. Invalid authorization token")
return 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{ peer := RPC{
remote: remote.FromContext(c), remote: remote.FromContext(c),
store: store.FromContext(c), store: store.FromContext(c),

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<meta content="ie=edge" http-equiv="x-ua-compatible"/>
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/>
<link href="/static/favicon.ico" rel="icon" type="image/x-icon"/>
<link rel="stylesheet" href="/static/app.css" />
<title>error | drone</title>
</head>
<body>
{{ .error }}
</body>
</html>

View file

@ -1,19 +1,23 @@
package version package version
import "fmt" import "github.com/coreos/go-semver/semver"
var ( var (
// VersionMajor is for an API incompatible changes // VersionMajor is for an API incompatible changes
VersionMajor = 0 VersionMajor int64 = 0
// VersionMinor is for functionality in a backwards-compatible manner // VersionMinor is for functionality in a backwards-compatible manner
VersionMinor = 6 VersionMinor int64 = 6
// VersionPatch is for backwards-compatible bug fixes // VersionPatch is for backwards-compatible bug fixes
VersionPatch = 0 VersionPatch int64 = 0
// VersionDev indicates development branch. Releases will be empty string. // VersionDev indicates development branch. Releases will be empty string.
VersionDev = "dev" VersionDev string
) )
// Version is the specification version that the package types support. // Version is the specification version that the package types support.
var Version = fmt.Sprintf("%d.%d.%d+%s", var Version = semver.Version{
VersionMajor, VersionMinor, VersionPatch, VersionDev) Major: VersionMajor,
Minor: VersionMinor,
Patch: VersionPatch,
Metadata: VersionDev,
}