refactor: make Cosmovisor use cobra (#11823)
## Description Closes: #11789 --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#pr-targeting)) - [x] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/main/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#testing) - [x] added a changelog entry to `CHANGELOG.md` - [x] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [x] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
This commit is contained in:
parent
c0f65e1e5d
commit
8076144bfc
|
@ -37,7 +37,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||
## [Unreleased]
|
||||
<!-- NOTE: when creating a new release, update cosmovisor/cmd/cosmovisor/cmd/version.go:Version -->
|
||||
|
||||
* [\#11731](https://github.com/cosmos/cosmos-sdk/pull/11731) `cosmovisor version --json` returns the cosmovisor version and the result of `simd --output json --long` in one JSON object.
|
||||
### Features
|
||||
|
||||
* [\#11823](https://github.com/cosmos/cosmos-sdk/pull/11823) Refactor `cosmovisor` CLI to use `cobra`.
|
||||
* [\#11731](https://github.com/cosmos/cosmos-sdk/pull/11731) `cosmovisor version -o json` returns the cosmovisor version and the result of `simd --output json --long` in one JSON object.
|
||||
|
||||
## v1.1.0 2022-10-02
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ To install a previous version, you can specify the version. IMPORTANT: Chains th
|
|||
go install github.com/cosmos/cosmos-sdk/cosmovisor/cmd/cosmovisor@v0.1.0
|
||||
```
|
||||
|
||||
You can run `cosmovisor --version` to check the Cosmovisor version (works only with Cosmovisor >=1.0.0).
|
||||
You can run `cosmovisor version` to check the Cosmovisor version (works only with Cosmovisor >1.1.0).
|
||||
|
||||
You can also install from source by pulling the cosmos-sdk repository and switching to the correct version and building as follows:
|
||||
|
||||
|
@ -62,7 +62,7 @@ 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`, or `--version` - Output the `cosmovisor` version and also run the binary with the `version` argument.
|
||||
* `version` - Output the `cosmovisor` version and also run the binary with the `version` argument.
|
||||
|
||||
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.
|
||||
|
||||
|
@ -209,7 +209,6 @@ You can also use `sha512sum` if you would prefer to use longer hashes, or `md5su
|
|||
|
||||
The following instructions provide a demonstration of `cosmovisor` using the simulation application (`simapp`) shipped with the Cosmos SDK's source code. The following commands are to be run from within the `cosmos-sdk` repository.
|
||||
|
||||
|
||||
### Chain Setup
|
||||
|
||||
Let's create a new chain using the `v0.44` version of simapp (the Cosmos SDK demo app):
|
||||
|
@ -289,12 +288,10 @@ cp ./build/simd $DAEMON_HOME/cosmovisor/genesis/bin
|
|||
|
||||
Now you can run cosmovisor with simapp v0.44:
|
||||
|
||||
|
||||
```sh
|
||||
cosmovisor run start
|
||||
```
|
||||
|
||||
|
||||
#### Update App
|
||||
|
||||
Update app to the latest version (e.g. v0.45).
|
||||
|
@ -314,7 +311,6 @@ mkdir -p $DAEMON_HOME/cosmovisor/upgrades/test1/bin
|
|||
cp ./build/simd $DAEMON_HOME/cosmovisor/upgrades/test1/bin
|
||||
```
|
||||
|
||||
|
||||
Open a new terminal window and submit an upgrade proposal along with a deposit and a vote (these commands must be run within 20 seconds of each other):
|
||||
|
||||
```sh
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/cosmovisor"
|
||||
)
|
||||
|
||||
// HelpArgs are the strings that indicate a cosmovisor help command.
|
||||
var HelpArgs = []string{"help", "--help", "-h"}
|
||||
|
||||
// ShouldGiveHelp checks the env and provided args to see if help is needed or being requested.
|
||||
// Help is needed if either cosmovisor.EnvName and/or cosmovisor.EnvHome env vars aren't set.
|
||||
// Help is requested if the first arg is "help", "--help", or "-h".
|
||||
func ShouldGiveHelp(arg string) bool {
|
||||
return isOneOf(arg, HelpArgs)
|
||||
}
|
||||
|
||||
// DoHelp outputs help text
|
||||
func DoHelp() error {
|
||||
// Not using the logger for this output because the header and footer look weird for help text.
|
||||
fmt.Println(GetHelpText())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetHelpText creates the help text multi-line string.
|
||||
func GetHelpText() string {
|
||||
return fmt.Sprintf(`Cosmosvisor - A process manager for Cosmos SDK application binaries.
|
||||
|
||||
Cosmovisor is a wrapper for a Cosmos SDK based App (set using the required %s env variable).
|
||||
It starts the App by passing all provided arguments and monitors the %s/data/upgrade-info.json
|
||||
file to perform an update. The upgrade-info.json file is created by the App x/upgrade module
|
||||
when the blockchain height reaches an approved upgrade proposal. The file includes data from
|
||||
the proposal. Cosmovisor interprets that data to perform an update: switch a current binary
|
||||
and restart the App.
|
||||
|
||||
Configuration of Cosmovisor is done through environment variables, which are
|
||||
documented in: https://github.com/cosmos/cosmos-sdk/tree/main/cosmovisor/README.md
|
||||
|
||||
To get help for the configured binary:
|
||||
cosmovisor run help
|
||||
|
||||
Available Commands:
|
||||
help This help message
|
||||
run Runs app passing all subsequent parameters
|
||||
version Prints version of cosmovisor and the associated app.
|
||||
`, cosmovisor.EnvName, cosmovisor.EnvHome)
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// RunCosmovisorCommand executes the desired cosmovisor command.
|
||||
func RunCosmovisorCommand(logger *zerolog.Logger, args []string) error {
|
||||
arg0 := ""
|
||||
if len(args) > 0 {
|
||||
arg0 = strings.TrimSpace(args[0])
|
||||
}
|
||||
|
||||
switch {
|
||||
case IsVersionCommand(arg0):
|
||||
return PrintVersion(logger, args[1:])
|
||||
|
||||
case ShouldGiveHelp(arg0):
|
||||
return DoHelp()
|
||||
|
||||
case IsRunCommand(arg0):
|
||||
return Run(logger, args[1:])
|
||||
}
|
||||
|
||||
warnRun := func() {
|
||||
logger.Warn().Msg("use of cosmovisor without the 'run' command is deprecated. Use: cosmovisor run [args]")
|
||||
}
|
||||
warnRun()
|
||||
defer warnRun()
|
||||
|
||||
return Run(logger, args)
|
||||
}
|
||||
|
||||
// isOneOf returns true if the given arg equals one of the provided options (ignoring case).
|
||||
func isOneOf(arg string, options []string) bool {
|
||||
for _, opt := range options {
|
||||
if strings.EqualFold(arg, opt) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestIsRunCommand(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
arg string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "empty string",
|
||||
arg: "",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "random",
|
||||
arg: "random",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "run",
|
||||
arg: "run",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "run weird casing",
|
||||
arg: "RUn",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "--run",
|
||||
arg: "--run",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "help",
|
||||
arg: "help",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "-h",
|
||||
arg: "-h",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "--help",
|
||||
arg: "--help",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "version",
|
||||
arg: "version",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "--version",
|
||||
arg: "--version",
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(fmt.Sprintf("%s - %t", tc.name, tc.expected), func(t *testing.T) {
|
||||
actual := IsRunCommand(tc.arg)
|
||||
require.Equal(t, tc.expected, actual)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Write tests for func Run(args []string) error
|
|
@ -1,88 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
cverrors "github.com/cosmos/cosmos-sdk/cosmovisor/errors"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
var (
|
||||
// FlagJSON formats the output in json
|
||||
FlagJSON = "--json"
|
||||
// Version represents Cosmovisor version value. Overwritten during build
|
||||
Version = "1.1.0"
|
||||
// VersionArgs is the strings that indicate a cosmovisor version command.
|
||||
VersionArgs = []string{"version", "--version"}
|
||||
)
|
||||
|
||||
// IsVersionCommand checks if the given args indicate that the version is being requested.
|
||||
func IsVersionCommand(arg string) bool {
|
||||
return isOneOf(arg, VersionArgs)
|
||||
}
|
||||
|
||||
// PrintVersion prints the cosmovisor version.
|
||||
func PrintVersion(logger *zerolog.Logger, args []string) error {
|
||||
for _, arg := range args {
|
||||
if strings.Contains(arg, FlagJSON) {
|
||||
return printVersionJSON(logger, args)
|
||||
}
|
||||
}
|
||||
|
||||
return printVersion(logger, args)
|
||||
}
|
||||
|
||||
func printVersion(logger *zerolog.Logger, args []string) error {
|
||||
fmt.Println("Cosmovisor Version: ", Version)
|
||||
|
||||
if err := Run(logger, append([]string{"version"}, args...)); err != nil {
|
||||
handleRunVersionFailure(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func printVersionJSON(logger *zerolog.Logger, args []string) error {
|
||||
buf := new(strings.Builder)
|
||||
|
||||
// disable logger
|
||||
l := logger.Level(zerolog.Disabled)
|
||||
logger = &l
|
||||
|
||||
if err := Run(
|
||||
logger,
|
||||
[]string{"version", "--long", "--output", "json"},
|
||||
StdOutRunOption(buf),
|
||||
); err != nil {
|
||||
handleRunVersionFailure(err)
|
||||
}
|
||||
|
||||
out, err := json.Marshal(struct {
|
||||
Version string `json:"cosmovisor_version"`
|
||||
AppVersion json.RawMessage `json:"app_version"`
|
||||
}{
|
||||
Version: Version,
|
||||
AppVersion: json.RawMessage(buf.String()),
|
||||
})
|
||||
if err != nil {
|
||||
l := logger.Level(zerolog.TraceLevel)
|
||||
logger = &l
|
||||
return fmt.Errorf("Can't print version output, expected valid json from APP, got: %s - %w", buf.String(), err)
|
||||
}
|
||||
|
||||
fmt.Println(string(out))
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleRunVersionFailure(err error) {
|
||||
// Check the config and output details or any errors.
|
||||
// Not using the cosmovisor.Logger in order to ignore any level it might have set,
|
||||
// and also to not have any of the extra parameters in the output.
|
||||
output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.Kitchen}
|
||||
logger := zerolog.New(output).With().Timestamp().Logger()
|
||||
cverrors.LogErrors(&logger, "Can't run APP version", err)
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestIsVersionCommand(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
arg string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "empty string",
|
||||
arg: "",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "random",
|
||||
arg: "random",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "version",
|
||||
arg: "version",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "--version",
|
||||
arg: "--version",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "version weird casing",
|
||||
arg: "veRSiOn",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
// -v should be reserved for verbose, and should not be used for --version.
|
||||
name: "-v",
|
||||
arg: "-v",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "typo",
|
||||
arg: "vrsion",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "non version command",
|
||||
arg: "start",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "help",
|
||||
arg: "help",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "-h",
|
||||
arg: "-h",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "--help",
|
||||
arg: "--help",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "run",
|
||||
arg: "run",
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(fmt.Sprintf("%s - %t", tc.name, tc.expected), func(t *testing.T) {
|
||||
actual := IsVersionCommand(tc.arg)
|
||||
require.Equal(t, tc.expected, actual)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/cosmovisor"
|
||||
)
|
||||
|
||||
// GetHelpText creates the help text multi-line string.
|
||||
func GetHelpText() string {
|
||||
return fmt.Sprintf(`Cosmosvisor - A process manager for Cosmos SDK application binaries.
|
||||
|
||||
Cosmovisor is a wrapper for a Cosmos SDK based App (set using the required %s env variable).
|
||||
It starts the App by passing all provided arguments and monitors the %s/data/upgrade-info.json
|
||||
file to perform an update. The upgrade-info.json file is created by the App x/upgrade module
|
||||
when the blockchain height reaches an approved upgrade proposal. The file includes data from
|
||||
the proposal. Cosmovisor interprets that data to perform an update: switch a current binary
|
||||
and restart the App.
|
||||
|
||||
Configuration of Cosmovisor is done through environment variables, which are
|
||||
documented in: https://github.com/cosmos/cosmos-sdk/tree/main/cosmovisor/README.md`,
|
||||
cosmovisor.EnvName, cosmovisor.EnvHome,
|
||||
)
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
package cmd
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
|
@ -88,72 +87,6 @@ func (s *HelpTestSuite) setEnv(t *testing.T, env *cosmovisorHelpEnv) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s HelpTestSuite) TestShouldGiveHelpArg() {
|
||||
initialEnv := s.clearEnv()
|
||||
defer s.setEnv(nil, initialEnv)
|
||||
|
||||
s.setEnv(s.T(), &cosmovisorHelpEnv{"/testhome", "testname"})
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
arg string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "empty string",
|
||||
arg: "",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "random",
|
||||
arg: "random",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "help",
|
||||
arg: "help",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "-h",
|
||||
arg: "-h",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "--help",
|
||||
arg: "--help",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "help weird casing",
|
||||
arg: "hELP",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "version",
|
||||
arg: "version",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "--version",
|
||||
arg: "--version",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "run",
|
||||
arg: "run",
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
s.T().Run(fmt.Sprintf("%s - %t", tc.name, tc.expected), func(t *testing.T) {
|
||||
actual := ShouldGiveHelp(tc.arg)
|
||||
assert.Equal(t, tc.expected, actual)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HelpTestSuite) TestGetHelpText() {
|
||||
expectedPieces := []string{
|
||||
"Cosmosvisor",
|
|
@ -1,16 +1,18 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/cosmovisor"
|
||||
"github.com/cosmos/cosmos-sdk/cosmovisor/cmd/cosmovisor/cmd"
|
||||
cverrors "github.com/cosmos/cosmos-sdk/cosmovisor/errors"
|
||||
)
|
||||
|
||||
func main() {
|
||||
logger := cosmovisor.NewLogger()
|
||||
if err := cmd.RunCosmovisorCommand(logger, os.Args[1:]); err != nil {
|
||||
ctx := context.WithValue(context.Background(), cosmovisor.LoggerKey, logger)
|
||||
|
||||
if err := rootCmd.ExecuteContext(ctx); err != nil {
|
||||
cverrors.LogErrors(logger, "", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "cosmovisor",
|
||||
Short: "A process manager for Cosmos SDK application binaries.",
|
||||
Long: GetHelpText(),
|
||||
}
|
|
@ -1,16 +1,25 @@
|
|||
package cmd
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/cosmovisor"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// RunArgs are the strings that indicate a cosmovisor run command.
|
||||
var RunArgs = []string{"run"}
|
||||
func init() {
|
||||
rootCmd.AddCommand(runCmd)
|
||||
}
|
||||
|
||||
// IsRunCommand checks if the given args indicate that a run is desired.
|
||||
func IsRunCommand(arg string) bool {
|
||||
return isOneOf(arg, RunArgs)
|
||||
var runCmd = &cobra.Command{
|
||||
Use: "run",
|
||||
Short: "Run an APP command.",
|
||||
SilenceUsage: true,
|
||||
DisableFlagParsing: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
logger := cmd.Context().Value(cosmovisor.LoggerKey).(*zerolog.Logger)
|
||||
|
||||
return Run(logger, args)
|
||||
},
|
||||
}
|
||||
|
||||
// Run runs the configured program with the given args and monitors it for upgrades.
|
|
@ -1,4 +1,4 @@
|
|||
package cmd
|
||||
package main
|
||||
|
||||
import (
|
||||
"io"
|
|
@ -0,0 +1,4 @@
|
|||
package main
|
||||
|
||||
// TODO: Write tests for func Run(args []string) error
|
||||
// https://github.com/cosmos/cosmos-sdk/issues/11852
|
|
@ -0,0 +1,81 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/cosmovisor"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/spf13/cobra"
|
||||
tmcli "github.com/tendermint/tendermint/libs/cli"
|
||||
)
|
||||
|
||||
func init() {
|
||||
versionCmd.Flags().StringP(OutputFlag, "o", "text", "Output format (text|json)")
|
||||
rootCmd.AddCommand(versionCmd)
|
||||
}
|
||||
|
||||
var (
|
||||
// Version represents Cosmovisor version value. Overwritten during build
|
||||
Version = "1.1.0"
|
||||
// OutputFlag defines the output format flag
|
||||
OutputFlag = tmcli.OutputFlag
|
||||
)
|
||||
|
||||
var versionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Prints the version of Cosmovisor.",
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
logger := cmd.Context().Value(cosmovisor.LoggerKey).(*zerolog.Logger)
|
||||
|
||||
if val, err := cmd.Flags().GetString(OutputFlag); val == "json" && err == nil {
|
||||
return printVersionJSON(logger, args)
|
||||
}
|
||||
|
||||
return printVersion(logger, args)
|
||||
},
|
||||
}
|
||||
|
||||
func printVersion(logger *zerolog.Logger, args []string) error {
|
||||
fmt.Println("cosmovisor version: ", Version)
|
||||
|
||||
if err := Run(logger, append([]string{"version"}, args...)); err != nil {
|
||||
return fmt.Errorf("failed to run version command: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func printVersionJSON(logger *zerolog.Logger, args []string) error {
|
||||
buf := new(strings.Builder)
|
||||
|
||||
// disable logger
|
||||
l := logger.Level(zerolog.Disabled)
|
||||
logger = &l
|
||||
|
||||
if err := Run(
|
||||
logger,
|
||||
[]string{"version", "--long", "--output", "json"},
|
||||
StdOutRunOption(buf),
|
||||
); err != nil {
|
||||
return fmt.Errorf("failed to run version command: %w", err)
|
||||
}
|
||||
|
||||
out, err := json.Marshal(struct {
|
||||
Version string `json:"cosmovisor_version"`
|
||||
AppVersion json.RawMessage `json:"app_version"`
|
||||
}{
|
||||
Version: Version,
|
||||
AppVersion: json.RawMessage(buf.String()),
|
||||
})
|
||||
if err != nil {
|
||||
l := logger.Level(zerolog.TraceLevel)
|
||||
logger = &l
|
||||
return fmt.Errorf("can't print version output, expected valid json from APP, got: %s - %w", buf.String(), err)
|
||||
}
|
||||
|
||||
fmt.Println(string(out))
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/cosmovisor"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestVersionCommand_Error(t *testing.T) {
|
||||
logger := cosmovisor.NewLogger()
|
||||
|
||||
rootCmd.SetArgs([]string{"version"})
|
||||
_, out := testutil.ApplyMockIO(rootCmd)
|
||||
ctx := context.WithValue(context.Background(), cosmovisor.LoggerKey, logger)
|
||||
|
||||
require.Error(t, rootCmd.ExecuteContext(ctx))
|
||||
require.Contains(t, out.String(), "DAEMON_NAME is not set")
|
||||
}
|
|
@ -7,7 +7,9 @@ require (
|
|||
github.com/hashicorp/go-getter v1.5.11
|
||||
github.com/otiai10/copy v1.7.0
|
||||
github.com/rs/zerolog v1.26.1
|
||||
github.com/spf13/cobra v1.4.0
|
||||
github.com/stretchr/testify v1.7.1
|
||||
github.com/tendermint/tendermint v0.35.2
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -85,7 +87,6 @@ require (
|
|||
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect
|
||||
github.com/spf13/afero v1.8.0 // indirect
|
||||
github.com/spf13/cast v1.4.1 // indirect
|
||||
github.com/spf13/cobra v1.4.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.10.1 // indirect
|
||||
|
@ -95,7 +96,6 @@ require (
|
|||
github.com/tendermint/btcd v0.1.1 // indirect
|
||||
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect
|
||||
github.com/tendermint/go-amino v0.16.0 // indirect
|
||||
github.com/tendermint/tendermint v0.35.2 // indirect
|
||||
github.com/tendermint/tm-db v0.6.6 // indirect
|
||||
github.com/ulikunitz/xz v0.5.8 // indirect
|
||||
github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266 // indirect
|
||||
|
|
|
@ -7,6 +7,8 @@ import (
|
|||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
var LoggerKey struct{}
|
||||
|
||||
func NewLogger() *zerolog.Logger {
|
||||
output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.Kitchen}
|
||||
logger := zerolog.New(output).With().Str("module", "cosmovisor").Timestamp().Logger()
|
||||
|
|
Loading…
Reference in New Issue