mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
server: Integrate version validation logic into tests
This commit is contained in:
parent
620832a4a5
commit
f92b4f9a28
@ -273,7 +273,8 @@ func (c *RaftCluster) Recover(onSet func(*zap.Logger, *semver.Version)) {
|
||||
if c.downgradeInfo != nil {
|
||||
d = &serverversion.DowngradeInfo{Enabled: c.downgradeInfo.Enabled, TargetVersion: c.downgradeInfo.TargetVersion}
|
||||
}
|
||||
serverversion.MustDetectDowngrade(c.lg, c.version, d)
|
||||
sv := semver.Must(semver.NewVersion(version.Version))
|
||||
serverversion.MustDetectDowngrade(c.lg, sv, c.version, d)
|
||||
onSet(c.lg, c.version)
|
||||
|
||||
for _, m := range c.members {
|
||||
@ -541,7 +542,8 @@ func (c *RaftCluster) SetVersion(ver *semver.Version, onSet func(*zap.Logger, *s
|
||||
}
|
||||
oldVer := c.version
|
||||
c.version = ver
|
||||
serverversion.MustDetectDowngrade(c.lg, c.version, c.downgradeInfo)
|
||||
sv := semver.Must(semver.NewVersion(version.Version))
|
||||
serverversion.MustDetectDowngrade(c.lg, sv, c.version, c.downgradeInfo)
|
||||
if c.v2store != nil {
|
||||
mustSaveClusterVersionToStore(c.lg, c.v2store, ver)
|
||||
}
|
||||
|
@ -34,47 +34,46 @@ func (d *DowngradeInfo) GetTargetVersion() *semver.Version {
|
||||
|
||||
// isValidDowngrade verifies whether the cluster can be downgraded from verFrom to verTo
|
||||
func isValidDowngrade(verFrom *semver.Version, verTo *semver.Version) bool {
|
||||
return verTo.Equal(*AllowedDowngradeVersion(verFrom))
|
||||
return verTo.Equal(*allowedDowngradeVersion(verFrom))
|
||||
}
|
||||
|
||||
// MustDetectDowngrade will detect unexpected downgrade when the local server is recovered.
|
||||
func MustDetectDowngrade(lg *zap.Logger, cv *semver.Version, d *DowngradeInfo) {
|
||||
lv := semver.Must(semver.NewVersion(version.Version))
|
||||
func MustDetectDowngrade(lg *zap.Logger, sv, cv *semver.Version, d *DowngradeInfo) {
|
||||
// only keep major.minor version for comparison against cluster version
|
||||
lv = &semver.Version{Major: lv.Major, Minor: lv.Minor}
|
||||
sv = &semver.Version{Major: sv.Major, Minor: sv.Minor}
|
||||
|
||||
// if the cluster enables downgrade, check local version against downgrade target version.
|
||||
if d != nil && d.Enabled && d.TargetVersion != "" {
|
||||
if lv.Equal(*d.GetTargetVersion()) {
|
||||
if sv.Equal(*d.GetTargetVersion()) {
|
||||
if cv != nil {
|
||||
lg.Info(
|
||||
"cluster is downgrading to target version",
|
||||
zap.String("target-cluster-version", d.TargetVersion),
|
||||
zap.String("determined-cluster-version", version.Cluster(cv.String())),
|
||||
zap.String("current-server-version", version.Version),
|
||||
zap.String("current-server-version", sv.String()),
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
lg.Panic(
|
||||
"invalid downgrade; server version is not allowed to join when downgrade is enabled",
|
||||
zap.String("current-server-version", version.Version),
|
||||
zap.String("current-server-version", sv.String()),
|
||||
zap.String("target-cluster-version", d.TargetVersion),
|
||||
)
|
||||
}
|
||||
|
||||
// if the cluster disables downgrade, check local version against determined cluster version.
|
||||
// the validation passes when local version is not less than cluster version
|
||||
if cv != nil && lv.LessThan(*cv) {
|
||||
if cv != nil && sv.LessThan(*cv) {
|
||||
lg.Panic(
|
||||
"invalid downgrade; server version is lower than determined cluster version",
|
||||
zap.String("current-server-version", version.Version),
|
||||
zap.String("current-server-version", sv.String()),
|
||||
zap.String("determined-cluster-version", version.Cluster(cv.String())),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func AllowedDowngradeVersion(ver *semver.Version) *semver.Version {
|
||||
func allowedDowngradeVersion(ver *semver.Version) *semver.Version {
|
||||
// Todo: handle the case that downgrading from higher major version(e.g. downgrade from v4.0 to v3.x)
|
||||
return &semver.Version{Major: ver.Major, Minor: ver.Minor - 1}
|
||||
}
|
||||
|
@ -110,7 +110,8 @@ func TestMustDetectDowngrade(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
lg := zaptest.NewLogger(t)
|
||||
err := tryMustDetectDowngrade(lg, tt.clusterVersion, tt.downgrade)
|
||||
sv := semver.Must(semver.NewVersion(version.Version))
|
||||
err := tryMustDetectDowngrade(lg, sv, tt.clusterVersion, tt.downgrade)
|
||||
|
||||
if tt.success != (err == nil) {
|
||||
t.Errorf("Unexpected status, got %q, wanted: %v", err, tt.success)
|
||||
@ -123,11 +124,11 @@ func TestMustDetectDowngrade(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func tryMustDetectDowngrade(lg *zap.Logger, cv *semver.Version, d *DowngradeInfo) (err interface{}) {
|
||||
func tryMustDetectDowngrade(lg *zap.Logger, sv, cv *semver.Version, d *DowngradeInfo) (err interface{}) {
|
||||
defer func() {
|
||||
err = recover()
|
||||
}()
|
||||
MustDetectDowngrade(lg, cv, d)
|
||||
MustDetectDowngrade(lg, sv, cv, d)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ func (m *Manager) DowngradeValidate(ctx context.Context, targetVersion *semver.V
|
||||
return err
|
||||
}
|
||||
cv := m.s.GetClusterVersion()
|
||||
allowedTargetVersion := AllowedDowngradeVersion(cv)
|
||||
allowedTargetVersion := allowedDowngradeVersion(cv)
|
||||
if !targetVersion.Equal(*allowedTargetVersion) {
|
||||
return ErrInvalidDowngradeTargetVersion
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ func TestUpgradeThreeNodes(t *testing.T) {
|
||||
|
||||
func newCluster(lg *zap.Logger, memberCount int, ver semver.Version) *clusterMock {
|
||||
cluster := &clusterMock{
|
||||
lg: lg,
|
||||
clusterVersion: ver,
|
||||
members: make([]*memberMock, 0, memberCount),
|
||||
}
|
||||
@ -99,13 +100,14 @@ func (c *clusterMock) StepMonitors() {
|
||||
}
|
||||
|
||||
type clusterMock struct {
|
||||
lg *zap.Logger
|
||||
clusterVersion semver.Version
|
||||
downgradeInfo *DowngradeInfo
|
||||
members []*memberMock
|
||||
}
|
||||
|
||||
func (c *clusterMock) DowngradeEnable(ver semver.Version) {
|
||||
c.downgradeInfo = &DowngradeInfo{TargetVersion: ver.String(), Enabled: true}
|
||||
func (c *clusterMock) Version() *Manager {
|
||||
return NewManager(c.lg, c.members[0])
|
||||
}
|
||||
|
||||
func (c *clusterMock) MembersVersions() map[string]*version.Versions {
|
||||
@ -120,9 +122,7 @@ func (c *clusterMock) MembersVersions() map[string]*version.Versions {
|
||||
}
|
||||
|
||||
func (c *clusterMock) ReplaceMemberBinary(mid int, newServerVersion semver.Version) {
|
||||
if newServerVersion.LessThan(c.clusterVersion) {
|
||||
panic("Members cannot join clusters with higher version")
|
||||
}
|
||||
MustDetectDowngrade(c.lg, &c.members[mid].serverVersion, &c.clusterVersion, c.downgradeInfo)
|
||||
c.members[mid].serverVersion = newServerVersion
|
||||
}
|
||||
|
||||
@ -146,7 +146,10 @@ func (m *memberMock) LinearizableReadNotify(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (m *memberMock) DowngradeEnable(ctx context.Context, targetVersion *semver.Version) error {
|
||||
m.cluster.downgradeInfo = nil
|
||||
m.cluster.downgradeInfo = &DowngradeInfo{
|
||||
TargetVersion: targetVersion.String(),
|
||||
Enabled: true,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user