feat(cosmovisor): enable logger configuration with env variable (#16573)
Signed-off-by: Artur Troian <troian.ap@gmail.com>
This commit is contained in:
parent
7b26ff5bec
commit
a318ca9f86
@ -38,8 +38,9 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
## Features
|
||||
|
||||
* [#12457](https://github.com/cosmos/cosmos-sdk/issues/12457) Add `cosmovisor pre-upgrade` command to manually add an upgrade to cosmovisor.
|
||||
* [#16573](https://github.com/cosmos/cosmos-sdk/pull/16573) Extend `cosmovisor` configuration with new log format options
|
||||
* [#15361](https://github.com/cosmos/cosmos-sdk/pull/15361) Add `cosmovisor config` command to display the configuration used by cosmovisor.
|
||||
* [#12457](https://github.com/cosmos/cosmos-sdk/issues/12457) Add `cosmovisor pre-upgrade` command to manually add an upgrade to cosmovisor.
|
||||
|
||||
## Improvements
|
||||
|
||||
|
||||
@ -95,6 +95,8 @@ Use of `cosmovisor` without one of the action arguments is deprecated. For backw
|
||||
* `UNSAFE_SKIP_BACKUP` (defaults to `false`), if set to `true`, upgrades directly without performing a backup. Otherwise (`false`, default) backs up the data before trying the upgrade. The default value of false is useful and recommended in case of failures and when a backup needed to rollback. We recommend using the default backup option `UNSAFE_SKIP_BACKUP=false`.
|
||||
* `DAEMON_PREUPGRADE_MAX_RETRIES` (defaults to `0`). The maximum number of times to call [`pre-upgrade`](https://docs.cosmos.network/main/building-apps/app-upgrade#pre-upgrade-handling) in the application after exit status of `31`. After the maximum number of retries, Cosmovisor fails the upgrade.
|
||||
* `COSMOVISOR_DISABLE_LOGS` (defaults to `false`). If set to true, this will disable Cosmovisor logs (but not the underlying process) completely. This may be useful, for example, when a Cosmovisor subcommand you are executing returns a valid JSON you are then parsing, as logs added by Cosmovisor make this output not a valid JSON.
|
||||
* `COSMOVISOR_COLOR_LOGS` (defaults to `true`). If set to true, this will colorise Cosmovisor logs (but not the underlying process).
|
||||
* `COSMOVISOR_TIMEFORMAT_LOGS` (defaults to `kitchen`). If set to a value (`layout|ansic|unixdate|rubydate|rfc822|rfc822z|rfc850|rfc1123|rfc1123z|rfc3339|rfc3339nano|kitchen`), this will add timestamp prefix to Cosmovisor logs (but not the underlying process).
|
||||
|
||||
### Folder Layout
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -11,8 +12,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/x/upgrade/plan"
|
||||
upgradetypes "cosmossdk.io/x/upgrade/types"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// environment variable names
|
||||
@ -28,6 +31,8 @@ const (
|
||||
EnvInterval = "DAEMON_POLL_INTERVAL"
|
||||
EnvPreupgradeMaxRetries = "DAEMON_PREUPGRADE_MAX_RETRIES"
|
||||
EnvDisableLogs = "COSMOVISOR_DISABLE_LOGS"
|
||||
EnvColorLogs = "COSMOVISOR_COLOR_LOGS"
|
||||
EnvTimeFormatLogs = "COSMOVISOR_TIMEFORMAT_LOGS"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -53,7 +58,8 @@ type Config struct {
|
||||
DataBackupPath string
|
||||
PreupgradeMaxRetries int
|
||||
DisableLogs bool
|
||||
|
||||
ColorLogs bool
|
||||
TimeFormatLogs string
|
||||
// currently running upgrade
|
||||
currentUpgrade upgradetypes.Plan
|
||||
}
|
||||
@ -151,19 +157,25 @@ func GetConfigFromEnv() (*Config, error) {
|
||||
}
|
||||
|
||||
var err error
|
||||
if cfg.AllowDownloadBinaries, err = booleanOption(EnvDownloadBin, false); err != nil {
|
||||
if cfg.AllowDownloadBinaries, err = BooleanOption(EnvDownloadBin, false); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if cfg.DownloadMustHaveChecksum, err = booleanOption(EnvDownloadMustHaveChecksum, false); err != nil {
|
||||
if cfg.DownloadMustHaveChecksum, err = BooleanOption(EnvDownloadMustHaveChecksum, false); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if cfg.RestartAfterUpgrade, err = booleanOption(EnvRestartUpgrade, true); err != nil {
|
||||
if cfg.RestartAfterUpgrade, err = BooleanOption(EnvRestartUpgrade, true); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if cfg.UnsafeSkipBackup, err = booleanOption(EnvSkipBackup, false); err != nil {
|
||||
if cfg.UnsafeSkipBackup, err = BooleanOption(EnvSkipBackup, false); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if cfg.DisableLogs, err = booleanOption(EnvDisableLogs, false); err != nil {
|
||||
if cfg.DisableLogs, err = BooleanOption(EnvDisableLogs, false); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if cfg.ColorLogs, err = BooleanOption(EnvColorLogs, true); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if cfg.TimeFormatLogs, err = TimeFormatOptionFromEnv(EnvTimeFormatLogs, time.Kitchen); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
@ -203,6 +215,20 @@ func GetConfigFromEnv() (*Config, error) {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (cfg *Config) Logger(dst io.Writer) log.Logger {
|
||||
var logger log.Logger
|
||||
|
||||
if cfg.DisableLogs {
|
||||
logger = log.NewCustomLogger(zerolog.Nop())
|
||||
} else {
|
||||
logger = log.NewLogger(dst,
|
||||
log.ColorOption(cfg.ColorLogs),
|
||||
log.TimeFormatOption(cfg.TimeFormatLogs)).With(log.ModuleKey, "cosmovisor")
|
||||
}
|
||||
|
||||
return logger
|
||||
}
|
||||
|
||||
func parseEnvDuration(input string) (time.Duration, error) {
|
||||
duration, err := time.ParseDuration(input)
|
||||
if err != nil {
|
||||
@ -338,7 +364,7 @@ returnError:
|
||||
}
|
||||
|
||||
// checks and validates env option
|
||||
func booleanOption(name string, defaultVal bool) (bool, error) {
|
||||
func BooleanOption(name string, defaultVal bool) (bool, error) {
|
||||
p := strings.ToLower(os.Getenv(name))
|
||||
switch p {
|
||||
case "":
|
||||
@ -351,6 +377,43 @@ func booleanOption(name string, defaultVal bool) (bool, error) {
|
||||
return false, fmt.Errorf("env variable %q must have a boolean value (\"true\" or \"false\"), got %q", name, p)
|
||||
}
|
||||
|
||||
// checks and validates env option
|
||||
func TimeFormatOptionFromEnv(env, defaultVal string) (string, error) {
|
||||
val, set := os.LookupEnv(env)
|
||||
if !set {
|
||||
return defaultVal, nil
|
||||
}
|
||||
switch val {
|
||||
case "layout":
|
||||
return time.Layout, nil
|
||||
case "ansic":
|
||||
return time.ANSIC, nil
|
||||
case "unixdate":
|
||||
return time.UnixDate, nil
|
||||
case "rubydate":
|
||||
return time.RubyDate, nil
|
||||
case "rfc822":
|
||||
return time.RFC822, nil
|
||||
case "rfc822z":
|
||||
return time.RFC822Z, nil
|
||||
case "rfc850":
|
||||
return time.RFC850, nil
|
||||
case "rfc1123":
|
||||
return time.RFC1123, nil
|
||||
case "rfc1123z":
|
||||
return time.RFC1123Z, nil
|
||||
case "rfc3339":
|
||||
return time.RFC3339, nil
|
||||
case "rfc3339nano":
|
||||
return time.RFC3339Nano, nil
|
||||
case "kitchen":
|
||||
return time.Kitchen, nil
|
||||
case "":
|
||||
return "", nil
|
||||
}
|
||||
return "", fmt.Errorf("env variable %q must have a timeformat value (\"layout|ansic|unixdate|rubydate|rfc822|rfc822z|rfc850|rfc1123|rfc1123z|rfc3339|rfc3339nano|kitchen\"), got %q", EnvTimeFormatLogs, val)
|
||||
}
|
||||
|
||||
// DetailString returns a multi-line string with details about this config.
|
||||
func (cfg Config) DetailString() string {
|
||||
configEntries := []struct{ name, value string }{
|
||||
@ -365,6 +428,8 @@ func (cfg Config) DetailString() string {
|
||||
{EnvDataBackupPath, cfg.DataBackupPath},
|
||||
{EnvPreupgradeMaxRetries, fmt.Sprintf("%d", cfg.PreupgradeMaxRetries)},
|
||||
{EnvDisableLogs, fmt.Sprintf("%t", cfg.DisableLogs)},
|
||||
{EnvColorLogs, fmt.Sprintf("%t", cfg.ColorLogs)},
|
||||
{EnvTimeFormatLogs, cfg.TimeFormatLogs},
|
||||
}
|
||||
|
||||
derivedEntries := []struct{ name, value string }{
|
||||
|
||||
@ -35,22 +35,31 @@ type cosmovisorEnv struct {
|
||||
Interval string
|
||||
PreupgradeMaxRetries string
|
||||
DisableLogs string
|
||||
ColorLogs string
|
||||
TimeFormatLogs string
|
||||
}
|
||||
|
||||
type envMap struct {
|
||||
val string
|
||||
allowEmpty bool
|
||||
}
|
||||
|
||||
// ToMap creates a map of the cosmovisorEnv where the keys are the env var names.
|
||||
func (c cosmovisorEnv) ToMap() map[string]string {
|
||||
return map[string]string{
|
||||
EnvHome: c.Home,
|
||||
EnvName: c.Name,
|
||||
EnvDownloadBin: c.DownloadBin,
|
||||
EnvDownloadMustHaveChecksum: c.DownloadMustHaveChecksum,
|
||||
EnvRestartUpgrade: c.RestartUpgrade,
|
||||
EnvRestartDelay: c.RestartDelay,
|
||||
EnvSkipBackup: c.SkipBackup,
|
||||
EnvDataBackupPath: c.DataBackupPath,
|
||||
EnvInterval: c.Interval,
|
||||
EnvPreupgradeMaxRetries: c.PreupgradeMaxRetries,
|
||||
EnvDisableLogs: c.DisableLogs,
|
||||
func (c cosmovisorEnv) ToMap() map[string]envMap {
|
||||
return map[string]envMap{
|
||||
EnvHome: {val: c.Home, allowEmpty: false},
|
||||
EnvName: {val: c.Name, allowEmpty: false},
|
||||
EnvDownloadBin: {val: c.DownloadBin, allowEmpty: false},
|
||||
EnvDownloadMustHaveChecksum: {val: c.DownloadMustHaveChecksum, allowEmpty: false},
|
||||
EnvRestartUpgrade: {val: c.RestartUpgrade, allowEmpty: false},
|
||||
EnvRestartDelay: {val: c.RestartDelay, allowEmpty: false},
|
||||
EnvSkipBackup: {val: c.SkipBackup, allowEmpty: false},
|
||||
EnvDataBackupPath: {val: c.DataBackupPath, allowEmpty: false},
|
||||
EnvInterval: {val: c.Interval, allowEmpty: false},
|
||||
EnvPreupgradeMaxRetries: {val: c.PreupgradeMaxRetries, allowEmpty: false},
|
||||
EnvDisableLogs: {val: c.DisableLogs, allowEmpty: false},
|
||||
EnvColorLogs: {val: c.ColorLogs, allowEmpty: false},
|
||||
EnvTimeFormatLogs: {val: c.TimeFormatLogs, allowEmpty: true},
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,6 +88,10 @@ func (c *cosmovisorEnv) Set(envVar, envVal string) {
|
||||
c.PreupgradeMaxRetries = envVal
|
||||
case EnvDisableLogs:
|
||||
c.DisableLogs = envVal
|
||||
case EnvColorLogs:
|
||||
c.ColorLogs = envVal
|
||||
case EnvTimeFormatLogs:
|
||||
c.TimeFormatLogs = envVal
|
||||
default:
|
||||
panic(fmt.Errorf("Unknown environment variable [%s]. Ccannot set field to [%s]. ", envVar, envVal))
|
||||
}
|
||||
@ -109,9 +122,9 @@ func (s *argsTestSuite) setEnv(t *testing.T, env *cosmovisorEnv) {
|
||||
for envVar, envVal := range env.ToMap() {
|
||||
var err error
|
||||
var msg string
|
||||
if len(envVal) != 0 {
|
||||
err = os.Setenv(envVar, envVal)
|
||||
msg = fmt.Sprintf("setting %s to %s", envVar, envVal)
|
||||
if len(envVal.val) != 0 || envVal.allowEmpty {
|
||||
err = os.Setenv(envVar, envVal.val)
|
||||
msg = fmt.Sprintf("setting %s to %s", envVar, envVal.val)
|
||||
} else {
|
||||
err = os.Unsetenv(envVar)
|
||||
msg = fmt.Sprintf("unsetting %s", envVar)
|
||||
@ -283,7 +296,7 @@ func (s *argsTestSuite) TestBooleanOption() {
|
||||
name := "COSMOVISOR_TEST_VAL"
|
||||
|
||||
check := func(def, expected, isErr bool, msg string) {
|
||||
v, err := booleanOption(name, def)
|
||||
v, err := BooleanOption(name, def)
|
||||
if isErr {
|
||||
s.Require().Error(err)
|
||||
return
|
||||
@ -317,6 +330,57 @@ func (s *argsTestSuite) TestBooleanOption() {
|
||||
check(false, true, false, "should handle true value case not sensitive")
|
||||
}
|
||||
|
||||
func (s *argsTestSuite) TestTimeFormat() {
|
||||
initialEnv := s.clearEnv()
|
||||
defer s.setEnv(nil, initialEnv)
|
||||
|
||||
name := "COSMOVISOR_TEST_VAL"
|
||||
|
||||
check := func(def, expected string, isErr bool, msg string) {
|
||||
v, err := TimeFormatOptionFromEnv(name, def)
|
||||
if isErr {
|
||||
s.Require().Error(err)
|
||||
return
|
||||
}
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(expected, v, msg)
|
||||
}
|
||||
|
||||
os.Unsetenv(name)
|
||||
check(time.Kitchen, time.Kitchen, false, "should correctly set default value")
|
||||
|
||||
os.Setenv(name, "")
|
||||
check(time.Kitchen, "", false, "should correctly set to a none")
|
||||
|
||||
os.Setenv(name, "wrong")
|
||||
check(time.Kitchen, "", true, "should error on wrong value")
|
||||
|
||||
os.Setenv(name, "layout")
|
||||
check(time.Kitchen, time.Layout, false, "should handle layout value")
|
||||
os.Setenv(name, "ansic")
|
||||
check(time.Kitchen, time.ANSIC, false, "should handle ansic value")
|
||||
os.Setenv(name, "unixdate")
|
||||
check(time.Kitchen, time.UnixDate, false, "should handle unixdate value")
|
||||
os.Setenv(name, "rubydate")
|
||||
check(time.Kitchen, time.RubyDate, false, "should handle rubydate value")
|
||||
os.Setenv(name, "rfc822")
|
||||
check(time.Kitchen, time.RFC822, false, "should handle rfc822 value")
|
||||
os.Setenv(name, "rfc822z")
|
||||
check(time.Kitchen, time.RFC822Z, false, "should handle rfc822z value")
|
||||
os.Setenv(name, "rfc850")
|
||||
check(time.Kitchen, time.RFC850, false, "should handle rfc850 value")
|
||||
os.Setenv(name, "rfc1123")
|
||||
check(time.Kitchen, time.RFC1123, false, "should handle rfc1123 value")
|
||||
os.Setenv(name, "rfc1123z")
|
||||
check(time.Kitchen, time.RFC1123Z, false, "should handle rfc1123z value")
|
||||
os.Setenv(name, "rfc3339")
|
||||
check(time.Kitchen, time.RFC3339, false, "should handle rfc3339 value")
|
||||
os.Setenv(name, "rfc3339nano")
|
||||
check(time.Kitchen, time.RFC3339Nano, false, "should handle rfc3339nano value")
|
||||
os.Setenv(name, "kitchen")
|
||||
check(time.Kitchen, time.Kitchen, false, "should handle kitchen value")
|
||||
}
|
||||
|
||||
func (s *argsTestSuite) TestDetailString() {
|
||||
home := "/home"
|
||||
name := "test-name"
|
||||
@ -350,6 +414,9 @@ func (s *argsTestSuite) TestDetailString() {
|
||||
fmt.Sprintf("%s: %t", EnvSkipBackup, unsafeSkipBackup),
|
||||
fmt.Sprintf("%s: %s", EnvDataBackupPath, home),
|
||||
fmt.Sprintf("%s: %d", EnvPreupgradeMaxRetries, preupgradeMaxRetries),
|
||||
fmt.Sprintf("%s: %t", EnvDisableLogs, cfg.DisableLogs),
|
||||
fmt.Sprintf("%s: %t", EnvColorLogs, cfg.ColorLogs),
|
||||
fmt.Sprintf("%s: %s", EnvTimeFormatLogs, cfg.TimeFormatLogs),
|
||||
"Derived Values:",
|
||||
fmt.Sprintf("Root Dir: %s", home),
|
||||
fmt.Sprintf("Upgrade Dir: %s", home),
|
||||
@ -373,7 +440,18 @@ func (s *argsTestSuite) TestGetConfigFromEnv() {
|
||||
absPath, perr := filepath.Abs(relPath)
|
||||
s.Require().NoError(perr)
|
||||
|
||||
newConfig := func(home, name string, downloadBin, downloadMustHaveChecksum, restartUpgrade bool, restartDelay int, skipBackup bool, dataBackupPath string, interval, preupgradeMaxRetries int, disableLogs bool) *Config {
|
||||
newConfig := func(
|
||||
home, name string,
|
||||
downloadBin bool,
|
||||
downloadMustHaveChecksum bool,
|
||||
restartUpgrade bool,
|
||||
restartDelay int,
|
||||
skipBackup bool,
|
||||
dataBackupPath string,
|
||||
interval, preupgradeMaxRetries int,
|
||||
disableLogs, colorLogs bool,
|
||||
timeFormatLogs string,
|
||||
) *Config {
|
||||
return &Config{
|
||||
Home: home,
|
||||
Name: name,
|
||||
@ -386,6 +464,8 @@ func (s *argsTestSuite) TestGetConfigFromEnv() {
|
||||
DataBackupPath: dataBackupPath,
|
||||
PreupgradeMaxRetries: preupgradeMaxRetries,
|
||||
DisableLogs: disableLogs,
|
||||
ColorLogs: colorLogs,
|
||||
TimeFormatLogs: timeFormatLogs,
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,215 +488,248 @@ func (s *argsTestSuite) TestGetConfigFromEnv() {
|
||||
DataBackupPath: "bad",
|
||||
Interval: "bad",
|
||||
PreupgradeMaxRetries: "bad",
|
||||
TimeFormatLogs: "bad",
|
||||
},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 10,
|
||||
expectedErrCount: 11,
|
||||
},
|
||||
{
|
||||
name: "all good",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "303ms", "1", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, 303, 1, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, 303, 1, false, true, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "nothing set",
|
||||
envVals: cosmovisorEnv{"", "", "", "", "", "", "", "", "", "", "false"},
|
||||
envVals: cosmovisorEnv{"", "", "", "", "", "", "", "", "", "", "false", "false", ""},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 3,
|
||||
},
|
||||
// Note: Home and Name tests are done in TestValidate
|
||||
// timeformat tests are done in the TestTimeFormat
|
||||
{
|
||||
name: "download bin bad",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "bad", "true", "false", "600ms", "true", "", "303ms", "1", "false"},
|
||||
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"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, true, absPath, 303, 1, false),
|
||||
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),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "download bin true",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "303ms", "1", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, 303, 1, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, 303, 1, false, true, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "download bin false",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "true", "", "303ms", "1", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, true, absPath, 303, 1, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "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),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "download ensure checksum true",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "303ms", "1", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, 303, 1, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, 303, 1, false, true, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "download ensure checksum false",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "false", "false", "600ms", "true", "", "303ms", "1", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, false, false, 600, true, absPath, 303, 1, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "false", "false", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, false, false, 600, true, absPath, 303, 1, false, true, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "restart upgrade bad",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "bad", "600ms", "true", "", "303ms", "1", "false"},
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "bad", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 1,
|
||||
},
|
||||
{
|
||||
name: "restart upgrade not set",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "", "600ms", "true", "", "303ms", "1", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, true, 600, true, absPath, 303, 1, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, true, 600, true, absPath, 303, 1, false, true, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "restart upgrade true",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "true", "600ms", "true", "", "303ms", "1", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, true, 600, true, absPath, 303, 1, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "true", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, true, 600, true, absPath, 303, 1, false, true, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "restart upgrade true",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "303ms", "1", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, 303, 1, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, 303, 1, false, true, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "skip unsafe backups bad",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "bad", "", "303ms", "1", "false"},
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "bad", "", "303ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 1,
|
||||
},
|
||||
{
|
||||
name: "skip unsafe backups not set",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "", "", "303ms", "1", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, false, 600, false, absPath, 303, 1, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "", "", "303ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, false, 600, false, absPath, 303, 1, false, true, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "skip unsafe backups true",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "303ms", "1", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, 303, 1, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "true", "", "303ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, false, 600, true, absPath, 303, 1, false, true, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "skip unsafe backups false",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "false", "", "303ms", "1", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, false, 600, false, absPath, 303, 1, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "false", "600ms", "false", "", "303ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", true, true, false, 600, false, absPath, 303, 1, false, true, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "poll interval bad",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "bad", "1", "false"},
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "bad", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 1,
|
||||
},
|
||||
{
|
||||
name: "poll interval 0",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "0", "1", "false"},
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "0", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 1,
|
||||
},
|
||||
{
|
||||
name: "poll interval not set",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "1", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 300, 1, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "", "1", "false", "false", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 300, 1, false, false, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "poll interval 600",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "600", "1", "false"},
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "600", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 1,
|
||||
},
|
||||
{
|
||||
name: "poll interval 1s",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "1s", "1", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 1000, 1, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "1s", "1", "false", "false", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 1000, 1, false, false, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "poll interval -3m",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "-3m", "1", "false"},
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "-3m", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 1,
|
||||
},
|
||||
{
|
||||
name: "restart delay bad",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "bad", "false", "", "303ms", "1", "false"},
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "bad", "false", "", "303ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 1,
|
||||
},
|
||||
{
|
||||
name: "restart delay 0",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "0", "false", "", "303ms", "1", "false"},
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "0", "false", "", "303ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 1,
|
||||
},
|
||||
{
|
||||
name: "restart delay not set",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "", "false", "", "303ms", "1", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 0, false, absPath, 303, 1, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "", "false", "", "303ms", "1", "false", "false", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 0, false, absPath, 303, 1, false, false, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "restart delay 600",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600", "false", "", "300ms", "1", "false"},
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600", "false", "", "300ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 1,
|
||||
},
|
||||
{
|
||||
name: "restart delay 1s",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "1s", "false", "", "303ms", "1", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 1000, false, absPath, 303, 1, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "1s", "false", "", "303ms", "1", "false", "false", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 1000, false, absPath, 303, 1, false, false, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "restart delay -3m",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "-3m", "false", "", "303ms", "1", "false"},
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "-3m", "false", "", "303ms", "1", "false", "true", "kitchen"},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 1,
|
||||
},
|
||||
{
|
||||
name: "prepupgrade max retries bad",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "bad", "false"},
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "bad", "false", "true", "kitchen"},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 1,
|
||||
},
|
||||
{
|
||||
name: "prepupgrade max retries 0",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "0", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "0", "false", "false", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, false, false, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "prepupgrade max retries not set",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "false", "false", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, false, false, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "prepupgrade max retries 5",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "5", "false"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 5, false),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "5", "false", "false", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 5, false, false, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "disable logs bad",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "5", "bad"},
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "5", "bad", "true", "kitchen"},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 1,
|
||||
},
|
||||
{
|
||||
name: "disable logs good",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "true"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, true),
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "true", "false", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, true, false, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "disable logs color bad",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "5", "true", "bad", "kitchen"},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 1,
|
||||
},
|
||||
{
|
||||
name: "disable logs color good",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "true", "false", "kitchen"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, true, false, time.Kitchen),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "disable logs timestamp",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "true", "false", ""},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, true, false, ""),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "enable rf3339 logs timestamp",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "true", "true", "rfc3339"},
|
||||
expectedCfg: newConfig(absPath, "testname", false, true, false, 600, false, absPath, 406, 0, true, true, time.RFC3339),
|
||||
expectedErrCount: 0,
|
||||
},
|
||||
{
|
||||
name: "invalid logs timestamp format",
|
||||
envVals: cosmovisorEnv{absPath, "testname", "false", "true", "false", "600ms", "false", "", "406ms", "", "true", "true", "invalid"},
|
||||
expectedCfg: nil,
|
||||
expectedErrCount: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
|
||||
@ -5,10 +5,9 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/tools/cosmovisor"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"cosmossdk.io/tools/cosmovisor"
|
||||
)
|
||||
|
||||
func NewAddUpgradeCmd() *cobra.Command {
|
||||
@ -32,10 +31,7 @@ func AddUpgrade(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
logger := cmd.Context().Value(log.ContextKey).(log.Logger)
|
||||
if cfg.DisableLogs {
|
||||
logger = log.NewCustomLogger(zerolog.Nop())
|
||||
}
|
||||
logger := cfg.Logger(os.Stdout)
|
||||
|
||||
upgradeName := args[0]
|
||||
if len(upgradeName) == 0 {
|
||||
|
||||
@ -6,12 +6,14 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/tools/cosmovisor"
|
||||
"cosmossdk.io/x/upgrade/plan"
|
||||
|
||||
"cosmossdk.io/tools/cosmovisor"
|
||||
)
|
||||
|
||||
var initCmd = &cobra.Command{
|
||||
@ -19,8 +21,7 @@ var initCmd = &cobra.Command{
|
||||
Short: "Initialize a cosmovisor daemon home directory.",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
logger := cmd.Context().Value(log.ContextKey).(log.Logger)
|
||||
return InitializeCosmovisor(logger, args)
|
||||
return InitializeCosmovisor(nil, args)
|
||||
},
|
||||
}
|
||||
|
||||
@ -43,6 +44,10 @@ func InitializeCosmovisor(logger log.Logger, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if logger == nil {
|
||||
logger = cfg.Logger(os.Stdout)
|
||||
}
|
||||
|
||||
logger.Info("checking on the genesis/bin directory")
|
||||
genBinExe := cfg.GenesisBin()
|
||||
genBinDir, _ := filepath.Split(genBinExe)
|
||||
@ -95,6 +100,15 @@ func getConfigForInitCmd() (*cosmovisor.Config, error) {
|
||||
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 len(cfg.Name) == 0 {
|
||||
errs = append(errs, fmt.Errorf("%s is not set", cosmovisor.EnvName))
|
||||
}
|
||||
@ -105,7 +119,7 @@ func getConfigForInitCmd() (*cosmovisor.Config, error) {
|
||||
errs = append(errs, fmt.Errorf("%s must be an absolute path", cosmovisor.EnvHome))
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
return nil, errors.Join(errs...)
|
||||
return cfg, errors.Join(errs...)
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ import (
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
|
||||
"cosmossdk.io/tools/cosmovisor"
|
||||
)
|
||||
|
||||
@ -28,15 +29,24 @@ func TestInitTestSuite(t *testing.T) {
|
||||
|
||||
// cosmovisorInitEnv are some string values of environment variables used to configure Cosmovisor, and used by the init command.
|
||||
type cosmovisorInitEnv struct {
|
||||
Home string
|
||||
Name string
|
||||
Home string
|
||||
Name string
|
||||
ColorLogs string
|
||||
TimeFormatLogs string
|
||||
}
|
||||
|
||||
type envMap struct {
|
||||
val string
|
||||
allowEmpty bool
|
||||
}
|
||||
|
||||
// ToMap creates a map of the cosmovisorInitEnv where the keys are the env var names.
|
||||
func (c cosmovisorInitEnv) ToMap() map[string]string {
|
||||
return map[string]string{
|
||||
cosmovisor.EnvHome: c.Home,
|
||||
cosmovisor.EnvName: c.Name,
|
||||
func (c cosmovisorInitEnv) ToMap() map[string]envMap {
|
||||
return map[string]envMap{
|
||||
cosmovisor.EnvHome: {val: c.Home, allowEmpty: false},
|
||||
cosmovisor.EnvName: {val: c.Name, allowEmpty: false},
|
||||
cosmovisor.EnvColorLogs: {val: c.ColorLogs, allowEmpty: false},
|
||||
cosmovisor.EnvTimeFormatLogs: {val: c.TimeFormatLogs, allowEmpty: true},
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,6 +57,10 @@ func (c *cosmovisorInitEnv) Set(envVar, envVal string) {
|
||||
c.Home = envVal
|
||||
case cosmovisor.EnvName:
|
||||
c.Name = envVal
|
||||
case cosmovisor.EnvColorLogs:
|
||||
c.Name = envVal
|
||||
case cosmovisor.EnvTimeFormatLogs:
|
||||
c.Name = envVal
|
||||
default:
|
||||
panic(fmt.Errorf("Unknown environment variable [%s]. Cannot set field to [%s]. ", envVar, envVal))
|
||||
}
|
||||
@ -77,9 +91,9 @@ func (s *InitTestSuite) setEnv(t *testing.T, env *cosmovisorInitEnv) {
|
||||
for envVar, envVal := range env.ToMap() {
|
||||
var err error
|
||||
var msg string
|
||||
if len(envVal) != 0 {
|
||||
err = os.Setenv(envVar, envVal)
|
||||
msg = fmt.Sprintf("setting %s to %s", envVar, envVal)
|
||||
if len(envVal.val) != 0 || envVal.allowEmpty {
|
||||
err = os.Setenv(envVar, envVal.val)
|
||||
msg = fmt.Sprintf("setting %s to %s", envVar, envVal.val)
|
||||
} else {
|
||||
err = os.Unsetenv(envVar)
|
||||
msg = fmt.Sprintf("unsetting %s", envVar)
|
||||
|
||||
@ -3,15 +3,14 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
logger := log.NewLogger(os.Stdout).With(log.ModuleKey, "cosmovisor")
|
||||
ctx := context.WithValue(context.Background(), log.ContextKey, logger)
|
||||
// error logger used only during configuration phase
|
||||
cfg, _ := getConfigForInitCmd()
|
||||
logger := cfg.Logger(os.Stderr)
|
||||
|
||||
if err := NewRootCmd().ExecuteContext(ctx); err != nil {
|
||||
if err := NewRootCmd().ExecuteContext(context.Background()); err != nil {
|
||||
if errMulti, ok := err.(interface{ Unwrap() []error }); ok {
|
||||
err := errMulti.Unwrap()
|
||||
for _, e := range err {
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/tools/cosmovisor"
|
||||
"github.com/rs/zerolog"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"cosmossdk.io/tools/cosmovisor"
|
||||
)
|
||||
|
||||
var runCmd = &cobra.Command{
|
||||
@ -12,23 +13,19 @@ var runCmd = &cobra.Command{
|
||||
Short: "Run an APP command.",
|
||||
SilenceUsage: true,
|
||||
DisableFlagParsing: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return Run(cmd, args)
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
return run(args)
|
||||
},
|
||||
}
|
||||
|
||||
// Run runs the configured program with the given args and monitors it for upgrades.
|
||||
func Run(cmd *cobra.Command, args []string, options ...RunOption) error {
|
||||
// run runs the configured program with the given args and monitors it for upgrades.
|
||||
func run(args []string, options ...RunOption) error {
|
||||
cfg, err := cosmovisor.GetConfigFromEnv()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logger := cmd.Context().Value(log.ContextKey).(log.Logger)
|
||||
|
||||
if cfg.DisableLogs {
|
||||
logger = log.NewCustomLogger(zerolog.Nop())
|
||||
}
|
||||
logger := cfg.Logger(os.Stdout)
|
||||
|
||||
runCfg := DefaultRunConfig
|
||||
for _, opt := range options {
|
||||
|
||||
@ -26,7 +26,7 @@ func StdOutRunOption(w io.Writer) RunOption {
|
||||
}
|
||||
}
|
||||
|
||||
// SdErrRunOption sets the StdErr writer for the Run command
|
||||
// StdErrRunOption sets the StdErr writer for the Run command
|
||||
func StdErrRunOption(w io.Writer) RunOption {
|
||||
return func(cfg *RunConfig) {
|
||||
cfg.StdErr = w
|
||||
|
||||
@ -6,8 +6,9 @@ import (
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
|
||||
"cosmossdk.io/tools/cosmovisor"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"cosmossdk.io/tools/cosmovisor"
|
||||
)
|
||||
|
||||
func NewVersionCmd() *cobra.Command {
|
||||
@ -45,7 +46,7 @@ func printVersion(cmd *cobra.Command, args []string, noAppVersion bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := Run(cmd, append([]string{"version"}, args...)); err != nil {
|
||||
if err := run(append([]string{"version"}, args...)); err != nil {
|
||||
return fmt.Errorf("failed to run version command: %w", err)
|
||||
}
|
||||
|
||||
@ -59,8 +60,7 @@ func printVersionJSON(cmd *cobra.Command, args []string, noAppVersion bool) erro
|
||||
}
|
||||
|
||||
buf := new(strings.Builder)
|
||||
if err := Run(
|
||||
cmd,
|
||||
if err := run(
|
||||
[]string{"version", "--long", "--output", "json"},
|
||||
StdOutRunOption(buf),
|
||||
); err != nil {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user