MM-28859 Add feature flag managment system using split.io and remove viper. (#15954)

* Add feature flag managment system using split.io and remove viper.

* Fixing tests.

* Attempt to fix postgres tests.

* Fix watch filepath for advanced logging.

* Review fixes.

* Some error wrapping.

* Remove unessisary store interface.

* Desanitize SplitKey

* Simplify.

* Review feedback.

* Rename split mlog adatper to split logger.

* fsInner

* Style.

* Restore oldcfg test.

* Downgrading non-actionable feature flag errors to warnings.

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
Christopher Speller
2020-10-29 15:54:39 -07:00
коммит произвёл GitHub
родитель 8bb772638c
Коммит 1aadd36644
423 изменённых файлов: 37646 добавлений и 20257 удалений

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

@@ -11,7 +11,6 @@ import (
"strconv"
"strings"
"github.com/mattermost/viper"
"github.com/pkg/errors"
"github.com/spf13/cobra"
@@ -141,14 +140,12 @@ func configSubpathCmdF(command *cobra.Command, args []string) error {
return nil
}
func getConfigStore(command *cobra.Command) (config.Store, error) {
func getConfigStore(command *cobra.Command) (*config.Store, error) {
if err := utils.TranslationsPreInit(); err != nil {
return nil, errors.Wrap(err, "failed to initialize i18n")
}
configDSN := viper.GetString("config")
configStore, err := config.NewStore(configDSN, false)
configStore, err := config.NewStore(getConfigDSN(command, config.GetEnvironment()), false)
if err != nil {
return nil, errors.Wrap(err, "failed to initialize config store")
}

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

@@ -94,6 +94,7 @@ func TestConfigValidate(t *testing.T) {
tempFile, err := ioutil.TempFile("", "TestConfigValidate")
require.NoError(t, err)
defer os.Remove(tempFile.Name())
tempFile.Write([]byte("{"))
assert.Error(t, th.RunCommand(t, "--config", tempFile.Name(), "config", "validate"))
th.CheckCommand(t, "config", "validate")

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

@@ -5,16 +5,14 @@ package commands
import (
"github.com/mattermost/mattermost-server/v5/app"
"github.com/mattermost/mattermost-server/v5/config"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/utils"
"github.com/mattermost/viper"
"github.com/spf13/cobra"
)
func InitDBCommandContextCobra(command *cobra.Command) (*app.App, error) {
config := viper.GetString("config")
a, err := InitDBCommandContext(config)
a, err := InitDBCommandContext(getConfigDSN(command, config.GetEnvironment()))
if err != nil {
// Returning an error just prints the usage message, so actually panic

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

@@ -9,8 +9,8 @@ import (
"syscall"
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/config"
"github.com/mattermost/mattermost-server/v5/mlog"
"github.com/mattermost/viper"
"github.com/spf13/cobra"
)
@@ -32,10 +32,8 @@ func jobserverCmdF(command *cobra.Command, args []string) error {
noJobs, _ := command.Flags().GetBool("nojobs")
noSchedule, _ := command.Flags().GetBool("noschedule")
config := viper.GetString("config")
// Initialize
a, err := InitDBCommandContext(config)
a, err := InitDBCommandContext(getConfigDSN(command, config.GetEnvironment()))
if err != nil {
return err
}

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

@@ -37,17 +37,21 @@ func TestPlugin(t *testing.T) {
fs, err := config.NewFileStore(th.ConfigPath(), false)
require.Nil(t, err)
require.NotNil(t, fs.Get().PluginSettings.PluginStates["testplugin"])
assert.True(t, fs.Get().PluginSettings.PluginStates["testplugin"].Enable)
fs.Close()
cfsStore, err := config.NewStoreFromBacking(fs)
require.Nil(t, err)
require.NotNil(t, cfsStore.Get().PluginSettings.PluginStates["testplugin"])
assert.True(t, cfsStore.Get().PluginSettings.PluginStates["testplugin"].Enable)
cfsStore.Close()
output = th.CheckCommand(t, "plugin", "disable", "testplugin")
assert.Contains(t, output, "Disabled plugin: testplugin")
fs, err = config.NewFileStore(th.ConfigPath(), false)
require.Nil(t, err)
require.NotNil(t, fs.Get().PluginSettings.PluginStates["testplugin"])
assert.False(t, fs.Get().PluginSettings.PluginStates["testplugin"].Enable)
fs.Close()
cfsStore, err = config.NewStoreFromBacking(fs)
require.Nil(t, err)
require.NotNil(t, cfsStore.Get().PluginSettings.PluginStates["testplugin"])
assert.False(t, cfsStore.Get().PluginSettings.PluginStates["testplugin"].Enable)
cfsStore.Close()
th.CheckCommand(t, "plugin", "list")

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

@@ -4,7 +4,6 @@
package commands
import (
"github.com/mattermost/viper"
"github.com/spf13/cobra"
)
@@ -22,12 +21,8 @@ var RootCmd = &cobra.Command{
}
func init() {
RootCmd.PersistentFlags().StringP("config", "c", "config.json", "Configuration file to use.")
RootCmd.PersistentFlags().StringP("config", "c", "", "Configuration file to use.")
RootCmd.PersistentFlags().Bool("disableconfigwatch", false, "When set config.json will not be loaded from disk when the file is changed.")
RootCmd.PersistentFlags().Bool("platform", false, "This flag signifies that the user tried to start the command from the platform binary, so we can log a mssage")
RootCmd.PersistentFlags().MarkHidden("platform")
viper.SetEnvPrefix("mm")
viper.BindEnv("config")
viper.BindPFlag("config", RootCmd.PersistentFlags().Lookup("config"))
}

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

@@ -18,7 +18,6 @@ import (
"github.com/mattermost/mattermost-server/v5/utils"
"github.com/mattermost/mattermost-server/v5/web"
"github.com/mattermost/mattermost-server/v5/wsapi"
"github.com/mattermost/viper"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -36,8 +35,6 @@ func init() {
}
func serverCmdF(command *cobra.Command, args []string) error {
configDSN := viper.GetString("config")
disableConfigWatch, _ := command.Flags().GetBool("disableconfigwatch")
usedPlatform, _ := command.Flags().GetBool("platform")
@@ -46,7 +43,7 @@ func serverCmdF(command *cobra.Command, args []string) error {
if err := utils.TranslationsPreInit(); err != nil {
return errors.Wrapf(err, "unable to load Mattermost translation files")
}
configStore, err := config.NewStore(configDSN, !disableConfigWatch)
configStore, err := config.NewStore(getConfigDSN(command, config.GetEnvironment()), !disableConfigWatch)
if err != nil {
return errors.Wrap(err, "failed to load configuration")
}
@@ -54,7 +51,7 @@ func serverCmdF(command *cobra.Command, args []string) error {
return runServer(configStore, disableConfigWatch, usedPlatform, interruptChan)
}
func runServer(configStore config.Store, disableConfigWatch bool, usedPlatform bool, interruptChan chan os.Signal) error {
func runServer(configStore *config.Store, disableConfigWatch bool, usedPlatform bool, interruptChan chan os.Signal) error {
// Setting the highest traceback level from the code.
// This is done to print goroutines from all threads (see golang.org/issue/13161)
// and also preserve a crash dump for later investigation.

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

@@ -57,13 +57,12 @@ func TestRunServerSuccess(t *testing.T) {
th := SetupServerTest(t)
defer th.TearDownServerTest()
configStore, err := config.NewMemoryStore()
require.NoError(t, err)
configStore := config.NewTestMemoryStore()
// Use non-default listening port in case another server instance is already running.
*configStore.Get().ServiceSettings.ListenAddress = UnitTestListeningPort
err = runServer(configStore, th.disableConfigWatch, false, th.interruptChan)
err := runServer(configStore, th.disableConfigWatch, false, th.interruptChan)
require.NoError(t, err)
}
@@ -108,8 +107,7 @@ func TestRunServerSystemdNotification(t *testing.T) {
ch <- string(data)
}(socketReader)
configStore, err := config.NewMemoryStore()
require.NoError(t, err)
configStore := config.NewTestMemoryStore()
// Use non-default listening port in case another server instance is already running.
*configStore.Get().ServiceSettings.ListenAddress = UnitTestListeningPort
@@ -132,12 +130,11 @@ func TestRunServerNoSystemd(t *testing.T) {
os.Unsetenv("NOTIFY_SOCKET")
defer os.Setenv("NOTIFY_SOCKET", originalSocket)
configStore, err := config.NewMemoryStore()
require.NoError(t, err)
configStore := config.NewTestMemoryStore()
// Use non-default listening port in case another server instance is already running.
*configStore.Get().ServiceSettings.ListenAddress = UnitTestListeningPort
err = runServer(configStore, th.disableConfigWatch, false, th.interruptChan)
err := runServer(configStore, th.disableConfigWatch, false, th.interruptChan)
require.NoError(t, err)
}

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

@@ -11,6 +11,7 @@ import (
"strings"
"github.com/mattermost/mattermost-server/v5/mlog"
"github.com/spf13/cobra"
)
// prettyPrintStruct will return a prettyPrint version of a given struct
@@ -99,3 +100,19 @@ func printStringMap(value reflect.Value, tabVal int) string {
return out.String()
}
func getConfigDSN(command *cobra.Command, env map[string]string) string {
configDSN, _ := command.Flags().GetString("config")
// Config not supplied in flag, check env
if configDSN == "" {
configDSN = env["MM_CONFIG"]
}
// Config not supplied in env or flag use default
if configDSN == "" {
configDSN = "config.json"
}
return configDSN
}