[MM-41576] Add schema version to the client configuration (#19757)
* revamp db version and add applied migrations endpoint * replace old schema version with new * add db version subcommand * add to local api * reflect review comments * log errors * remove setting the version from model.CurrentVersion * fix a test * use different field for schema version * add build hash and current version to the support packet * add tests * update test to use new assets
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
47c44a9b7d
Коммит
b03d87af40
@@ -353,10 +353,10 @@ func (ss *SqlStore) DriverName() string {
|
||||
return *ss.settings.DriverName
|
||||
}
|
||||
|
||||
func (ss *SqlStore) GetCurrentSchemaVersion() string {
|
||||
func (ss *SqlStore) getCurrentSchemaVersion() (string, error) {
|
||||
var version string
|
||||
_ = ss.GetMasterX().Get(&version, "SELECT Value FROM Systems WHERE Name='Version'")
|
||||
return version
|
||||
err := ss.GetMasterX().Get(&version, "SELECT Value FROM Systems WHERE Name='Version'")
|
||||
return version, err
|
||||
}
|
||||
|
||||
// GetDbVersion returns the version of the database being used.
|
||||
@@ -949,6 +949,7 @@ func (ss *SqlStore) DropAllTables() {
|
||||
FROM pg_class
|
||||
WHERE relkind = 'r' -- only tables
|
||||
AND relnamespace = 'public'::regnamespace
|
||||
AND NOT relname = 'db_migrations'
|
||||
);
|
||||
END
|
||||
$func$;`)
|
||||
@@ -956,7 +957,9 @@ func (ss *SqlStore) DropAllTables() {
|
||||
tables := []string{}
|
||||
ss.masterX.Select(&tables, `show tables`)
|
||||
for _, t := range tables {
|
||||
ss.masterX.Exec(`TRUNCATE TABLE ` + t)
|
||||
if t != "db_migrations" {
|
||||
ss.masterX.Exec(`TRUNCATE TABLE ` + t)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1204,3 +1207,20 @@ func (ss *SqlStore) toReserveCase(str string) string {
|
||||
|
||||
return fmt.Sprintf("`%s`", strings.Title(str))
|
||||
}
|
||||
|
||||
func (ss *SqlStore) GetDBSchemaVersion() (int, error) {
|
||||
var version int
|
||||
if err := ss.GetMasterX().Get(&version, "SELECT Version FROM db_migrations ORDER BY Version DESC LIMIT 1"); err != nil {
|
||||
return 0, errors.Wrap(err, "unable to select from db_migrations")
|
||||
}
|
||||
return version, nil
|
||||
}
|
||||
|
||||
func (ss *SqlStore) GetAppliedMigrations() ([]model.AppliedMigration, error) {
|
||||
migrations := []model.AppliedMigration{}
|
||||
if err := ss.GetMasterX().Select(&migrations, "SELECT Version, Name FROM db_migrations ORDER BY Version DESC"); err != nil {
|
||||
return nil, errors.Wrap(err, "unable to select from db_migrations")
|
||||
}
|
||||
|
||||
return migrations, nil
|
||||
}
|
||||
|
||||
@@ -6,7 +6,11 @@ package sqlstore
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -18,6 +22,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/db"
|
||||
"github.com/mattermost/mattermost-server/v6/einterfaces/mocks"
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/store"
|
||||
@@ -784,3 +789,79 @@ func TestMySQLReadTimeout(t *testing.T) {
|
||||
_, err = store.GetMasterX().ExecNoTimeout(`SELECT SLEEP(3)`)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestGetDBSchemaVersion(t *testing.T) {
|
||||
testDrivers := []string{
|
||||
model.DatabaseDriverPostgres,
|
||||
model.DatabaseDriverMysql,
|
||||
}
|
||||
|
||||
assets := db.Assets()
|
||||
|
||||
for _, driver := range testDrivers {
|
||||
t.Run("Should return latest version number of applied migrations for "+driver, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
settings := makeSqlSettings(driver)
|
||||
store := New(*settings, nil)
|
||||
|
||||
assetsList, err := assets.ReadDir(filepath.Join("migrations", driver))
|
||||
require.NoError(t, err)
|
||||
|
||||
var assetNamesForDriver []string
|
||||
for _, entry := range assetsList {
|
||||
assetNamesForDriver = append(assetNamesForDriver, entry.Name())
|
||||
}
|
||||
sort.Strings(assetNamesForDriver)
|
||||
|
||||
require.NotEmpty(t, assetNamesForDriver)
|
||||
lastMigration := assetNamesForDriver[len(assetNamesForDriver)-1]
|
||||
expectedVersion := strings.Split(lastMigration, "_")[0]
|
||||
|
||||
version, err := store.GetDBSchemaVersion()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedVersion, fmt.Sprintf("%06d", version))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAppliedMigrations(t *testing.T) {
|
||||
testDrivers := []string{
|
||||
model.DatabaseDriverPostgres,
|
||||
model.DatabaseDriverMysql,
|
||||
}
|
||||
|
||||
assets := db.Assets()
|
||||
|
||||
for _, driver := range testDrivers {
|
||||
t.Run("Should return db applied migrations for "+driver, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
settings := makeSqlSettings(driver)
|
||||
store := New(*settings, nil)
|
||||
|
||||
assetsList, err := assets.ReadDir(filepath.Join("migrations", driver))
|
||||
require.NoError(t, err)
|
||||
|
||||
var migrationsFromFiles []model.AppliedMigration
|
||||
for _, entry := range assetsList {
|
||||
if strings.HasSuffix(entry.Name(), ".up.sql") {
|
||||
versionString := strings.Split(entry.Name(), "_")[0]
|
||||
version, vErr := strconv.Atoi(versionString)
|
||||
require.NoError(t, vErr)
|
||||
|
||||
name := strings.TrimSuffix(strings.TrimLeft(entry.Name(), versionString+"_"), ".up.sql")
|
||||
|
||||
migrationsFromFiles = append(migrationsFromFiles, model.AppliedMigration{
|
||||
Version: version,
|
||||
Name: name,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
require.NotEmpty(t, migrationsFromFiles)
|
||||
|
||||
migrations, err := store.GetAppliedMigrations()
|
||||
require.NoError(t, err)
|
||||
require.ElementsMatch(t, migrationsFromFiles, migrations)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,8 +114,12 @@ func upgradeDatabase(sqlStore *SqlStore, currentModelVersionString string) error
|
||||
return errors.Wrapf(err, "failed to parse oldest supported version %s", OldestSupportedVersion)
|
||||
}
|
||||
|
||||
currentSchemaVersionString, err := sqlStore.getCurrentSchemaVersion()
|
||||
if err != nil {
|
||||
mlog.Warn("could not receive the schema version from systems table", mlog.Err(err))
|
||||
}
|
||||
|
||||
var currentSchemaVersion *semver.Version
|
||||
currentSchemaVersionString := sqlStore.GetCurrentSchemaVersion()
|
||||
if currentSchemaVersionString != "" {
|
||||
currentSchemaVersion, err = semver.New(currentSchemaVersionString)
|
||||
if err != nil {
|
||||
@@ -232,7 +236,11 @@ func saveSchemaVersion(sqlStore *SqlStore, version string) {
|
||||
}
|
||||
|
||||
func shouldPerformUpgrade(sqlStore *SqlStore, currentSchemaVersion string, expectedSchemaVersion string) bool {
|
||||
storedSchemaVersion := sqlStore.GetCurrentSchemaVersion()
|
||||
storedSchemaVersion, err := sqlStore.getCurrentSchemaVersion()
|
||||
if err != nil {
|
||||
mlog.Error("could not receive the schema version from systems table", mlog.Err(err))
|
||||
return false
|
||||
}
|
||||
|
||||
storedVersion, err := semver.Parse(storedSchemaVersion)
|
||||
if err != nil {
|
||||
|
||||
@@ -17,7 +17,11 @@ func TestStoreUpgradeDotRelease(t *testing.T) {
|
||||
saveSchemaVersion(sqlStore, "5.33.1")
|
||||
err := upgradeDatabase(sqlStore, CurrentSchemaVersion)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, CurrentSchemaVersion, sqlStore.GetCurrentSchemaVersion())
|
||||
|
||||
currentVersion, err := sqlStore.getCurrentSchemaVersion()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, CurrentSchemaVersion, currentVersion)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -34,28 +38,44 @@ func TestStoreUpgrade(t *testing.T) {
|
||||
saveSchemaVersion(sqlStore, "invalid")
|
||||
err := upgradeDatabase(sqlStore, "5.8.0")
|
||||
require.EqualError(t, err, "failed to parse database schema version invalid: No Major.Minor.Patch elements found")
|
||||
require.Equal(t, "invalid", sqlStore.GetCurrentSchemaVersion())
|
||||
|
||||
currentVersion, err := sqlStore.getCurrentSchemaVersion()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "invalid", currentVersion)
|
||||
})
|
||||
|
||||
t.Run("upgrade from unsupported version", func(t *testing.T) {
|
||||
saveSchemaVersion(sqlStore, "2.0.0")
|
||||
err := upgradeDatabase(sqlStore, "5.8.0")
|
||||
require.EqualError(t, err, "Database schema version 2.0.0 is no longer supported. This Mattermost server supports automatic upgrades from schema version 3.0.0 through schema version 5.8.0. Please manually upgrade to at least version 3.0.0 before continuing.")
|
||||
require.Equal(t, "2.0.0", sqlStore.GetCurrentSchemaVersion())
|
||||
|
||||
currentVersion, err := sqlStore.getCurrentSchemaVersion()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "2.0.0", currentVersion)
|
||||
})
|
||||
|
||||
t.Run("upgrade from earliest supported version", func(t *testing.T) {
|
||||
saveSchemaVersion(sqlStore, Version300)
|
||||
err := upgradeDatabase(sqlStore, CurrentSchemaVersion)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, CurrentSchemaVersion, sqlStore.GetCurrentSchemaVersion())
|
||||
|
||||
currentVersion, err := sqlStore.getCurrentSchemaVersion()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, CurrentSchemaVersion, currentVersion)
|
||||
})
|
||||
|
||||
t.Run("upgrade from no existing version", func(t *testing.T) {
|
||||
saveSchemaVersion(sqlStore, "")
|
||||
err := upgradeDatabase(sqlStore, CurrentSchemaVersion)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, CurrentSchemaVersion, sqlStore.GetCurrentSchemaVersion())
|
||||
|
||||
currentVersion, err := sqlStore.getCurrentSchemaVersion()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, CurrentSchemaVersion, currentVersion)
|
||||
})
|
||||
|
||||
t.Run("upgrade schema running earlier minor version", func(t *testing.T) {
|
||||
@@ -64,28 +84,44 @@ func TestStoreUpgrade(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
// Assert CurrentSchemaVersion, not 5.8.0, since the migrations will move
|
||||
// past 5.8.0 regardless of the input parameter.
|
||||
require.Equal(t, CurrentSchemaVersion, sqlStore.GetCurrentSchemaVersion())
|
||||
|
||||
currentVersion, err := sqlStore.getCurrentSchemaVersion()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, CurrentSchemaVersion, currentVersion)
|
||||
})
|
||||
|
||||
t.Run("upgrade schema running later minor version", func(t *testing.T) {
|
||||
saveSchemaVersion(sqlStore, "5.99.0")
|
||||
err := upgradeDatabase(sqlStore, "5.8.0")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "5.99.0", sqlStore.GetCurrentSchemaVersion())
|
||||
|
||||
currentVersion, err := sqlStore.getCurrentSchemaVersion()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "5.99.0", currentVersion)
|
||||
})
|
||||
|
||||
t.Run("upgrade schema running earlier major version", func(t *testing.T) {
|
||||
saveSchemaVersion(sqlStore, "4.1.0")
|
||||
err := upgradeDatabase(sqlStore, CurrentSchemaVersion)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, CurrentSchemaVersion, sqlStore.GetCurrentSchemaVersion())
|
||||
|
||||
currentVersion, err := sqlStore.getCurrentSchemaVersion()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, CurrentSchemaVersion, currentVersion)
|
||||
})
|
||||
|
||||
t.Run("upgrade schema running later major version", func(t *testing.T) {
|
||||
saveSchemaVersion(sqlStore, "6.0.0")
|
||||
err := upgradeDatabase(sqlStore, "5.8.0")
|
||||
require.EqualError(t, err, "Database schema version 6.0.0 is not supported. This Mattermost server supports only >=5.8.0, <6.0.0. Please upgrade to at least version 6.0.0 before continuing.")
|
||||
require.Equal(t, "6.0.0", sqlStore.GetCurrentSchemaVersion())
|
||||
|
||||
currentVersion, err := sqlStore.getCurrentSchemaVersion()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "6.0.0", currentVersion)
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -100,7 +136,11 @@ func TestSaveSchemaVersion(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, Version300, props["Version"])
|
||||
require.Equal(t, Version300, sqlStore.GetCurrentSchemaVersion())
|
||||
|
||||
currentVersion, err := sqlStore.getCurrentSchemaVersion()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, Version300, currentVersion)
|
||||
})
|
||||
|
||||
t.Run("set current version", func(t *testing.T) {
|
||||
@@ -109,7 +149,11 @@ func TestSaveSchemaVersion(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, CurrentSchemaVersion, props["Version"])
|
||||
require.Equal(t, CurrentSchemaVersion, sqlStore.GetCurrentSchemaVersion())
|
||||
|
||||
currentVersion, err := sqlStore.getCurrentSchemaVersion()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, CurrentSchemaVersion, currentVersion)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user