mirror of
https://github.com/coder/coder.git
synced 2025-03-14 10:09:57 +00:00
90 lines
2.5 KiB
Go
90 lines
2.5 KiB
Go
package apiversion
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"golang.org/x/xerrors"
|
|
)
|
|
|
|
// New returns an *APIVersion with the given major.minor and
|
|
// additional supported major versions.
|
|
func New(maj, min int) *APIVersion {
|
|
v := &APIVersion{
|
|
supportedMajor: maj,
|
|
supportedMinor: min,
|
|
additionalMajors: make([]int, 0),
|
|
}
|
|
return v
|
|
}
|
|
|
|
type APIVersion struct {
|
|
supportedMajor int
|
|
supportedMinor int
|
|
additionalMajors []int
|
|
}
|
|
|
|
func (v *APIVersion) WithBackwardCompat(majs ...int) *APIVersion {
|
|
v.additionalMajors = append(v.additionalMajors, majs...)
|
|
return v
|
|
}
|
|
|
|
func (v *APIVersion) String() string {
|
|
return fmt.Sprintf("%d.%d", v.supportedMajor, v.supportedMinor)
|
|
}
|
|
|
|
// Validate validates the given version against the given constraints:
|
|
// A given major.minor version is valid iff:
|
|
// 1. The requested major version is contained within v.supportedMajors
|
|
// 2. If the requested major version is the 'current major', then
|
|
// the requested minor version must be less than or equal to the supported
|
|
// minor version.
|
|
//
|
|
// For example, given majors {1, 2} and minor 2, then:
|
|
// - 0.x is not supported,
|
|
// - 1.x is supported,
|
|
// - 2.0, 2.1, and 2.2 are supported,
|
|
// - 2.3+ is not supported.
|
|
func (v *APIVersion) Validate(version string) error {
|
|
major, minor, err := Parse(version)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if major > v.supportedMajor {
|
|
return xerrors.Errorf("server is at version %d.%d, behind requested major version %s",
|
|
v.supportedMajor, v.supportedMinor, version)
|
|
}
|
|
if major == v.supportedMajor {
|
|
if minor > v.supportedMinor {
|
|
return xerrors.Errorf("server is at version %d.%d, behind requested minor version %s",
|
|
v.supportedMajor, v.supportedMinor, version)
|
|
}
|
|
return nil
|
|
}
|
|
for _, mjr := range v.additionalMajors {
|
|
if major == mjr {
|
|
return nil
|
|
}
|
|
}
|
|
return xerrors.Errorf("version %s is no longer supported", version)
|
|
}
|
|
|
|
// Parse parses a valid major.minor version string into (major, minor).
|
|
// Both major and minor must be valid integers separated by a period '.'.
|
|
func Parse(version string) (major int, minor int, err error) {
|
|
parts := strings.Split(version, ".")
|
|
if len(parts) != 2 {
|
|
return 0, 0, xerrors.Errorf("invalid version string: %s", version)
|
|
}
|
|
major, err = strconv.Atoi(parts[0])
|
|
if err != nil {
|
|
return 0, 0, xerrors.Errorf("invalid major version: %s", version)
|
|
}
|
|
minor, err = strconv.Atoi(parts[1])
|
|
if err != nil {
|
|
return 0, 0, xerrors.Errorf("invalid minor version: %s", version)
|
|
}
|
|
return major, minor, nil
|
|
}
|