etcdserver: Move Read/Update methods on Meta bucket to one place
There are still some left like compact keys, but they will require more work to avoid circular dependency.
This commit is contained in:
@ -20,13 +20,12 @@ import (
|
||||
|
||||
"github.com/coreos/go-semver/semver"
|
||||
"github.com/stretchr/testify/assert"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"go.etcd.io/etcd/api/v3/version"
|
||||
"go.etcd.io/etcd/raft/v3/raftpb"
|
||||
"go.etcd.io/etcd/server/v3/mvcc/backend"
|
||||
betesting "go.etcd.io/etcd/server/v3/mvcc/backend/testing"
|
||||
"go.etcd.io/etcd/server/v3/mvcc/buckets"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func TestUpdateStorageVersion(t *testing.T) {
|
||||
@ -37,7 +36,6 @@ func TestUpdateStorageVersion(t *testing.T) {
|
||||
expectVersion *semver.Version
|
||||
expectError bool
|
||||
expectedErrorMsg string
|
||||
expectedMetaKeys [][]byte
|
||||
}{
|
||||
{
|
||||
name: `Backend before 3.6 without "confState" should be rejected`,
|
||||
@ -53,51 +51,54 @@ func TestUpdateStorageVersion(t *testing.T) {
|
||||
expectVersion: nil,
|
||||
expectError: true,
|
||||
expectedErrorMsg: `cannot determine storage version: missing "term" key`,
|
||||
expectedMetaKeys: [][]byte{buckets.MetaConfStateName},
|
||||
},
|
||||
{
|
||||
name: "Backend with 3.5 with all metadata keys should be upgraded to v3.6",
|
||||
version: "",
|
||||
metaKeys: [][]byte{buckets.MetaTermKeyName, buckets.MetaConfStateName},
|
||||
expectVersion: &semver.Version{Major: 3, Minor: 6},
|
||||
expectedMetaKeys: [][]byte{buckets.MetaTermKeyName, buckets.MetaConfStateName, buckets.MetaStorageVersionName},
|
||||
name: "Backend with 3.5 with all metadata keys should be upgraded to v3.6",
|
||||
version: "",
|
||||
metaKeys: [][]byte{buckets.MetaTermKeyName, buckets.MetaConfStateName},
|
||||
expectVersion: &semver.Version{Major: 3, Minor: 6},
|
||||
},
|
||||
{
|
||||
name: "Backend in 3.6.0 should be skipped",
|
||||
version: "3.6.0",
|
||||
metaKeys: [][]byte{buckets.MetaTermKeyName, buckets.MetaConfStateName, buckets.MetaStorageVersionName},
|
||||
expectVersion: &semver.Version{Major: 3, Minor: 6},
|
||||
expectedMetaKeys: [][]byte{buckets.MetaTermKeyName, buckets.MetaConfStateName, buckets.MetaStorageVersionName},
|
||||
name: "Backend in 3.6.0 should be skipped",
|
||||
version: "3.6.0",
|
||||
metaKeys: [][]byte{buckets.MetaTermKeyName, buckets.MetaConfStateName, buckets.MetaStorageVersionName},
|
||||
expectVersion: &semver.Version{Major: 3, Minor: 6},
|
||||
},
|
||||
{
|
||||
name: "Backend with current version should be skipped",
|
||||
version: version.Version,
|
||||
metaKeys: [][]byte{buckets.MetaTermKeyName, buckets.MetaConfStateName, buckets.MetaStorageVersionName},
|
||||
expectVersion: &semver.Version{Major: 3, Minor: 6},
|
||||
expectedMetaKeys: [][]byte{buckets.MetaTermKeyName, buckets.MetaConfStateName, buckets.MetaStorageVersionName},
|
||||
name: "Backend with current version should be skipped",
|
||||
version: version.Version,
|
||||
metaKeys: [][]byte{buckets.MetaTermKeyName, buckets.MetaConfStateName, buckets.MetaStorageVersionName},
|
||||
expectVersion: &semver.Version{Major: 3, Minor: 6},
|
||||
},
|
||||
{
|
||||
name: "Backend in 3.7.0 should be skipped",
|
||||
version: "3.7.0",
|
||||
metaKeys: [][]byte{buckets.MetaTermKeyName, buckets.MetaConfStateName, buckets.MetaStorageVersionName, []byte("future-key")},
|
||||
expectVersion: &semver.Version{Major: 3, Minor: 7},
|
||||
expectedMetaKeys: [][]byte{buckets.MetaTermKeyName, buckets.MetaConfStateName, buckets.MetaStorageVersionName, []byte("future-key")},
|
||||
name: "Backend in 3.7.0 should be skipped",
|
||||
version: "3.7.0",
|
||||
metaKeys: [][]byte{buckets.MetaTermKeyName, buckets.MetaConfStateName, buckets.MetaStorageVersionName, []byte("future-key")},
|
||||
expectVersion: &semver.Version{Major: 3, Minor: 7},
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
lg := zap.NewNop()
|
||||
be, tmpPath := betesting.NewTmpBackend(t, time.Microsecond, 10)
|
||||
tx := be.BatchTx()
|
||||
if tx == nil {
|
||||
t.Fatal("batch tx is nil")
|
||||
}
|
||||
tx.Lock()
|
||||
tx.UnsafeCreateBucket(buckets.Meta)
|
||||
buckets.UnsafeCreateMetaBucket(tx)
|
||||
for _, k := range tc.metaKeys {
|
||||
tx.UnsafePut(buckets.Meta, k, []byte{})
|
||||
switch string(k) {
|
||||
case string(buckets.MetaConfStateName):
|
||||
buckets.MustUnsafeSaveConfStateToBackend(lg, tx, &raftpb.ConfState{})
|
||||
case string(buckets.MetaTermKeyName):
|
||||
buckets.UnsafeUpdateConsistentIndex(tx, 1, 1, false)
|
||||
default:
|
||||
tx.UnsafePut(buckets.Meta, k, []byte{})
|
||||
}
|
||||
}
|
||||
if tc.version != "" {
|
||||
unsafeSetStorageVersion(tx, semver.New(tc.version))
|
||||
buckets.UnsafeSetStorageVersion(tx, semver.New(tc.version))
|
||||
}
|
||||
tx.Unlock()
|
||||
be.ForceCommit()
|
||||
@ -105,123 +106,15 @@ func TestUpdateStorageVersion(t *testing.T) {
|
||||
|
||||
b := backend.NewDefaultBackend(tmpPath)
|
||||
defer b.Close()
|
||||
err := UpdateStorageVersion(zap.NewNop(), b.BatchTx())
|
||||
err := UpdateStorageVersion(lg, b.BatchTx())
|
||||
if (err != nil) != tc.expectError {
|
||||
t.Errorf("UpgradeStorage(...) = %+v, expected error: %v", err, tc.expectError)
|
||||
}
|
||||
if err != nil && err.Error() != tc.expectedErrorMsg {
|
||||
t.Errorf("UpgradeStorage(...) = %q, expected error message: %q", err, tc.expectedErrorMsg)
|
||||
}
|
||||
v := unsafeReadStorageVersion(b.BatchTx())
|
||||
v := buckets.UnsafeReadStorageVersion(b.BatchTx())
|
||||
assert.Equal(t, tc.expectVersion, v)
|
||||
keys, _ := b.BatchTx().UnsafeRange(buckets.Meta, []byte("a"), []byte("z"), 0)
|
||||
assert.ElementsMatch(t, tc.expectedMetaKeys, keys)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestVersion ensures that unsafeSetStorageVersion/unsafeReadStorageVersion work well together.
|
||||
func TestVersion(t *testing.T) {
|
||||
tcs := []struct {
|
||||
version string
|
||||
expectVersion string
|
||||
}{
|
||||
{
|
||||
version: "3.5.0",
|
||||
expectVersion: "3.5.0",
|
||||
},
|
||||
{
|
||||
version: "3.5.0-alpha",
|
||||
expectVersion: "3.5.0",
|
||||
},
|
||||
{
|
||||
version: "3.5.0-beta.0",
|
||||
expectVersion: "3.5.0",
|
||||
},
|
||||
{
|
||||
version: "3.5.0-rc.1",
|
||||
expectVersion: "3.5.0",
|
||||
},
|
||||
{
|
||||
version: "3.5.1",
|
||||
expectVersion: "3.5.0",
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.version, func(t *testing.T) {
|
||||
be, tmpPath := betesting.NewTmpBackend(t, time.Microsecond, 10)
|
||||
tx := be.BatchTx()
|
||||
if tx == nil {
|
||||
t.Fatal("batch tx is nil")
|
||||
}
|
||||
tx.Lock()
|
||||
tx.UnsafeCreateBucket(buckets.Meta)
|
||||
unsafeSetStorageVersion(tx, semver.New(tc.version))
|
||||
tx.Unlock()
|
||||
be.ForceCommit()
|
||||
be.Close()
|
||||
|
||||
b := backend.NewDefaultBackend(tmpPath)
|
||||
defer b.Close()
|
||||
v := unsafeReadStorageVersion(b.BatchTx())
|
||||
|
||||
assert.Equal(t, tc.expectVersion, v.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestVersionSnapshot ensures that unsafeSetStorageVersion/unsafeReadStorageVersionFromSnapshot work well together.
|
||||
func TestVersionSnapshot(t *testing.T) {
|
||||
tcs := []struct {
|
||||
version string
|
||||
expectVersion string
|
||||
}{
|
||||
{
|
||||
version: "3.5.0",
|
||||
expectVersion: "3.5.0",
|
||||
},
|
||||
{
|
||||
version: "3.5.0-alpha",
|
||||
expectVersion: "3.5.0",
|
||||
},
|
||||
{
|
||||
version: "3.5.0-beta.0",
|
||||
expectVersion: "3.5.0",
|
||||
},
|
||||
{
|
||||
version: "3.5.0-rc.1",
|
||||
expectVersion: "3.5.0",
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.version, func(t *testing.T) {
|
||||
be, tmpPath := betesting.NewTmpBackend(t, time.Microsecond, 10)
|
||||
tx := be.BatchTx()
|
||||
if tx == nil {
|
||||
t.Fatal("batch tx is nil")
|
||||
}
|
||||
tx.Lock()
|
||||
tx.UnsafeCreateBucket(buckets.Meta)
|
||||
unsafeSetStorageVersion(tx, semver.New(tc.version))
|
||||
tx.Unlock()
|
||||
be.ForceCommit()
|
||||
be.Close()
|
||||
db, err := bolt.Open(tmpPath, 0400, &bolt.Options{ReadOnly: true})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
var ver *semver.Version
|
||||
if err = db.View(func(tx *bolt.Tx) error {
|
||||
ver = ReadStorageVersionFromSnapshot(tx)
|
||||
return nil
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, tc.expectVersion, ver.String())
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user