From ef9ef7fdf962c4c0945bcefa3eb332af2ece5768 Mon Sep 17 00:00:00 2001 From: 0x4r45h <0x4r45h@gmail.com> Date: Fri, 12 Jul 2024 21:59:53 +0330 Subject: [PATCH 01/12] Add DataDir config --- tools/cosmovisor/args.go | 32 +++++++++++++++++++++++++++++++- tools/cosmovisor/process.go | 4 ++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/tools/cosmovisor/args.go b/tools/cosmovisor/args.go index be94fbadaf6c..fbf96786eefd 100644 --- a/tools/cosmovisor/args.go +++ b/tools/cosmovisor/args.go @@ -31,6 +31,7 @@ const ( EnvShutdownGrace = "DAEMON_SHUTDOWN_GRACE" EnvSkipBackup = "UNSAFE_SKIP_BACKUP" EnvDataBackupPath = "DAEMON_DATA_BACKUP_DIR" + EnvDataPath = "DAEMON_DATA_DIR" EnvInterval = "DAEMON_POLL_INTERVAL" EnvPreupgradeMaxRetries = "DAEMON_PREUPGRADE_MAX_RETRIES" EnvDisableLogs = "COSMOVISOR_DISABLE_LOGS" @@ -45,6 +46,7 @@ const ( genesisDir = "genesis" upgradesDir = "upgrades" currentLink = "current" + dataDir = "data" cfgFileName = "config" cfgExtension = "toml" @@ -62,6 +64,7 @@ type Config struct { PollInterval time.Duration `toml:"daemon_poll_interval" mapstructure:"daemon_poll_interval" default:"300ms"` UnsafeSkipBackup bool `toml:"unsafe_skip_backup" mapstructure:"unsafe_skip_backup" default:"false"` DataBackupPath string `toml:"daemon_data_backup_dir" mapstructure:"daemon_data_backup_dir"` + DataPath string `toml:"daemon_data_dir" mapstructure:"daemon_data_dir"` PreUpgradeMaxRetries int `toml:"daemon_preupgrade_max_retries" mapstructure:"daemon_preupgrade_max_retries" default:"0"` DisableLogs bool `toml:"cosmovisor_disable_logs" mapstructure:"cosmovisor_disable_logs" default:"false"` ColorLogs bool `toml:"cosmovisor_color_logs" mapstructure:"cosmovisor_color_logs" default:"true"` @@ -106,7 +109,17 @@ func (cfg *Config) BaseUpgradeDir() string { // UpgradeInfoFilePath is the expected upgrade-info filename created by `x/upgrade/keeper`. func (cfg *Config) UpgradeInfoFilePath() string { - return filepath.Join(cfg.Home, "data", upgradetypes.UpgradeInfoFilename) + return filepath.Join(cfg.DataDirPath(), upgradetypes.UpgradeInfoFilename) +} + +func (cfg *Config) DataDirPath() string { + if cfg.DataPath != "" { + // Return the Absolute path defined by user + return cfg.DataPath + } + // Otherwise, return the default path + return filepath.Join(cfg.Home, dataDir) + } // SymLinkToGenesis creates a symbolic link from "./current" to the genesis directory. @@ -210,6 +223,7 @@ func GetConfigFromEnv(skipValidate bool) (*Config, error) { Home: os.Getenv(EnvHome), Name: os.Getenv(EnvName), DataBackupPath: os.Getenv(EnvDataBackupPath), + DataPath: os.Getenv(EnvDataPath), CustomPreUpgrade: os.Getenv(EnvCustomPreupgrade), } @@ -344,6 +358,20 @@ func (cfg *Config) validate() []error { errs = append(errs, fmt.Errorf("%s is not a directory", cfg.Root())) } } + // validate DataPath + switch { + case cfg.DataPath == "": + break + case !filepath.IsAbs(cfg.DataPath): + errs = append(errs, fmt.Errorf("%s must be an absolute path", cfg.DataPath)) + default: + switch info, err := os.Stat(cfg.DataPath); { + case err != nil: + errs = append(errs, fmt.Errorf("%q must be a valid directory: %w", cfg.DataPath, err)) + case !info.IsDir(): + errs = append(errs, fmt.Errorf("%q must be a valid directory", cfg.DataPath)) + } + } // check the DataBackupPath if cfg.UnsafeSkipBackup { @@ -542,6 +570,7 @@ func (cfg Config) DetailString() string { {EnvInterval, cfg.PollInterval.String()}, {EnvSkipBackup, fmt.Sprintf("%t", cfg.UnsafeSkipBackup)}, {EnvDataBackupPath, cfg.DataBackupPath}, + {EnvDataPath, cfg.DataPath}, {EnvPreupgradeMaxRetries, fmt.Sprintf("%d", cfg.PreUpgradeMaxRetries)}, {EnvDisableLogs, fmt.Sprintf("%t", cfg.DisableLogs)}, {EnvColorLogs, fmt.Sprintf("%t", cfg.ColorLogs)}, @@ -556,6 +585,7 @@ func (cfg Config) DetailString() string { {"Genesis Bin", cfg.GenesisBin()}, {"Monitored File", cfg.UpgradeInfoFilePath()}, {"Data Backup Dir", cfg.DataBackupPath}, + {"Data Dir", cfg.DataDirPath()}, } var sb strings.Builder diff --git a/tools/cosmovisor/process.go b/tools/cosmovisor/process.go index ac759bde39f4..f75c4405b30b 100644 --- a/tools/cosmovisor/process.go +++ b/tools/cosmovisor/process.go @@ -187,8 +187,8 @@ func (l Launcher) doBackup() error { l.logger.Info("starting to take backup of data directory", "backup start time", st) - // copy the $DAEMON_HOME/data to a backup dir - if err = copy.Copy(filepath.Join(l.cfg.Home, "data"), dst); err != nil { + // copy the data dir to a backup dir + if err = copy.Copy(filepath.Join(l.cfg.DataDirPath()), dst); err != nil { return fmt.Errorf("error while taking data backup: %w", err) } From 88ed0eec324b660ecac83d1d22b1c8867ba1d33f Mon Sep 17 00:00:00 2001 From: 0x4r45h <0x4r45h@gmail.com> Date: Sat, 13 Jul 2024 00:52:25 +0330 Subject: [PATCH 02/12] args test done --- tools/cosmovisor/args_test.go | 185 +++++++++++++++++++++------------- 1 file changed, 113 insertions(+), 72 deletions(-) diff --git a/tools/cosmovisor/args_test.go b/tools/cosmovisor/args_test.go index f121a3989d9f..b2ace17ab2a0 100644 --- a/tools/cosmovisor/args_test.go +++ b/tools/cosmovisor/args_test.go @@ -33,6 +33,7 @@ type cosmovisorEnv struct { RestartDelay string SkipBackup string DataBackupPath string + DataPath string Interval string PreupgradeMaxRetries string DisableLogs string @@ -60,6 +61,7 @@ func (c cosmovisorEnv) ToMap() map[string]envMap { EnvShutdownGrace: {val: c.ShutdownGrace, allowEmpty: false}, EnvSkipBackup: {val: c.SkipBackup, allowEmpty: false}, EnvDataBackupPath: {val: c.DataBackupPath, allowEmpty: false}, + EnvDataPath: {val: c.DataPath, allowEmpty: true}, EnvInterval: {val: c.Interval, allowEmpty: false}, EnvPreupgradeMaxRetries: {val: c.PreupgradeMaxRetries, allowEmpty: false}, EnvDisableLogs: {val: c.DisableLogs, allowEmpty: false}, @@ -91,6 +93,8 @@ func (c *cosmovisorEnv) Set(envVar, envVal string) { c.SkipBackup = envVal case EnvDataBackupPath: c.DataBackupPath = envVal + case EnvDataPath: + c.DataPath = envVal case EnvInterval: c.Interval = envVal case EnvPreupgradeMaxRetries: @@ -229,6 +233,14 @@ func (s *argsTestSuite) TestValidate() { cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataBackupPath: relPath}, valid: true, }, + "happy with empty data path": { + cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataPath: ""}, + valid: true, + }, + "happy with absolute data path": { + cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataPath: absPath}, + valid: true, + }, "missing home": { cfg: Config{Name: "bind"}, valid: false, @@ -261,9 +273,18 @@ func (s *argsTestSuite) TestValidate() { cfg: Config{Home: absPath, Name: "bind", DataBackupPath: relPath}, valid: false, }, + "no such data path dir": { + cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataPath: filepath.FromSlash("/no/such/dir")}, + valid: false, + }, + "relative data path": { + cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataPath: relPath}, + valid: false, + }, } - for _, tc := range cases { + for title, tc := range cases { + fmt.Println(title) errs := tc.cfg.validate() if tc.valid { s.Require().Len(errs, 0) @@ -403,6 +424,7 @@ func (s *argsTestSuite) TestDetailString() { pollInterval := 406 * time.Millisecond unsafeSkipBackup := false dataBackupPath := "/home" + dataPath := "" preupgradeMaxRetries := 8 cfg := &Config{ Home: home, @@ -413,6 +435,7 @@ func (s *argsTestSuite) TestDetailString() { PollInterval: pollInterval, UnsafeSkipBackup: unsafeSkipBackup, DataBackupPath: dataBackupPath, + DataPath: dataPath, PreUpgradeMaxRetries: preupgradeMaxRetries, } @@ -426,6 +449,7 @@ func (s *argsTestSuite) TestDetailString() { fmt.Sprintf("%s: %s", EnvInterval, pollInterval), fmt.Sprintf("%s: %t", EnvSkipBackup, unsafeSkipBackup), fmt.Sprintf("%s: %s", EnvDataBackupPath, home), + fmt.Sprintf("%s: %s", EnvDataPath, dataPath), fmt.Sprintf("%s: %d", EnvPreupgradeMaxRetries, preupgradeMaxRetries), fmt.Sprintf("%s: %t", EnvDisableLogs, cfg.DisableLogs), fmt.Sprintf("%s: %t", EnvColorLogs, cfg.ColorLogs), @@ -436,6 +460,7 @@ func (s *argsTestSuite) TestDetailString() { fmt.Sprintf("Genesis Bin: %s", home), fmt.Sprintf("Monitored File: %s", home), fmt.Sprintf("Data Backup Dir: %s", home), + fmt.Sprintf("Data Dir: %s/data", home), } actual := cfg.DetailString() @@ -453,6 +478,7 @@ var newConfig = func( restartDelay int, skipBackup bool, dataBackupPath string, + dataPath string, interval, preupgradeMaxRetries int, disableLogs, colorLogs bool, timeFormatLogs string, @@ -470,6 +496,7 @@ var newConfig = func( PollInterval: time.Millisecond * time.Duration(interval), UnsafeSkipBackup: skipBackup, DataBackupPath: dataBackupPath, + DataPath: dataPath, PreUpgradeMaxRetries: preupgradeMaxRetries, DisableLogs: disableLogs, ColorLogs: colorLogs, @@ -505,6 +532,7 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { RestartDelay: "bad", SkipBackup: "bad", DataBackupPath: "bad", + DataPath: "bad", Interval: "bad", PreupgradeMaxRetries: "bad", TimeFormatLogs: "bad", @@ -513,17 +541,17 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { ShutdownGrace: "bad", }, expectedCfg: nil, - expectedErrCount: 13, + expectedErrCount: 14, }, { name: "all good", - envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "true", "10s"}, - expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", true, 10000000000), + envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "true", "10s"}, + expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", true, 10000000000), expectedErrCount: 0, }, { name: "nothing set", - envVals: cosmovisorEnv{"", "", "", "", "", "", "", "", "", "", "false", "false", "", "", "", ""}, + envVals: cosmovisorEnv{"", "", "", "", "", "", "", "", "", "", "", "false", "false", "", "", "", ""}, expectedCfg: nil, expectedErrCount: 3, }, @@ -531,235 +559,248 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { // timeformat tests are done in the TestTimeFormat { name: "download bin bad", - envVals: cosmovisorEnv{absPath, "testname", "bad", "true", "false", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen", "", "", ""}, + envVals: cosmovisorEnv{absPath, "testname", "bad", "true", "false", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "", "", ""}, expectedCfg: nil, expectedErrCount: 1, }, { name: "download bin not set", - envVals: cosmovisorEnv{absPath, "testname", "", "true", "false", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen", "", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, true, absPath, 303, 1, false, true, time.Kitchen, "", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "", "true", "false", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "", "", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "", false, 0), expectedErrCount: 0, }, { name: "download bin true", - envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "download bin false", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, true, absPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "download ensure checksum true", - envVals: cosmovisorEnv{absPath, "testname", "true", "false", "false", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, false, false, 600, true, absPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "true", "false", "false", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", true, false, false, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "restart upgrade bad", - envVals: cosmovisorEnv{absPath, "testname", "true", "true", "bad", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + envVals: cosmovisorEnv{absPath, "testname", "true", "true", "bad", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, expectedCfg: nil, expectedErrCount: 1, }, { name: "restart upgrade not set", - envVals: cosmovisorEnv{absPath, "testname", "true", "true", "", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, true, true, 600, true, absPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "true", "true", "", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", true, true, true, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "restart upgrade true", - envVals: cosmovisorEnv{absPath, "testname", "true", "true", "true", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, true, true, 600, true, absPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "true", "true", "true", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", true, true, true, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "restart upgrade true", - envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "skip unsafe backups bad", - envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "bad", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "bad", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, expectedCfg: nil, expectedErrCount: 1, }, { name: "skip unsafe backups not set", - envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, true, false, 600, false, absPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", true, true, false, 600, false, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "skip unsafe backups true", - envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "skip unsafe backups false", - envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "false", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, true, false, 600, false, absPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "false", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", true, true, false, 600, false, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "poll interval bad", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "bad", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "bad", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, expectedCfg: nil, expectedErrCount: 1, }, { name: "poll interval 0", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "0", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "0", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, expectedCfg: nil, expectedErrCount: 1, }, { name: "poll interval not set", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "1", "false", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 300, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "", "1", "false", "false", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 300, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "poll interval 600", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "600", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "600", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, expectedCfg: nil, expectedErrCount: 1, }, { name: "poll interval 1s", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "1s", "1", "false", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 1000, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "1s", "1", "false", "false", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 1000, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "poll interval -3m", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "-3m", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "-3m", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, expectedCfg: nil, expectedErrCount: 1, }, { name: "restart delay bad", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "bad", "false", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "bad", "false", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, expectedCfg: nil, expectedErrCount: 1, }, { name: "restart delay 0", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "0", "false", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "0", "false", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, expectedCfg: nil, expectedErrCount: 1, }, { name: "restart delay not set", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "", "false", "", "303ms", "1", "false", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 0, false, absPath, 303, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "", "false", "", "", "303ms", "1", "false", "false", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 0, false, absPath, "", 303, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "restart delay 600", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600", "false", "", "300ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600", "false", "", "", "300ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, expectedCfg: nil, expectedErrCount: 1, }, { name: "restart delay 1s", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "1s", "false", "", "303ms", "1", "false", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 1000, false, absPath, 303, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "1s", "false", "", "", "303ms", "1", "false", "false", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 1000, false, absPath, "", 303, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "restart delay -3m", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "-3m", "false", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "-3m", "false", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, expectedCfg: nil, expectedErrCount: 1, }, { name: "prepupgrade max retries bad", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "bad", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "bad", "false", "true", "kitchen", "preupgrade.sh", "", ""}, expectedCfg: nil, expectedErrCount: 1, }, { name: "prepupgrade max retries 0", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "0", "false", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, false, false, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "0", "false", "false", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, false, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "prepupgrade max retries not set", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "false", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, false, false, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "false", "false", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, false, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "prepupgrade max retries 5", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "5", "false", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 5, false, false, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "5", "false", "false", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 5, false, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "disable logs bad", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "5", "bad", "true", "kitchen", "preupgrade.sh", "", ""}, + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "5", "bad", "true", "kitchen", "preupgrade.sh", "", ""}, expectedCfg: nil, expectedErrCount: 1, }, { name: "disable logs good", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "true", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, true, false, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "true", "false", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, true, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "disable logs color bad", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "5", "true", "bad", "kitchen", "preupgrade.sh", "", ""}, + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "5", "true", "bad", "kitchen", "preupgrade.sh", "", ""}, expectedCfg: nil, expectedErrCount: 1, }, { name: "disable logs color good", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "true", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, true, false, time.Kitchen, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "true", "false", "kitchen", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, true, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "disable logs timestamp", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "true", "false", "", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, true, false, "", "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "true", "false", "", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, true, false, "", "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "enable rf3339 logs timestamp", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "true", "true", "rfc3339", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, true, true, time.RFC3339, "preupgrade.sh", false, 0), + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "true", "true", "rfc3339", "preupgrade.sh", "", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, true, true, time.RFC3339, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "invalid logs timestamp format", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "true", "true", "invalid", "preupgrade.sh", "", ""}, + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "true", "true", "invalid", "preupgrade.sh", "", ""}, expectedCfg: nil, expectedErrCount: 1, }, { name: "disable recase good", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "true", "true", "rfc3339", "preupgrade.sh", "true", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, true, true, time.RFC3339, "preupgrade.sh", true, 0), + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "true", "true", "rfc3339", "preupgrade.sh", "true", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, true, true, time.RFC3339, "preupgrade.sh", true, 0), expectedErrCount: 0, }, { name: "disable recase bad", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "true", "true", "rfc3339", "preupgrade.sh", "bad", ""}, + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "true", "true", "rfc3339", "preupgrade.sh", "bad", ""}, expectedErrCount: 1, }, { name: "shutdown grace good", - envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "true", "true", "rfc3339", "preupgrade.sh", "true", "15s"}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, true, true, time.RFC3339, "preupgrade.sh", true, 15000000000), + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "true", "true", "rfc3339", "preupgrade.sh", "true", "15s"}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, true, true, time.RFC3339, "preupgrade.sh", true, 15000000000), + expectedErrCount: 0, + }, + + { + name: "data dir bad (relative path)", + envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "", "", relPath, "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, + expectedErrCount: 1, + }, + + { + name: "data dir good (abs path)", + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", absPath, "406ms", "", "true", "true", "rfc3339", "preupgrade.sh", "true", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, absPath, 406, 0, true, true, time.RFC3339, "preupgrade.sh", true, 0), expectedErrCount: 0, }, } @@ -794,7 +835,7 @@ func (s *argsTestSuite) setUpDir() string { func (s *argsTestSuite) setupConfig(home string) string { s.T().Helper() - cfg := newConfig(home, "test", true, true, true, 406, false, home, 8, 0, false, true, "kitchen", "", true, 10000000000) + cfg := newConfig(home, "test", true, true, true, 406, false, home, home, 8, 0, false, true, "kitchen", "", true, 10000000000) path := filepath.Join(home, rootName, "config.toml") f, err := os.Create(path) s.Require().NoError(err) @@ -824,7 +865,7 @@ func (s *argsTestSuite) TestConfigFromFile() { { name: "valid config", expectedCfg: func() *Config { - return newConfig(home, "test", true, true, true, 406, false, home, 8, 0, false, true, time.Kitchen, "", true, 10000000000) + return newConfig(home, "test", true, true, true, 406, false, home, home, 8, 0, false, true, time.Kitchen, "", true, 10000000000) }, filePath: cfgFilePath, expectedError: "", @@ -839,18 +880,18 @@ func (s *argsTestSuite) TestConfigFromFile() { os.Setenv(EnvName, "env-name") }, expectedCfg: func() *Config { - return newConfig(home, "env-name", true, true, true, 406, false, home, 8, 0, false, true, time.Kitchen, "", true, 10000000000) + return newConfig(home, "env-name", true, true, true, 406, false, home, home, 8, 0, false, true, time.Kitchen, "", true, 10000000000) }, }, { name: "empty config file path will load config from ENV variables", expectedCfg: func() *Config { - return newConfig(home, "test", true, true, true, 406, false, home, 8, 0, false, true, time.Kitchen, "", true, 10000000000) + return newConfig(home, "test", true, true, true, 406, false, home, home, 8, 0, false, true, time.Kitchen, "", true, 10000000000) }, filePath: "", expectedError: "", malleate: func() { - s.setEnv(s.T(), &cosmovisorEnv{home, "test", "true", "true", "true", "406ms", "false", home, "8ms", "0", "false", "true", "kitchen", "", "true", "10s"}) + s.setEnv(s.T(), &cosmovisorEnv{home, "test", "true", "true", "true", "406ms", "false", home, home, "8ms", "0", "false", "true", "kitchen", "", "true", "10s"}) }, }, } From ee5ed4092bd6922512a357cf02fba5e7caeebbd1 Mon Sep 17 00:00:00 2001 From: 0x4r45h <0x4r45h@gmail.com> Date: Sat, 13 Jul 2024 01:52:10 +0330 Subject: [PATCH 03/12] change data path init flow --- tools/cosmovisor/args.go | 16 +++---- tools/cosmovisor/args_test.go | 62 ++++++++++++++----------- tools/cosmovisor/cmd/cosmovisor/init.go | 26 +++++++++++ tools/cosmovisor/process.go | 2 +- 4 files changed, 68 insertions(+), 38 deletions(-) diff --git a/tools/cosmovisor/args.go b/tools/cosmovisor/args.go index fbf96786eefd..fc01cccc88ab 100644 --- a/tools/cosmovisor/args.go +++ b/tools/cosmovisor/args.go @@ -109,17 +109,11 @@ func (cfg *Config) BaseUpgradeDir() string { // UpgradeInfoFilePath is the expected upgrade-info filename created by `x/upgrade/keeper`. func (cfg *Config) UpgradeInfoFilePath() string { - return filepath.Join(cfg.DataDirPath(), upgradetypes.UpgradeInfoFilename) + return filepath.Join(cfg.DataPath, upgradetypes.UpgradeInfoFilename) } -func (cfg *Config) DataDirPath() string { - if cfg.DataPath != "" { - // Return the Absolute path defined by user - return cfg.DataPath - } - // Otherwise, return the default path +func (cfg *Config) DefaultDataDirPath() string { return filepath.Join(cfg.Home, dataDir) - } // SymLinkToGenesis creates a symbolic link from "./current" to the genesis directory. @@ -231,6 +225,10 @@ func GetConfigFromEnv(skipValidate bool) (*Config, error) { cfg.DataBackupPath = cfg.Home } + if cfg.DataPath == "" { + cfg.DataPath = cfg.DefaultDataDirPath() + } + var err error if cfg.AllowDownloadBinaries, err = BooleanOption(EnvDownloadBin, false); err != nil { errs = append(errs, err) @@ -585,7 +583,7 @@ func (cfg Config) DetailString() string { {"Genesis Bin", cfg.GenesisBin()}, {"Monitored File", cfg.UpgradeInfoFilePath()}, {"Data Backup Dir", cfg.DataBackupPath}, - {"Data Dir", cfg.DataDirPath()}, + {"Data Dir", cfg.DataPath}, } var sb strings.Builder diff --git a/tools/cosmovisor/args_test.go b/tools/cosmovisor/args_test.go index b2ace17ab2a0..503b67705311 100644 --- a/tools/cosmovisor/args_test.go +++ b/tools/cosmovisor/args_test.go @@ -424,7 +424,7 @@ func (s *argsTestSuite) TestDetailString() { pollInterval := 406 * time.Millisecond unsafeSkipBackup := false dataBackupPath := "/home" - dataPath := "" + dataPath := "/home/data" preupgradeMaxRetries := 8 cfg := &Config{ Home: home, @@ -460,7 +460,7 @@ func (s *argsTestSuite) TestDetailString() { fmt.Sprintf("Genesis Bin: %s", home), fmt.Sprintf("Monitored File: %s", home), fmt.Sprintf("Data Backup Dir: %s", home), - fmt.Sprintf("Data Dir: %s/data", home), + fmt.Sprintf("Data Dir: %s", dataPath), } actual := cfg.DetailString() @@ -514,6 +514,7 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { relPath := filepath.Join("testdata", "validate") absPath, perr := filepath.Abs(relPath) s.Require().NoError(perr) + dataDirPath := filepath.Join(absPath, "/data") tests := []struct { name string @@ -546,14 +547,14 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { { name: "all good", envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "true", "10s"}, - expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", true, 10000000000), + expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, dataDirPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", true, 10000000000), expectedErrCount: 0, }, { name: "nothing set", envVals: cosmovisorEnv{"", "", "", "", "", "", "", "", "", "", "", "false", "false", "", "", "", ""}, expectedCfg: nil, - expectedErrCount: 3, + expectedErrCount: 4, }, // Note: Home and Name tests are done in TestValidate // timeformat tests are done in the TestTimeFormat @@ -566,25 +567,25 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { { name: "download bin not set", envVals: cosmovisorEnv{absPath, "testname", "", "true", "false", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "", false, 0), + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, true, absPath, dataDirPath, 303, 1, false, true, time.Kitchen, "", false, 0), expectedErrCount: 0, }, { name: "download bin true", envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, dataDirPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "download bin false", envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, true, absPath, dataDirPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "download ensure checksum true", envVals: cosmovisorEnv{absPath, "testname", "true", "false", "false", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, false, false, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", true, false, false, 600, true, absPath, dataDirPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { @@ -596,19 +597,19 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { { name: "restart upgrade not set", envVals: cosmovisorEnv{absPath, "testname", "true", "true", "", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, true, true, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", true, true, true, 600, true, absPath, dataDirPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "restart upgrade true", envVals: cosmovisorEnv{absPath, "testname", "true", "true", "true", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, true, true, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", true, true, true, 600, true, absPath, dataDirPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "restart upgrade true", envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, dataDirPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { @@ -620,19 +621,19 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { { name: "skip unsafe backups not set", envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, true, false, 600, false, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", true, true, false, 600, false, absPath, dataDirPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "skip unsafe backups true", envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, dataDirPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "skip unsafe backups false", envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "false", "", "", "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", true, true, false, 600, false, absPath, "", 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", true, true, false, 600, false, absPath, dataDirPath, 303, 1, false, true, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { @@ -650,7 +651,7 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { { name: "poll interval not set", envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "", "1", "false", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 300, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, dataDirPath, 300, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { @@ -662,7 +663,7 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { { name: "poll interval 1s", envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "1s", "1", "false", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 1000, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, dataDirPath, 1000, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { @@ -686,7 +687,7 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { { name: "restart delay not set", envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "", "false", "", "", "303ms", "1", "false", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 0, false, absPath, "", 303, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", false, true, false, 0, false, absPath, dataDirPath, 303, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { @@ -698,7 +699,7 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { { name: "restart delay 1s", envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "1s", "false", "", "", "303ms", "1", "false", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 1000, false, absPath, "", 303, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", false, true, false, 1000, false, absPath, dataDirPath, 303, 1, false, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { @@ -716,19 +717,19 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { { name: "prepupgrade max retries 0", envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "0", "false", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, false, false, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, dataDirPath, 406, 0, false, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "prepupgrade max retries not set", envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "false", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, false, false, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, dataDirPath, 406, 0, false, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "prepupgrade max retries 5", envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "5", "false", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 5, false, false, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, dataDirPath, 406, 5, false, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { @@ -740,7 +741,7 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { { name: "disable logs good", envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "true", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, true, false, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, dataDirPath, 406, 0, true, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { @@ -752,19 +753,19 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { { name: "disable logs color good", envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "true", "false", "kitchen", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, true, false, time.Kitchen, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, dataDirPath, 406, 0, true, false, time.Kitchen, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "disable logs timestamp", envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "true", "false", "", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, true, false, "", "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, dataDirPath, 406, 0, true, false, "", "preupgrade.sh", false, 0), expectedErrCount: 0, }, { name: "enable rf3339 logs timestamp", envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "true", "true", "rfc3339", "preupgrade.sh", "", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, true, true, time.RFC3339, "preupgrade.sh", false, 0), + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, dataDirPath, 406, 0, true, true, time.RFC3339, "preupgrade.sh", false, 0), expectedErrCount: 0, }, { @@ -776,7 +777,7 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { { name: "disable recase good", envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "true", "true", "rfc3339", "preupgrade.sh", "true", ""}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, true, true, time.RFC3339, "preupgrade.sh", true, 0), + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, dataDirPath, 406, 0, true, true, time.RFC3339, "preupgrade.sh", true, 0), expectedErrCount: 0, }, { @@ -787,7 +788,7 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { { name: "shutdown grace good", envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "true", "true", "rfc3339", "preupgrade.sh", "true", "15s"}, - expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, "", 406, 0, true, true, time.RFC3339, "preupgrade.sh", true, 15000000000), + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, dataDirPath, 406, 0, true, true, time.RFC3339, "preupgrade.sh", true, 15000000000), expectedErrCount: 0, }, @@ -796,13 +797,18 @@ func (s *argsTestSuite) TestGetConfigFromEnv() { envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "", "", relPath, "303ms", "1", "false", "true", "kitchen", "preupgrade.sh", "", ""}, expectedErrCount: 1, }, - { name: "data dir good (abs path)", envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", absPath, "406ms", "", "true", "true", "rfc3339", "preupgrade.sh", "true", ""}, expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, absPath, 406, 0, true, true, time.RFC3339, "preupgrade.sh", true, 0), expectedErrCount: 0, }, + { + name: "data dir good (empty path)", + envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "406ms", "", "true", "true", "rfc3339", "preupgrade.sh", "true", ""}, + expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, dataDirPath, 406, 0, true, true, time.RFC3339, "preupgrade.sh", true, 0), + expectedErrCount: 0, + }, } for _, tc := range tests { diff --git a/tools/cosmovisor/cmd/cosmovisor/init.go b/tools/cosmovisor/cmd/cosmovisor/init.go index 5f78e2845c02..ef73426cb0c8 100644 --- a/tools/cosmovisor/cmd/cosmovisor/init.go +++ b/tools/cosmovisor/cmd/cosmovisor/init.go @@ -111,6 +111,32 @@ func InitializeCosmovisor(logger log.Logger, args []string) error { func minConfigValidate(cfg *cosmovisor.Config) error { var errs []error + + // Note: Not using GetConfigFromEnv here because that checks that the directories already exist. + // We also don't care about the rest of the configuration stuff in here. + cfg := &cosmovisor.Config{ + Home: os.Getenv(cosmovisor.EnvHome), + Name: os.Getenv(cosmovisor.EnvName), + } + + var err error + if cfg.ColorLogs, err = cosmovisor.BooleanOption(cosmovisor.EnvColorLogs, true); err != nil { + errs = append(errs, err) + } + + if cfg.TimeFormatLogs, err = cosmovisor.TimeFormatOptionFromEnv(cosmovisor.EnvTimeFormatLogs, time.Kitchen); err != nil { + errs = append(errs, err) + } + + // if backup is not set, use the home directory + if cfg.DataBackupPath == "" { + cfg.DataBackupPath = cfg.Home + } + + if cfg.DataPath == "" { + cfg.DataPath = cfg.DefaultDataDirPath() + } + if len(cfg.Name) == 0 { errs = append(errs, fmt.Errorf("%s is not set", cosmovisor.EnvName)) } diff --git a/tools/cosmovisor/process.go b/tools/cosmovisor/process.go index f75c4405b30b..01a65ee87d5c 100644 --- a/tools/cosmovisor/process.go +++ b/tools/cosmovisor/process.go @@ -188,7 +188,7 @@ func (l Launcher) doBackup() error { l.logger.Info("starting to take backup of data directory", "backup start time", st) // copy the data dir to a backup dir - if err = copy.Copy(filepath.Join(l.cfg.DataDirPath()), dst); err != nil { + if err = copy.Copy(filepath.Join(l.cfg.DataPath), dst); err != nil { return fmt.Errorf("error while taking data backup: %w", err) } From ee61c34d3ac60b4db549a162f5664a3bb70ef284 Mon Sep 17 00:00:00 2001 From: 0x4r45h <0x4r45h@gmail.com> Date: Sat, 13 Jul 2024 13:28:54 +0330 Subject: [PATCH 04/12] add test for upgrade using custom data path fix failing test in process_test.go --- tools/cosmovisor/process_test.go | 65 +++++++++++++++++-- .../cosmovisor/genesis/bin/dummyd | 9 +++ .../cosmovisor/upgrades/chain2/bin/dummyd | 6 ++ .../custom-location/data/.gitkeep | 0 4 files changed, 75 insertions(+), 5 deletions(-) create mode 100755 tools/cosmovisor/testdata/custom-data-path/cosmovisor/genesis/bin/dummyd create mode 100755 tools/cosmovisor/testdata/custom-data-path/cosmovisor/upgrades/chain2/bin/dummyd create mode 100644 tools/cosmovisor/testdata/custom-data-path/custom-location/data/.gitkeep diff --git a/tools/cosmovisor/process_test.go b/tools/cosmovisor/process_test.go index 988bcf0a8074..f22136b634ea 100644 --- a/tools/cosmovisor/process_test.go +++ b/tools/cosmovisor/process_test.go @@ -25,7 +25,8 @@ import ( func TestLaunchProcess(t *testing.T) { // binaries from testdata/validate directory home := copyTestData(t, "validate") - cfg := &cosmovisor.Config{Home: home, Name: "dummyd", PollInterval: 15, UnsafeSkipBackup: true} + dataPath := filepath.Join(home, "data") + cfg := &cosmovisor.Config{Home: home, Name: "dummyd", DataPath: dataPath, PollInterval: 15, UnsafeSkipBackup: true} logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor") // should run the genesis binary and produce expected output @@ -70,7 +71,8 @@ func TestLaunchProcess(t *testing.T) { func TestPlanDisableRecase(t *testing.T) { // binaries from testdata/validate directory home := copyTestData(t, "norecase") - cfg := &cosmovisor.Config{Home: home, Name: "dummyd", PollInterval: 20, UnsafeSkipBackup: true, DisableRecase: true} + dataPath := filepath.Join(home, "data") + cfg := &cosmovisor.Config{Home: home, Name: "dummyd", DataPath: dataPath, PollInterval: 20, UnsafeSkipBackup: true, DisableRecase: true} logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor") // should run the genesis binary and produce expected output @@ -114,7 +116,8 @@ func TestPlanDisableRecase(t *testing.T) { func TestLaunchProcessWithRestartDelay(t *testing.T) { // binaries from testdata/validate directory home := copyTestData(t, "validate") - cfg := &cosmovisor.Config{Home: home, Name: "dummyd", RestartDelay: 5 * time.Second, PollInterval: 20, UnsafeSkipBackup: true} + dataPath := filepath.Join(home, "data") + cfg := &cosmovisor.Config{Home: home, Name: "dummyd", DataPath: dataPath, RestartDelay: 5 * time.Second, PollInterval: 20, UnsafeSkipBackup: true} logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor") // should run the genesis binary and produce expected output @@ -145,7 +148,8 @@ func TestLaunchProcessWithRestartDelay(t *testing.T) { func TestPlanShutdownGrace(t *testing.T) { // binaries from testdata/validate directory home := copyTestData(t, "dontdie") - cfg := &cosmovisor.Config{Home: home, Name: "dummyd", PollInterval: 15, UnsafeSkipBackup: true, ShutdownGrace: 2 * time.Second} + dataPath := filepath.Join(home, "data") + cfg := &cosmovisor.Config{Home: home, Name: "dummyd", DataPath: dataPath, PollInterval: 15, UnsafeSkipBackup: true, ShutdownGrace: 2 * time.Second} logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor") // should run the genesis binary and produce expected output @@ -194,7 +198,8 @@ func TestLaunchProcessWithDownloads(t *testing.T) { // chain2-zip_bin -> ref_to_chain3-zip_dir.json = (json for the next download instructions) -> chain3-zip_dir // chain3-zip_dir - doesn't upgrade home := copyTestData(t, "download") - cfg := &cosmovisor.Config{Home: home, Name: "autod", AllowDownloadBinaries: true, PollInterval: 100, UnsafeSkipBackup: true} + dataPath := filepath.Join(home, "data") + cfg := &cosmovisor.Config{Home: home, Name: "autod", DataPath: dataPath, AllowDownloadBinaries: true, PollInterval: 100, UnsafeSkipBackup: true} logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmovisor") upgradeFilename := cfg.UpgradeInfoFilePath() @@ -257,9 +262,11 @@ func TestLaunchProcessWithDownloadsAndMissingPreupgrade(t *testing.T) { // chain2-zip_bin -> ref_to_chain3-zip_dir.json = (json for the next download instructions) -> chain3-zip_dir // chain3-zip_dir - doesn't upgrade home := copyTestData(t, "download") + dataPath := filepath.Join(home, "data") cfg := &cosmovisor.Config{ Home: home, Name: "autod", + DataPath: dataPath, AllowDownloadBinaries: true, PollInterval: 100, UnsafeSkipBackup: true, @@ -293,9 +300,11 @@ func TestLaunchProcessWithDownloadsAndPreupgrade(t *testing.T) { // chain2-zip_bin -> ref_to_chain3-zip_dir.json = (json for the next download instructions) -> chain3-zip_dir // chain3-zip_dir - doesn't upgrade home := copyTestData(t, "download") + dataPath := filepath.Join(home, "data") cfg := &cosmovisor.Config{ Home: home, Name: "autod", + DataPath: dataPath, AllowDownloadBinaries: true, PollInterval: 100, UnsafeSkipBackup: true, @@ -362,6 +371,52 @@ func TestLaunchProcessWithDownloadsAndPreupgrade(t *testing.T) { require.Equal(t, cfg.UpgradeBin("chain3"), currentBin) } +// TestPlanCustomDataLocation will detect upgrade when chain data dir is not located in the default path +// the custom path should be provided as an absolute path to the configs +func () TestPlanCustomDataLocation(t *testing.T) { + // binaries from testdata/validate directory + home := copyTestData(t, "custom-data-path") + dataPath := filepath.Join(home, "custom-location/data") + cfg := &cosmovisor.Config{Home: home, Name: "dummyd", DataPath: dataPath, PollInterval: 20, UnsafeSkipBackup: true} + logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor") + + // should run the genesis binary and produce expected output + stdout, stderr := newBuffer(), newBuffer() + currentBin, err := cfg.CurrentBin() + require.NoError(t, err) + require.Equal(t, cfg.GenesisBin(), currentBin) + + launcher, err := cosmovisor.NewLauncher(logger, cfg) + require.NoError(t, err) + + upgradeFile := cfg.UpgradeInfoFilePath() + + args := []string{"foo", "bar", "1234", upgradeFile} + doUpgrade, err := launcher.Run(args, stdout, stderr) + require.NoError(t, err) + require.True(t, doUpgrade) + require.Equal(t, "", stderr.String()) + require.Equal(t, fmt.Sprintf("Genesis foo bar 1234 %s\nUPGRADE \"chain2\" NEEDED at height: 49: {}\n", upgradeFile), stdout.String()) + + // ensure this is upgraded now and produces new output + currentBin, err = cfg.CurrentBin() + require.NoError(t, err) + + require.Equal(cfg.UpgradeBin("chain2"), currentBin) + args = []string{"second", "run", "--verbose"} + stdout.Reset() + stderr.Reset() + + doUpgrade, err = launcher.Run(args, stdout, stderr) + require.NoError(t, err) + require.False(t, doUpgrade) + require.Equal(t, "", stderr.String()) + require.Equal(t, "chain 2 is live!\nArgs: second run --verbose\nFinished successfully\n", stdout.String()) + + // ended without other upgrade + require.Equal(t, cfg.UpgradeBin("chain2"), currentBin) +} + // TestSkipUpgrade tests heights that are identified to be skipped and return if upgrade height matches the skip heights func TestSkipUpgrade(t *testing.T) { cases := []struct { diff --git a/tools/cosmovisor/testdata/custom-data-path/cosmovisor/genesis/bin/dummyd b/tools/cosmovisor/testdata/custom-data-path/cosmovisor/genesis/bin/dummyd new file mode 100755 index 000000000000..8d54d60d076e --- /dev/null +++ b/tools/cosmovisor/testdata/custom-data-path/cosmovisor/genesis/bin/dummyd @@ -0,0 +1,9 @@ +#!/bin/sh + +echo Genesis $@ +sleep 1 +test -z $4 && exit 1001 +echo 'UPGRADE "chain2" NEEDED at height: 49: {}' +echo '{"name":"chain2","height":49,"info":""}' > $4 +sleep 2 +echo Never should be printed!!! diff --git a/tools/cosmovisor/testdata/custom-data-path/cosmovisor/upgrades/chain2/bin/dummyd b/tools/cosmovisor/testdata/custom-data-path/cosmovisor/upgrades/chain2/bin/dummyd new file mode 100755 index 000000000000..e0c09e283e13 --- /dev/null +++ b/tools/cosmovisor/testdata/custom-data-path/cosmovisor/upgrades/chain2/bin/dummyd @@ -0,0 +1,6 @@ +#!/bin/sh + +echo chain 2 is live! +echo Args: $@ +sleep 1 +echo Finished successfully diff --git a/tools/cosmovisor/testdata/custom-data-path/custom-location/data/.gitkeep b/tools/cosmovisor/testdata/custom-data-path/custom-location/data/.gitkeep new file mode 100644 index 000000000000..e69de29bb2d1 From 568fd9651f379273ae80ba447142afca97ffe65a Mon Sep 17 00:00:00 2001 From: 0x4r45h <0x4r45h@gmail.com> Date: Sat, 13 Jul 2024 17:47:40 +0330 Subject: [PATCH 05/12] fix lint --- tools/cosmovisor/process.go | 2 +- tools/cosmovisor/process_test.go | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/cosmovisor/process.go b/tools/cosmovisor/process.go index 01a65ee87d5c..dba36d915a77 100644 --- a/tools/cosmovisor/process.go +++ b/tools/cosmovisor/process.go @@ -188,7 +188,7 @@ func (l Launcher) doBackup() error { l.logger.Info("starting to take backup of data directory", "backup start time", st) // copy the data dir to a backup dir - if err = copy.Copy(filepath.Join(l.cfg.DataPath), dst); err != nil { + if err = copy.Copy(l.cfg.DataPath, dst); err != nil { return fmt.Errorf("error while taking data backup: %w", err) } diff --git a/tools/cosmovisor/process_test.go b/tools/cosmovisor/process_test.go index f22136b634ea..7b193708365e 100644 --- a/tools/cosmovisor/process_test.go +++ b/tools/cosmovisor/process_test.go @@ -373,7 +373,7 @@ func TestLaunchProcessWithDownloadsAndPreupgrade(t *testing.T) { // TestPlanCustomDataLocation will detect upgrade when chain data dir is not located in the default path // the custom path should be provided as an absolute path to the configs -func () TestPlanCustomDataLocation(t *testing.T) { +func TestPlanCustomDataLocation(t *testing.T) { // binaries from testdata/validate directory home := copyTestData(t, "custom-data-path") dataPath := filepath.Join(home, "custom-location/data") @@ -381,6 +381,7 @@ func () TestPlanCustomDataLocation(t *testing.T) { logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor") // should run the genesis binary and produce expected output + stdin, _ := os.Open(os.DevNull) stdout, stderr := newBuffer(), newBuffer() currentBin, err := cfg.CurrentBin() require.NoError(t, err) @@ -392,7 +393,7 @@ func () TestPlanCustomDataLocation(t *testing.T) { upgradeFile := cfg.UpgradeInfoFilePath() args := []string{"foo", "bar", "1234", upgradeFile} - doUpgrade, err := launcher.Run(args, stdout, stderr) + doUpgrade, err := launcher.Run(args, stdin, stdout, stderr) require.NoError(t, err) require.True(t, doUpgrade) require.Equal(t, "", stderr.String()) @@ -402,12 +403,12 @@ func () TestPlanCustomDataLocation(t *testing.T) { currentBin, err = cfg.CurrentBin() require.NoError(t, err) - require.Equal(cfg.UpgradeBin("chain2"), currentBin) + require.Equal(t, cfg.UpgradeBin("chain2"), currentBin) args = []string{"second", "run", "--verbose"} stdout.Reset() stderr.Reset() - doUpgrade, err = launcher.Run(args, stdout, stderr) + doUpgrade, err = launcher.Run(args, stdin, stdout, stderr) require.NoError(t, err) require.False(t, doUpgrade) require.Equal(t, "", stderr.String()) From 78f8f6885158bf491a02aaea7ffec9a2a5333dbf Mon Sep 17 00:00:00 2001 From: 0x4r45h <0x4r45h@gmail.com> Date: Sun, 29 Sep 2024 21:19:15 +0330 Subject: [PATCH 06/12] rebase on main fix failing tests --- tools/cosmovisor/args.go | 4 ++-- tools/cosmovisor/args_test.go | 22 +++++++++--------- tools/cosmovisor/cmd/cosmovisor/init.go | 30 +------------------------ 3 files changed, 14 insertions(+), 42 deletions(-) diff --git a/tools/cosmovisor/args.go b/tools/cosmovisor/args.go index fc01cccc88ab..e0c36ee2d507 100644 --- a/tools/cosmovisor/args.go +++ b/tools/cosmovisor/args.go @@ -359,9 +359,9 @@ func (cfg *Config) validate() []error { // validate DataPath switch { case cfg.DataPath == "": - break + errs = append(errs, fmt.Errorf("%s is not set", EnvDataPath)) case !filepath.IsAbs(cfg.DataPath): - errs = append(errs, fmt.Errorf("%s must be an absolute path", cfg.DataPath)) + errs = append(errs, fmt.Errorf("%s must be an absolute path", EnvDataPath)) default: switch info, err := os.Stat(cfg.DataPath); { case err != nil: diff --git a/tools/cosmovisor/args_test.go b/tools/cosmovisor/args_test.go index 503b67705311..1e4ebf1e15ae 100644 --- a/tools/cosmovisor/args_test.go +++ b/tools/cosmovisor/args_test.go @@ -210,31 +210,27 @@ func (s *argsTestSuite) TestValidate() { valid bool }{ "happy": { - cfg: Config{Home: absPath, Name: "bind", DataBackupPath: absPath}, + cfg: Config{Home: absPath, Name: "bind", DataBackupPath: absPath, DataPath: absPath}, valid: true, }, "happy with download": { - cfg: Config{Home: absPath, Name: "bind", AllowDownloadBinaries: true, DataBackupPath: absPath}, + cfg: Config{Home: absPath, Name: "bind", AllowDownloadBinaries: true, DataBackupPath: absPath, DataPath: absPath}, valid: true, }, "happy with skip data backup": { - cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataBackupPath: absPath}, + cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataBackupPath: absPath, DataPath: absPath}, valid: true, }, "happy with skip data backup and empty data backup path": { - cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataBackupPath: ""}, + cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataBackupPath: "", DataPath: absPath}, valid: true, }, "happy with skip data backup and no such data backup path dir": { - cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataBackupPath: filepath.FromSlash("/no/such/dir")}, + cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataBackupPath: filepath.FromSlash("/no/such/dir"), DataPath: absPath}, valid: true, }, "happy with skip data backup and relative data backup path": { - cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataBackupPath: relPath}, - valid: true, - }, - "happy with empty data path": { - cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataPath: ""}, + cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataBackupPath: relPath, DataPath: absPath}, valid: true, }, "happy with absolute data path": { @@ -273,6 +269,10 @@ func (s *argsTestSuite) TestValidate() { cfg: Config{Home: absPath, Name: "bind", DataBackupPath: relPath}, valid: false, }, + "missing data path": { + cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataPath: ""}, + valid: false, + }, "no such data path dir": { cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataPath: filepath.FromSlash("/no/such/dir")}, valid: false, @@ -299,7 +299,7 @@ func (s *argsTestSuite) TestEnsureBin() { absPath, err := filepath.Abs(relPath) s.Require().NoError(err) - cfg := Config{Home: absPath, Name: "dummyd", DataBackupPath: absPath} + cfg := Config{Home: absPath, Name: "dummyd", DataBackupPath: absPath, DataPath: absPath} s.Require().Len(cfg.validate(), 0, "validation errors") s.Require().NoError(plan.EnsureBinary(cfg.GenesisBin())) diff --git a/tools/cosmovisor/cmd/cosmovisor/init.go b/tools/cosmovisor/cmd/cosmovisor/init.go index ef73426cb0c8..b1bf9f073113 100644 --- a/tools/cosmovisor/cmd/cosmovisor/init.go +++ b/tools/cosmovisor/cmd/cosmovisor/init.go @@ -3,12 +3,11 @@ package main import ( "errors" "fmt" + "github.com/spf13/cobra" "io" "os" "path/filepath" - "github.com/spf13/cobra" - "cosmossdk.io/log" "cosmossdk.io/tools/cosmovisor" "cosmossdk.io/x/upgrade/plan" @@ -111,36 +110,9 @@ func InitializeCosmovisor(logger log.Logger, args []string) error { func minConfigValidate(cfg *cosmovisor.Config) error { var errs []error - - // Note: Not using GetConfigFromEnv here because that checks that the directories already exist. - // We also don't care about the rest of the configuration stuff in here. - cfg := &cosmovisor.Config{ - Home: os.Getenv(cosmovisor.EnvHome), - Name: os.Getenv(cosmovisor.EnvName), - } - - var err error - if cfg.ColorLogs, err = cosmovisor.BooleanOption(cosmovisor.EnvColorLogs, true); err != nil { - errs = append(errs, err) - } - - if cfg.TimeFormatLogs, err = cosmovisor.TimeFormatOptionFromEnv(cosmovisor.EnvTimeFormatLogs, time.Kitchen); err != nil { - errs = append(errs, err) - } - - // if backup is not set, use the home directory - if cfg.DataBackupPath == "" { - cfg.DataBackupPath = cfg.Home - } - - if cfg.DataPath == "" { - cfg.DataPath = cfg.DefaultDataDirPath() - } - if len(cfg.Name) == 0 { errs = append(errs, fmt.Errorf("%s is not set", cosmovisor.EnvName)) } - switch { case len(cfg.Home) == 0: errs = append(errs, fmt.Errorf("%s is not set", cosmovisor.EnvHome)) From e4461b48b105a77bb0978364db30ed0c645437b6 Mon Sep 17 00:00:00 2001 From: 0x4r45h <0x4r45h@gmail.com> Date: Sun, 29 Sep 2024 22:20:41 +0330 Subject: [PATCH 07/12] lint-fix --- tools/cosmovisor/cmd/cosmovisor/init.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/cosmovisor/cmd/cosmovisor/init.go b/tools/cosmovisor/cmd/cosmovisor/init.go index b1bf9f073113..77ed1466042d 100644 --- a/tools/cosmovisor/cmd/cosmovisor/init.go +++ b/tools/cosmovisor/cmd/cosmovisor/init.go @@ -3,11 +3,12 @@ package main import ( "errors" "fmt" - "github.com/spf13/cobra" "io" "os" "path/filepath" + "github.com/spf13/cobra" + "cosmossdk.io/log" "cosmossdk.io/tools/cosmovisor" "cosmossdk.io/x/upgrade/plan" From 59dcf0900ad80e5b851f09224b8d607f70c6c05c Mon Sep 17 00:00:00 2001 From: 0x4r45h <0x4r45h@gmail.com> Date: Sun, 29 Sep 2024 22:48:02 +0330 Subject: [PATCH 08/12] update CHANGELOG.md update README.md --- CHANGELOG.md | 1 + tools/cosmovisor/README.md | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba6219268f7c..1366fcb3d469 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i * (client/keys) [#21829](https://github.com/cosmos/cosmos-sdk/pull/21829) Add support for importing hex key using standard input. * (x/validate) [#21822](https://github.com/cosmos/cosmos-sdk/pull/21822) New module solely responsible for providing ante/post handlers and tx validators for v2. It can be extended by the app developer to provide extra tx validators. * In comparison to x/auth/tx/config, there is no app config to skip ante/post handlers, as overwriting them in baseapp or not injecting the x/validate module has the same effect. +* (cosmovisor) [#21971](https://github.com/cosmos/cosmos-sdk/pull/21971) Support Custom path to application data directory ### Improvements diff --git a/tools/cosmovisor/README.md b/tools/cosmovisor/README.md index db15ab0a5d64..7a1560b04397 100644 --- a/tools/cosmovisor/README.md +++ b/tools/cosmovisor/README.md @@ -92,6 +92,7 @@ All arguments passed to `cosmovisor run` will be passed to the application binar * `DAEMON_HOME` is the location where the `cosmovisor/` directory is kept that contains the genesis binary, the upgrade binaries, and any additional auxiliary files associated with each binary (e.g. `$HOME/.gaiad`, `$HOME/.regend`, `$HOME/.simd`, etc.). * `DAEMON_NAME` is the name of the binary itself (e.g. `gaiad`, `regend`, `simd`, etc.). +* `DAEMON_DATA_DIR` option to set an absolute path to the `data` directory. this path is used to detect upgrade info file and backups. If not set, `$DAEMON_HOME/data` is used. * `DAEMON_ALLOW_DOWNLOAD_BINARIES` (*optional*), if set to `true`, will enable auto-downloading of new binaries (for security reasons, this is intended for full nodes rather than validators). By default, `cosmovisor` will not auto-download new binaries. * `DAEMON_DOWNLOAD_MUST_HAVE_CHECKSUM` (*optional*, default = `false`), if `true` cosmovisor will require that a checksum is provided in the upgrade plan for the binary to be downloaded. If `false`, cosmovisor will not require a checksum to be provided, but still check the checksum if one is provided. * `DAEMON_RESTART_AFTER_UPGRADE` (*optional*, default = `true`), if `true`, restarts the subprocess with the same command-line arguments and flags (but with the new binary) after a successful upgrade. Otherwise (`false`), `cosmovisor` stops running after an upgrade and requires the system administrator to manually restart it. Note restart is only after the upgrade and does not auto-restart the subprocess after an error occurs. @@ -127,7 +128,7 @@ All arguments passed to `cosmovisor run` will be passed to the application binar The `cosmovisor/` directory includes a subdirectory for each version of the application (i.e. `genesis` or `upgrades/`). Within each subdirectory is the application binary (i.e. `bin/$DAEMON_NAME`) and any additional auxiliary files associated with each binary. `current` is a symbolic link to the currently active directory (i.e. `genesis` or `upgrades/`). The `name` variable in `upgrades/` is the lowercased URI-encoded name of the upgrade as specified in the upgrade module plan. Note that the upgrade name path are normalized to be lowercased: for instance, `MyUpgrade` is normalized to `myupgrade`, and its path is `upgrades/myupgrade`. -Please note that `$DAEMON_HOME/cosmovisor` only stores the *application binaries*. The `cosmovisor` binary itself can be stored in any typical location (e.g. `/usr/local/bin`). The application will continue to store its data in the default data directory (e.g. `$HOME/.simapp`) or the data directory specified with the `--home` flag. `$DAEMON_HOME` is dependent of the data directory and must be set to the same directory as the data directory, you will end up with a configuration like the following: +Please note that `$DAEMON_HOME/cosmovisor` only stores the *application binaries*. The `cosmovisor` binary itself can be stored in any typical location (e.g. `/usr/local/bin`). The application will continue to store its data in the default data directory (e.g. `$HOME/.simapp`) or the data directory specified with the `--home` flag. `$DAEMON_HOME` is independent of the data directory and can be set to any location and the actual data directory path can be set through `DAEMON_DATA_DIR` config. If you set `$DAEMON_HOME` to the same directory as the data directory, you will end up with a configuration like the following: ```text .simapp From de6f983b6b42e478efd33eb6012b4ca2a28fbe8f Mon Sep 17 00:00:00 2001 From: 0x4r45h <0x4r45h@gmail.com> Date: Wed, 2 Oct 2024 20:48:23 +0330 Subject: [PATCH 09/12] correct CHANGELOG.md --- CHANGELOG.md | 1 - tools/cosmovisor/CHANGELOG.md | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1366fcb3d469..ba6219268f7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,7 +48,6 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i * (client/keys) [#21829](https://github.com/cosmos/cosmos-sdk/pull/21829) Add support for importing hex key using standard input. * (x/validate) [#21822](https://github.com/cosmos/cosmos-sdk/pull/21822) New module solely responsible for providing ante/post handlers and tx validators for v2. It can be extended by the app developer to provide extra tx validators. * In comparison to x/auth/tx/config, there is no app config to skip ante/post handlers, as overwriting them in baseapp or not injecting the x/validate module has the same effect. -* (cosmovisor) [#21971](https://github.com/cosmos/cosmos-sdk/pull/21971) Support Custom path to application data directory ### Improvements diff --git a/tools/cosmovisor/CHANGELOG.md b/tools/cosmovisor/CHANGELOG.md index ae0de6b86ffe..6b56f8928a04 100644 --- a/tools/cosmovisor/CHANGELOG.md +++ b/tools/cosmovisor/CHANGELOG.md @@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements * [#21462](https://github.com/cosmos/cosmos-sdk/pull/21462) Pass `stdin` to binary. +* [#21971](https://github.com/cosmos/cosmos-sdk/pull/21971) Support Custom path to application data directory ### Features From 1f88eca525843cdcf707ca0b4bf0e309606fb117 Mon Sep 17 00:00:00 2001 From: 0x4r45h <0x4r45h@gmail.com> Date: Wed, 2 Oct 2024 21:09:17 +0330 Subject: [PATCH 10/12] add example to README.md --- tools/cosmovisor/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/cosmovisor/README.md b/tools/cosmovisor/README.md index 7a1560b04397..0bfbf82e01e7 100644 --- a/tools/cosmovisor/README.md +++ b/tools/cosmovisor/README.md @@ -136,6 +136,16 @@ Please note that `$DAEMON_HOME/cosmovisor` only stores the *application binaries ├── data └── cosmovisor ``` +Otherwise, if you decide to set `$DAEMON_HOME` to an arbitrary location, such as `$HOME/.simapp_manager`, and use the `--home` flag of the application as `$HOME/.simapp`, you must explicitly set the `DAEMON_DATA_DIR` to the application's data directory path, `$HOME/.simapp/data`. Your directory structure will look like this: + +```text +$HOME + ├── .simapp + │ ├── config + │ └── data + └── .simapp_manager + └── cosmovisor +``` ## Usage From be336e92a217c4c42f9c0e14ac85bdcc6319799e Mon Sep 17 00:00:00 2001 From: 0x4r45h <0x4r45h@gmail.com> Date: Mon, 11 Nov 2024 03:50:26 +0330 Subject: [PATCH 11/12] fix failing tests --- tools/cosmovisor/process_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/cosmovisor/process_test.go b/tools/cosmovisor/process_test.go index 1711ca11bed4..af3d83a56c04 100644 --- a/tools/cosmovisor/process_test.go +++ b/tools/cosmovisor/process_test.go @@ -474,13 +474,13 @@ func TestPlanCustomDataLocation(t *testing.T) { t, fmt.Sprintf("%s/%s", workDir, "testdata/custom-data-path"), cosmovisor.Config{ - Name: "autod", + Name: "dummyd", AllowDownloadBinaries: true, PollInterval: 100, UnsafeSkipBackup: true, }, ) - + cfg.DataPath = filepath.Join(cfg.Home, "custom-location/data") logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor") // should run the genesis binary and produce expected output From 8f07c8feb0a43b8d38878ad23b0764b812a27655 Mon Sep 17 00:00:00 2001 From: 0x4r45h <0x4r45h@gmail.com> Date: Wed, 20 Nov 2024 13:51:20 +0330 Subject: [PATCH 12/12] revert unwanted formatting changes in dec_test.go --- math/dec_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/math/dec_test.go b/math/dec_test.go index a51f3339b445..316b6aaa63dc 100644 --- a/math/dec_test.go +++ b/math/dec_test.go @@ -629,10 +629,10 @@ func BenchmarkMarshalTo(b *testing.B) { }{ { math.LegacyNewDec(1e8), []byte{ - 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - }, + 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + }, }, {math.LegacyNewDec(0), []byte{0x30}}, } @@ -1067,4 +1067,4 @@ func Test_DocumentLegacyAsymmetry(t *testing.T) { // !!! this is the key point, they are not equal, it looks like a bug require.NotEqual(t, emptyDecJSON, emptyDecRoundTripJSON) require.NotEqual(t, emptyDec, emptyDecRoundTrip) -} \ No newline at end of file +}