Disable read/search db replicas in TE/E0 (#14400)

* Disable read/search db replicas in TE/E0

* fixing tests

* Removing unnecesary text.

* Updating without-license read-replicas config before store initialization

* Reconnecting to database after remove read replicas
Этот коммит содержится в:
Jesús Espino
2020-05-07 14:11:05 +02:00
коммит произвёл GitHub
родитель 37f43a7094
Коммит ef5ac519d9
7 изменённых файлов: 101 добавлений и 17 удалений

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

@@ -41,6 +41,7 @@ import (
"github.com/mattermost/mattermost-server/v5/services/timezones" "github.com/mattermost/mattermost-server/v5/services/timezones"
"github.com/mattermost/mattermost-server/v5/services/tracing" "github.com/mattermost/mattermost-server/v5/services/tracing"
"github.com/mattermost/mattermost-server/v5/store" "github.com/mattermost/mattermost-server/v5/store"
"github.com/mattermost/mattermost-server/v5/store/sqlstore"
"github.com/mattermost/mattermost-server/v5/utils" "github.com/mattermost/mattermost-server/v5/utils"
) )
@@ -48,6 +49,7 @@ var MaxNotificationsPerChannelDefault int64 = 1000000
type Server struct { type Server struct {
Store store.Store Store store.Store
sqlStore *sqlstore.SqlSupplier
WebSocketRouter *WebSocketRouter WebSocketRouter *WebSocketRouter
// RootRouter is the starting point for all HTTP requests to the server. // RootRouter is the starting point for all HTTP requests to the server.
@@ -276,11 +278,22 @@ func NewServer(options ...Option) (*Server, error) {
license := s.License() license := s.License()
if license == nil && len(s.Config().SqlSettings.DataSourceReplicas) > 1 { if license == nil && len(s.Config().SqlSettings.DataSourceReplicas) > 0 {
mlog.Warn("More than 1 read replica functionality disabled by current license. Please contact your system administrator about upgrading your enterprise license.") mlog.Warn("Read replicas functionality disabled by current license. Please contact your system administrator about upgrading your enterprise license.")
s.UpdateConfig(func(cfg *model.Config) { s.UpdateConfig(func(cfg *model.Config) {
cfg.SqlSettings.DataSourceReplicas = cfg.SqlSettings.DataSourceReplicas[:1] cfg.SqlSettings.DataSourceReplicas = []string{}
}) })
s.Store.Close()
s.Store = s.newStore()
}
if license == nil && len(s.Config().SqlSettings.DataSourceSearchReplicas) > 0 {
mlog.Warn("Search replicas functionality disabled by current license. Please contact your system administrator about upgrading your enterprise license.")
s.UpdateConfig(func(cfg *model.Config) {
cfg.SqlSettings.DataSourceSearchReplicas = []string{}
})
s.Store.Close()
s.Store = s.newStore()
} }
if license == nil { if license == nil {

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

@@ -61,10 +61,11 @@ func (s *Server) RunOldAppInitialization() error {
if s.newStore == nil { if s.newStore == nil {
s.newStore = func() store.Store { s.newStore = func() store.Store {
s.sqlStore = sqlstore.NewSqlSupplier(s.Config().SqlSettings, s.Metrics)
return store.NewTimerLayer( return store.NewTimerLayer(
searchlayer.NewSearchLayer( searchlayer.NewSearchLayer(
localcachelayer.NewLocalCacheLayer( localcachelayer.NewLocalCacheLayer(
sqlstore.NewSqlSupplier(s.Config().SqlSettings, s.Metrics), s.sqlStore,
s.Metrics, s.Metrics,
s.Cluster, s.Cluster,
s.CacheProvider, s.CacheProvider,

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

@@ -6,7 +6,6 @@ package app
import ( import (
"bufio" "bufio"
"crypto/tls" "crypto/tls"
"github.com/mattermost/mattermost-server/v5/mlog"
"io/ioutil" "io/ioutil"
"net" "net"
"net/http" "net/http"
@@ -16,6 +15,8 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/mattermost/mattermost-server/v5/mlog"
"github.com/mattermost/mattermost-server/v5/config" "github.com/mattermost/mattermost-server/v5/config"
"github.com/mattermost/mattermost-server/v5/model" "github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/utils/fileutils" "github.com/mattermost/mattermost-server/v5/utils/fileutils"
@@ -36,6 +37,66 @@ func TestStartServerSuccess(t *testing.T) {
require.NoError(t, serverErr) require.NoError(t, serverErr)
} }
func TestReadReplicaDisabledBasedOnLicense(t *testing.T) {
t.Run("Read Replicas with no License", func(t *testing.T) {
s, err := NewServer(func(server *Server) error {
configStore, _ := config.NewFileStore("config.json", true)
server.configStore = configStore
server.UpdateConfig(func(cfg *model.Config) {
cfg.SqlSettings.DataSourceReplicas = []string{*cfg.SqlSettings.DataSource}
})
return nil
})
require.NoError(t, err)
require.Equal(t, s.sqlStore.GetMaster(), s.sqlStore.GetReplica())
require.Len(t, s.Config().SqlSettings.DataSourceReplicas, 0)
})
t.Run("Read Replicas With License", func(t *testing.T) {
s, err := NewServer(func(server *Server) error {
configStore, _ := config.NewFileStore("config.json", true)
server.configStore = configStore
server.licenseValue.Store(model.NewTestLicense())
server.UpdateConfig(func(cfg *model.Config) {
cfg.SqlSettings.DataSourceReplicas = []string{*cfg.SqlSettings.DataSource}
})
return nil
})
require.NoError(t, err)
require.NotEqual(t, s.sqlStore.GetMaster(), s.sqlStore.GetReplica())
require.Len(t, s.Config().SqlSettings.DataSourceReplicas, 1)
})
t.Run("Search Replicas with no License", func(t *testing.T) {
s, err := NewServer(func(server *Server) error {
configStore, _ := config.NewFileStore("config.json", true)
server.configStore = configStore
server.UpdateConfig(func(cfg *model.Config) {
cfg.SqlSettings.DataSourceSearchReplicas = []string{*cfg.SqlSettings.DataSource}
})
return nil
})
require.NoError(t, err)
require.Equal(t, s.sqlStore.GetMaster(), s.sqlStore.GetSearchReplica())
require.Len(t, s.Config().SqlSettings.DataSourceSearchReplicas, 0)
})
t.Run("Search Replicas With License", func(t *testing.T) {
s, err := NewServer(func(server *Server) error {
configStore, _ := config.NewFileStore("config.json", true)
server.configStore = configStore
server.licenseValue.Store(model.NewTestLicense())
server.UpdateConfig(func(cfg *model.Config) {
cfg.SqlSettings.DataSourceSearchReplicas = []string{*cfg.SqlSettings.DataSource}
})
return nil
})
require.NoError(t, err)
require.NotEqual(t, s.sqlStore.GetMaster(), s.sqlStore.GetSearchReplica())
require.Len(t, s.Config().SqlSettings.DataSourceSearchReplicas, 1)
})
}
func TestStartServerRateLimiterCriticalError(t *testing.T) { func TestStartServerRateLimiterCriticalError(t *testing.T) {
// Attempt to use Rate Limiter with an invalid config // Attempt to use Rate Limiter with an invalid config
ms, err := config.NewMemoryStoreWithOptions(&config.MemoryStoreOptions{ ms, err := config.NewMemoryStoreWithOptions(&config.MemoryStoreOptions{

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

@@ -35,6 +35,21 @@ func desanitize(actual, target *model.Config) {
if *target.SqlSettings.DataSource == model.FAKE_SETTING { if *target.SqlSettings.DataSource == model.FAKE_SETTING {
*target.SqlSettings.DataSource = *actual.SqlSettings.DataSource *target.SqlSettings.DataSource = *actual.SqlSettings.DataSource
} }
if len(target.SqlSettings.DataSourceReplicas) == 1 && target.SqlSettings.DataSourceReplicas[0] == model.FAKE_SETTING {
target.SqlSettings.DataSourceReplicas = make([]string, len(actual.SqlSettings.DataSourceReplicas))
for i := range target.SqlSettings.DataSourceReplicas {
target.SqlSettings.DataSourceReplicas[i] = actual.SqlSettings.DataSourceReplicas[i]
}
}
if len(target.SqlSettings.DataSourceSearchReplicas) == 1 && target.SqlSettings.DataSourceSearchReplicas[0] == model.FAKE_SETTING {
target.SqlSettings.DataSourceSearchReplicas = make([]string, len(actual.SqlSettings.DataSourceSearchReplicas))
for i := range target.SqlSettings.DataSourceSearchReplicas {
target.SqlSettings.DataSourceSearchReplicas[i] = actual.SqlSettings.DataSourceSearchReplicas[i]
}
}
if *target.SqlSettings.AtRestEncryptKey == model.FAKE_SETTING { if *target.SqlSettings.AtRestEncryptKey == model.FAKE_SETTING {
target.SqlSettings.AtRestEncryptKey = actual.SqlSettings.AtRestEncryptKey target.SqlSettings.AtRestEncryptKey = actual.SqlSettings.AtRestEncryptKey
} }
@@ -42,16 +57,6 @@ func desanitize(actual, target *model.Config) {
if *target.ElasticsearchSettings.Password == model.FAKE_SETTING { if *target.ElasticsearchSettings.Password == model.FAKE_SETTING {
*target.ElasticsearchSettings.Password = *actual.ElasticsearchSettings.Password *target.ElasticsearchSettings.Password = *actual.ElasticsearchSettings.Password
} }
target.SqlSettings.DataSourceReplicas = make([]string, len(actual.SqlSettings.DataSourceReplicas))
for i := range target.SqlSettings.DataSourceReplicas {
target.SqlSettings.DataSourceReplicas[i] = actual.SqlSettings.DataSourceReplicas[i]
}
target.SqlSettings.DataSourceSearchReplicas = make([]string, len(actual.SqlSettings.DataSourceSearchReplicas))
for i := range target.SqlSettings.DataSourceSearchReplicas {
target.SqlSettings.DataSourceSearchReplicas[i] = actual.SqlSettings.DataSourceSearchReplicas[i]
}
} }
// fixConfig patches invalid or missing data in the configuration, returning true if changed. // fixConfig patches invalid or missing data in the configuration, returning true if changed.

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

@@ -50,8 +50,8 @@ func TestDesanitize(t *testing.T) {
target.SqlSettings.DataSource = sToP(model.FAKE_SETTING) target.SqlSettings.DataSource = sToP(model.FAKE_SETTING)
target.SqlSettings.AtRestEncryptKey = sToP(model.FAKE_SETTING) target.SqlSettings.AtRestEncryptKey = sToP(model.FAKE_SETTING)
target.ElasticsearchSettings.Password = sToP(model.FAKE_SETTING) target.ElasticsearchSettings.Password = sToP(model.FAKE_SETTING)
target.SqlSettings.DataSourceReplicas = append(target.SqlSettings.DataSourceReplicas, "old_replica0") target.SqlSettings.DataSourceReplicas = []string{model.FAKE_SETTING}
target.SqlSettings.DataSourceSearchReplicas = append(target.SqlSettings.DataSourceReplicas, "old_search_replica0") target.SqlSettings.DataSourceSearchReplicas = []string{model.FAKE_SETTING}
actualClone := actual.Clone() actualClone := actual.Clone()
desanitize(actual, target) desanitize(actual, target)

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

@@ -3342,6 +3342,8 @@ func (o *Config) Sanitize() {
} }
*o.SqlSettings.DataSource = FAKE_SETTING *o.SqlSettings.DataSource = FAKE_SETTING
o.SqlSettings.DataSourceReplicas = []string{FAKE_SETTING}
o.SqlSettings.DataSourceSearchReplicas = []string{FAKE_SETTING}
*o.SqlSettings.AtRestEncryptKey = FAKE_SETTING *o.SqlSettings.AtRestEncryptKey = FAKE_SETTING
*o.ElasticsearchSettings.Password = FAKE_SETTING *o.ElasticsearchSettings.Password = FAKE_SETTING

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

@@ -1239,6 +1239,8 @@ func TestConfigSanitize(t *testing.T) {
assert.Equal(t, FAKE_SETTING, *c.EmailSettings.SMTPPassword) assert.Equal(t, FAKE_SETTING, *c.EmailSettings.SMTPPassword)
assert.Equal(t, FAKE_SETTING, *c.GitLabSettings.Secret) assert.Equal(t, FAKE_SETTING, *c.GitLabSettings.Secret)
assert.Equal(t, FAKE_SETTING, *c.SqlSettings.DataSource) assert.Equal(t, FAKE_SETTING, *c.SqlSettings.DataSource)
assert.Equal(t, []string{FAKE_SETTING}, c.SqlSettings.DataSourceReplicas)
assert.Equal(t, []string{FAKE_SETTING}, c.SqlSettings.DataSourceSearchReplicas)
assert.Equal(t, FAKE_SETTING, *c.SqlSettings.AtRestEncryptKey) assert.Equal(t, FAKE_SETTING, *c.SqlSettings.AtRestEncryptKey)
assert.Equal(t, FAKE_SETTING, *c.ElasticsearchSettings.Password) assert.Equal(t, FAKE_SETTING, *c.ElasticsearchSettings.Password)
assert.Equal(t, FAKE_SETTING, c.SqlSettings.DataSourceReplicas[0]) assert.Equal(t, FAKE_SETTING, c.SqlSettings.DataSourceReplicas[0])