feat(cosmovisor): add add-upgrade command (#16413)
This commit is contained in:
parent
0f1bfea1ab
commit
c91ad30f77
@ -38,6 +38,7 @@ 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.
|
||||
* [#15361](https://github.com/cosmos/cosmos-sdk/pull/15361) Add `cosmovisor config` command to display the configuration used by cosmovisor.
|
||||
|
||||
## Client Breaking Changes
|
||||
|
||||
@ -73,10 +73,14 @@ The first argument passed to `cosmovisor` is the action for `cosmovisor` to take
|
||||
* `help`, `--help`, or `-h` - Output `cosmovisor` help information and check your `cosmovisor` configuration.
|
||||
* `run` - Run the configured binary using the rest of the provided arguments.
|
||||
* `version` - Output the `cosmovisor` version and also run the binary with the `version` argument.
|
||||
* `config` - Display the current `cosmovisor` configuration, that means displaying the environment variables value that `cosmovisor` is using.
|
||||
* `add-upgrade` - Add an upgrade manually to `cosmovisor`.
|
||||
|
||||
All arguments passed to `cosmovisor run` will be passed to the application binary (as a subprocess). `cosmovisor` will return `/dev/stdout` and `/dev/stderr` of the subprocess as its own. For this reason, `cosmovisor run` cannot accept any command-line arguments other than those available to the application binary.
|
||||
|
||||
*Note: Use of `cosmovisor` without one of the action arguments is deprecated. For backwards compatibility, if the first argument is not an action argument, `run` is assumed. However, this fallback might be removed in future versions, so it is recommended that you always provide `run`.
|
||||
:::warning
|
||||
Use of `cosmovisor` without one of the action arguments is deprecated. For backwards compatibility, if the first argument is not an action argument, `run` is assumed. However, this fallback might be removed in future versions, so it is recommended that you always provide `run`.
|
||||
:::
|
||||
|
||||
`cosmovisor` reads its configuration from environment variables:
|
||||
|
||||
|
||||
84
tools/cosmovisor/cmd/cosmovisor/add_upgrade.go
Normal file
84
tools/cosmovisor/cmd/cosmovisor/add_upgrade.go
Normal file
@ -0,0 +1,84 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/tools/cosmovisor"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func NewAddUpgradeCmd() *cobra.Command {
|
||||
addUpgrade := &cobra.Command{
|
||||
Use: "add-upgrade [upgrade-name] [path to executable]",
|
||||
Short: "Manually add upgrade binary to Cosmovisor",
|
||||
SilenceUsage: true,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: AddUpgrade,
|
||||
}
|
||||
|
||||
addUpgrade.Flags().Bool(cosmovisor.FlagForce, false, "overwrite existing upgrade binary")
|
||||
|
||||
return addUpgrade
|
||||
}
|
||||
|
||||
// AddUpgrade adds upgrade info to manifest
|
||||
func AddUpgrade(cmd *cobra.Command, args []string) 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())
|
||||
}
|
||||
|
||||
upgradeName := args[0]
|
||||
if len(upgradeName) == 0 {
|
||||
return fmt.Errorf("upgrade name cannot be empty")
|
||||
}
|
||||
|
||||
executablePath := args[1]
|
||||
if _, err := os.Stat(executablePath); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return fmt.Errorf("invalid executable path: %w", err)
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed to load executable path: %w", err)
|
||||
}
|
||||
|
||||
// create upgrade dir
|
||||
upgradeLocation := cfg.UpgradeDir(upgradeName)
|
||||
if err := os.MkdirAll(path.Join(upgradeLocation, "bin"), 0o750); err != nil {
|
||||
return fmt.Errorf("failed to create upgrade directory: %w", err)
|
||||
}
|
||||
|
||||
// copy binary to upgrade dir
|
||||
executableData, err := os.ReadFile(executablePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read binary: %w", err)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(cfg.UpgradeBin(upgradeName)); err == nil {
|
||||
if force, _ := cmd.Flags().GetBool(cosmovisor.FlagForce); !force {
|
||||
return fmt.Errorf("upgrade binary already exists at %s", cfg.UpgradeBin(upgradeName))
|
||||
}
|
||||
|
||||
logger.Info(fmt.Sprintf("Overwriting %s for %s upgrade", executablePath, upgradeName))
|
||||
} else if !os.IsNotExist(err) {
|
||||
return fmt.Errorf("failed to check if upgrade binary exists: %w", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(cfg.UpgradeBin(upgradeName), executableData, 0o600); err != nil {
|
||||
return fmt.Errorf("failed to write binary to location: %w", err)
|
||||
}
|
||||
|
||||
logger.Info(fmt.Sprintf("Using %s for %s upgrade", executablePath, upgradeName))
|
||||
logger.Info(fmt.Sprintf("Upgrade binary located at %s", cfg.UpgradeBin(upgradeName)))
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -1,8 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/tools/cosmovisor"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -17,7 +15,7 @@ var configCmd = &cobra.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprint(cmd.OutOrStdout(), cfg.DetailString())
|
||||
cmd.Print(cfg.DetailString())
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
@ -7,7 +7,6 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
@ -21,14 +20,13 @@ 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).(*zerolog.Logger)
|
||||
|
||||
logger := cmd.Context().Value(log.ContextKey).(log.Logger)
|
||||
return InitializeCosmovisor(logger, args)
|
||||
},
|
||||
}
|
||||
|
||||
// InitializeCosmovisor initializes the cosmovisor directories, current link, and initial executable.
|
||||
func InitializeCosmovisor(logger *zerolog.Logger, args []string) error {
|
||||
func InitializeCosmovisor(logger log.Logger, args []string) error {
|
||||
if len(args) < 1 || len(args[0]) == 0 {
|
||||
return errors.New("no <path to executable> provided")
|
||||
}
|
||||
@ -46,14 +44,14 @@ func InitializeCosmovisor(logger *zerolog.Logger, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Info().Msg("checking on the genesis/bin directory")
|
||||
logger.Info("checking on the genesis/bin directory")
|
||||
genBinExe := cfg.GenesisBin()
|
||||
genBinDir, _ := filepath.Split(genBinExe)
|
||||
genBinDir = filepath.Clean(genBinDir)
|
||||
switch genBinDirInfo, genBinDirErr := os.Stat(genBinDir); {
|
||||
case os.IsNotExist(genBinDirErr):
|
||||
logger.Info().Msgf("creating directory (and any parents): %q", genBinDir)
|
||||
mkdirErr := os.MkdirAll(genBinDir, 0o755)
|
||||
logger.Info(fmt.Sprintf("creating directory (and any parents): %q", genBinDir))
|
||||
mkdirErr := os.MkdirAll(genBinDir, 0o750)
|
||||
if mkdirErr != nil {
|
||||
return mkdirErr
|
||||
}
|
||||
@ -62,29 +60,29 @@ func InitializeCosmovisor(logger *zerolog.Logger, args []string) error {
|
||||
case !genBinDirInfo.IsDir():
|
||||
return fmt.Errorf("the path %q already exists but is not a directory", genBinDir)
|
||||
default:
|
||||
logger.Info().Msgf("the %q directory already exists", genBinDir)
|
||||
logger.Info(fmt.Sprintf("the %q directory already exists", genBinDir))
|
||||
}
|
||||
|
||||
logger.Info().Msg("checking on the genesis/bin executable")
|
||||
logger.Info("checking on the genesis/bin executable")
|
||||
if _, err = os.Stat(genBinExe); os.IsNotExist(err) {
|
||||
logger.Info().Msgf("copying executable into place: %q", genBinExe)
|
||||
logger.Info(fmt.Sprintf("copying executable into place: %q", genBinExe))
|
||||
if cpErr := copyFile(pathToExe, genBinExe); cpErr != nil {
|
||||
return cpErr
|
||||
}
|
||||
} else {
|
||||
logger.Info().Msgf("the %q file already exists", genBinExe)
|
||||
logger.Info(fmt.Sprintf("the %q file already exists", genBinExe))
|
||||
}
|
||||
logger.Info().Msgf("making sure %q is executable", genBinExe)
|
||||
logger.Info(fmt.Sprintf("making sure %q is executable", genBinExe))
|
||||
if err = plan.EnsureBinary(genBinExe); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Info().Msg("checking on the current symlink and creating it if needed")
|
||||
logger.Info("checking on the current symlink and creating it if needed")
|
||||
cur, curErr := cfg.CurrentBin()
|
||||
if curErr != nil {
|
||||
return curErr
|
||||
}
|
||||
logger.Info().Msgf("the current symlink points to: %q", cur)
|
||||
logger.Info(fmt.Sprintf("the current symlink points to: %q", cur))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/tools/cosmovisor"
|
||||
)
|
||||
|
||||
@ -227,12 +228,12 @@ func (p *BufferedPipe) panicIfStarted(msg string) {
|
||||
}
|
||||
|
||||
// NewCapturingLogger creates a buffered stdout pipe, and a logger that uses it.
|
||||
func (s *InitTestSuite) NewCapturingLogger() (*BufferedPipe, *zerolog.Logger) {
|
||||
func (s *InitTestSuite) NewCapturingLogger() (*BufferedPipe, log.Logger) {
|
||||
bufferedStdOut, err := StartNewBufferedPipe("stdout", os.Stdout)
|
||||
s.Require().NoError(err, "creating stdout buffered pipe")
|
||||
output := zerolog.ConsoleWriter{Out: bufferedStdOut, TimeFormat: time.RFC3339Nano}
|
||||
logger := zerolog.New(output).With().Str("module", "cosmovisor").Timestamp().Logger()
|
||||
return &bufferedStdOut, &logger
|
||||
logger := log.NewCustomLogger(zerolog.New(output).With().Str("module", "cosmovisor").Timestamp().Logger())
|
||||
return &bufferedStdOut, logger
|
||||
}
|
||||
|
||||
// CreateHelloWorld creates a shell script that outputs HELLO WORLD.
|
||||
@ -348,9 +349,9 @@ func (s *InitTestSuite) TestInitializeCosmovisorInvalidExisting() {
|
||||
require.NoError(t, copyFile(hwExe, genBin), "copying exe to genesis/bin")
|
||||
|
||||
s.setEnv(t, env)
|
||||
logger := zerolog.Nop()
|
||||
logger := log.NewNopLogger()
|
||||
expErr := fmt.Sprintf("the path %q already exists but is not a directory", genBin)
|
||||
err := InitializeCosmovisor(&logger, []string{hwExe})
|
||||
err := InitializeCosmovisor(logger, []string{hwExe})
|
||||
require.EqualError(t, err, expErr, "invalid path to executable: must not be a directory", "calling InitializeCosmovisor")
|
||||
})
|
||||
|
||||
@ -379,7 +380,7 @@ func (s *InitTestSuite) TestInitializeCosmovisorInvalidExisting() {
|
||||
|
||||
s.setEnv(t, env)
|
||||
buffer, logger := s.NewCapturingLogger()
|
||||
logger.Info().Msgf("Calling InitializeCosmovisor: %s", t.Name())
|
||||
logger.Info(fmt.Sprintf("Calling InitializeCosmovisor: %s", t.Name()))
|
||||
err := InitializeCosmovisor(logger, []string{hwExe})
|
||||
require.EqualError(t, err, expErr, "calling InitializeCosmovisor")
|
||||
bufferBz := buffer.Collect()
|
||||
@ -407,7 +408,7 @@ func (s *InitTestSuite) TestInitializeCosmovisorInvalidExisting() {
|
||||
|
||||
s.setEnv(t, env)
|
||||
buffer, logger := s.NewCapturingLogger()
|
||||
logger.Info().Msgf("Calling InitializeCosmovisor: %s", t.Name())
|
||||
logger.Info(fmt.Sprintf("Calling InitializeCosmovisor: %s", t.Name()))
|
||||
err := InitializeCosmovisor(logger, []string{hwExe})
|
||||
require.EqualError(t, err, expErr, "calling InitializeCosmovisor")
|
||||
bufferBz := buffer.Collect()
|
||||
@ -462,7 +463,7 @@ func (s *InitTestSuite) TestInitializeCosmovisorValid() {
|
||||
|
||||
s.setEnv(s.T(), env)
|
||||
buffer, logger := s.NewCapturingLogger()
|
||||
logger.Info().Msgf("Calling InitializeCosmovisor: %s", t.Name())
|
||||
logger.Info(fmt.Sprintf("Calling InitializeCosmovisor: %s", t.Name()))
|
||||
err := InitializeCosmovisor(logger, []string{hwNonExe})
|
||||
require.NoError(t, err, "calling InitializeCosmovisor")
|
||||
|
||||
@ -514,7 +515,7 @@ func (s *InitTestSuite) TestInitializeCosmovisorValid() {
|
||||
|
||||
s.setEnv(t, env)
|
||||
buffer, logger := s.NewCapturingLogger()
|
||||
logger.Info().Msgf("Calling InitializeCosmovisor: %s", t.Name())
|
||||
logger.Info(fmt.Sprintf("Calling InitializeCosmovisor: %s", t.Name()))
|
||||
err := InitializeCosmovisor(logger, []string{hwExe})
|
||||
require.NoError(t, err, "calling InitializeCosmovisor")
|
||||
bufferBz := buffer.Collect()
|
||||
@ -546,7 +547,7 @@ func (s *InitTestSuite) TestInitializeCosmovisorValid() {
|
||||
|
||||
s.setEnv(t, env)
|
||||
buffer, logger := s.NewCapturingLogger()
|
||||
logger.Info().Msgf("Calling InitializeCosmovisor: %s", t.Name())
|
||||
logger.Info(fmt.Sprintf("Calling InitializeCosmovisor: %s", t.Name()))
|
||||
err := InitializeCosmovisor(logger, []string{hwExe})
|
||||
require.NoError(t, err, "calling InitializeCosmovisor")
|
||||
bufferBz := buffer.Collect()
|
||||
|
||||
@ -16,6 +16,7 @@ func NewRootCmd() *cobra.Command {
|
||||
runCmd,
|
||||
configCmd,
|
||||
NewVersionCmd(),
|
||||
NewAddUpgradeCmd(),
|
||||
)
|
||||
|
||||
return rootCmd
|
||||
|
||||
@ -6,27 +6,26 @@ import (
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
|
||||
"cosmossdk.io/tools/cosmovisor"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// OutputFlag defines the output format flag
|
||||
var OutputFlag = "output"
|
||||
|
||||
func NewVersionCmd() *cobra.Command {
|
||||
versionCmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Display cosmovisor and APP version.",
|
||||
SilenceUsage: true,
|
||||
Use: "version",
|
||||
Short: "Display cosmovisor and APP version.",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if val, err := cmd.Flags().GetString(OutputFlag); val == "json" && err == nil {
|
||||
return printVersionJSON(cmd, args)
|
||||
noAppVersion, _ := cmd.Flags().GetBool(cosmovisor.FlagNoAppVersion)
|
||||
if val, err := cmd.Flags().GetString(cosmovisor.FlagOutput); val == "json" && err == nil {
|
||||
return printVersionJSON(cmd, args, noAppVersion)
|
||||
}
|
||||
|
||||
return printVersion(cmd, args)
|
||||
return printVersion(cmd, args, noAppVersion)
|
||||
},
|
||||
}
|
||||
|
||||
versionCmd.Flags().StringP(OutputFlag, "o", "text", "Output format (text|json)")
|
||||
versionCmd.Flags().StringP(cosmovisor.FlagOutput, "o", "text", "Output format (text|json)")
|
||||
versionCmd.Flags().Bool(cosmovisor.FlagNoAppVersion, false, "Don't print APP version")
|
||||
|
||||
return versionCmd
|
||||
}
|
||||
@ -40,8 +39,11 @@ func getVersion() string {
|
||||
return strings.TrimSpace(version.Main.Version)
|
||||
}
|
||||
|
||||
func printVersion(cmd *cobra.Command, args []string) error {
|
||||
fmt.Printf("cosmovisor version: %s\n", getVersion())
|
||||
func printVersion(cmd *cobra.Command, args []string, noAppVersion bool) error {
|
||||
cmd.Printf("cosmovisor version: %s\n", getVersion())
|
||||
if noAppVersion {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := Run(cmd, append([]string{"version"}, args...)); err != nil {
|
||||
return fmt.Errorf("failed to run version command: %w", err)
|
||||
@ -50,9 +52,13 @@ func printVersion(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func printVersionJSON(cmd *cobra.Command, args []string) error {
|
||||
buf := new(strings.Builder)
|
||||
func printVersionJSON(cmd *cobra.Command, args []string, noAppVersion bool) error {
|
||||
if noAppVersion {
|
||||
cmd.Printf(`{"cosmovisor_version":"%s"}`+"\n", getVersion())
|
||||
return nil
|
||||
}
|
||||
|
||||
buf := new(strings.Builder)
|
||||
if err := Run(
|
||||
cmd,
|
||||
[]string{"version", "--long", "--output", "json"},
|
||||
@ -72,6 +78,6 @@ func printVersionJSON(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("can't print version output, expected valid json from APP, got: %s - %w", buf.String(), err)
|
||||
}
|
||||
|
||||
fmt.Println(string(out))
|
||||
cmd.Println(string(out))
|
||||
return nil
|
||||
}
|
||||
|
||||
8
tools/cosmovisor/flags.go
Normal file
8
tools/cosmovisor/flags.go
Normal file
@ -0,0 +1,8 @@
|
||||
package cosmovisor
|
||||
|
||||
const (
|
||||
FlagOutput = "output"
|
||||
FlagSkipUpgradeHeight = "unsafe-skip-upgrades"
|
||||
FlagNoAppVersion = "no-app-version"
|
||||
FlagForce = "force"
|
||||
)
|
||||
@ -78,7 +78,7 @@ func (l Launcher) Run(args []string, stdout, stderr io.Writer) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if err := UpgradeBinary(l.logger, l.cfg, l.fw.currentInfo); err != nil {
|
||||
if err := UpgradeBinary(log.NewCustomLogger(*l.logger), l.cfg, l.fw.currentInfo); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@ -232,7 +232,7 @@ func IsSkipUpgradeHeight(args []string, upgradeInfo upgradetypes.Plan) bool {
|
||||
func UpgradeSkipHeights(args []string) []int {
|
||||
var heights []int
|
||||
for i, arg := range args {
|
||||
if arg == "--unsafe-skip-upgrades" {
|
||||
if arg == fmt.Sprintf("--%s", FlagSkipUpgradeHeight) {
|
||||
j := i + 1
|
||||
|
||||
for j < len(args) {
|
||||
|
||||
@ -6,8 +6,7 @@ import (
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/x/upgrade/plan"
|
||||
upgradetypes "cosmossdk.io/x/upgrade/types"
|
||||
)
|
||||
@ -15,7 +14,7 @@ import (
|
||||
// UpgradeBinary will be called after the log message has been parsed and the process has terminated.
|
||||
// We can now make any changes to the underlying directory without interference and leave it
|
||||
// in a state, so we can make a proper restart
|
||||
func UpgradeBinary(logger *zerolog.Logger, cfg *Config, p upgradetypes.Plan) error {
|
||||
func UpgradeBinary(logger log.Logger, cfg *Config, p upgradetypes.Plan) error {
|
||||
// simplest case is to switch the link
|
||||
err := plan.EnsureBinary(cfg.UpgradeBin(p.Name))
|
||||
if err == nil {
|
||||
@ -55,11 +54,11 @@ func UpgradeBinary(logger *zerolog.Logger, cfg *Config, p upgradetypes.Plan) err
|
||||
}
|
||||
|
||||
// If not there, then we try to download it... maybe
|
||||
logger.Info().Msg("no upgrade binary found, beginning to download it")
|
||||
logger.Info("no upgrade binary found, beginning to download it")
|
||||
if err := plan.DownloadUpgrade(cfg.UpgradeDir(p.Name), url, cfg.Name); err != nil {
|
||||
return fmt.Errorf("cannot download binary. %w", err)
|
||||
}
|
||||
logger.Info().Msg("downloading binary complete")
|
||||
logger.Info("downloading binary complete")
|
||||
|
||||
// and then set the binary again
|
||||
if err := plan.EnsureBinary(cfg.UpgradeBin(p.Name)); err != nil {
|
||||
|
||||
@ -11,7 +11,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/otiai10/copy"
|
||||
"github.com/rs/zerolog"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
@ -95,7 +94,7 @@ func (s *upgradeTestSuite) assertCurrentLink(cfg cosmovisor.Config, target strin
|
||||
func (s *upgradeTestSuite) TestUpgradeBinaryNoDownloadUrl() {
|
||||
home := copyTestData(s.T(), "validate")
|
||||
cfg := &cosmovisor.Config{Home: home, Name: "dummyd", AllowDownloadBinaries: true}
|
||||
logger := log.NewLogger(os.Stdout).With(log.ModuleKey, "cosmovisor").Impl().(*zerolog.Logger)
|
||||
logger := log.NewLogger(os.Stdout).With(log.ModuleKey, "cosmovisor")
|
||||
|
||||
currentBin, err := cfg.CurrentBin()
|
||||
s.Require().NoError(err)
|
||||
@ -128,7 +127,7 @@ func (s *upgradeTestSuite) TestUpgradeBinaryNoDownloadUrl() {
|
||||
}
|
||||
|
||||
func (s *upgradeTestSuite) TestUpgradeBinary() {
|
||||
logger := log.NewLogger(os.Stdout).With(log.ModuleKey, "cosmovisor").Impl().(*zerolog.Logger)
|
||||
logger := log.NewLogger(os.Stdout).With(log.ModuleKey, "cosmovisor")
|
||||
|
||||
cases := map[string]struct {
|
||||
url string
|
||||
|
||||
Loading…
Reference in New Issue
Block a user