MM-53228: Adding schema version to cluster info (#24209)

With the schema version available, a job can query for
the cluster info to confirm whether or not all nodes
in a cluster are upgraded to the same version or not.

This will help it in determining whether to start
the job or not.

https://mattermost.atlassian.net/browse/MM-53228

```release-note
NONE
```
Этот коммит содержится в:
Agniva De Sarker
2023-08-10 09:40:49 +05:30
коммит произвёл GitHub
родитель ace88288f0
Коммит 45a14e23a9
9 изменённых файлов: 110 добавлений и 16 удалений

Просмотреть файл

@@ -8,6 +8,7 @@ import (
"database/sql"
dbsql "database/sql"
"fmt"
"path"
"strconv"
"strings"
"sync"
@@ -20,10 +21,12 @@ import (
_ "github.com/golang-migrate/migrate/v4/source/file"
"github.com/jmoiron/sqlx"
"github.com/lib/pq"
"github.com/mattermost/morph/models"
"github.com/pkg/errors"
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/mattermost/mattermost/server/v8/channels/db"
"github.com/mattermost/mattermost/server/v8/channels/store"
"github.com/mattermost/mattermost/server/v8/einterfaces"
)
@@ -1289,6 +1292,34 @@ func (ss *SqlStore) toReserveCase(str string) string {
return fmt.Sprintf("`%s`", strings.Title(str))
}
func (ss *SqlStore) GetLocalSchemaVersion() (int, error) {
assets := db.Assets()
assetsList, err := assets.ReadDir(path.Join("migrations", ss.DriverName()))
if err != nil {
return 0, err
}
maxVersion := 0
for _, entry := range assetsList {
// parse the version name from the file name
m := models.Regex.FindStringSubmatch(entry.Name())
if len(m) < 2 {
return 0, fmt.Errorf("migration file name incorrectly formed: %s", entry.Name())
}
version, err := strconv.Atoi(m[1])
if err != nil {
return 0, err
}
// store the highest version
if maxVersion < version {
maxVersion = version
}
}
return maxVersion, nil
}
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 {

Просмотреть файл

@@ -889,6 +889,32 @@ func TestGetDBSchemaVersion(t *testing.T) {
}
}
func TestGetLocalSchemaVersion(t *testing.T) {
testDrivers := []string{
model.DatabaseDriverPostgres,
model.DatabaseDriverMysql,
}
for _, d := range testDrivers {
driver := d
t.Run(driver, func(t *testing.T) {
settings, err := makeSqlSettings(driver)
if err != nil {
t.Skip(err)
}
store, err := New(*settings, nil)
require.NoError(t, err)
ver, err := store.GetLocalSchemaVersion()
require.NoError(t, err)
dbVer, err := store.GetDBSchemaVersion()
require.NoError(t, err)
require.Equal(t, ver, dbVer)
})
}
}
func TestGetAppliedMigrations(t *testing.T) {
testDrivers := []string{
model.DatabaseDriverPostgres,

Просмотреть файл

@@ -67,6 +67,7 @@ type Store interface {
DropAllTables()
RecycleDBConnections(d time.Duration)
GetDBSchemaVersion() (int, error)
GetLocalSchemaVersion() (int, error)
GetAppliedMigrations() ([]model.AppliedMigration, error)
GetDbVersion(numerical bool) (string, error)
// GetInternalMasterDB allows access to the raw master DB

Просмотреть файл

@@ -346,6 +346,30 @@ func (_m *Store) GetInternalReplicaDB() *sql.DB {
return r0
}
// GetLocalSchemaVersion provides a mock function with given fields:
func (_m *Store) GetLocalSchemaVersion() (int, error) {
ret := _m.Called()
var r0 int
var r1 error
if rf, ok := ret.Get(0).(func() (int, error)); ok {
return rf()
}
if rf, ok := ret.Get(0).(func() int); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(int)
}
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Group provides a mock function with given fields:
func (_m *Store) Group() store.GroupStore {
ret := _m.Called()

Просмотреть файл

@@ -114,17 +114,18 @@ func (s *Store) PostAcknowledgement() store.PostAcknowledgementStore {
func (s *Store) PostPersistentNotification() store.PostPersistentNotificationStore {
return &s.PostPersistentNotificationStore
}
func (s *Store) MarkSystemRanUnitTests() { /* do nothing */ }
func (s *Store) Close() { /* do nothing */ }
func (s *Store) LockToMaster() { /* do nothing */ }
func (s *Store) UnlockFromMaster() { /* do nothing */ }
func (s *Store) DropAllTables() { /* do nothing */ }
func (s *Store) GetDbVersion(bool) (string, error) { return "", nil }
func (s *Store) GetInternalMasterDB() *sql.DB { return nil }
func (s *Store) GetInternalReplicaDB() *sql.DB { return nil }
func (s *Store) GetInternalReplicaDBs() []*sql.DB { return nil }
func (s *Store) RecycleDBConnections(time.Duration) {}
func (s *Store) GetDBSchemaVersion() (int, error) { return 1, nil }
func (s *Store) MarkSystemRanUnitTests() { /* do nothing */ }
func (s *Store) Close() { /* do nothing */ }
func (s *Store) LockToMaster() { /* do nothing */ }
func (s *Store) UnlockFromMaster() { /* do nothing */ }
func (s *Store) DropAllTables() { /* do nothing */ }
func (s *Store) GetDbVersion(bool) (string, error) { return "", nil }
func (s *Store) GetInternalMasterDB() *sql.DB { return nil }
func (s *Store) GetInternalReplicaDB() *sql.DB { return nil }
func (s *Store) GetInternalReplicaDBs() []*sql.DB { return nil }
func (s *Store) RecycleDBConnections(time.Duration) {}
func (s *Store) GetDBSchemaVersion() (int, error) { return 1, nil }
func (s *Store) GetLocalSchemaVersion() (int, error) { return 1, nil }
func (s *Store) GetAppliedMigrations() ([]model.AppliedMigration, error) {
return []model.AppliedMigration{}, nil
}

Просмотреть файл

@@ -4,9 +4,10 @@
package model
type ClusterInfo struct {
Id string `json:"id"`
Version string `json:"version"`
ConfigHash string `json:"config_hash"`
IPAddress string `json:"ipaddress"`
Hostname string `json:"hostname"`
Id string `json:"id"`
Version string `json:"version"`
SchemaVersion string `json:"schema_version"`
ConfigHash string `json:"config_hash"`
IPAddress string `json:"ipaddress"`
Hostname string `json:"hostname"`
}