[MM-12623] Create CLI command "config reset" (#10296)
Этот коммит содержится в:
коммит произвёл
Ben Schumacher
родитель
3687a0b6c1
Коммит
63a28700f5
@@ -11,6 +11,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/mattermost/viper"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@@ -18,7 +19,6 @@ import (
|
||||
"github.com/mattermost/mattermost-server/mlog"
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
"github.com/mattermost/mattermost-server/utils"
|
||||
"github.com/mattermost/viper"
|
||||
)
|
||||
|
||||
const noSettingsNamed = "unable to find a setting named: %s"
|
||||
@@ -80,8 +80,17 @@ var MigrateConfigCmd = &cobra.Command{
|
||||
RunE: configMigrateCmdF,
|
||||
}
|
||||
|
||||
var ConfigResetCmd = &cobra.Command{
|
||||
Use: "reset",
|
||||
Short: "Reset config setting",
|
||||
Long: "Resets the value of a config setting by its name in dot notation or a setting section. Accepts multiple values for array settings.",
|
||||
Example: "config reset SqlSettings.DriverName LogSettings",
|
||||
RunE: configResetCmdF,
|
||||
}
|
||||
|
||||
func init() {
|
||||
ConfigSubpathCmd.Flags().String("path", "", "Optional subpath; defaults to value in SiteURL")
|
||||
ConfigResetCmd.Flags().Bool("confirm", false, "Confirm you really want to reset all configuration settings to its default value")
|
||||
ConfigShowCmd.Flags().Bool("json", false, "Output the configuration as JSON.")
|
||||
|
||||
ConfigCmd.AddCommand(
|
||||
@@ -91,6 +100,7 @@ func init() {
|
||||
ConfigShowCmd,
|
||||
ConfigSetCmd,
|
||||
MigrateConfigCmd,
|
||||
ConfigResetCmd,
|
||||
)
|
||||
RootCmd.AddCommand(ConfigCmd)
|
||||
}
|
||||
@@ -367,6 +377,92 @@ func UpdateMap(configMap map[string]interface{}, configSettings []string, newVal
|
||||
}
|
||||
}
|
||||
|
||||
func configResetCmdF(command *cobra.Command, args []string) error {
|
||||
configStore, err := getConfigStore(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defaultConfig := &model.Config{}
|
||||
defaultConfig.SetDefaults()
|
||||
|
||||
confirmFlag, _ := command.Flags().GetBool("confirm")
|
||||
if confirmFlag {
|
||||
if _, err = configStore.Set(defaultConfig); err != nil {
|
||||
return errors.Wrap(err, "failed to set config")
|
||||
}
|
||||
}
|
||||
|
||||
if !confirmFlag && len(args) == 0 {
|
||||
var confirmResetAll string
|
||||
CommandPrettyPrintln("Are you sure you want to reset all the configuration settings?(YES/NO): ")
|
||||
fmt.Scanln(&confirmResetAll)
|
||||
if confirmResetAll == "YES" {
|
||||
if _, err = configStore.Set(defaultConfig); err != nil {
|
||||
return errors.Wrap(err, "failed to set config")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tempConfig := configStore.Get()
|
||||
tempConfigMap := configToMap(*tempConfig)
|
||||
defaultConfigMap := configToMap(*defaultConfig)
|
||||
for _, arg := range args {
|
||||
err = changeMap(tempConfigMap, defaultConfigMap, strings.Split(arg, "."))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to reset config")
|
||||
}
|
||||
}
|
||||
bs, err := json.Marshal(tempConfigMap)
|
||||
if err != nil {
|
||||
fmt.Printf("Error while marshalling map to json %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = json.Unmarshal(bs, tempConfig)
|
||||
if err != nil {
|
||||
fmt.Printf("Error while unmarshalling json to struct %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if changed := config.FixInvalidLocales(tempConfig); changed {
|
||||
return errors.New("Invalid locale configuration")
|
||||
}
|
||||
|
||||
if _, err := configStore.Set(tempConfig); err != nil {
|
||||
return errors.Wrap(err, "failed to set config")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func changeMap(oldConfigMap, defaultConfigMap map[string]interface{}, configSettings []string) error {
|
||||
resOld, ok := oldConfigMap[configSettings[0]]
|
||||
if !ok {
|
||||
return fmt.Errorf("Unable to find a setting with that name %s", configSettings[0])
|
||||
}
|
||||
resDef := defaultConfigMap[configSettings[0]]
|
||||
valueOld := reflect.ValueOf(resOld)
|
||||
|
||||
if valueOld.Kind() == reflect.Map {
|
||||
if len(configSettings) == 1 {
|
||||
return changeSection(resOld.(map[string]interface{}), resDef.(map[string]interface{}))
|
||||
}
|
||||
return changeMap(resOld.(map[string]interface{}), resDef.(map[string]interface{}), configSettings[1:])
|
||||
}
|
||||
if len(configSettings) == 1 {
|
||||
oldConfigMap[configSettings[0]] = defaultConfigMap[configSettings[0]]
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Unable to find a setting with that name %s", configSettings[0])
|
||||
}
|
||||
|
||||
func changeSection(oldConfigMap, defaultConfigMap map[string]interface{}) error {
|
||||
valueOld := reflect.ValueOf(oldConfigMap)
|
||||
for _, key := range valueOld.MapKeys() {
|
||||
oldConfigMap[key.String()] = defaultConfigMap[key.String()]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// configToMap converts our config into a map
|
||||
func configToMap(s interface{}) map[string]interface{} {
|
||||
return structToMap(s)
|
||||
|
||||
@@ -13,11 +13,10 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/mattermost/mattermost-server/config"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/mattermost/mattermost-server/config"
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
)
|
||||
|
||||
@@ -168,6 +167,64 @@ func TestConfigSet(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestConfigReset(t *testing.T) {
|
||||
th := Setup()
|
||||
defer th.TearDown()
|
||||
|
||||
t.Run("No Error when no arguments are given (reset all the configurations)", func(t *testing.T) {
|
||||
assert.NoError(t, th.RunCommand(t, "config", "reset"))
|
||||
})
|
||||
|
||||
t.Run("No Error when a configuration section is given", func(t *testing.T) {
|
||||
assert.NoError(t, th.RunCommand(t, "config", "reset", "JobSettings"))
|
||||
})
|
||||
|
||||
t.Run("No Error when a configuration setting is given", func(t *testing.T) {
|
||||
assert.NoError(t, th.RunCommand(t, "config", "reset", "JobSettings.RunJobs"))
|
||||
})
|
||||
|
||||
t.Run("Error when the wrong configuration section is given", func(t *testing.T) {
|
||||
assert.Error(t, th.RunCommand(t, "config", "reset", "InvalidSettings"))
|
||||
})
|
||||
|
||||
t.Run("Error when the wrong configuration setting is given", func(t *testing.T) {
|
||||
assert.Error(t, th.RunCommand(t, "config", "reset", "JobSettings.InvalidConfiguration"))
|
||||
})
|
||||
|
||||
t.Run("Success when the confirm boolean flag is given", func(t *testing.T) {
|
||||
assert.NoError(t, th.RunCommand(t, "config", "set", "JobSettings.RunJobs", "false"))
|
||||
assert.NoError(t, th.RunCommand(t, "config", "set", "PrivacySettings.ShowFullName", "false"))
|
||||
assert.NoError(t, th.RunCommand(t, "config", "reset", "--confirm"))
|
||||
output1 := th.CheckCommand(t, "config", "get", "JobSettings.RunJobs")
|
||||
output2 := th.CheckCommand(t, "config", "get", "PrivacySettings.ShowFullName")
|
||||
assert.Contains(t, output1, "true")
|
||||
assert.Contains(t, output2, "true")
|
||||
})
|
||||
|
||||
t.Run("Success when a configuration section is given", func(t *testing.T) {
|
||||
assert.NoError(t, th.RunCommand(t, "config", "set", "JobSettings.RunJobs", "false"))
|
||||
assert.NoError(t, th.RunCommand(t, "config", "set", "JobSettings.RunScheduler", "false"))
|
||||
assert.NoError(t, th.RunCommand(t, "config", "set", "PrivacySettings.ShowFullName", "false"))
|
||||
assert.NoError(t, th.RunCommand(t, "config", "reset", "JobSettings"))
|
||||
output1 := th.CheckCommand(t, "config", "get", "JobSettings.RunJobs")
|
||||
output2 := th.CheckCommand(t, "config", "get", "JobSettings.RunScheduler")
|
||||
output3 := th.CheckCommand(t, "config", "get", "PrivacySettings.ShowFullName")
|
||||
assert.Contains(t, output1, "true")
|
||||
assert.Contains(t, output2, "true")
|
||||
assert.Contains(t, output3, "false")
|
||||
})
|
||||
|
||||
t.Run("Success when a configuration setting is given", func(t *testing.T) {
|
||||
assert.NoError(t, th.RunCommand(t, "config", "set", "JobSettings.RunJobs", "false"))
|
||||
assert.NoError(t, th.RunCommand(t, "config", "set", "JobSettings.RunScheduler", "false"))
|
||||
assert.NoError(t, th.RunCommand(t, "config", "reset", "JobSettings.RunJobs"))
|
||||
output1 := th.CheckCommand(t, "config", "get", "JobSettings.RunJobs")
|
||||
output2 := th.CheckCommand(t, "config", "get", "JobSettings.RunScheduler")
|
||||
assert.Contains(t, output1, "true")
|
||||
assert.Contains(t, output2, "false")
|
||||
})
|
||||
}
|
||||
|
||||
func TestConfigToMap(t *testing.T) {
|
||||
// This test is almost the same as TestStructToMap, but I have it here for the sake of completions
|
||||
cases := []struct {
|
||||
|
||||
Ссылка в новой задаче
Block a user