MM-31356: Add a minimum required version check for Postgres (#16597)

* MM-31356: Add a minimum required version check for Postgres

To keep conformance with our failing fast and obvious philosophy,
we add a check to prevent Mattermost server from starting
if the postgres version is below 10.0.

This gives customers a chance to upgrade their database before upgrading
their Mattermost version, than to run into weird compatibility issues
after they have finished the upgrade.

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

```release-note
NONE
```

* fix lint errors

* Use a function to pretty-print version string

* rectify comment
Этот коммит содержится в:
Agniva De Sarker
2020-12-23 22:06:13 +05:30
коммит произвёл GitHub
родитель 83afd756b6
Коммит c54b262351
8 изменённых файлов: 77 добавлений и 14 удалений

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

@@ -9,6 +9,7 @@ import (
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
"sync"
"sync/atomic"
@@ -38,6 +39,12 @@ const (
MYSQL_DUP_TABLE_ERROR_CODE = uint16(1050) // see https://dev.mysql.com/doc/mysql-errors/5.7/en/server-error-reference.html#error_er_table_exists_error
DB_PING_ATTEMPTS = 18
DB_PING_TIMEOUT_SECS = 10
// This is a numerical version string by postgres. The format is
// 2 characters for major, minor, and patch version prior to 10.
// After 10, it's major and minor only.
// 10.1 would be 100001.
// 9.6.3 would be 90603.
MINIMUM_REQUIRED_POSTGRES_VERSION = 100000
)
const (
@@ -321,10 +328,17 @@ func (ss *SqlStore) GetCurrentSchemaVersion() string {
return version
}
func (ss *SqlStore) GetDbVersion() (string, error) {
// GetDbVersion returns the version of the database being used.
// If numerical is set to true, it attempts to return a numerical version string
// that can be parsed by callers.
func (ss *SqlStore) GetDbVersion(numerical bool) (string, error) {
var sqlVersion string
if ss.DriverName() == model.DATABASE_DRIVER_POSTGRES {
sqlVersion = `SHOW server_version`
if numerical {
sqlVersion = `SHOW server_version_num`
} else {
sqlVersion = `SHOW server_version`
}
} else if ss.DriverName() == model.DATABASE_DRIVER_MYSQL {
sqlVersion = `SELECT version()`
} else if ss.DriverName() == model.DATABASE_DRIVER_SQLITE {
@@ -1347,3 +1361,13 @@ func IsDuplicate(err error) bool {
return false
}
// VersionString converts an integer representation of a DB version
// to a pretty-printed string.
// Postgres doesn't follow three-part version numbers from 10.0 onwards:
// https://www.postgresql.org/docs/13/libpq-status.html#LIBPQ-PQSERVERVERSION.
func VersionString(v int) string {
minor := v % 10000
major := v / 10000
return strconv.Itoa(major) + "." + strconv.Itoa(minor)
}

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

@@ -369,7 +369,7 @@ func TestGetDbVersion(t *testing.T) {
settings := makeSqlSettings(driver)
store := New(*settings, nil)
version, err := store.GetDbVersion()
version, err := store.GetDbVersion(false)
require.Nil(t, err)
require.Regexp(t, regexp.MustCompile(`\d+\.\d+(\.\d+)?`), version)
})
@@ -471,6 +471,31 @@ func TestIsDuplicate(t *testing.T) {
}
}
func TestVersionString(t *testing.T) {
versions := []struct {
input int
output string
}{
{
input: 100000,
output: "10.0",
},
{
input: 90603,
output: "9.603",
},
{
input: 120005,
output: "12.5",
},
}
for _, v := range versions {
out := VersionString(v.input)
assert.Equal(t, v.output, out)
}
}
func makeSqlSettings(driver string) *model.SqlSettings {
switch driver {
case model.DATABASE_DRIVER_POSTGRES: