Skip to content

Commit

Permalink
Merge pull request #16313 from CaojiamingAlan/check_version
Browse files Browse the repository at this point in the history
checks the client supported versions based on the current version
  • Loading branch information
ahrtr authored Aug 1, 2023
2 parents 4d4ba98 + c023c06 commit 9ad5189
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 17 deletions.
3 changes: 3 additions & 0 deletions api/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ var (
V3_6 = semver.Version{Major: 3, Minor: 6}
V3_7 = semver.Version{Major: 3, Minor: 7}
V4_0 = semver.Version{Major: 4, Minor: 0}

// AllVersions keeps all the versions in ascending order.
AllVersions = []semver.Version{V3_0, V3_1, V3_2, V3_3, V3_4, V3_5, V3_6, V3_7, V4_0}
)

func init() {
Expand Down
38 changes: 24 additions & 14 deletions client/v3/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ import (
"context"
"errors"
"fmt"
"strconv"
"strings"
"sync"
"time"

"github.com/coreos/go-semver/semver"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
Expand All @@ -32,6 +32,7 @@ import (
"google.golang.org/grpc/status"

"go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
"go.etcd.io/etcd/api/v3/version"
"go.etcd.io/etcd/client/pkg/v3/logutil"
"go.etcd.io/etcd/client/v3/credentials"
"go.etcd.io/etcd/client/v3/internal/endpoint"
Expand Down Expand Up @@ -475,6 +476,22 @@ func (c *Client) roundRobinQuorumBackoff(waitBetween time.Duration, jitterFracti
}
}

// minSupportedVersion returns the minimum version supported, which is the previous minor release.
func minSupportedVersion() *semver.Version {
ver := semver.Must(semver.NewVersion(version.Version))
// consider only major and minor version
ver = &semver.Version{Major: ver.Major, Minor: ver.Minor}
for i := range version.AllVersions {
if version.AllVersions[i].Equal(*ver) {
if i == 0 {
return ver
}
return &version.AllVersions[i-1]
}
}
panic("current version is not in the version list")
}

func (c *Client) checkVersion() (err error) {
var wg sync.WaitGroup

Expand All @@ -496,20 +513,13 @@ func (c *Client) checkVersion() (err error) {
errc <- rerr
return
}
vs := strings.Split(resp.Version, ".")
maj, min := 0, 0
if len(vs) >= 2 {
var serr error
if maj, serr = strconv.Atoi(vs[0]); serr != nil {
errc <- serr
return
}
if min, serr = strconv.Atoi(vs[1]); serr != nil {
errc <- serr
return
}
vs, serr := semver.NewVersion(resp.Version)
if serr != nil {
errc <- serr
return
}
if maj < 3 || (maj == 3 && min < 4) {

if vs.LessThan(*minSupportedVersion()) {
rerr = ErrOldCluster
}
errc <- rerr
Expand Down
48 changes: 46 additions & 2 deletions client/v3/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ import (
"testing"
"time"

"github.com/coreos/go-semver/semver"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"go.uber.org/zap"
"go.uber.org/zap/zaptest"

"go.etcd.io/etcd/api/v3/etcdserverpb"
"go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
"go.etcd.io/etcd/api/v3/version"
"go.etcd.io/etcd/client/pkg/v3/testutil"

"google.golang.org/grpc"
Expand Down Expand Up @@ -312,6 +315,47 @@ func TestSyncFiltersMembers(t *testing.T) {
}
}

func TestMinSupportedVersion(t *testing.T) {
testutil.BeforeTest(t)
var tests = []struct {
name string
currentVersion semver.Version
minSupportedVersion semver.Version
}{
{
name: "v3.6 client should accept v3.5",
currentVersion: version.V3_6,
minSupportedVersion: version.V3_5,
},
{
name: "v3.7 client should accept v3.6",
currentVersion: version.V3_7,
minSupportedVersion: version.V3_6,
},
{
name: "first minor version should accept its previous version",
currentVersion: version.V4_0,
minSupportedVersion: version.V3_7,
},
{
name: "first version in list should not accept previous versions",
currentVersion: version.V3_0,
minSupportedVersion: version.V3_0,
},
}

versionBackup := version.Version
t.Cleanup(func() {
version.Version = versionBackup
})
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
version.Version = tt.currentVersion.String()
require.True(t, minSupportedVersion().Equal(tt.minSupportedVersion))
})
}
}

func TestClientRejectOldCluster(t *testing.T) {
testutil.BeforeTest(t)
var tests = []struct {
Expand All @@ -323,13 +367,13 @@ func TestClientRejectOldCluster(t *testing.T) {
{
name: "all new versions with the same value",
endpoints: []string{"192.168.3.41:22379", "192.168.3.41:22479", "192.168.3.41:22579"},
versions: []string{"3.5.4", "3.5.4", "3.5.4"},
versions: []string{version.Version, version.Version, version.Version},
expectedError: nil,
},
{
name: "all new versions with different values",
endpoints: []string{"192.168.3.41:22379", "192.168.3.41:22479", "192.168.3.41:22579"},
versions: []string{"3.5.4", "3.5.4", "3.4.0"},
versions: []string{version.Version, minSupportedVersion().String(), minSupportedVersion().String()},
expectedError: nil,
},
{
Expand Down
2 changes: 1 addition & 1 deletion client/v3/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module go.etcd.io/etcd/client/v3
go 1.19

require (
github.com/coreos/go-semver v0.3.1
github.com/dustin/go-humanize v1.0.1
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/prometheus/client_golang v1.16.0
Expand All @@ -18,7 +19,6 @@ require (
github.com/benbjohnson/clock v1.1.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
Expand Down

0 comments on commit 9ad5189

Please sign in to comment.