From 3583c65f5b44a3d1f7fd3a3e8f7718f600e56aee Mon Sep 17 00:00:00 2001 From: Stefan Benten Date: Tue, 2 Jul 2019 17:28:06 +0200 Subject: [PATCH] Move from allowed range to minimum for Version Control (#2421) --- internal/testplanet/bootstrap.go | 1 + internal/version/service.go | 16 ++++----- internal/version/version.go | 62 +++++++++++--------------------- versioncontrol/peer.go | 39 ++++++++++++-------- 4 files changed, 55 insertions(+), 63 deletions(-) diff --git a/internal/testplanet/bootstrap.go b/internal/testplanet/bootstrap.go index 32de61f63..2e54a53bf 100644 --- a/internal/testplanet/bootstrap.go +++ b/internal/testplanet/bootstrap.go @@ -122,6 +122,7 @@ func (planet *Planet) newVersionControlServer() (peer *versioncontrol.Peer, err Storagenode: "v0.0.1", Uplink: "v0.0.1", Gateway: "v0.0.1", + Identity: "v0.0.1", }, } peer, err = versioncontrol.New(log, config) diff --git a/internal/version/service.go b/internal/version/service.go index 17ae4c1fe..c16886269 100644 --- a/internal/version/service.go +++ b/internal/version/service.go @@ -109,14 +109,14 @@ func (srv *Service) checkVersion(ctx context.Context) (allowed bool) { return true } - list := getFieldString(&accepted, srv.service) - zap.S().Debugf("allowed versions from Control Server: %v", list) + minimum := getFieldString(&accepted, srv.service) + zap.S().Debugf("allowed minimum version from control server is: %s", minimum.String()) - if list == nil { - zap.S().Errorf("Empty List from Versioning Server") + if minimum.String() == "" { + zap.S().Errorf("no version from control server, accepting to run") return true } - if containsVersion(list, srv.info.Version) { + if isAcceptedVersion(srv.info.Version, minimum) { zap.S().Infof("running on version %s", srv.info.Version.String()) return true } @@ -168,12 +168,12 @@ func DebugHandler(w http.ResponseWriter, r *http.Request) { } } -func getFieldString(array *AllowedVersions, field string) []SemVer { +func getFieldString(array *AllowedVersions, field string) SemVer { r := reflect.ValueOf(array) f := reflect.Indirect(r).FieldByName(field).Interface() - result, ok := f.([]SemVer) + result, ok := f.(SemVer) if ok { return result } - return nil + return SemVer{} } diff --git a/internal/version/version.go b/internal/version/version.go index 42c267cff..5020f92f5 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -5,7 +5,6 @@ package version import ( "encoding/json" - "errors" "fmt" "regexp" "strconv" @@ -13,7 +12,8 @@ import ( "time" "github.com/golang/protobuf/ptypes" - monkit "gopkg.in/spacemonkeygo/monkit.v2" + "github.com/zeebo/errs" + "gopkg.in/spacemonkeygo/monkit.v2" "storj.io/storj/pkg/pb" ) @@ -21,6 +21,7 @@ import ( var ( mon = monkit.Package() + verError = errs.Class("version error") // the following fields are set by linker flags. if any of them // are set and fail to parse, the program will fail to start buildTimestamp string // unix seconds since epoch @@ -50,14 +51,14 @@ type SemVer struct { Patch int64 `json:"patch"` } -// AllowedVersions provides a list of SemVer per Service +// AllowedVersions provides the Minimum SemVer per Service type AllowedVersions struct { - Bootstrap []SemVer - Satellite []SemVer - Storagenode []SemVer - Uplink []SemVer - Gateway []SemVer - Identity []SemVer + Bootstrap SemVer + Satellite SemVer + Storagenode SemVer + Uplink SemVer + Gateway SemVer + Identity SemVer } // SemVerRegex is the regular expression used to parse a semantic version. @@ -68,33 +69,29 @@ var versionRegex = regexp.MustCompile("^" + SemVerRegex + "$") // NewSemVer parses a given version and returns an instance of SemVer or // an error if unable to parse the version. -func NewSemVer(v string) (*SemVer, error) { +func NewSemVer(v string) (sv SemVer, err error) { m := versionRegex.FindStringSubmatch(v) if m == nil { - return nil, errors.New("invalid semantic version for build") + return SemVer{}, verError.New("invalid semantic version for build %s", v) } - sv := SemVer{} - - var err error - // first entry of m is the entire version string sv.Major, err = strconv.ParseInt(m[1], 10, 64) if err != nil { - return nil, err + return SemVer{}, err } sv.Minor, err = strconv.ParseInt(m[2], 10, 64) if err != nil { - return nil, err + return SemVer{}, err } sv.Patch, err = strconv.ParseInt(m[3], 10, 64) if err != nil { - return nil, err + return SemVer{}, err } - return &sv, nil + return sv, nil } // String converts the SemVer struct to a more easy to handle string @@ -130,26 +127,9 @@ func (v Info) Proto() (*pb.NodeVersion, error) { }, nil } -// containsVersion compares the allowed version array against the passed version -func containsVersion(all []SemVer, x SemVer) bool { - for _, n := range all { - if x == n { - return true - } - } - return false -} - -// StrToSemVerList converts a list of versions to a list of SemVer -func StrToSemVerList(serviceVersions []string) (versions []SemVer, err error) { - for _, subversion := range serviceVersions { - sVer, err := NewSemVer(subversion) - if err != nil { - return nil, err - } - versions = append(versions, *sVer) - } - return versions, err +// isAcceptedVersion compares and checks if the passed version is greater/equal than the minimum required version +func isAcceptedVersion(test SemVer, target SemVer) bool { + return test.Major > target.Major || (test.Major == target.Major && (test.Minor > target.Minor || (test.Minor == target.Minor && test.Patch >= target.Patch))) } func init() { @@ -158,7 +138,7 @@ func init() { } timestamp, err := strconv.ParseInt(buildTimestamp, 10, 64) if err != nil { - panic(fmt.Sprintf("invalid timestamp: %v", err)) + panic(verError.Wrap(err)) } Build = Info{ Timestamp: time.Unix(timestamp, 0), @@ -171,7 +151,7 @@ func init() { panic(err) } - Build.Version = *sv + Build.Version = sv if Build.Timestamp.Unix() == 0 || Build.CommitHash == "" { Build.Release = false diff --git a/versioncontrol/peer.go b/versioncontrol/peer.go index 79b39643a..d158178a6 100644 --- a/versioncontrol/peer.go +++ b/versioncontrol/peer.go @@ -8,7 +8,6 @@ import ( "encoding/json" "net" "net/http" - "strings" "github.com/zeebo/errs" "go.uber.org/zap" @@ -77,24 +76,36 @@ func New(log *zap.Logger, config *Config) (peer *Peer, err error) { Log: log, } - // Convert each Service's Version String to List of SemVer - bootstrapVersions := strings.Split(config.Versions.Bootstrap, ",") - peer.Versions.Bootstrap, err = version.StrToSemVerList(bootstrapVersions) + // Convert each Service's Version String to SemVer + peer.Versions.Bootstrap, err = version.NewSemVer(config.Versions.Bootstrap) + if err != nil { + return &Peer{}, err + } - satelliteVersions := strings.Split(config.Versions.Satellite, ",") - peer.Versions.Satellite, err = version.StrToSemVerList(satelliteVersions) + peer.Versions.Satellite, err = version.NewSemVer(config.Versions.Satellite) + if err != nil { + return &Peer{}, err + } - storagenodeVersions := strings.Split(config.Versions.Storagenode, ",") - peer.Versions.Storagenode, err = version.StrToSemVerList(storagenodeVersions) + peer.Versions.Storagenode, err = version.NewSemVer(config.Versions.Storagenode) + if err != nil { + return &Peer{}, err + } - uplinkVersions := strings.Split(config.Versions.Uplink, ",") - peer.Versions.Uplink, err = version.StrToSemVerList(uplinkVersions) + peer.Versions.Uplink, err = version.NewSemVer(config.Versions.Uplink) + if err != nil { + return &Peer{}, err + } - gatewayVersions := strings.Split(config.Versions.Gateway, ",") - peer.Versions.Gateway, err = version.StrToSemVerList(gatewayVersions) + peer.Versions.Gateway, err = version.NewSemVer(config.Versions.Gateway) + if err != nil { + return &Peer{}, err + } - identityVersions := strings.Split(config.Versions.Identity, ",") - peer.Versions.Identity, err = version.StrToSemVerList(identityVersions) + peer.Versions.Identity, err = version.NewSemVer(config.Versions.Identity) + if err != nil { + return &Peer{}, err + } peer.response, err = json.Marshal(peer.Versions)