[MM-32234] Fix config.json getting reset (#16805)

* Add support for read-only config stores

* Allow read/write config store for plugin commands that require it
Этот коммит содержится в:
Claudio Costa
2021-01-28 20:04:17 +01:00
коммит произвёл GitHub
родитель 77da23e84b
Коммит 9c9fbe6dd9
22 изменённых файлов: 211 добавлений и 92 удалений

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

@@ -96,7 +96,7 @@ func setupTestHelper(dbStore store.Store, searchEngine *searchengine.Broker, ent
}
memoryStore.Set(memoryConfig)
configStore, err := config.NewStoreFromBacking(memoryStore, nil)
configStore, err := config.NewStoreFromBacking(memoryStore, nil, false)
if err != nil {
panic(err)
}

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

@@ -691,11 +691,11 @@ func TestMigrateConfig(t *testing.T) {
})
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
f, err := config.NewStore("from.json", false, nil)
f, err := config.NewStore("from.json", false, false, nil)
require.NoError(t, err)
defer f.RemoveFile("from.json")
_, err = config.NewStore("to.json", false, nil)
_, err = config.NewStore("to.json", false, false, nil)
require.NoError(t, err)
defer f.RemoveFile("to.json")

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

@@ -46,6 +46,9 @@ func (a *App) EnvironmentConfig() map[string]interface{} {
}
func (s *Server) UpdateConfig(f func(*model.Config)) {
if s.configStore.IsReadOnly() {
return
}
old := s.Config()
updated := old.Clone()
f(updated)

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

@@ -43,9 +43,9 @@ func StoreOverride(override interface{}) Option {
// or a database connection string. It receives as well a set of
// custom defaults that will be applied for any unset property of the
// config loaded from the dsn on top of the normal defaults
func Config(dsn string, watch bool, configDefaults *model.Config) Option {
func Config(dsn string, watch, readOnly bool, configDefaults *model.Config) Option {
return func(s *Server) error {
configStore, err := config.NewStore(dsn, watch, configDefaults)
configStore, err := config.NewStore(dsn, watch, readOnly, configDefaults)
if err != nil {
return errors.Wrap(err, "failed to apply Config option")
}

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

@@ -210,7 +210,7 @@ func NewServer(options ...Option) (*Server, error) {
if err != nil {
return nil, errors.Wrap(err, "failed to load config")
}
configStore, err := config.NewStoreFromBacking(innerStore, nil)
configStore, err := config.NewStoreFromBacking(innerStore, nil, false)
if err != nil {
return nil, errors.Wrap(err, "failed to load config")
}

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

@@ -384,7 +384,7 @@ func TestSentry(t *testing.T) {
s, err := NewServer(func(server *Server) error {
configStore, _ := config.NewFileStore("config.json", true)
store, _ := config.NewStoreFromBacking(configStore, nil)
store, _ := config.NewStoreFromBacking(configStore, nil, false)
server.configStore = store
server.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ListenAddress = ":0"
@@ -435,7 +435,7 @@ func TestSentry(t *testing.T) {
s, err := NewServer(func(server *Server) error {
configStore, _ := config.NewFileStore("config.json", true)
store, _ := config.NewStoreFromBacking(configStore, nil)
store, _ := config.NewStoreFromBacking(configStore, nil, false)
server.configStore = store
server.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ListenAddress = ":0"

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

@@ -145,7 +145,7 @@ func getConfigStore(command *cobra.Command) (*config.Store, error) {
return nil, errors.Wrap(err, "failed to initialize i18n")
}
configStore, err := config.NewStore(getConfigDSN(command, config.GetEnvironment()), false, nil)
configStore, err := config.NewStore(getConfigDSN(command, config.GetEnvironment()), false, false, nil)
if err != nil {
return nil, errors.Wrap(err, "failed to initialize config store")
}

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

@@ -543,9 +543,9 @@ func TestConfigMigrate(t *testing.T) {
sqlDSN := getDsn(*sqlSettings.DriverName, *sqlSettings.DataSource)
fileDSN := "config.json"
ds, err := config.NewStore(sqlDSN, false, nil)
ds, err := config.NewStore(sqlDSN, false, false, nil)
require.NoError(t, err)
fs, err := config.NewStore(fileDSN, false, nil)
fs, err := config.NewStore(fileDSN, false, false, nil)
require.NoError(t, err)
defer ds.Close()

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

@@ -57,7 +57,7 @@ func initDbCmdF(command *cobra.Command, _ []string) error {
return errors.Wrap(err, "error loading custom configuration defaults")
}
configStore, err := config.NewStore(getConfigDSN(command, config.GetEnvironment()), false, customDefaults)
configStore, err := config.NewStore(getConfigDSN(command, config.GetEnvironment()), false, false, customDefaults)
if err != nil {
return errors.Wrap(err, "failed to load configuration")
}

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

@@ -12,8 +12,8 @@ import (
"github.com/mattermost/mattermost-server/v5/utils"
)
func InitDBCommandContextCobra(command *cobra.Command) (*app.App, error) {
a, err := InitDBCommandContext(getConfigDSN(command, config.GetEnvironment()))
func initDBCommandContextCobra(command *cobra.Command, readOnlyConfigStore bool) (*app.App, error) {
a, err := initDBCommandContext(getConfigDSN(command, config.GetEnvironment()), readOnlyConfigStore)
if err != nil {
// Returning an error just prints the usage message, so actually panic
panic(err)
@@ -25,14 +25,22 @@ func InitDBCommandContextCobra(command *cobra.Command) (*app.App, error) {
return a, nil
}
func InitDBCommandContext(configDSN string) (*app.App, error) {
func InitDBCommandContextCobra(command *cobra.Command) (*app.App, error) {
return initDBCommandContextCobra(command, true)
}
func InitDBCommandContextCobraReadWrite(command *cobra.Command) (*app.App, error) {
return initDBCommandContextCobra(command, false)
}
func initDBCommandContext(configDSN string, readOnlyConfigStore bool) (*app.App, error) {
if err := utils.TranslationsPreInit(); err != nil {
return nil, err
}
model.AppErrorInit(utils.T)
s, err := app.NewServer(
app.Config(configDSN, false, nil),
app.Config(configDSN, false, readOnlyConfigStore, nil),
app.StartSearchEngine,
)
if err != nil {

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

@@ -34,7 +34,7 @@ func jobserverCmdF(command *cobra.Command, args []string) error {
noSchedule, _ := command.Flags().GetBool("noschedule")
// Initialize
a, err := InitDBCommandContext(getConfigDSN(command, config.GetEnvironment()))
a, err := initDBCommandContext(getConfigDSN(command, config.GetEnvironment()), false)
if err != nil {
return err
}

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

@@ -104,7 +104,7 @@ func init() {
}
func pluginAddCmdF(command *cobra.Command, args []string) error {
a, err := InitDBCommandContextCobra(command)
a, err := InitDBCommandContextCobraReadWrite(command)
if err != nil {
return err
}
@@ -134,7 +134,7 @@ func pluginAddCmdF(command *cobra.Command, args []string) error {
}
func pluginDeleteCmdF(command *cobra.Command, args []string) error {
a, err := InitDBCommandContextCobra(command)
a, err := InitDBCommandContextCobraReadWrite(command)
if err != nil {
return err
}
@@ -158,7 +158,7 @@ func pluginDeleteCmdF(command *cobra.Command, args []string) error {
}
func pluginEnableCmdF(command *cobra.Command, args []string) error {
a, err := InitDBCommandContextCobra(command)
a, err := InitDBCommandContextCobraReadWrite(command)
if err != nil {
return err
}
@@ -182,7 +182,7 @@ func pluginEnableCmdF(command *cobra.Command, args []string) error {
}
func pluginDisableCmdF(command *cobra.Command, args []string) error {
a, err := InitDBCommandContextCobra(command)
a, err := InitDBCommandContextCobraReadWrite(command)
if err != nil {
return err
}
@@ -265,7 +265,7 @@ func pluginPublicKeysCmdF(command *cobra.Command, args []string) error {
}
func pluginAddPublicKeyCmdF(command *cobra.Command, args []string) error {
a, err := InitDBCommandContextCobra(command)
a, err := InitDBCommandContextCobraReadWrite(command)
if err != nil {
return err
}
@@ -296,7 +296,7 @@ func pluginAddPublicKeyCmdF(command *cobra.Command, args []string) error {
}
func pluginDeletePublicKeyCmdF(command *cobra.Command, args []string) error {
a, err := InitDBCommandContextCobra(command)
a, err := InitDBCommandContextCobraReadWrite(command)
if err != nil {
return err
}

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

@@ -38,7 +38,7 @@ func TestPlugin(t *testing.T) {
fs, err := config.NewFileStore(th.ConfigPath(), false)
require.Nil(t, err)
cfsStore, err := config.NewStoreFromBacking(fs, nil)
cfsStore, err := config.NewStoreFromBacking(fs, nil, false)
require.Nil(t, err)
require.NotNil(t, cfsStore.Get().PluginSettings.PluginStates["testplugin"])
assert.True(t, cfsStore.Get().PluginSettings.PluginStates["testplugin"].Enable)
@@ -48,7 +48,7 @@ func TestPlugin(t *testing.T) {
assert.Contains(t, output, "Disabled plugin: testplugin")
fs, err = config.NewFileStore(th.ConfigPath(), false)
require.Nil(t, err)
cfsStore, err = config.NewStoreFromBacking(fs, nil)
cfsStore, err = config.NewStoreFromBacking(fs, nil, false)
require.Nil(t, err)
require.NotNil(t, cfsStore.Get().PluginSettings.PluginStates["testplugin"])
assert.False(t, cfsStore.Get().PluginSettings.PluginStates["testplugin"].Enable)

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

@@ -50,7 +50,7 @@ func serverCmdF(command *cobra.Command, args []string) error {
mlog.Warn("Error loading custom configuration defaults: " + err.Error())
}
configStore, err := config.NewStore(getConfigDSN(command, config.GetEnvironment()), !disableConfigWatch, customDefaults)
configStore, err := config.NewStore(getConfigDSN(command, config.GetEnvironment()), !disableConfigWatch, false, customDefaults)
if err != nil {
return errors.Wrap(err, "failed to load configuration")
}

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

@@ -140,7 +140,7 @@ func TestMergeConfigs(t *testing.T) {
func TestConfigEnvironmentOverrides(t *testing.T) {
memstore, err := config.NewMemoryStore()
require.NoError(t, err)
base, err := config.NewStoreFromBacking(memstore, nil)
base, err := config.NewStoreFromBacking(memstore, nil, false)
require.NoError(t, err)
originalConfig := &model.Config{}
originalConfig.ServiceSettings.SiteURL = newString("http://notoverriden.ca")
@@ -169,7 +169,7 @@ func TestRemoveEnvironmentOverrides(t *testing.T) {
memstore, err := config.NewMemoryStore()
require.NoError(t, err)
base, err := config.NewStoreFromBacking(memstore, nil)
base, err := config.NewStoreFromBacking(memstore, nil, false)
require.NoError(t, err)
oldCfg := base.Get()
assert.Equal(t, "http://overridden.ca", *oldCfg.ServiceSettings.SiteURL)

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

@@ -120,7 +120,7 @@ func newTestDatabaseStore(t *testing.T, customDefaults *model.Config) (*config.S
dss, err := config.NewDatabaseStore(getDsn(*sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
cStore, err := config.NewStoreFromBacking(dss, customDefaults)
cStore, err := config.NewStoreFromBacking(dss, customDefaults, false)
require.NoError(t, err)
return cStore, nil

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

@@ -91,7 +91,7 @@ func TestFileStoreNew(t *testing.T) {
fs, err := config.NewFileStore(path, false)
require.NoError(t, err)
configStore, err := config.NewStoreFromBacking(fs, nil)
configStore, err := config.NewStoreFromBacking(fs, nil, false)
require.NoError(t, err)
defer configStore.Close()
@@ -105,7 +105,7 @@ func TestFileStoreNew(t *testing.T) {
fs, err := config.NewFileStore(path, false)
require.NoError(t, err)
configStore, err := config.NewStoreFromBacking(fs, customConfigDefaults)
configStore, err := config.NewStoreFromBacking(fs, customConfigDefaults, false)
require.NoError(t, err)
defer configStore.Close()
@@ -124,7 +124,7 @@ func TestFileStoreNew(t *testing.T) {
fs, err := config.NewFileStore(path, false)
require.NoError(t, err)
configStore, err := config.NewStoreFromBacking(fs, nil)
configStore, err := config.NewStoreFromBacking(fs, nil, false)
require.NoError(t, err)
defer configStore.Close()
@@ -138,7 +138,7 @@ func TestFileStoreNew(t *testing.T) {
fs, err := config.NewFileStore(path, false)
require.NoError(t, err)
configStore, err := config.NewStoreFromBacking(fs, customConfigDefaults)
configStore, err := config.NewStoreFromBacking(fs, customConfigDefaults, false)
require.NoError(t, err)
defer configStore.Close()
@@ -160,7 +160,7 @@ func TestFileStoreNew(t *testing.T) {
path := filepath.Join(tempDir, "does_not_exist")
fs, err := config.NewFileStore(path, false)
require.NoError(t, err)
configStore, err := config.NewStoreFromBacking(fs, nil)
configStore, err := config.NewStoreFromBacking(fs, nil, false)
require.NoError(t, err)
defer configStore.Close()
@@ -179,7 +179,7 @@ func TestFileStoreNew(t *testing.T) {
path := filepath.Join(tempDir, "does_not_exist")
fs, err := config.NewFileStore(path, false)
require.NoError(t, err)
configStore, err := config.NewStoreFromBacking(fs, customConfigDefaults)
configStore, err := config.NewStoreFromBacking(fs, customConfigDefaults, false)
require.NoError(t, err)
defer configStore.Close()
@@ -198,7 +198,7 @@ func TestFileStoreNew(t *testing.T) {
path := filepath.Join(tempDir, "does/not/exist")
fs, err := config.NewFileStore(path, false)
require.NoError(t, err)
configStore, err := config.NewStoreFromBacking(fs, nil)
configStore, err := config.NewStoreFromBacking(fs, nil, false)
require.Nil(t, configStore)
require.Error(t, err)
})
@@ -220,7 +220,7 @@ func TestFileStoreNew(t *testing.T) {
fs, err := config.NewFileStore(path, false)
require.NoError(t, err)
configStore, err := config.NewStoreFromBacking(fs, nil)
configStore, err := config.NewStoreFromBacking(fs, nil, false)
require.NoError(t, err)
defer configStore.Close()
@@ -239,7 +239,7 @@ func TestFileStoreNew(t *testing.T) {
path := "TestFileStoreNew/a/b/c/config.json"
fs, err := config.NewFileStore(path, false)
require.NoError(t, err)
configStore, err := config.NewStoreFromBacking(fs, nil)
configStore, err := config.NewStoreFromBacking(fs, nil, false)
require.NoError(t, err)
defer configStore.Close()
@@ -254,7 +254,7 @@ func TestFileStoreGet(t *testing.T) {
fs, err := config.NewFileStore(path, false)
require.NoError(t, err)
configStore, err := config.NewStoreFromBacking(fs, nil)
configStore, err := config.NewStoreFromBacking(fs, nil, false)
require.NoError(t, err)
defer configStore.Close()
@@ -280,7 +280,7 @@ func TestFileStoreGetEnivironmentOverrides(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -292,7 +292,7 @@ func TestFileStoreGetEnivironmentOverrides(t *testing.T) {
fsInner, err = config.NewFileStore(path, false)
require.NoError(t, err)
fs, err = config.NewStoreFromBacking(fsInner, nil)
fs, err = config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -306,7 +306,7 @@ func TestFileStoreGetEnivironmentOverrides(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, customConfigDefaults)
fs, err := config.NewStoreFromBacking(fsInner, customConfigDefaults, false)
require.NoError(t, err)
defer fs.Close()
@@ -318,7 +318,7 @@ func TestFileStoreGetEnivironmentOverrides(t *testing.T) {
fsInner, err = config.NewFileStore(path, false)
require.NoError(t, err)
fs, err = config.NewStoreFromBacking(fsInner, customConfigDefaults)
fs, err = config.NewStoreFromBacking(fsInner, customConfigDefaults, false)
require.NoError(t, err)
defer fs.Close()
@@ -333,7 +333,7 @@ func TestFileStoreGetEnivironmentOverrides(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -345,7 +345,7 @@ func TestFileStoreGetEnivironmentOverrides(t *testing.T) {
fsInner, err = config.NewFileStore(path, false)
require.NoError(t, err)
fs, err = config.NewStoreFromBacking(fsInner, nil)
fs, err = config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -359,7 +359,7 @@ func TestFileStoreGetEnivironmentOverrides(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -371,7 +371,7 @@ func TestFileStoreGetEnivironmentOverrides(t *testing.T) {
fsInner, err = config.NewFileStore(path, false)
require.NoError(t, err)
fs, err = config.NewStoreFromBacking(fsInner, nil)
fs, err = config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -385,7 +385,7 @@ func TestFileStoreGetEnivironmentOverrides(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -397,7 +397,7 @@ func TestFileStoreGetEnivironmentOverrides(t *testing.T) {
fsInner, err = config.NewFileStore(path, false)
require.NoError(t, err)
fs, err = config.NewStoreFromBacking(fsInner, nil)
fs, err = config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -411,7 +411,7 @@ func TestFileStoreGetEnivironmentOverrides(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -423,7 +423,7 @@ func TestFileStoreGetEnivironmentOverrides(t *testing.T) {
fsInner, err = config.NewFileStore(path, false)
require.NoError(t, err)
fs, err = config.NewStoreFromBacking(fsInner, nil)
fs, err = config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -440,7 +440,7 @@ func TestFileStoreGetEnivironmentOverrides(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -452,7 +452,7 @@ func TestFileStoreGetEnivironmentOverrides(t *testing.T) {
fsInner, err = config.NewFileStore(path, false)
require.NoError(t, err)
fs, err = config.NewStoreFromBacking(fsInner, nil)
fs, err = config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -468,7 +468,7 @@ func TestFileStoreSet(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -489,7 +489,7 @@ func TestFileStoreSet(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -508,7 +508,7 @@ func TestFileStoreSet(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -529,7 +529,7 @@ func TestFileStoreSet(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -548,7 +548,7 @@ func TestFileStoreSet(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -570,7 +570,7 @@ func TestFileStoreSet(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -598,7 +598,7 @@ func TestFileStoreSet(t *testing.T) {
fsInner, err := config.NewFileStore(path, true)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -630,7 +630,7 @@ func TestFileStoreLoad(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -647,7 +647,7 @@ func TestFileStoreLoad(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -671,7 +671,7 @@ func TestFileStoreLoad(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -696,7 +696,7 @@ func TestFileStoreLoad(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -721,7 +721,7 @@ func TestFileStoreLoad(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -746,7 +746,7 @@ func TestFileStoreLoad(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -771,7 +771,7 @@ func TestFileStoreLoad(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -798,7 +798,7 @@ func TestFileStoreLoad(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -820,7 +820,7 @@ func TestFileStoreLoad(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -841,7 +841,7 @@ func TestFileStoreLoad(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -860,7 +860,7 @@ func TestFileStoreLoad(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -887,7 +887,7 @@ func TestFileStoreWatcherEmitter(t *testing.T) {
defer tearDown()
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -913,7 +913,7 @@ func TestFileStoreWatcherEmitter(t *testing.T) {
defer tearDown()
fsInner, err := config.NewFileStore(path, true)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -938,7 +938,7 @@ func TestFileStoreSave(t *testing.T) {
fsInner, err := config.NewFileStore(path, false)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.NoError(t, err)
defer fs.Close()
@@ -1262,3 +1262,25 @@ func wasCalled(c chan bool, duration time.Duration) bool {
}
return false
}
func TestFileStoreReadOnly(t *testing.T) {
path, tearDown := setupConfigFile(t, emptyConfig)
defer tearDown()
fsInner, err := config.NewFileStore(path, true)
require.NoError(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil, true)
require.NoError(t, err)
defer fs.Close()
called := make(chan bool, 1)
callback := func(oldfg, newCfg *model.Config) {
called <- true
}
fs.AddListener(callback)
cfg, err := fs.Set(minimalConfig)
require.Nil(t, cfg)
require.Equal(t, config.ErrReadOnlyStore, err)
require.False(t, wasCalled(called, 1*time.Second), "callback should not have been called since config is read-only")
}

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

@@ -9,13 +9,13 @@ import (
// Migrate migrates SAML keys, certificates, and other config files from one store to another given their data source names.
func Migrate(from, to string) error {
source, err := NewStore(from, false, nil)
source, err := NewStore(from, false, false, nil)
if err != nil {
return errors.Wrapf(err, "failed to access source config %s", from)
}
defer source.Close()
destination, err := NewStore(to, false, nil)
destination, err := NewStore(to, false, false, nil)
if err != nil {
return errors.Wrapf(err, "failed to access destination config %s", to)
}

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

@@ -103,7 +103,7 @@ func TestMigrate(t *testing.T) {
sourcedb, err := config.NewDatabaseStore(sourceDSN)
require.NoError(t, err)
source, err := config.NewStoreFromBacking(sourcedb, nil)
source, err := config.NewStoreFromBacking(sourcedb, nil, false)
require.NoError(t, err)
defer source.Close()
@@ -113,7 +113,7 @@ func TestMigrate(t *testing.T) {
destinationfile, err := config.NewFileStore(destinationDSN, false)
require.NoError(t, err)
destination, err := config.NewStoreFromBacking(destinationfile, nil)
destination, err := config.NewStoreFromBacking(destinationfile, nil, false)
require.NoError(t, err)
defer destination.Close()
@@ -132,7 +132,7 @@ func TestMigrate(t *testing.T) {
sourcefile, err := config.NewFileStore(sourceDSN, false)
require.NoError(t, err)
source, err := config.NewStoreFromBacking(sourcefile, nil)
source, err := config.NewStoreFromBacking(sourcefile, nil, false)
require.NoError(t, err)
defer source.Close()
@@ -142,7 +142,7 @@ func TestMigrate(t *testing.T) {
destinationdb, err := config.NewDatabaseStore(destinationDSN)
require.NoError(t, err)
destination, err := config.NewStoreFromBacking(destinationdb, nil)
destination, err := config.NewStoreFromBacking(destinationdb, nil, false)
require.NoError(t, err)
defer destination.Close()

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

@@ -14,6 +14,12 @@ import (
"github.com/mattermost/mattermost-server/v5/utils/jsonutils"
)
var (
// ErrReadOnlyStore is returned when an attempt to modify a read-only
// configuration store is made.
ErrReadOnlyStore = errors.New("configuration store is read-only")
)
// Listener is a callback function invoked when the configuration changes.
type Listener func(oldConfig *model.Config, newConfig *model.Config)
@@ -48,13 +54,13 @@ type BackingStore interface {
}
// NewStore creates a database or file store given a data source name by which to connect.
func NewStore(dsn string, watch bool, customDefaults *model.Config) (*Store, error) {
func NewStore(dsn string, watch, readOnly bool, customDefaults *model.Config) (*Store, error) {
backingStore, err := getBackingStore(dsn, watch)
if err != nil {
return nil, err
}
store, err := NewStoreFromBacking(backingStore, customDefaults)
store, err := NewStoreFromBacking(backingStore, customDefaults, readOnly)
if err != nil {
backingStore.Close()
return nil, errors.Wrap(err, "failed to create store")
@@ -63,10 +69,11 @@ func NewStore(dsn string, watch bool, customDefaults *model.Config) (*Store, err
return store, nil
}
func NewStoreFromBacking(backingStore BackingStore, customDefaults *model.Config) (*Store, error) {
func NewStoreFromBacking(backingStore BackingStore, customDefaults *model.Config, readOnly bool) (*Store, error) {
store := &Store{
backingStore: backingStore,
configCustomDefaults: customDefaults,
readOnly: readOnly,
}
if err := store.Load(); err != nil {
@@ -96,7 +103,7 @@ func NewTestMemoryStore() *Store {
panic("failed to initialize memory store: " + err.Error())
}
configStore, err := NewStoreFromBacking(memoryStore, nil)
configStore, err := NewStoreFromBacking(memoryStore, nil, false)
if err != nil {
panic("failed to initialize config store: " + err.Error())
}
@@ -114,6 +121,7 @@ type Store struct {
configCustomDefaults *model.Config
persistFeatureFlags bool
readOnly bool
}
// Get fetches the current, cached configuration.
@@ -156,6 +164,10 @@ func (s *Store) Set(newCfg *model.Config) (*model.Config, error) {
var unlockOnce sync.Once
defer unlockOnce.Do(s.configLock.Unlock)
if s.readOnly {
return nil, ErrReadOnlyStore
}
oldCfg := s.config.Clone()
// Really just for some tests we need to set defaults here
@@ -236,7 +248,7 @@ func (s *Store) loadLockedWithOld(oldCfg *model.Config, unlockOnce *sync.Once) e
if err != nil {
return errors.Wrap(err, "failed to marshal loaded config")
}
if len(configBytes) == 0 || !bytes.Equal(oldCfgBytes, newCfgBytes) {
if !s.readOnly && (len(configBytes) == 0 || !bytes.Equal(oldCfgBytes, newCfgBytes)) {
if err := s.backingStore.Set(s.configNoEnv); err != nil {
if !errors.Is(err, ErrReadOnlyConfiguration) {
return errors.Wrap(err, "failed to persist")
@@ -276,6 +288,9 @@ func (s *Store) GetFile(name string) ([]byte, error) {
func (s *Store) SetFile(name string, data []byte) error {
s.configLock.Lock()
defer s.configLock.Unlock()
if s.readOnly {
return ErrReadOnlyStore
}
return s.backingStore.SetFile(name, data)
}
@@ -290,6 +305,9 @@ func (s *Store) HasFile(name string) (bool, error) {
func (s *Store) RemoveFile(name string) error {
s.configLock.Lock()
defer s.configLock.Unlock()
if s.readOnly {
return ErrReadOnlyStore
}
return s.backingStore.RemoveFile(name)
}
@@ -304,3 +322,10 @@ func (s *Store) Close() error {
defer s.configLock.Unlock()
return s.backingStore.Close()
}
// IsReadOnly returns whether or not the store is read-only.
func (s *Store) IsReadOnly() bool {
s.configLock.RLock()
defer s.configLock.RUnlock()
return s.readOnly
}

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

@@ -29,26 +29,87 @@ func TestNewStore(t *testing.T) {
require.NoError(t, os.Mkdir(filepath.Join(tempDir, "config"), 0700))
t.Run("database dsn", func(t *testing.T) {
ds, err := config.NewStore(getDsn(*sqlSettings.DriverName, *sqlSettings.DataSource), false, nil)
ds, err := config.NewStore(getDsn(*sqlSettings.DriverName, *sqlSettings.DataSource), false, false, nil)
require.NoError(t, err)
ds.Close()
})
t.Run("database dsn, watch ignored", func(t *testing.T) {
ds, err := config.NewStore(getDsn(*sqlSettings.DriverName, *sqlSettings.DataSource), true, nil)
ds, err := config.NewStore(getDsn(*sqlSettings.DriverName, *sqlSettings.DataSource), true, false, nil)
require.NoError(t, err)
ds.Close()
})
t.Run("file dsn", func(t *testing.T) {
fs, err := config.NewStore("config.json", false, nil)
fs, err := config.NewStore("config.json", false, false, nil)
require.NoError(t, err)
fs.Close()
})
t.Run("file dsn, watch", func(t *testing.T) {
fs, err := config.NewStore("config.json", true, nil)
fs, err := config.NewStore("config.json", true, false, nil)
require.NoError(t, err)
fs.Close()
})
}
func TestNewStoreReadOnly(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
sqlSettings := mainHelper.GetSQLSettings()
tempDir, err := ioutil.TempDir("", "TestNewStore")
require.NoError(t, err)
err = os.Chdir(tempDir)
require.NoError(t, err)
require.NoError(t, os.Mkdir(filepath.Join(tempDir, "config"), 0700))
t.Run("database dsn", func(t *testing.T) {
ds, err := config.NewStore(getDsn(*sqlSettings.DriverName, *sqlSettings.DataSource), false, true, nil)
require.NoError(t, err)
t.Run("Set", func(t *testing.T) {
cfg, err := ds.Set(emptyConfig)
require.Nil(t, cfg)
require.Equal(t, config.ErrReadOnlyStore, err)
})
t.Run("SetFile", func(t *testing.T) {
err := ds.SetFile("config.json", []byte{})
require.Equal(t, config.ErrReadOnlyStore, err)
})
t.Run("RemoveFile", func(t *testing.T) {
err := ds.RemoveFile("config.json")
require.Equal(t, config.ErrReadOnlyStore, err)
})
ds.Close()
})
t.Run("file dsn", func(t *testing.T) {
fs, err := config.NewStore("config.json", false, true, nil)
require.NoError(t, err)
t.Run("Set", func(t *testing.T) {
cfg, err := fs.Set(emptyConfig)
require.Nil(t, cfg)
require.Equal(t, config.ErrReadOnlyStore, err)
})
t.Run("SetFile", func(t *testing.T) {
err := fs.SetFile("config.json", []byte{})
require.Equal(t, config.ErrReadOnlyStore, err)
})
t.Run("RemoveFile", func(t *testing.T) {
err := fs.RemoveFile("config.json")
require.Equal(t, config.ErrReadOnlyStore, err)
})
fs.Close()
})
}

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

@@ -129,7 +129,7 @@ func TestSendMailUsingConfig(t *testing.T) {
fsInner, err := config.NewFileStore("config.json", false)
require.Nil(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.Nil(t, err)
cfg := fs.Get()
@@ -170,7 +170,7 @@ func TestSendMailWithEmbeddedFilesUsingConfig(t *testing.T) {
fsInner, err := config.NewFileStore("config.json", false)
require.Nil(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.Nil(t, err)
cfg := fs.Get()
@@ -217,7 +217,7 @@ func TestSendMailUsingConfigAdvanced(t *testing.T) {
fsInner, err := config.NewFileStore("config.json", false)
require.Nil(t, err)
fs, err := config.NewStoreFromBacking(fsInner, nil)
fs, err := config.NewStoreFromBacking(fsInner, nil, false)
require.Nil(t, err)
cfg := fs.Get()