From d3466da97dfcee4584e2333a1d298d050901d9de Mon Sep 17 00:00:00 2001 From: Mikhail Elhimov Date: Thu, 13 Mar 2025 11:04:57 +0300 Subject: [PATCH 01/13] logging: reimplement log handler --- cli/cmd/root.go | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/cli/cmd/root.go b/cli/cmd/root.go index d09c171d7..7735cc655 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -28,8 +28,6 @@ var ( // InjectedCmds is populated with the command to be injected into root. // TT-EE. InjectedCmds []*cobra.Command - - bold = color.New(color.Bold) ) // GetCmdCtxPtr returns a pointer to cmdCtx, which can be used to create injected commands. @@ -75,35 +73,25 @@ func GetModulesInfoPtr() *modules.ModulesInfo { return &modulesInfo } -// printLogEntryColored prints log entry message using level specific colors. -func printLogEntryColored(logHandler *cli.Handler, logEntry *log.Entry) error { - printColor := cli.Colors[logEntry.Level] - level := cli.Strings[logEntry.Level] - - if logEntry.Level >= log.ErrorLevel { - printColor = color.New(color.Bold, color.FgHiRed) - } - - printColor.Fprintf(logHandler.Writer, "%s ", bold.Sprintf("%*s", logHandler.Padding+1, level)) - printColor.Fprintf(logHandler.Writer, "%s\n", logEntry.Message) - - return nil -} - // LogHandler is a custom log handler implementation used to print formatted error and warning // log messages. -type LogHandler struct{} - -var defaultLogHandler = &LogHandler{} +type LogHandler struct { + baseHandler *cli.Handler +} // HandleLog performs log handling in accordance with log entry level. -func (handler *LogHandler) HandleLog(logEntry *log.Entry) error { - switch logEntry.Level { - case log.ErrorLevel, log.WarnLevel, log.FatalLevel: - return printLogEntryColored(cli.Default, logEntry) - default: - return cli.Default.HandleLog(logEntry) +func (h *LogHandler) HandleLog(logEntry *log.Entry) error { + if logEntry.Level >= log.WarnLevel { + logEntry = &log.Entry{ + Logger: logEntry.Logger, + Fields: logEntry.Fields, + Level: logEntry.Level, + Timestamp: logEntry.Timestamp, + // For warnings and errors display the whole message colored not only prefix bullet. + Message: cli.Colors[logEntry.Level].Sprint(logEntry.Message), + } } + return h.baseHandler.HandleLog(logEntry) } // NewCmdRoot creates a new root command. @@ -202,7 +190,11 @@ After that tt will be able to manage the application using 'replicaset_example' rootCmd.InitDefaultHelpCmd() - log.SetHandler(defaultLogHandler) + // Adjust logger color mapping (display errors with hi-intencity color and bold). + cli.Colors[log.ErrorLevel] = color.New(color.Bold, color.FgHiRed) + cli.Colors[log.FatalLevel] = color.New(color.Bold, color.FgHiRed) + + log.SetHandler(&LogHandler{cli.Default}) return rootCmd } From 19234bee104909999b9e9461ddfc6b8fdeb0f7f6 Mon Sep 17 00:00:00 2001 From: Mikhail Elhimov Date: Thu, 13 Mar 2025 11:10:19 +0300 Subject: [PATCH 02/13] make Cobra's errors look similar to logger errors --- cli/cmd/root.go | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/cli/cmd/root.go b/cli/cmd/root.go index 7735cc655..602f1b31a 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -3,8 +3,10 @@ package cmd import ( "errors" "fmt" + "io" "os" "path/filepath" + "strings" "github.com/tarantool/tt/cli/util" "github.com/tarantool/tt/lib/integrity" @@ -94,6 +96,32 @@ func (h *LogHandler) HandleLog(logEntry *log.Entry) error { return h.baseHandler.HandleLog(logEntry) } +// setWriter sets the underlying writer and returns the original one. +func (h *LogHandler) setWriter(w io.Writer) io.Writer { + orig := h.baseHandler.Writer + h.baseHandler.Writer = w + return orig +} + +// logErrorWriterDecorator is used to decorate messages sent to writer +// in the same way as log.Error. +type logErrorWriterDecorator struct { + writer io.Writer + handler *LogHandler +} + +// Write decorates the original output in the same way as log.Error. +func (d logErrorWriterDecorator) Write(p []byte) (int, error) { + // Setup LogHandler to write to string to get the decorated string. + var logdst strings.Builder + orig := d.handler.setWriter(&logdst) + log.Errorf(string(p)) + // Restore LogHandler with the original writer. + d.handler.setWriter(orig) + // Send the decorated data. + return fmt.Fprint(d.writer, logdst.String()) +} + // NewCmdRoot creates a new root command. func NewCmdRoot() *cobra.Command { rootCmd := &cobra.Command{ @@ -188,13 +216,17 @@ After that tt will be able to manage the application using 'replicaset_example' panic(err.Error()) } - rootCmd.InitDefaultHelpCmd() - // Adjust logger color mapping (display errors with hi-intencity color and bold). cli.Colors[log.ErrorLevel] = color.New(color.Bold, color.FgHiRed) cli.Colors[log.FatalLevel] = color.New(color.Bold, color.FgHiRed) - log.SetHandler(&LogHandler{cli.Default}) + logHandler := &LogHandler{cli.Default} + + log.SetHandler(logHandler) + + // Setup decoration for Command's error messages. + rootCmd.SetErr(&logErrorWriterDecorator{rootCmd.ErrOrStderr(), logHandler}) + rootCmd.InitDefaultHelpCmd() return rootCmd } From 72539ab4f86cf64a00801bf414dd43c00c52c966 Mon Sep 17 00:00:00 2001 From: Mikhail Elhimov Date: Thu, 6 Mar 2025 21:33:18 +0300 Subject: [PATCH 03/13] use Cobra's functionality to validate arguments Closes #1125 --- cli/cmd/aeon.go | 7 +-- cli/cmd/binaries.go | 49 ++++++++++--------- cli/cmd/cat.go | 11 +++-- cli/cmd/create.go | 3 +- cli/cmd/daemon.go | 20 ++------ cli/cmd/download.go | 16 ++++-- cli/cmd/enable.go | 11 +++-- cli/cmd/install.go | 4 ++ cli/cmd/pack.go | 33 +++++-------- cli/cmd/play.go | 9 +++- cli/cmd/replicaset.go | 22 +++++---- cli/cmd/search.go | 3 ++ cli/cmd/uninstall.go | 8 +-- cli/create/create.go | 9 +--- cli/download/download.go | 18 ++----- cli/install/install.go | 5 -- cli/util/util.go | 4 -- cli/util/util_test.go | 5 +- test/integration/cat/test_cat.py | 2 +- test/integration/pack/test_pack.py | 3 +- .../replicaset/test_replicaset_rebootstrap.py | 8 ++- 21 files changed, 117 insertions(+), 133 deletions(-) diff --git a/cli/cmd/aeon.go b/cli/cmd/aeon.go index b32e5e006..8fca44eee 100644 --- a/cli/cmd/aeon.go +++ b/cli/cmd/aeon.go @@ -37,18 +37,13 @@ func newAeonConnectCmd() *cobra.Command { tt aeon connect http://localhost:50051 tt aeon connect unix:// tt aeon connect /path/to/config INSTANCE_NAME>`, - PreRunE: func(cmd *cobra.Command, args []string) error { - err := aeonConnectValidateArgs(cmd, args) - util.HandleCmdErr(cmd, err) - return err - }, Run: func(cmd *cobra.Command, args []string) { cmdCtx.CommandName = cmd.Name() err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalAeonConnect, args) util.HandleCmdErr(cmd, err) }, - Args: cobra.RangeArgs(1, 2), + Args: cobra.MatchAll(cobra.RangeArgs(1, 2), aeonConnectValidateArgs), } aeonCmd.Flags().StringVar(&connectCtx.Ssl.KeyFile, "sslkeyfile", "", diff --git a/cli/cmd/binaries.go b/cli/cmd/binaries.go index 2248d77ab..a52ab444b 100644 --- a/cli/cmd/binaries.go +++ b/cli/cmd/binaries.go @@ -12,6 +12,12 @@ import ( "golang.org/x/exp/slices" ) +var binariesSupportedPrograms = []string{ + search.ProgramCe, + search.ProgramEe, + search.ProgramTt, +} + // NewBinariesCmd creates binaries command. func NewBinariesCmd() *cobra.Command { var binariesCmd = &cobra.Command{ @@ -42,6 +48,7 @@ You will need to choose version using arrow keys in your console. internalSwitchModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.MatchAll(cobra.MaximumNArgs(2), binariesSwitchValidateArgs), } var listCmd = &cobra.Command{ Use: "list", @@ -57,44 +64,42 @@ You will need to choose version using arrow keys in your console. return binariesCmd } +// binariesSwitchValidateArgs validates non-flag arguments of 'binaries switch' command. +func binariesSwitchValidateArgs(cmd *cobra.Command, args []string) error { + if len(args) > 0 { + if !slices.Contains(binariesSupportedPrograms, args[0]) { + return fmt.Errorf("not supported program: %s", args[0]) + } + } + return nil +} + // internalSwitchModule is a switch module. func internalSwitchModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { if !isConfigExist(cmdCtx) { return errNoConfig } var switchCtx binary.SwitchCtx - supportedPrograms := []string{search.ProgramCe, search.ProgramEe, search.ProgramTt} - var err error - switch len(args) { - case 2: - switchCtx.Version = args[1] - switchCtx.ProgramName = args[0] - if !slices.Contains(supportedPrograms, switchCtx.ProgramName) { - return fmt.Errorf("not supported program: %s", switchCtx.ProgramName) - } - case 1: + + if len(args) > 0 { switchCtx.ProgramName = args[0] - if !slices.Contains(supportedPrograms, switchCtx.ProgramName) { - return fmt.Errorf("not supported program: %s", switchCtx.ProgramName) - } - switchCtx.Version, err = binary.ChooseVersion(cliOpts.Env.BinDir, switchCtx.ProgramName) - if err != nil { - return err - } - case 0: - switchCtx.ProgramName, err = binary.ChooseProgram(supportedPrograms) + } else { + switchCtx.ProgramName, err = binary.ChooseProgram(binariesSupportedPrograms) if err != nil { return err } + } + + if len(args) > 1 { + switchCtx.Version = args[1] + } else { switchCtx.Version, err = binary.ChooseVersion(cliOpts.Env.BinDir, switchCtx.ProgramName) if err != nil { return err } - default: - return fmt.Errorf("invalid number of arguments") - } + switchCtx.BinDir = cliOpts.Env.BinDir switchCtx.IncDir = cliOpts.Env.IncludeDir diff --git a/cli/cmd/cat.go b/cli/cmd/cat.go index aa0f8c8c1..6ac8b969b 100644 --- a/cli/cmd/cat.go +++ b/cli/cmd/cat.go @@ -44,6 +44,13 @@ func NewCatCmd() *cobra.Command { "--timestamp 2024-11-13T14:02:36.818700000+00:00\n" + " tt cat /path/to/file.snap /path/to/file.xlog /path/to/dir/ " + "--timestamp=1731592956.818", + Args: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + return errors.New("it is required to specify at least one .xlog/.snap file " + + "or directory") + } + return nil + }, } catCmd.Flags().Uint64Var(&catFlags.To, "to", catFlags.To, @@ -66,10 +73,6 @@ func NewCatCmd() *cobra.Command { // internalCatModule is a default cat module. func internalCatModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { - if len(args) == 0 { - return errors.New("it is required to specify at least one .xlog or .snap file") - } - walFiles, err := util.CollectWALFiles(args) if err != nil { return util.InternalError( diff --git a/cli/cmd/create.go b/cli/cmd/create.go index 841a2c10d..b83cb2352 100644 --- a/cli/cmd/create.go +++ b/cli/cmd/create.go @@ -133,6 +133,7 @@ func internalCreateModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { createCtx := create_ctx.CreateCtx{ AppName: appName, + TemplateName: args[0], ForceMode: forceMode, SilentMode: nonInteractiveMode, VarsFromCli: *varsFromCli, @@ -141,7 +142,7 @@ func internalCreateModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { CliOpts: cliOpts, } - if err := create.FillCtx(cliOpts, &createCtx, args); err != nil { + if err := create.FillCtx(cliOpts, &createCtx); err != nil { return err } diff --git a/cli/cmd/daemon.go b/cli/cmd/daemon.go index a1a15a955..1818a7ab1 100644 --- a/cli/cmd/daemon.go +++ b/cli/cmd/daemon.go @@ -22,56 +22,44 @@ func NewDaemonCmd() *cobra.Command { Use: "start", Short: "start tt daemon", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 0 { - log.Fatalf("Wrong number of arguments") - } - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalDaemonStartModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.ExactArgs(0), } var stopCmd = &cobra.Command{ Use: "stop", Short: "stop tt daemon", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 0 { - log.Fatalf("Wrong number of arguments") - } - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalDaemonStopModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.ExactArgs(0), } var statusCmd = &cobra.Command{ Use: "status", Short: "status of tt daemon", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 0 { - log.Fatalf("Wrong number of arguments") - } - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalDaemonStatusModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.ExactArgs(0), } var restartCmd = &cobra.Command{ Use: "restart", Short: "restart tt daemon", Run: func(cmd *cobra.Command, args []string) { - if len(args) != 0 { - log.Fatalf("Wrong number of arguments") - } - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalDaemonRestartModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.ExactArgs(0), } daemonSubCommands := []*cobra.Command{ diff --git a/cli/cmd/download.go b/cli/cmd/download.go index 4272aab3f..9eed8594b 100644 --- a/cli/cmd/download.go +++ b/cli/cmd/download.go @@ -1,6 +1,8 @@ package cmd import ( + "errors" + "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" "github.com/tarantool/tt/cli/download" @@ -28,6 +30,14 @@ func NewDownloadCmd() *cobra.Command { internalDownloadModule, args) util.HandleCmdErr(cmd, err) }, + Args: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + return errors.New("to download Tarantool SDK, you need to specify the version") + } else if len(args) > 1 { + return errors.New("invalid number of parameters") + } + return nil + }, } cmd.Flags().BoolVar(&downloadCtx.DevBuild, "dev", false, "download development build") @@ -39,10 +49,6 @@ func NewDownloadCmd() *cobra.Command { } func internalDownloadModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { - var err error - if err = download.FillCtx(cmdCtx, &downloadCtx, args); err != nil { - return err - } - + downloadCtx.Version = args[0] return download.DownloadSDK(cmdCtx, downloadCtx, cliOpts) } diff --git a/cli/cmd/enable.go b/cli/cmd/enable.go index 199bb2801..76f0aac94 100644 --- a/cli/cmd/enable.go +++ b/cli/cmd/enable.go @@ -1,6 +1,7 @@ package cmd import ( + "errors" "fmt" "github.com/spf13/cobra" @@ -26,6 +27,12 @@ func NewEnableCmd() *cobra.Command { internalEnableModule, args) util.HandleCmdErr(cmd, err) }, + Args: func(cmd *cobra.Command, args []string) error { + if len(args) != 1 { + return errors.New("provide the path to a script or application directory") + } + return nil + }, } return initCmd @@ -33,10 +40,6 @@ func NewEnableCmd() *cobra.Command { // internalEnableModule is a default enable module. func internalEnableModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { - if len(args) != 1 { - return fmt.Errorf("provide the path to a script or application directory") - } - if cliOpts.Env.InstancesEnabled == "." { return fmt.Errorf("enabling application for instances enabled '.' is not supported") } diff --git a/cli/cmd/install.go b/cli/cmd/install.go index 3de043c43..71cd0157b 100644 --- a/cli/cmd/install.go +++ b/cli/cmd/install.go @@ -22,6 +22,7 @@ func newInstallTtCmd() *cobra.Command { internalInstallModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.MaximumNArgs(1), } return tntCmd @@ -39,6 +40,7 @@ func newInstallTarantoolCmd() *cobra.Command { internalInstallModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.MaximumNArgs(1), } tntCmd.Flags().BoolVarP(&installCtx.BuildInDocker, "use-docker", "", false, @@ -61,6 +63,7 @@ func newInstallTarantoolEeCmd() *cobra.Command { internalInstallModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.MaximumNArgs(1), } tntCmd.Flags().BoolVar(&installCtx.DevBuild, "dev", false, "install development build") @@ -86,6 +89,7 @@ func newInstallTarantoolDevCmd() *cobra.Command { internalInstallModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.ExactArgs(1), } tntCmd.Flags().StringVar(&installCtx.IncDir, "include-dir", "", diff --git a/cli/cmd/pack.go b/cli/cmd/pack.go index c595372f8..7c6bdd8a8 100644 --- a/cli/cmd/pack.go +++ b/cli/cmd/pack.go @@ -1,6 +1,7 @@ package cmd import ( + "errors" "fmt" "os" @@ -24,29 +25,12 @@ func NewPackCmd() *cobra.Command { The supported types are: tgz, deb, rpm`, ValidArgs: []string{"tgz", "deb", "rpm"}, Run: func(cmd *cobra.Command, args []string) { - err := cobra.ExactArgs(1)(cmd, args) - if err != nil { - err = fmt.Errorf("incorrect combination of command parameters: %s", err.Error()) - log.Fatalf(err.Error()) - } - err = cobra.OnlyValidArgs(cmd, args) - if err != nil { - err = fmt.Errorf("incorrect combination of command parameters: %s", err.Error()) - log.Fatalf(err.Error()) - } - if packCtx.CartridgeCompat && args[0] != "tgz" { - err = fmt.Errorf("cartridge-compat flag can only be used while packing tgz bundle") - log.Fatalf(err.Error()) - } - if packCtx.TarantoolVersion != "" && !packCtx.UseDocker { - err = fmt.Errorf("tarantool-version argument can only be " + - "used while packing in docker") - log.Fatalf(err.Error()) - } cmdCtx.CommandName = cmd.Name() - err = modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalPackModule, args) + err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, + internalPackModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), } // Common flags. @@ -150,12 +134,19 @@ func checkFlags(packCtx *pack.PackCtx) error { log.Warnf("You specified the --all flag," + " but you are not packaging a tarball. Flag will be ignored") } + if packCtx.CartridgeCompat { + return errors.New("cartridge-compat flag can only be used while packing tgz bundle") + } } // Check if --with-integrity-check and --without-binaries flags are provided // simultaneously. If this is the case, return an error for safety reasons. if packCtx.IntegrityPrivateKey != "" && packCtx.WithoutBinaries { - return fmt.Errorf("impossible combination of --with-integrity-check" + + return errors.New("impossible combination of --with-integrity-check" + " and --without-binaries flags") } + if packCtx.TarantoolVersion != "" && !packCtx.UseDocker { + return errors.New("tarantool-version argument can only be " + + "used while packing in docker") + } return nil } diff --git a/cli/cmd/play.go b/cli/cmd/play.go index 22c92220e..d3d8db10b 100644 --- a/cli/cmd/play.go +++ b/cli/cmd/play.go @@ -61,6 +61,7 @@ func NewPlayCmd() *cobra.Command { "/path/to/dir/ --timestamp 2024-11-13T14:02:36.818700000+00:00\n" + " tt play app:instance001 /path/to/file.snap /path/to/file.xlog " + "/path/to/dir/ --timestamp=1731592956.818", + Args: playValidateArgs, } playCmd.Flags().StringVarP(&playUsername, "username", "u", "", "username") @@ -89,13 +90,17 @@ func NewPlayCmd() *cobra.Command { return playCmd } -// internalPlayModule is a default play module. -func internalPlayModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { +// playValidateArgs validates non-flag arguments 'play' command. +func playValidateArgs(cmd *cobra.Command, args []string) error { if len(args) < 2 { return errors.New("it is required to specify an URI and at least one .xlog/.snap file " + "or directory") } + return nil +} +// internalPlayModule is a default play module. +func internalPlayModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { // FillCtx returns error if no instances found. var runningCtx running.RunningCtx err := running.FillCtx(cliOpts, cmdCtx, &runningCtx, []string{args[0]}, running.ConfigLoadAll) diff --git a/cli/cmd/replicaset.go b/cli/cmd/replicaset.go index c2f2c9177..03443083b 100644 --- a/cli/cmd/replicaset.go +++ b/cli/cmd/replicaset.go @@ -313,7 +313,7 @@ func newRebootstrapCmd() *cobra.Command { internalReplicasetRebootstrapModule, args) util.HandleCmdErr(cmd, err) }, - Args: cobra.ExactArgs(1), + Args: replicasetRebootstrapValidateArgs, } cmd.Flags().BoolVarP(&rebootstrapConfirmed, "yes", "y", false, @@ -813,21 +813,23 @@ func getOrchestrator() (replicaset.Orchestrator, error) { return orchestrator, nil } -// internalReplicasetRebootstrapModule is a "rebootstrap" command for the replicaset module. -func internalReplicasetRebootstrapModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { +// replicasetRebootstrapValidateArgs validates "rebootstrap" command arguments. +func replicasetRebootstrapValidateArgs(cmd *cobra.Command, args []string) error { if len(args) > 1 { - return util.NewArgError("only one instance supported for re-bootstrap") + return errors.New("only one instance supported for re-bootstrap") } if len(args) < 1 { - return util.NewArgError("instance for rebootstrap is not specified") + return errors.New("instance for rebootstrap is not specified") } - - appName, instName, found := strings.Cut(args[0], string(running.InstanceDelimiter)) - if !found { - return util.NewArgError( - "an instance name is not specified. Please use app:instance format.") + if !strings.Contains(args[0], string(running.InstanceDelimiter)) { + return errors.New("an instance name is not specified. Please use app:instance format") } + return nil +} +// internalReplicasetRebootstrapModule is a "rebootstrap" command for the replicaset module. +func internalReplicasetRebootstrapModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { + appName, instName, _ := strings.Cut(args[0], string(running.InstanceDelimiter)) return replicaset.Rebootstrap(*cmdCtx, *cliOpts, replicaset.RebootstrapCtx{ AppName: appName, InstanceName: instName, diff --git a/cli/cmd/search.go b/cli/cmd/search.go index 0fd86308f..f2055ac37 100644 --- a/cli/cmd/search.go +++ b/cli/cmd/search.go @@ -27,6 +27,7 @@ func newSearchTtCmd() *cobra.Command { internalSearchModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.ExactArgs(0), } return tntCmd @@ -43,6 +44,7 @@ func newSearchTarantoolCmd() *cobra.Command { internalSearchModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.ExactArgs(0), } return tntCmd @@ -59,6 +61,7 @@ func newSearchTarantoolEeCmd() *cobra.Command { internalSearchModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.ExactArgs(0), } tntCmd.Flags().BoolVar(&debug, "debug", debug, "search for debug builds of tarantool-ee SDK") diff --git a/cli/cmd/uninstall.go b/cli/cmd/uninstall.go index 219d2dd35..8a2c2b2b4 100644 --- a/cli/cmd/uninstall.go +++ b/cli/cmd/uninstall.go @@ -1,8 +1,6 @@ package cmd import ( - "fmt" - "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" "github.com/tarantool/tt/cli/modules" @@ -26,6 +24,7 @@ func newUninstallTtCmd() *cobra.Command { InternalUninstallModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.MaximumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, args []string, @@ -53,6 +52,7 @@ func newUninstallTarantoolCmd() *cobra.Command { InternalUninstallModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.MaximumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, args []string, @@ -80,6 +80,7 @@ func newUninstallTarantoolEeCmd() *cobra.Command { InternalUninstallModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.MaximumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, args []string, @@ -107,6 +108,7 @@ func newUninstallTarantoolDevCmd() *cobra.Command { InternalUninstallModule, args) util.HandleCmdErr(cmd, err) }, + Args: cobra.ExactArgs(0), } return tntCmd @@ -142,8 +144,6 @@ func InternalUninstallModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { programVersion := "" if len(args) == 1 { programVersion = args[0] - } else if len(args) > 1 { - return fmt.Errorf("wrong number of arguments") } err := uninstall.UninstallProgram(programName, programVersion, cliOpts.Env.BinDir, diff --git a/cli/create/create.go b/cli/create/create.go index 029c0c770..ef8a96bf1 100644 --- a/cli/create/create.go +++ b/cli/create/create.go @@ -14,18 +14,11 @@ import ( ) // FillCtx fills create context. -func FillCtx(cliOpts *config.CliOpts, createCtx *create_ctx.CreateCtx, args []string) error { +func FillCtx(cliOpts *config.CliOpts, createCtx *create_ctx.CreateCtx) error { for _, p := range cliOpts.Templates { createCtx.TemplateSearchPaths = append(createCtx.TemplateSearchPaths, p.Path) } - if len(args) >= 1 { - createCtx.TemplateName = args[0] - } else { - return fmt.Errorf("missing template name argument. " + - "Try `tt create --help` for more information") - } - workingDir, err := os.Getwd() if err != nil { return err diff --git a/cli/download/download.go b/cli/download/download.go index 375f127de..663924319 100644 --- a/cli/download/download.go +++ b/cli/download/download.go @@ -15,8 +15,8 @@ import ( ) type DownloadCtx struct { - // SDK version to download. - version string + // Version of SDK to download. + Version string // Path where the sdk will be saved. DirectoryPrefix string // Download development build. @@ -41,7 +41,7 @@ func DownloadSDK(cmdCtx *cmdcontext.CmdCtx, downloadCtx DownloadCtx, log.Info("Search for the requested version...") ver, err := search.GetTarantoolBundleInfo(cliOpts, false, - downloadCtx.DevBuild, nil, downloadCtx.version) + downloadCtx.DevBuild, nil, downloadCtx.Version) if err != nil { return fmt.Errorf("cannot get SDK bundle info: %s", err) } @@ -77,15 +77,3 @@ func DownloadSDK(cmdCtx *cmdcontext.CmdCtx, downloadCtx DownloadCtx, return err } - -func FillCtx(cmdCtx *cmdcontext.CmdCtx, downloadCtx *DownloadCtx, args []string) error { - if len(args) == 0 { - return fmt.Errorf("to download Tarantool SDK, you need to specify the version") - } else if len(args) == 1 { - downloadCtx.version = args[0] - } else if len(args) > 1 { - return fmt.Errorf("invalid number of parameters") - } - - return nil -} diff --git a/cli/install/install.go b/cli/install/install.go index 563f3e30e..15b67054a 100644 --- a/cli/install/install.go +++ b/cli/install/install.go @@ -1595,17 +1595,12 @@ func FillCtx(cmdCtx *cmdcontext.CmdCtx, installCtx *InstallCtx, args []string) e installCtx.skipMasterUpdate = cmdCtx.Cli.NoPrompt if cmdCtx.CommandName == search.ProgramDev { - if len(args) != 1 { - return fmt.Errorf("exactly one build directory must be specified") - } installCtx.buildDir = args[0] return nil } if len(args) == 1 { installCtx.version = args[0] - } else if len(args) > 1 { - return fmt.Errorf("invalid number of parameters") } return nil diff --git a/cli/util/util.go b/cli/util/util.go index 01eeb6f37..63307fa17 100644 --- a/cli/util/util.go +++ b/cli/util/util.go @@ -1001,10 +1001,6 @@ func StringToTimestamp(input string) (string, error) { // CollectWALFiles globs files from args. func CollectWALFiles(paths []string) ([]string, error) { - if len(paths) < 1 { - return nil, errors.New("it is required to specify at least one .xlog/.snap file " + - "or directory") - } collectedFiles := make([]string, 0) sortSnapFilesFirst := func(left, right string) int { diff --git a/cli/util/util_test.go b/cli/util/util_test.go index 254eb1639..421d26537 100644 --- a/cli/util/util_test.go +++ b/cli/util/util_test.go @@ -816,8 +816,9 @@ func TestCollectWALFiles(t *testing.T) { expectedErrMsg string }{ { - name: "no_file", - expectedErrMsg: "it is required to specify at least one .xlog/.snap file or directory", + name: "no_file", + input: []string{}, + output: []string{}, }, { name: "incorrect_file", diff --git a/test/integration/cat/test_cat.py b/test/integration/cat/test_cat.py index c3a9b6a65..421969f28 100644 --- a/test/integration/cat/test_cat.py +++ b/test/integration/cat/test_cat.py @@ -12,7 +12,7 @@ ( # Testing with unset .xlog or .snap file. "", - "it is required to specify at least one .xlog or .snap file", + "it is required to specify at least one .xlog/.snap file or directory", ), ( "path-to-non-existent-file", diff --git a/test/integration/pack/test_pack.py b/test/integration/pack/test_pack.py index bba754919..78e3f94db 100644 --- a/test/integration/pack/test_pack.py +++ b/test/integration/pack/test_pack.py @@ -1031,8 +1031,7 @@ def test_pack_incorrect_pack_type(tt_cmd, tmp_path): copy_function=shutil.copy2, ignore_dangling_symlinks=True, dirs_exist_ok=True) - expected_output = "incorrect combination of command parameters: " \ - "invalid argument \"de\" for \"tt pack\"" + expected_output = "invalid argument \"de\" for \"tt pack\"" rc, output = run_command_and_get_output( [tt_cmd, "pack", "de"], diff --git a/test/integration/replicaset/test_replicaset_rebootstrap.py b/test/integration/replicaset/test_replicaset_rebootstrap.py index 205a0a70c..7295be047 100644 --- a/test/integration/replicaset/test_replicaset_rebootstrap.py +++ b/test/integration/replicaset/test_replicaset_rebootstrap.py @@ -240,4 +240,10 @@ def test_rebootstrap_bad_cli_args(tt_cmd, vshard_app): rs_cmd = [tt_cmd, "replicaset", "rebootstrap"] rs_rc, out = run_command_and_get_output(rs_cmd, cwd=vshard_app.env_dir) assert rs_rc != 0 - assert "accepts 1 arg(s), received 0" in out + assert "instance for rebootstrap is not specified" in out + + # Multiple instances. + rs_cmd = [tt_cmd, "replicaset", "rebootstrap", "app:inst1", "app:inst2"] + rs_rc, out = run_command_and_get_output(rs_cmd, cwd=vshard_app.env_dir) + assert rs_rc != 0 + assert "only one instance supported for re-bootstrap" in out From 54fe584f407f2250f6af0aa4d22f5e565cdd3fed Mon Sep 17 00:00:00 2001 From: Mikhail Elhimov Date: Tue, 24 Dec 2024 22:47:42 +0300 Subject: [PATCH 04/13] install/uninstall/search: set program name in the proper place --- cli/cmd/install.go | 4 ---- cli/cmd/search.go | 7 ++++--- cli/cmd/uninstall.go | 9 +-------- cli/install/install.go | 3 ++- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/cli/cmd/install.go b/cli/cmd/install.go index 71cd0157b..fe0e0d89e 100644 --- a/cli/cmd/install.go +++ b/cli/cmd/install.go @@ -17,7 +17,6 @@ func newInstallTtCmd() *cobra.Command { Short: "Install tt", Run: func(cmd *cobra.Command, args []string) { cmdCtx.CommandName = cmd.Name() - installCtx.ProgramName = cmd.Name() err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalInstallModule, args) util.HandleCmdErr(cmd, err) @@ -35,7 +34,6 @@ func newInstallTarantoolCmd() *cobra.Command { Short: "Install tarantool community edition", Run: func(cmd *cobra.Command, args []string) { cmdCtx.CommandName = cmd.Name() - installCtx.ProgramName = cmd.Name() err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalInstallModule, args) util.HandleCmdErr(cmd, err) @@ -58,7 +56,6 @@ func newInstallTarantoolEeCmd() *cobra.Command { Short: "Install tarantool enterprise edition", Run: func(cmd *cobra.Command, args []string) { cmdCtx.CommandName = cmd.Name() - installCtx.ProgramName = cmd.Name() err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalInstallModule, args) util.HandleCmdErr(cmd, err) @@ -84,7 +81,6 @@ func newInstallTarantoolDevCmd() *cobra.Command { " tt run # runs the binary compiled above", Run: func(cmd *cobra.Command, args []string) { cmdCtx.CommandName = cmd.Name() - installCtx.ProgramName = cmd.Name() err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalInstallModule, args) util.HandleCmdErr(cmd, err) diff --git a/cli/cmd/search.go b/cli/cmd/search.go index f2055ac37..f3de09680 100644 --- a/cli/cmd/search.go +++ b/cli/cmd/search.go @@ -22,7 +22,7 @@ func newSearchTtCmd() *cobra.Command { Use: "tt", Short: "Search for available tt versions", Run: func(cmd *cobra.Command, args []string) { - searchCtx.ProgramName = cmd.Name() + cmdCtx.CommandName = cmd.Name() err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalSearchModule, args) util.HandleCmdErr(cmd, err) @@ -39,7 +39,7 @@ func newSearchTarantoolCmd() *cobra.Command { Use: "tarantool", Short: "Search for available tarantool community edition versions", Run: func(cmd *cobra.Command, args []string) { - searchCtx.ProgramName = cmd.Name() + cmdCtx.CommandName = cmd.Name() err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalSearchModule, args) util.HandleCmdErr(cmd, err) @@ -56,7 +56,7 @@ func newSearchTarantoolEeCmd() *cobra.Command { Use: "tarantool-ee", Short: "Search for available tarantool enterprise edition versions", Run: func(cmd *cobra.Command, args []string) { - searchCtx.ProgramName = cmd.Name() + cmdCtx.CommandName = cmd.Name() err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalSearchModule, args) util.HandleCmdErr(cmd, err) @@ -102,6 +102,7 @@ func NewSearchCmd() *cobra.Command { // internalSearchModule is a default search module. func internalSearchModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { var err error + searchCtx.ProgramName = cmdCtx.CommandName if local { err = search.SearchVersionsLocal(cmdCtx, cliOpts, searchCtx.ProgramName) } else { diff --git a/cli/cmd/uninstall.go b/cli/cmd/uninstall.go index 8a2c2b2b4..70d1ac77e 100644 --- a/cli/cmd/uninstall.go +++ b/cli/cmd/uninstall.go @@ -8,10 +8,6 @@ import ( "github.com/tarantool/tt/cli/util" ) -var ( - programName string -) - // newUninstallTtCmd creates a command to install tt. func newUninstallTtCmd() *cobra.Command { var tntCmd = &cobra.Command{ @@ -19,7 +15,6 @@ func newUninstallTtCmd() *cobra.Command { Short: "Uninstall tt", Run: func(cmd *cobra.Command, args []string) { cmdCtx.CommandName = cmd.Name() - programName = cmd.Name() err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, InternalUninstallModule, args) util.HandleCmdErr(cmd, err) @@ -47,7 +42,6 @@ func newUninstallTarantoolCmd() *cobra.Command { Short: "Uninstall tarantool community edition", Run: func(cmd *cobra.Command, args []string) { cmdCtx.CommandName = cmd.Name() - programName = cmd.Name() err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, InternalUninstallModule, args) util.HandleCmdErr(cmd, err) @@ -75,7 +69,6 @@ func newUninstallTarantoolEeCmd() *cobra.Command { Short: "Uninstall tarantool enterprise edition", Run: func(cmd *cobra.Command, args []string) { cmdCtx.CommandName = cmd.Name() - programName = cmd.Name() err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, InternalUninstallModule, args) util.HandleCmdErr(cmd, err) @@ -103,7 +96,6 @@ func newUninstallTarantoolDevCmd() *cobra.Command { Short: "Uninstall tarantool-dev", Run: func(cmd *cobra.Command, args []string) { cmdCtx.CommandName = cmd.Name() - programName = cmd.Name() err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, InternalUninstallModule, args) util.HandleCmdErr(cmd, err) @@ -141,6 +133,7 @@ func InternalUninstallModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { return errNoConfig } + programName := cmdCtx.CommandName programVersion := "" if len(args) == 1 { programVersion = args[0] diff --git a/cli/install/install.go b/cli/install/install.go index 15b67054a..ca120cf17 100644 --- a/cli/install/install.go +++ b/cli/install/install.go @@ -1591,10 +1591,11 @@ func Install(binDir string, includeDir string, installCtx InstallCtx, } func FillCtx(cmdCtx *cmdcontext.CmdCtx, installCtx *InstallCtx, args []string) error { + installCtx.ProgramName = cmdCtx.CommandName installCtx.verbose = cmdCtx.Cli.Verbose installCtx.skipMasterUpdate = cmdCtx.Cli.NoPrompt - if cmdCtx.CommandName == search.ProgramDev { + if installCtx.ProgramName == search.ProgramDev { installCtx.buildDir = args[0] return nil } From 88547980bf200cac951b296d16459841901a79cc Mon Sep 17 00:00:00 2001 From: Mikhail Elhimov Date: Fri, 7 Mar 2025 00:30:39 +0300 Subject: [PATCH 05/13] module: restore external module arguments in the proper place --- cli/cmd/completion.go | 1 - cli/cmd/help.go | 1 - cli/cmd/version.go | 1 - cli/modules/run.go | 10 +++++----- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/cli/cmd/completion.go b/cli/cmd/completion.go index 936a830ce..9906acd85 100644 --- a/cli/cmd/completion.go +++ b/cli/cmd/completion.go @@ -20,7 +20,6 @@ func NewCompletionCmd() *cobra.Command { ValidArgs: []string{"bash", "zsh"}, Run: func(cmd *cobra.Command, args []string) { cmdCtx.CommandName = cmd.Name() - args = modules.GetDefaultCmdArgs(cmd.Name()) err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalCompletionCmd, args) util.HandleCmdErr(cmd, err) diff --git a/cli/cmd/help.go b/cli/cmd/help.go index fbaaf3e98..e33e651d2 100644 --- a/cli/cmd/help.go +++ b/cli/cmd/help.go @@ -32,7 +32,6 @@ func configureHelpCommand(cmdCtx *cmdcontext.CmdCtx, rootCmd *cobra.Command) err return } - args = modules.GetDefaultCmdArgs("help") err := modules.RunCmd(cmdCtx, "tt help", &modulesInfo, getInternalHelpFunc(cmd, defaultHelp), args) if err != nil { diff --git a/cli/cmd/version.go b/cli/cmd/version.go index 5801eeb89..f04bfb055 100644 --- a/cli/cmd/version.go +++ b/cli/cmd/version.go @@ -22,7 +22,6 @@ func NewVersionCmd() *cobra.Command { Short: "Show Tarantool CLI version information", Run: func(cmd *cobra.Command, args []string) { cmdCtx.CommandName = cmd.Name() - args = modules.GetDefaultCmdArgs(cmd.Name()) err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalVersionModule, args) util.HandleCmdErr(cmd, err) diff --git a/cli/modules/run.go b/cli/modules/run.go index 1d5e2ff8d..d202d4b5f 100644 --- a/cli/modules/run.go +++ b/cli/modules/run.go @@ -4,10 +4,10 @@ import ( "fmt" "os" "os/exec" + "slices" "github.com/apex/log" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/util" ) // InternalFunc is a type of function that implements @@ -41,17 +41,17 @@ func RunCmd(cmdCtx *cmdcontext.CmdCtx, cmdPath string, modulesInfo *ModulesInfo, return fmt.Errorf("integrity check failed for %q: %w", info.ExternalPath, err) } f.Close() - if rc := RunExec(info.ExternalPath, args); rc != 0 { + if rc := RunExec(info.ExternalPath, getExternalCmdArgs(cmdCtx.CommandName)); rc != 0 { os.Exit(rc) } return nil } -// GetDefaultCmdArgs returns all arguments from the command line +// getExternalCmdArgs returns all arguments from the command line // to external module that come after the command name. -func GetDefaultCmdArgs(cmdName string) []string { - cmdNameIndexInArgs := util.Find(os.Args, cmdName) +func getExternalCmdArgs(cmdName string) []string { + cmdNameIndexInArgs := slices.Index(os.Args, cmdName) return os.Args[cmdNameIndexInArgs+1:] } From 7a7758baa4a89332d90a93231d1bbe82091ca8a1 Mon Sep 17 00:00:00 2001 From: Mikhail Elhimov Date: Tue, 24 Dec 2024 23:23:15 +0300 Subject: [PATCH 06/13] remove code duplication in Command.Run functions Closes #1072 --- cli/cmd/aeon.go | 8 +--- cli/cmd/binaries.go | 14 +------ cli/cmd/build.go | 10 +---- cli/cmd/cat.go | 8 +--- cli/cmd/cfg_dump.go | 9 +---- cli/cmd/check.go | 9 +---- cli/cmd/clean.go | 9 +---- cli/cmd/cluster.go | 74 +++++++---------------------------- cli/cmd/common.go | 13 +++++++ cli/cmd/completion.go | 10 +---- cli/cmd/connect.go | 8 +--- cli/cmd/coredump.go | 37 ++++++++---------- cli/cmd/create.go | 7 +--- cli/cmd/daemon.go | 34 ++++------------ cli/cmd/download.go | 9 +---- cli/cmd/enable.go | 8 +--- cli/cmd/env.go | 8 +--- cli/cmd/init.go | 8 +--- cli/cmd/install.go | 36 ++++------------- cli/cmd/instances.go | 11 +----- cli/cmd/kill.go | 8 +--- cli/cmd/log.go | 9 +---- cli/cmd/logrotate.go | 9 +---- cli/cmd/pack.go | 14 ++----- cli/cmd/play.go | 8 +--- cli/cmd/replicaset.go | 91 ++++++++----------------------------------- cli/cmd/restart.go | 10 +---- cli/cmd/rocks.go | 9 +---- cli/cmd/run.go | 11 +----- cli/cmd/search.go | 29 +++----------- cli/cmd/start.go | 9 +---- cli/cmd/status.go | 9 +---- cli/cmd/stop.go | 10 +---- cli/cmd/uninstall.go | 38 ++++-------------- cli/cmd/version.go | 9 +---- 35 files changed, 126 insertions(+), 477 deletions(-) diff --git a/cli/cmd/aeon.go b/cli/cmd/aeon.go index 8fca44eee..71f6f6dc3 100644 --- a/cli/cmd/aeon.go +++ b/cli/cmd/aeon.go @@ -13,7 +13,6 @@ import ( aeoncmd "github.com/tarantool/tt/cli/aeon/cmd" "github.com/tarantool/tt/cli/cmdcontext" "github.com/tarantool/tt/cli/console" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/running" "github.com/tarantool/tt/cli/util" "github.com/tarantool/tt/lib/cluster" @@ -37,12 +36,7 @@ func newAeonConnectCmd() *cobra.Command { tt aeon connect http://localhost:50051 tt aeon connect unix:// tt aeon connect /path/to/config INSTANCE_NAME>`, - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalAeonConnect, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalAeonConnect), Args: cobra.MatchAll(cobra.RangeArgs(1, 2), aeonConnectValidateArgs), } diff --git a/cli/cmd/binaries.go b/cli/cmd/binaries.go index a52ab444b..552739f25 100644 --- a/cli/cmd/binaries.go +++ b/cli/cmd/binaries.go @@ -6,9 +6,7 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/binary" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/search" - "github.com/tarantool/tt/cli/util" "golang.org/x/exp/slices" ) @@ -43,21 +41,13 @@ You will need to choose version using arrow keys in your console. # Switch with program and version. $ tt binaries switch tarantool 2.10.4`, - Run: func(cmd *cobra.Command, args []string) { - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalSwitchModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalSwitchModule), Args: cobra.MatchAll(cobra.MaximumNArgs(2), binariesSwitchValidateArgs), } var listCmd = &cobra.Command{ Use: "list", Short: "Show a list of installed binaries and their versions.", - Run: func(cmd *cobra.Command, args []string) { - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalListModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalListModule), } binariesCmd.AddCommand(switchCmd) binariesCmd.AddCommand(listCmd) diff --git a/cli/cmd/build.go b/cli/cmd/build.go index 02312b06d..cdf0349a7 100644 --- a/cli/cmd/build.go +++ b/cli/cmd/build.go @@ -4,9 +4,7 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/build" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/running" - "github.com/tarantool/tt/cli/util" ) var ( @@ -19,12 +17,8 @@ func NewBuildCmd() *cobra.Command { var buildCmd = &cobra.Command{ Use: "build [ | ] [flags]", Short: `Build an application (default ".")`, - Run: func(cmd *cobra.Command, args []string) { - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalBuildModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.MaximumNArgs(1), + Run: TtModuleCmdRun(internalBuildModule), + Args: cobra.MaximumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, args []string, diff --git a/cli/cmd/cat.go b/cli/cmd/cat.go index 6ac8b969b..edb1b69cf 100644 --- a/cli/cmd/cat.go +++ b/cli/cmd/cat.go @@ -12,7 +12,6 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/checkpoint" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/util" "github.com/tarantool/tt/cli/version" ) @@ -34,12 +33,7 @@ func NewCatCmd() *cobra.Command { var catCmd = &cobra.Command{ Use: "cat ...", Short: "Print into stdout the contents of .snap/.xlog FILE(s)", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalCatModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalCatModule), Example: "tt cat /path/to/file.snap /path/to/file.xlog /path/to/dir/ " + "--timestamp 2024-11-13T14:02:36.818700000+00:00\n" + " tt cat /path/to/file.snap /path/to/file.xlog /path/to/dir/ " + diff --git a/cli/cmd/cfg_dump.go b/cli/cmd/cfg_dump.go index 10cf56eb0..066493b1c 100644 --- a/cli/cmd/cfg_dump.go +++ b/cli/cmd/cfg_dump.go @@ -6,8 +6,6 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cfg" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" - "github.com/tarantool/tt/cli/util" ) var ( @@ -19,12 +17,7 @@ func NewDumpCmd() *cobra.Command { var dumpCmd = &cobra.Command{ Use: "dump", Short: "Print environment configuration", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalDumpModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalDumpModule), } dumpCmd.Flags().BoolVarP(&rawDump, "raw", "r", false, diff --git a/cli/cmd/check.go b/cli/cmd/check.go index 26d0727c6..5b06e4d8a 100644 --- a/cli/cmd/check.go +++ b/cli/cmd/check.go @@ -4,9 +4,7 @@ import ( "github.com/apex/log" "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/running" - "github.com/tarantool/tt/cli/util" ) // NewCheckCmd creates a new check command. @@ -14,12 +12,7 @@ func NewCheckCmd() *cobra.Command { var checkCmd = &cobra.Command{ Use: "check []", Short: "Check an application file for syntax errors", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalCheckModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalCheckModule), } return checkCmd diff --git a/cli/cmd/clean.go b/cli/cmd/clean.go index 3327602a0..d500db68b 100644 --- a/cli/cmd/clean.go +++ b/cli/cmd/clean.go @@ -9,7 +9,6 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmd/internal" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/process_utils" "github.com/tarantool/tt/cli/running" "github.com/tarantool/tt/cli/util" @@ -23,11 +22,7 @@ func NewCleanCmd() *cobra.Command { var cleanCmd = &cobra.Command{ Use: "clean [INSTANCE_NAME]", Short: "Clean instance(s) files", - Run: func(cmd *cobra.Command, args []string) { - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalCleanModule, - args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalCleanModule), ValidArgsFunction: func( cmd *cobra.Command, args []string, @@ -83,7 +78,7 @@ func clean(run *running.InstanceCtx) error { } if confirm || forceRemove { - for file, _ := range removeFiles { + for file := range removeFiles { err = os.Remove(file) if err != nil { return err diff --git a/cli/cmd/cluster.go b/cli/cmd/cluster.go index 62323f7bc..b284ec483 100644 --- a/cli/cmd/cluster.go +++ b/cli/cmd/cluster.go @@ -13,7 +13,6 @@ import ( clustercmd "github.com/tarantool/tt/cli/cluster/cmd" "github.com/tarantool/tt/cli/cmd/internal" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/replicaset" "github.com/tarantool/tt/cli/running" "github.com/tarantool/tt/cli/util" @@ -146,13 +145,8 @@ func newClusterReplicasetCmd() *cobra.Command { DisableFlagsInUseLine: true, Short: "Promote an instance", Long: "Promote an instance\n\n" + clusterUriHelp, - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalClusterReplicasetPromoteModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(2), + Run: TtModuleCmdRun(internalClusterReplicasetPromoteModule), + Args: cobra.ExactArgs(2), } promoteCmd.Flags().StringVarP(&promoteCtx.Username, "username", "u", "", "username (used as etcd/tarantool config storage credentials)") @@ -167,13 +161,8 @@ func newClusterReplicasetCmd() *cobra.Command { DisableFlagsInUseLine: true, Short: "Demote an instance", Long: "Demote an instance\n\n" + clusterUriHelp, - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalClusterReplicasetDemoteModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(2), + Run: TtModuleCmdRun(internalClusterReplicasetDemoteModule), + Args: cobra.ExactArgs(2), } demoteCmd.Flags().StringVarP(&demoteCtx.Username, "username", "u", "", @@ -189,13 +178,8 @@ func newClusterReplicasetCmd() *cobra.Command { DisableFlagsInUseLine: true, Short: "Expel an instance", Long: "Expel an instance\n\n" + clusterUriHelp, - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalClusterReplicasetExpelModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(2), + Run: TtModuleCmdRun(internalClusterReplicasetExpelModule), + Args: cobra.ExactArgs(2), } expelCmd.Flags().StringVarP(&expelCtx.Username, "username", "u", "", @@ -215,12 +199,7 @@ func newClusterReplicasetCmd() *cobra.Command { Use: "add [flags]", Short: "Add role to an instance, group or instance", Long: "Add role to an instance, group or instance\n\n" + clusterUriHelp, - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalClusterReplicasetRolesAddModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalClusterReplicasetRolesAddModule), Example: "tt cluster replicaset roles add http://user:pass@localhost:3301" + " roles.metrics-export --instance_name master", Args: cobra.ExactArgs(2), @@ -247,12 +226,7 @@ func newClusterReplicasetCmd() *cobra.Command { Use: "remove [flags]", Short: "Remove role from instance, group, instance or globally", Long: "Remove role from instance, group, instance or globally\n\n" + clusterUriHelp, - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalClusterReplicasetRolesRemoveModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalClusterReplicasetRolesRemoveModule), Example: "tt cluster replicaset roles remove http://user:pass@localhost:3301" + " roles.metrics-export --instance_name master", Args: cobra.ExactArgs(2), @@ -299,13 +273,8 @@ func newClusterFailoverCmd() *cobra.Command { Short: "Switch master instance", Long: "Switch master instance\n\n" + failoverUriHelp, Example: "tt cluster failover switch http://localhost:2379/app instance_name", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalClusterFailoverSwitchModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(2), + Run: TtModuleCmdRun(internalClusterFailoverSwitchModule), + Args: cobra.ExactArgs(2), } switchCmd.Flags().StringVarP(&switchCtx.Username, "username", "u", "", @@ -322,13 +291,8 @@ func newClusterFailoverCmd() *cobra.Command { DisableFlagsInUseLine: true, Short: "Show master switching status", Long: "Show master switching status\n\n" + failoverUriHelp, - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalClusterFailoverSwitchStatusModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(2), + Run: TtModuleCmdRun(internalClusterFailoverSwitchStatusModule), + Args: cobra.ExactArgs(2), } cmd.AddCommand(switchCmd) @@ -352,12 +316,7 @@ func NewClusterCmd() *cobra.Command { " tt cluster show application_name:instance_name\n" + " tt cluster show https://user:pass@localhost:2379/tt\n" + " tt cluster show https://user:pass@localhost:2379/tt?name=instance", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalClusterShowModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalClusterShowModule), Args: cobra.ExactArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -399,12 +358,7 @@ func NewClusterCmd() *cobra.Command { " tt cluster publish --group group --replicaset replicaset " + "https://user:pass@localhost:2379/tt?name=instance " + "instance.yaml", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalClusterPublishModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalClusterPublishModule), Args: cobra.ExactArgs(2), ValidArgsFunction: func( cmd *cobra.Command, diff --git a/cli/cmd/common.go b/cli/cmd/common.go index d851991a3..0fcc484b6 100644 --- a/cli/cmd/common.go +++ b/cli/cmd/common.go @@ -5,8 +5,11 @@ import ( "fmt" "io" + "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" "github.com/tarantool/tt/cli/configure" + "github.com/tarantool/tt/cli/modules" + "github.com/tarantool/tt/cli/util" libcluster "github.com/tarantool/tt/lib/cluster" "github.com/tarantool/tt/lib/integrity" ) @@ -67,3 +70,13 @@ func createDataCollectorsAndDataPublishers(ctx integrity.IntegrityCtx, } return collectors, publishers, err } + +func TtModuleCmdRun(internalModule modules.InternalFunc) func(*cobra.Command, []string) { + return func(cmd *cobra.Command, args []string) { + cmdCtx.CommandName = cmd.Name() + err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalModule, args) + if err != nil { + util.HandleCmdErr(cmd, err) + } + } +} diff --git a/cli/cmd/completion.go b/cli/cmd/completion.go index 9906acd85..ad92cb4d7 100644 --- a/cli/cmd/completion.go +++ b/cli/cmd/completion.go @@ -9,7 +9,6 @@ import ( "github.com/tarantool/tt/cli/cmdcontext" "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/rocks" - "github.com/tarantool/tt/cli/util" ) // NewCompletionCmd creates a new completion command. @@ -18,13 +17,8 @@ func NewCompletionCmd() *cobra.Command { Use: "completion ", Short: "Generate autocomplete for a specified shell. Supported shell type: bash | zsh", ValidArgs: []string{"bash", "zsh"}, - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalCompletionCmd, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), + Run: TtModuleCmdRun(internalCompletionCmd), + Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), Example: ` # Enable auto-completion in current bash shell. diff --git a/cli/cmd/connect.go b/cli/cmd/connect.go index e91b7dc52..43affd99d 100644 --- a/cli/cmd/connect.go +++ b/cli/cmd/connect.go @@ -13,7 +13,6 @@ import ( "github.com/tarantool/tt/cli/connect" "github.com/tarantool/tt/cli/connector" "github.com/tarantool/tt/cli/formatter" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/running" "github.com/tarantool/tt/cli/util" libconnect "github.com/tarantool/tt/lib/connect" @@ -61,12 +60,7 @@ func NewConnectCmd() *cobra.Command { "You could pass command line arguments to the interpreted SCRIPT" + " or COMMAND passed via -f flag:\n\n" + `echo "print(...)" | tt connect user:pass@localhost:3013 -f- 1, 2, 3`, - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalConnectModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalConnectModule), Args: cobra.MinimumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, diff --git a/cli/cmd/coredump.go b/cli/cmd/coredump.go index bc578568e..1d88f9456 100644 --- a/cli/cmd/coredump.go +++ b/cli/cmd/coredump.go @@ -4,8 +4,6 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" "github.com/tarantool/tt/cli/coredump" - "github.com/tarantool/tt/cli/modules" - "github.com/tarantool/tt/cli/util" ) var ( @@ -26,13 +24,8 @@ func NewCoredumpCmd() *cobra.Command { var packCmd = &cobra.Command{ Use: "pack COREDUMP", Short: "pack tarantool coredump into tar.gz archive", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalCoredumpPackModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(1), + Run: TtModuleCmdRun(internalCoredumpPackModule), + Args: cobra.ExactArgs(1), } packCmd.Flags().StringVarP(&coredumpPackExecutable, "executable", "e", "", "Tarantool executable path") @@ -48,23 +41,15 @@ func NewCoredumpCmd() *cobra.Command { var unpackCmd = &cobra.Command{ Use: "unpack ARCHIVE", Short: "unpack tarantool coredump tar.gz archive", - Run: func(cmd *cobra.Command, args []string) { - if err := coredump.Unpack(args[0]); err != nil { - util.HandleCmdErr(cmd, err) - } - }, - Args: cobra.ExactArgs(1), + Run: TtModuleCmdRun(internalCoredumpUnpackModule), + Args: cobra.ExactArgs(1), } var inspectCmd = &cobra.Command{ Use: "inspect {ARCHIVE|DIRECTORY}", Short: "inspect tarantool coredump", - Run: func(cmd *cobra.Command, args []string) { - if err := coredump.Inspect(args[0], coredumpInspectSourceDir); err != nil { - util.HandleCmdErr(cmd, err) - } - }, - Args: cobra.ExactArgs(1), + Run: TtModuleCmdRun(internalCoredumpInspectModule), + Args: cobra.ExactArgs(1), } inspectCmd.Flags().StringVarP(&coredumpInspectSourceDir, "sourcedir", "s", "", "Source directory") @@ -91,3 +76,13 @@ func internalCoredumpPackModule(cmdCtx *cmdcontext.CmdCtx, args []string) error coredumpPackTime, ) } + +// internalCoredumpUnpackModule is a default "unpack" command for the coredump module. +func internalCoredumpUnpackModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { + return coredump.Unpack(args[0]) +} + +// internalCoredumpInspectModule is a default "inspect" command for the coredump module. +func internalCoredumpInspectModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { + return coredump.Inspect(args[0], coredumpInspectSourceDir) +} diff --git a/cli/cmd/create.go b/cli/cmd/create.go index b83cb2352..b603c191d 100644 --- a/cli/cmd/create.go +++ b/cli/cmd/create.go @@ -10,7 +10,6 @@ import ( "github.com/tarantool/tt/cli/create" "github.com/tarantool/tt/cli/create/builtin_templates" create_ctx "github.com/tarantool/tt/cli/create/context" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/util" ) @@ -32,11 +31,7 @@ func NewCreateCmd() *cobra.Command { var createCmd = &cobra.Command{ Use: "create [flags]", Short: "Create an application from a template", - Run: func(cmd *cobra.Command, args []string) { - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalCreateModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalCreateModule), Args: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { return fmt.Errorf("requires template name argument") diff --git a/cli/cmd/daemon.go b/cli/cmd/daemon.go index 1818a7ab1..d35823236 100644 --- a/cli/cmd/daemon.go +++ b/cli/cmd/daemon.go @@ -6,9 +6,7 @@ import ( "github.com/tarantool/tt/cli/cmdcontext" "github.com/tarantool/tt/cli/configure" "github.com/tarantool/tt/cli/daemon" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/process_utils" - "github.com/tarantool/tt/cli/util" ) // NewDaemonCmd creates daemon command. @@ -21,45 +19,29 @@ func NewDaemonCmd() *cobra.Command { var startCmd = &cobra.Command{ Use: "start", Short: "start tt daemon", - Run: func(cmd *cobra.Command, args []string) { - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalDaemonStartModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(0), + Run: TtModuleCmdRun(internalDaemonStartModule), + Args: cobra.ExactArgs(0), } var stopCmd = &cobra.Command{ Use: "stop", Short: "stop tt daemon", - Run: func(cmd *cobra.Command, args []string) { - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalDaemonStopModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(0), + Run: TtModuleCmdRun(internalDaemonStopModule), + Args: cobra.ExactArgs(0), } var statusCmd = &cobra.Command{ Use: "status", Short: "status of tt daemon", - Run: func(cmd *cobra.Command, args []string) { - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalDaemonStatusModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(0), + Run: TtModuleCmdRun(internalDaemonStatusModule), + Args: cobra.ExactArgs(0), } var restartCmd = &cobra.Command{ Use: "restart", Short: "restart tt daemon", - Run: func(cmd *cobra.Command, args []string) { - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalDaemonRestartModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(0), + Run: TtModuleCmdRun(internalDaemonRestartModule), + Args: cobra.ExactArgs(0), } daemonSubCommands := []*cobra.Command{ diff --git a/cli/cmd/download.go b/cli/cmd/download.go index 9eed8594b..292c9d55b 100644 --- a/cli/cmd/download.go +++ b/cli/cmd/download.go @@ -6,8 +6,6 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" "github.com/tarantool/tt/cli/download" - "github.com/tarantool/tt/cli/modules" - "github.com/tarantool/tt/cli/util" ) var ( @@ -24,12 +22,7 @@ func NewDownloadCmd() *cobra.Command { $ tt download gc64-3.0.0-0-gf58f7d82a-r23 # Download Tarantool SDK development build to the /tmp directory. $ tt download gc64-3.0.0-beta1-2-gcbb569b4c-r612 --dev --directory-prefix /tmp`, - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalDownloadModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalDownloadModule), Args: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { return errors.New("to download Tarantool SDK, you need to specify the version") diff --git a/cli/cmd/enable.go b/cli/cmd/enable.go index 76f0aac94..3fd38fcb7 100644 --- a/cli/cmd/enable.go +++ b/cli/cmd/enable.go @@ -7,8 +7,6 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" "github.com/tarantool/tt/cli/enable" - "github.com/tarantool/tt/cli/modules" - "github.com/tarantool/tt/cli/util" ) // NewEnableCmd creates a new enable command. @@ -22,11 +20,7 @@ func NewEnableCmd() *cobra.Command { $ tt enable Users/myuser/my_scripts/script.lua # Create a symbolic link in 'instances_enabled' directory to an application directory. $ tt enable ../myuser/my_cool_app`, - Run: func(cmd *cobra.Command, args []string) { - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalEnableModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalEnableModule), Args: func(cmd *cobra.Command, args []string) error { if len(args) != 1 { return errors.New("provide the path to a script or application directory") diff --git a/cli/cmd/env.go b/cli/cmd/env.go index e40b2c65f..8a4527d32 100644 --- a/cli/cmd/env.go +++ b/cli/cmd/env.go @@ -6,8 +6,6 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" "github.com/tarantool/tt/cli/env" - "github.com/tarantool/tt/cli/modules" - "github.com/tarantool/tt/cli/util" ) // NewEnvCmd creates env command. @@ -17,11 +15,7 @@ func NewEnvCmd() *cobra.Command { Short: "Add current environment binaries location to the PATH variable", Long: "Add current environment binaries location to the PATH variable.\n" + "Also sets TARANTOOL_DIR variable.", - Run: func(cmd *cobra.Command, args []string) { - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalEnvModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalEnvModule), } return envCmd diff --git a/cli/cmd/init.go b/cli/cmd/init.go index 0907ccafe..6d4d447b9 100644 --- a/cli/cmd/init.go +++ b/cli/cmd/init.go @@ -7,8 +7,6 @@ import ( "github.com/tarantool/tt/cli/cmdcontext" "github.com/tarantool/tt/cli/configure" init_pkg "github.com/tarantool/tt/cli/init" - "github.com/tarantool/tt/cli/modules" - "github.com/tarantool/tt/cli/util" ) var initCtx init_pkg.InitCtx @@ -20,11 +18,7 @@ func NewInitCmd() *cobra.Command { var initCmd = &cobra.Command{ Use: "init [flags]", Short: "Create tt environment config for application in current directory", - Run: func(cmd *cobra.Command, args []string) { - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalInitModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalInitModule), } initCmd.Flags().BoolVarP(&initCtx.SkipConfig, "skip-config", "", false, diff --git a/cli/cmd/install.go b/cli/cmd/install.go index fe0e0d89e..9d03c15a6 100644 --- a/cli/cmd/install.go +++ b/cli/cmd/install.go @@ -4,8 +4,6 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" "github.com/tarantool/tt/cli/install" - "github.com/tarantool/tt/cli/modules" - "github.com/tarantool/tt/cli/util" ) var installCtx install.InstallCtx @@ -15,13 +13,8 @@ func newInstallTtCmd() *cobra.Command { var tntCmd = &cobra.Command{ Use: "tt [version|commit hash|pull-request]", Short: "Install tt", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalInstallModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.MaximumNArgs(1), + Run: TtModuleCmdRun(internalInstallModule), + Args: cobra.MaximumNArgs(1), } return tntCmd @@ -32,13 +25,8 @@ func newInstallTarantoolCmd() *cobra.Command { var tntCmd = &cobra.Command{ Use: "tarantool [version|commit hash|pull-request]", Short: "Install tarantool community edition", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalInstallModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.MaximumNArgs(1), + Run: TtModuleCmdRun(internalInstallModule), + Args: cobra.MaximumNArgs(1), } tntCmd.Flags().BoolVarP(&installCtx.BuildInDocker, "use-docker", "", false, @@ -54,13 +42,8 @@ func newInstallTarantoolEeCmd() *cobra.Command { var tntCmd = &cobra.Command{ Use: "tarantool-ee [version]", Short: "Install tarantool enterprise edition", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalInstallModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.MaximumNArgs(1), + Run: TtModuleCmdRun(internalInstallModule), + Args: cobra.MaximumNArgs(1), } tntCmd.Flags().BoolVar(&installCtx.DevBuild, "dev", false, "install development build") @@ -79,12 +62,7 @@ func newInstallTarantoolDevCmd() *cobra.Command { " make -j16 -C ~/src/tarantool/build\n" + " tt install tarantool-dev ~/src/tarantool/build\n" + " tt run # runs the binary compiled above", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalInstallModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalInstallModule), Args: cobra.ExactArgs(1), } diff --git a/cli/cmd/instances.go b/cli/cmd/instances.go index 272f54502..3db1968dd 100644 --- a/cli/cmd/instances.go +++ b/cli/cmd/instances.go @@ -4,8 +4,6 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" "github.com/tarantool/tt/cli/instances" - "github.com/tarantool/tt/cli/modules" - "github.com/tarantool/tt/cli/util" ) // NewInstancesCmd creates instances command. @@ -13,13 +11,8 @@ func NewInstancesCmd() *cobra.Command { var instancesCmd = &cobra.Command{ Use: "instances", Short: "Show list of enabled applications", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalInstancesModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(0), + Run: TtModuleCmdRun(internalInstancesModule), + Args: cobra.ExactArgs(0), } return instancesCmd diff --git a/cli/cmd/kill.go b/cli/cmd/kill.go index c4d3d10b4..864da5a07 100644 --- a/cli/cmd/kill.go +++ b/cli/cmd/kill.go @@ -9,7 +9,6 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmd/internal" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/running" "github.com/tarantool/tt/cli/util" ) @@ -22,12 +21,7 @@ func NewKillCmd() *cobra.Command { var killCmd = &cobra.Command{ Use: "kill [ | ]", Short: "Kill tarantool instance(s)", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalKillModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalKillModule), ValidArgsFunction: func( cmd *cobra.Command, args []string, diff --git a/cli/cmd/log.go b/cli/cmd/log.go index eaaa2f8d2..21ad9ef71 100644 --- a/cli/cmd/log.go +++ b/cli/cmd/log.go @@ -11,10 +11,8 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmd/internal" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/running" "github.com/tarantool/tt/cli/tail" - "github.com/tarantool/tt/cli/util" ) var logOpts struct { @@ -27,12 +25,7 @@ func NewLogCmd() *cobra.Command { var logCmd = &cobra.Command{ Use: "log [ | ] [flags]", Short: `Get logs of instance(s)`, - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalLogModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalLogModule), ValidArgsFunction: func( cmd *cobra.Command, args []string, diff --git a/cli/cmd/logrotate.go b/cli/cmd/logrotate.go index cf267c42a..3a351e397 100644 --- a/cli/cmd/logrotate.go +++ b/cli/cmd/logrotate.go @@ -5,9 +5,7 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmd/internal" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/running" - "github.com/tarantool/tt/cli/util" ) // NewLogrotateCmd creates logrotate command. @@ -15,12 +13,7 @@ func NewLogrotateCmd() *cobra.Command { var logrotateCmd = &cobra.Command{ Use: "logrotate [ | ]", Short: "Rotate logs of a started tarantool instance(s)", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalLogrotateModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalLogrotateModule), ValidArgsFunction: func( cmd *cobra.Command, args []string, diff --git a/cli/cmd/pack.go b/cli/cmd/pack.go index 7c6bdd8a8..bc9a565d1 100644 --- a/cli/cmd/pack.go +++ b/cli/cmd/pack.go @@ -8,9 +8,7 @@ import ( "github.com/apex/log" "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/pack" - "github.com/tarantool/tt/cli/util" "github.com/tarantool/tt/lib/integrity" ) @@ -18,19 +16,15 @@ import ( var packCtx = &pack.PackCtx{} func NewPackCmd() *cobra.Command { - var packCmd = &cobra.Command{Use: "pack TYPE [flags] ..", + var packCmd = &cobra.Command{ + Use: "pack TYPE [flags] ..", Short: "Pack application into a distributable bundle", Long: `Pack application into a distributable bundle The supported types are: tgz, deb, rpm`, ValidArgs: []string{"tgz", "deb", "rpm"}, - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalPackModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), + Run: TtModuleCmdRun(internalPackModule), + Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), } // Common flags. diff --git a/cli/cmd/play.go b/cli/cmd/play.go index d3d8db10b..02139f3ce 100644 --- a/cli/cmd/play.go +++ b/cli/cmd/play.go @@ -12,7 +12,6 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/checkpoint" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/running" "github.com/tarantool/tt/cli/util" "github.com/tarantool/tt/cli/version" @@ -51,12 +50,7 @@ func NewPlayCmd() *cobra.Command { var playCmd = &cobra.Command{ Use: "play ( | | ) ...", Short: "Play the contents of .snap/.xlog FILE(s) to another Tarantool instance", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalPlayModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalPlayModule), Example: "tt play localhost:3013 /path/to/file.snap /path/to/file.xlog " + "/path/to/dir/ --timestamp 2024-11-13T14:02:36.818700000+00:00\n" + " tt play app:instance001 /path/to/file.snap /path/to/file.xlog " + diff --git a/cli/cmd/replicaset.go b/cli/cmd/replicaset.go index 03443083b..240666ac6 100644 --- a/cli/cmd/replicaset.go +++ b/cli/cmd/replicaset.go @@ -11,11 +11,9 @@ import ( "github.com/tarantool/tt/cli/cmdcontext" "github.com/tarantool/tt/cli/connect" "github.com/tarantool/tt/cli/connector" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/replicaset" replicasetcmd "github.com/tarantool/tt/cli/replicaset/cmd" "github.com/tarantool/tt/cli/running" - "github.com/tarantool/tt/cli/util" libconnect "github.com/tarantool/tt/lib/connect" "github.com/tarantool/tt/lib/integrity" ) @@ -66,12 +64,7 @@ func newUpgradeCmd() *cobra.Command { Short: "Upgrade tarantool cluster", Long: "Upgrade tarantool cluster.\n\n" + libconnect.EnvCredentialsHelp + "\n\n", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalReplicasetUpgradeModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalReplicasetUpgradeModule), Args: cobra.ExactArgs(1), } @@ -108,12 +101,7 @@ func newDowngradeCmd() *cobra.Command { Short: "Downgrade tarantool cluster", Long: "Downgrade tarantool cluster.\n\n" + libconnect.EnvCredentialsHelp + "\n\n", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalReplicasetDowngradeModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalReplicasetDowngradeModule), Args: cobra.MatchAll(cobra.ExactArgs(2), validateVersion(1)), } @@ -138,12 +126,7 @@ func newStatusCmd() *cobra.Command { Short: "Show a replicaset status", Long: "Show a replicaset status.\n\n" + libconnect.EnvCredentialsHelp + "\n\n", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalReplicasetStatusModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalReplicasetStatusModule), Args: cobra.ExactArgs(1), } @@ -162,12 +145,7 @@ func newPromoteCmd() *cobra.Command { Short: "Promote an instance", Long: "Promote an instance.\n\n" + libconnect.EnvCredentialsHelp + "\n\n", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalReplicasetPromoteModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalReplicasetPromoteModule), Args: cobra.ExactArgs(1), } @@ -191,13 +169,8 @@ func newDemoteCmd() *cobra.Command { DisableFlagsInUseLine: true, Short: "Demote an instance", Long: "Demote an instance.", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalReplicasetDemoteModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(1), + Run: TtModuleCmdRun(internalReplicasetDemoteModule), + Args: cobra.ExactArgs(1), } addOrchestratorFlags(cmd) @@ -215,13 +188,8 @@ func newExpelCmd() *cobra.Command { "", Short: "Expel an instance from a replicaset", Long: "Expel an instance from a replicaset.", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalReplicasetExpelModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(1), + Run: TtModuleCmdRun(internalReplicasetExpelModule), + Args: cobra.ExactArgs(1), } addOrchestratorFlags(cmd) @@ -239,13 +207,8 @@ func newBootstrapCmd() *cobra.Command { Use: "bootstrap [--timeout secs] [flags] ", Short: "Bootstrap an application or instance", Long: "Bootstrap an application or instance.", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalReplicasetBootstrapModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(1), + Run: TtModuleCmdRun(internalReplicasetBootstrapModule), + Args: cobra.ExactArgs(1), } addOrchestratorFlags(cmd) @@ -271,12 +234,7 @@ func newBootstrapVShardCmd() *cobra.Command { Short: "Bootstrap vshard in the cluster", Long: "Bootstrap vshard in the cluster.\n\n" + libconnect.EnvCredentialsHelp + "\n\n", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalReplicasetBootstrapVShardModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalReplicasetBootstrapVShardModule), Args: cobra.ExactArgs(1), } @@ -307,13 +265,8 @@ func newRebootstrapCmd() *cobra.Command { Use: "rebootstrap ", DisableFlagsInUseLine: true, Short: "Re-bootstraps an instance", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalReplicasetRebootstrapModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: replicasetRebootstrapValidateArgs, + Run: TtModuleCmdRun(internalReplicasetRebootstrapModule), + Args: replicasetRebootstrapValidateArgs, } cmd.Flags().BoolVarP(&rebootstrapConfirmed, "yes", "y", false, @@ -340,13 +293,8 @@ func newRolesAddCmd() *cobra.Command { " [flags]", Short: "Adds a role for Cartridge and Tarantool 3 orchestrator", Long: "Adds a role for Cartridge and Tarantool 3 orchestrator", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalReplicasetRolesAddModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(2), + Run: TtModuleCmdRun(internalReplicasetRolesAddModule), + Args: cobra.ExactArgs(2), } cmd.Flags().StringVarP(&replicasetReplicasetName, "replicaset", "r", "", @@ -378,13 +326,8 @@ func newRolesRemoveCmd() *cobra.Command { " [flags]", Short: "Removes a role for Cartridge and Tarantool 3 orchestrator", Long: "Removes a role for Cartridge and Tarantool 3 orchestrator", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalReplicasetRolesRemoveModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(2), + Run: TtModuleCmdRun(internalReplicasetRolesRemoveModule), + Args: cobra.ExactArgs(2), } cmd.Flags().StringVarP(&replicasetReplicasetName, "replicaset", "r", "", diff --git a/cli/cmd/restart.go b/cli/cmd/restart.go index 65264d0df..4a780348a 100644 --- a/cli/cmd/restart.go +++ b/cli/cmd/restart.go @@ -8,7 +8,6 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmd/internal" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/running" "github.com/tarantool/tt/cli/util" ) @@ -22,13 +21,8 @@ func NewRestartCmd() *cobra.Command { var restartCmd = &cobra.Command{ Use: "restart [ | ]", Short: "Restart tarantool instance(s)", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalRestartModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.RangeArgs(0, 1), + Run: TtModuleCmdRun(internalRestartModule), + Args: cobra.RangeArgs(0, 1), ValidArgsFunction: func( cmd *cobra.Command, args []string, diff --git a/cli/cmd/rocks.go b/cli/cmd/rocks.go index 794041569..fae61c942 100644 --- a/cli/cmd/rocks.go +++ b/cli/cmd/rocks.go @@ -3,9 +3,7 @@ package cmd import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/rocks" - "github.com/tarantool/tt/cli/util" ) // NewRocksCmd creates rocks command. @@ -16,12 +14,7 @@ func NewRocksCmd() *cobra.Command { // Disabled all flags parsing on this commands leaf. // LuaRocks will handle it self. DisableFlagParsing: true, - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalRocksModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalRocksModule), } return rocksCmd diff --git a/cli/cmd/run.go b/cli/cmd/run.go index bc21c57e0..a78be2cf1 100644 --- a/cli/cmd/run.go +++ b/cli/cmd/run.go @@ -3,14 +3,7 @@ package cmd import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/running" - "github.com/tarantool/tt/cli/util" -) - -var ( - // runArgs contains command args. - runArgs []string ) func newRunInfo(cmdCtx cmdcontext.CmdCtx) *running.RunInfo { @@ -30,15 +23,13 @@ are passed after '--'. `, DisableFlagParsing: true, Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() for _, opt := range args { if opt == "-h" || opt == "--help" { cmd.Help() return } } - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, internalRunModule, args) - util.HandleCmdErr(cmd, err) + TtModuleCmdRun(internalRunModule)(cmd, args) }, Example: ` # Print current environment Tarantool version: diff --git a/cli/cmd/search.go b/cli/cmd/search.go index f3de09680..8b9d02a44 100644 --- a/cli/cmd/search.go +++ b/cli/cmd/search.go @@ -3,9 +3,7 @@ package cmd import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/search" - "github.com/tarantool/tt/cli/util" ) var ( @@ -21,13 +19,8 @@ func newSearchTtCmd() *cobra.Command { var tntCmd = &cobra.Command{ Use: "tt", Short: "Search for available tt versions", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalSearchModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(0), + Run: TtModuleCmdRun(internalSearchModule), + Args: cobra.ExactArgs(0), } return tntCmd @@ -38,13 +31,8 @@ func newSearchTarantoolCmd() *cobra.Command { var tntCmd = &cobra.Command{ Use: "tarantool", Short: "Search for available tarantool community edition versions", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalSearchModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(0), + Run: TtModuleCmdRun(internalSearchModule), + Args: cobra.ExactArgs(0), } return tntCmd @@ -55,13 +43,8 @@ func newSearchTarantoolEeCmd() *cobra.Command { var tntCmd = &cobra.Command{ Use: "tarantool-ee", Short: "Search for available tarantool enterprise edition versions", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalSearchModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(0), + Run: TtModuleCmdRun(internalSearchModule), + Args: cobra.ExactArgs(0), } tntCmd.Flags().BoolVar(&debug, "debug", debug, "search for debug builds of tarantool-ee SDK") diff --git a/cli/cmd/start.go b/cli/cmd/start.go index 2984e3d0f..551d069d2 100644 --- a/cli/cmd/start.go +++ b/cli/cmd/start.go @@ -13,10 +13,8 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmd/internal" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/running" "github.com/tarantool/tt/cli/tail" - "github.com/tarantool/tt/cli/util" "github.com/tarantool/tt/lib/integrity" ) @@ -39,12 +37,7 @@ func NewStartCmd() *cobra.Command { var startCmd = &cobra.Command{ Use: "start [ | ]", Short: "Start tarantool instance(s)", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalStartModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalStartModule), ValidArgsFunction: func( cmd *cobra.Command, args []string, diff --git a/cli/cmd/status.go b/cli/cmd/status.go index 9257d501f..63ffa0547 100644 --- a/cli/cmd/status.go +++ b/cli/cmd/status.go @@ -4,10 +4,8 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmd/internal" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/running" "github.com/tarantool/tt/cli/status" - "github.com/tarantool/tt/cli/util" ) var opts status.StatusOpts @@ -32,12 +30,7 @@ Columns: - CONFIG: The config info status (for Tarantool 3+). - BOX: The box info status. - UPSTREAM: The replication upstream status.`, - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalStatusModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalStatusModule), ValidArgsFunction: func( cmd *cobra.Command, args []string, diff --git a/cli/cmd/stop.go b/cli/cmd/stop.go index 0c49a36be..8dad3a139 100644 --- a/cli/cmd/stop.go +++ b/cli/cmd/stop.go @@ -8,7 +8,6 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmd/internal" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/running" "github.com/tarantool/tt/cli/util" ) @@ -18,13 +17,8 @@ func NewStopCmd() *cobra.Command { var stopCmd = &cobra.Command{ Use: "stop [ | ]", Short: "Stop tarantool instance(s)", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalStopWithConfirmationModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.RangeArgs(0, 1), + Run: TtModuleCmdRun(internalStopWithConfirmationModule), + Args: cobra.RangeArgs(0, 1), ValidArgsFunction: func( cmd *cobra.Command, args []string, diff --git a/cli/cmd/uninstall.go b/cli/cmd/uninstall.go index 70d1ac77e..cca786d09 100644 --- a/cli/cmd/uninstall.go +++ b/cli/cmd/uninstall.go @@ -3,9 +3,7 @@ package cmd import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" "github.com/tarantool/tt/cli/uninstall" - "github.com/tarantool/tt/cli/util" ) // newUninstallTtCmd creates a command to install tt. @@ -13,13 +11,8 @@ func newUninstallTtCmd() *cobra.Command { var tntCmd = &cobra.Command{ Use: "tt [version]", Short: "Uninstall tt", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - InternalUninstallModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.MaximumNArgs(1), + Run: TtModuleCmdRun(InternalUninstallModule), + Args: cobra.MaximumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, args []string, @@ -40,13 +33,8 @@ func newUninstallTarantoolCmd() *cobra.Command { var tntCmd = &cobra.Command{ Use: "tarantool [version]", Short: "Uninstall tarantool community edition", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - InternalUninstallModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.MaximumNArgs(1), + Run: TtModuleCmdRun(InternalUninstallModule), + Args: cobra.MaximumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, args []string, @@ -67,13 +55,8 @@ func newUninstallTarantoolEeCmd() *cobra.Command { var tntCmd = &cobra.Command{ Use: "tarantool-ee [version]", Short: "Uninstall tarantool enterprise edition", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - InternalUninstallModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.MaximumNArgs(1), + Run: TtModuleCmdRun(InternalUninstallModule), + Args: cobra.MaximumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, args []string, @@ -94,13 +77,8 @@ func newUninstallTarantoolDevCmd() *cobra.Command { tntCmd := &cobra.Command{ Use: "tarantool-dev", Short: "Uninstall tarantool-dev", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - InternalUninstallModule, args) - util.HandleCmdErr(cmd, err) - }, - Args: cobra.ExactArgs(0), + Run: TtModuleCmdRun(InternalUninstallModule), + Args: cobra.ExactArgs(0), } return tntCmd diff --git a/cli/cmd/version.go b/cli/cmd/version.go index f04bfb055..739e7c41f 100644 --- a/cli/cmd/version.go +++ b/cli/cmd/version.go @@ -5,8 +5,6 @@ import ( "github.com/spf13/cobra" "github.com/tarantool/tt/cli/cmdcontext" - "github.com/tarantool/tt/cli/modules" - "github.com/tarantool/tt/cli/util" "github.com/tarantool/tt/cli/version" ) @@ -20,12 +18,7 @@ func NewVersionCmd() *cobra.Command { var versionCmd = &cobra.Command{ Use: "version", Short: "Show Tarantool CLI version information", - Run: func(cmd *cobra.Command, args []string) { - cmdCtx.CommandName = cmd.Name() - err := modules.RunCmd(&cmdCtx, cmd.CommandPath(), &modulesInfo, - internalVersionModule, args) - util.HandleCmdErr(cmd, err) - }, + Run: TtModuleCmdRun(internalVersionModule), } versionCmd.Flags().BoolVar(&showShort, "short", false, "Show version in short format") From 0b0057b0831ea424ec01b315cf46cb284eed8633 Mon Sep 17 00:00:00 2001 From: Mikhail Elhimov Date: Fri, 17 Jan 2025 21:35:01 +0300 Subject: [PATCH 07/13] uninstall: make uninstall handler private --- cli/cmd/common_test.go | 2 +- cli/cmd/uninstall.go | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cli/cmd/common_test.go b/cli/cmd/common_test.go index d1b4748f7..a3b94edc9 100644 --- a/cli/cmd/common_test.go +++ b/cli/cmd/common_test.go @@ -33,7 +33,7 @@ func TestCheckConfig(t *testing.T) { {"start", internalStartModule(&cmdcontext.CmdCtx{}, nil)}, {"status", internalStatusModule(&cmdcontext.CmdCtx{}, nil)}, {"stop", internalStopModule(&cmdcontext.CmdCtx{}, nil)}, - {"uninstall", InternalUninstallModule(&cmdcontext.CmdCtx{}, nil)}, + {"uninstall", internalUninstallModule(&cmdcontext.CmdCtx{}, nil)}, } for _, tc := range cases { diff --git a/cli/cmd/uninstall.go b/cli/cmd/uninstall.go index cca786d09..47648d389 100644 --- a/cli/cmd/uninstall.go +++ b/cli/cmd/uninstall.go @@ -11,7 +11,7 @@ func newUninstallTtCmd() *cobra.Command { var tntCmd = &cobra.Command{ Use: "tt [version]", Short: "Uninstall tt", - Run: TtModuleCmdRun(InternalUninstallModule), + Run: TtModuleCmdRun(internalUninstallModule), Args: cobra.MaximumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -33,7 +33,7 @@ func newUninstallTarantoolCmd() *cobra.Command { var tntCmd = &cobra.Command{ Use: "tarantool [version]", Short: "Uninstall tarantool community edition", - Run: TtModuleCmdRun(InternalUninstallModule), + Run: TtModuleCmdRun(internalUninstallModule), Args: cobra.MaximumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -55,7 +55,7 @@ func newUninstallTarantoolEeCmd() *cobra.Command { var tntCmd = &cobra.Command{ Use: "tarantool-ee [version]", Short: "Uninstall tarantool enterprise edition", - Run: TtModuleCmdRun(InternalUninstallModule), + Run: TtModuleCmdRun(internalUninstallModule), Args: cobra.MaximumNArgs(1), ValidArgsFunction: func( cmd *cobra.Command, @@ -77,7 +77,7 @@ func newUninstallTarantoolDevCmd() *cobra.Command { tntCmd := &cobra.Command{ Use: "tarantool-dev", Short: "Uninstall tarantool-dev", - Run: TtModuleCmdRun(InternalUninstallModule), + Run: TtModuleCmdRun(internalUninstallModule), Args: cobra.ExactArgs(0), } @@ -105,8 +105,8 @@ func NewUninstallCmd() *cobra.Command { return uninstallCmd } -// InternalUninstallModule is a default uninstall module. -func InternalUninstallModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { +// internalUninstallModule is a default uninstall module. +func internalUninstallModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { if !isConfigExist(cmdCtx) { return errNoConfig } From 1f404bef146de9820faba220fda4e0e658f44659 Mon Sep 17 00:00:00 2001 From: Mikhail Elhimov Date: Fri, 17 Jan 2025 22:12:40 +0300 Subject: [PATCH 08/13] uninstall: remove unused cmdCtx argument --- cli/cmd/uninstall.go | 2 +- cli/uninstall/uninstall.go | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/cli/cmd/uninstall.go b/cli/cmd/uninstall.go index 47648d389..b14148e22 100644 --- a/cli/cmd/uninstall.go +++ b/cli/cmd/uninstall.go @@ -118,6 +118,6 @@ func internalUninstallModule(cmdCtx *cmdcontext.CmdCtx, args []string) error { } err := uninstall.UninstallProgram(programName, programVersion, cliOpts.Env.BinDir, - cliOpts.Env.IncludeDir+"/include", cmdCtx) + cliOpts.Env.IncludeDir+"/include") return err } diff --git a/cli/uninstall/uninstall.go b/cli/uninstall/uninstall.go index 501570526..466f0e65d 100644 --- a/cli/uninstall/uninstall.go +++ b/cli/uninstall/uninstall.go @@ -11,7 +11,6 @@ import ( "github.com/tarantool/tt/cli/install" "github.com/apex/log" - "github.com/tarantool/tt/cli/cmdcontext" "github.com/tarantool/tt/cli/config" "github.com/tarantool/tt/cli/search" "github.com/tarantool/tt/cli/util" @@ -32,8 +31,7 @@ var errNotInstalled = errors.New("program is not installed") // remove removes binary/directory and symlinks from directory. // It returns true if symlink was removed, error. -func remove(program string, programVersion string, directory string, - cmdCtx *cmdcontext.CmdCtx) (bool, error) { +func remove(program string, programVersion string, directory string) (bool, error) { var linkPath string var err error @@ -94,8 +92,8 @@ func remove(program string, programVersion string, directory string, } // UninstallProgram uninstalls program and symlinks. -func UninstallProgram(program string, programVersion string, binDst string, headerDst string, - cmdCtx *cmdcontext.CmdCtx) error { +func UninstallProgram(program string, programVersion string, + binDst string, headerDst string) error { log.Infof("Removing binary...") var err error @@ -134,7 +132,7 @@ func UninstallProgram(program string, programVersion string, binDst string, head var isSymlinkRemoved bool for _, verToDel := range versionsToDelete { - isSymlinkRemoved, err = remove(program, verToDel, binDst, cmdCtx) + isSymlinkRemoved, err = remove(program, verToDel, binDst) if err != nil && !errors.Is(err, errNotInstalled) { return err } @@ -148,7 +146,7 @@ func UninstallProgram(program string, programVersion string, binDst string, head if strings.Contains(program, "tarantool") { log.Infof("Removing headers...") - _, err = remove(program, programVersion, headerDst, cmdCtx) + _, err = remove(program, programVersion, headerDst) if err != nil { return err } From f45c6ea681f0817444c5b1d58bce4ee2bc74ab29 Mon Sep 17 00:00:00 2001 From: Mikhail Elhimov Date: Sat, 18 Jan 2025 00:19:05 +0300 Subject: [PATCH 09/13] uninstall: avoid duplication of Command.ValidArgsFunction --- cli/cmd/uninstall.go | 66 ++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 42 deletions(-) diff --git a/cli/cmd/uninstall.go b/cli/cmd/uninstall.go index b14148e22..c0d539b30 100644 --- a/cli/cmd/uninstall.go +++ b/cli/cmd/uninstall.go @@ -6,23 +6,23 @@ import ( "github.com/tarantool/tt/cli/uninstall" ) +func uninstallValidArgsFunc(cmd *cobra.Command, args []string, toComplete string) ( + []string, cobra.ShellCompDirective) { + if len(args) > 0 { + return []string{}, cobra.ShellCompDirectiveNoFileComp + } + return uninstall.GetList(cliOpts, cmd.Name()), + cobra.ShellCompDirectiveNoFileComp +} + // newUninstallTtCmd creates a command to install tt. func newUninstallTtCmd() *cobra.Command { var tntCmd = &cobra.Command{ - Use: "tt [version]", - Short: "Uninstall tt", - Run: TtModuleCmdRun(internalUninstallModule), - Args: cobra.MaximumNArgs(1), - ValidArgsFunction: func( - cmd *cobra.Command, - args []string, - toComplete string) ([]string, cobra.ShellCompDirective) { - if len(args) > 0 { - return []string{}, cobra.ShellCompDirectiveNoFileComp - } - return uninstall.GetList(cliOpts, cmd.Name()), - cobra.ShellCompDirectiveNoFileComp - }, + Use: "tt [version]", + Short: "Uninstall tt", + Run: TtModuleCmdRun(internalUninstallModule), + Args: cobra.MaximumNArgs(1), + ValidArgsFunction: uninstallValidArgsFunc, } return tntCmd @@ -31,20 +31,11 @@ func newUninstallTtCmd() *cobra.Command { // newUninstallTarantoolCmd creates a command to install tarantool. func newUninstallTarantoolCmd() *cobra.Command { var tntCmd = &cobra.Command{ - Use: "tarantool [version]", - Short: "Uninstall tarantool community edition", - Run: TtModuleCmdRun(internalUninstallModule), - Args: cobra.MaximumNArgs(1), - ValidArgsFunction: func( - cmd *cobra.Command, - args []string, - toComplete string) ([]string, cobra.ShellCompDirective) { - if len(args) > 0 { - return []string{}, cobra.ShellCompDirectiveNoFileComp - } - return uninstall.GetList(cliOpts, cmd.Name()), - cobra.ShellCompDirectiveNoFileComp - }, + Use: "tarantool [version]", + Short: "Uninstall tarantool community edition", + Run: TtModuleCmdRun(internalUninstallModule), + Args: cobra.MaximumNArgs(1), + ValidArgsFunction: uninstallValidArgsFunc, } return tntCmd @@ -53,20 +44,11 @@ func newUninstallTarantoolCmd() *cobra.Command { // newUninstallTarantoolEeCmd creates a command to install tarantool-ee. func newUninstallTarantoolEeCmd() *cobra.Command { var tntCmd = &cobra.Command{ - Use: "tarantool-ee [version]", - Short: "Uninstall tarantool enterprise edition", - Run: TtModuleCmdRun(internalUninstallModule), - Args: cobra.MaximumNArgs(1), - ValidArgsFunction: func( - cmd *cobra.Command, - args []string, - toComplete string) ([]string, cobra.ShellCompDirective) { - if len(args) > 0 { - return []string{}, cobra.ShellCompDirectiveNoFileComp - } - return uninstall.GetList(cliOpts, cmd.Name()), - cobra.ShellCompDirectiveNoFileComp - }, + Use: "tarantool-ee [version]", + Short: "Uninstall tarantool enterprise edition", + Run: TtModuleCmdRun(internalUninstallModule), + Args: cobra.MaximumNArgs(1), + ValidArgsFunction: uninstallValidArgsFunc, } return tntCmd From a2fc9392e060bff4bdec2c3c5cc14470ecbc81fd Mon Sep 17 00:00:00 2001 From: Mikhail Elhimov Date: Sat, 18 Jan 2025 00:22:13 +0300 Subject: [PATCH 10/13] uninstall: don't refer config.CliOpts in 'uninstall' package --- cli/cmd/uninstall.go | 2 +- cli/uninstall/uninstall.go | 10 +++++----- cli/uninstall/uninstall_test.go | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cli/cmd/uninstall.go b/cli/cmd/uninstall.go index c0d539b30..51d056838 100644 --- a/cli/cmd/uninstall.go +++ b/cli/cmd/uninstall.go @@ -11,7 +11,7 @@ func uninstallValidArgsFunc(cmd *cobra.Command, args []string, toComplete string if len(args) > 0 { return []string{}, cobra.ShellCompDirectiveNoFileComp } - return uninstall.GetList(cliOpts, cmd.Name()), + return uninstall.GetAvailableVersions(cmd.Name(), cliOpts.Env.BinDir), cobra.ShellCompDirectiveNoFileComp } diff --git a/cli/uninstall/uninstall.go b/cli/uninstall/uninstall.go index 466f0e65d..7544cb5d7 100644 --- a/cli/uninstall/uninstall.go +++ b/cli/uninstall/uninstall.go @@ -11,7 +11,6 @@ import ( "github.com/tarantool/tt/cli/install" "github.com/apex/log" - "github.com/tarantool/tt/cli/config" "github.com/tarantool/tt/cli/search" "github.com/tarantool/tt/cli/util" "github.com/tarantool/tt/cli/version" @@ -208,18 +207,19 @@ func getDefault(program, dir string) (string, error) { return ver, nil } -// GetList generates a list of options to uninstall. -func GetList(cliOpts *config.CliOpts, program string) []string { +// GetAvailableVersions returns a list of the program's versions installed into +// the binDir directory. +func GetAvailableVersions(program string, binDir string) []string { list := []string{} re := regexp.MustCompile( "^" + progRegexp + version.FsSeparator + verRegexp + "$", ) - if cliOpts.Env.BinDir == "" { + if binDir == "" { return nil } - installedPrograms, err := os.ReadDir(cliOpts.Env.BinDir) + installedPrograms, err := os.ReadDir(binDir) if err != nil { return nil } diff --git a/cli/uninstall/uninstall_test.go b/cli/uninstall/uninstall_test.go index 5fa09a2b7..986b56e21 100644 --- a/cli/uninstall/uninstall_test.go +++ b/cli/uninstall/uninstall_test.go @@ -25,7 +25,7 @@ func (mock *mockRepository) ValidateAll() error { return nil } -func TestGetList(t *testing.T) { +func TestGetAvailableVersions(t *testing.T) { assert := assert.New(t) workDir := t.TempDir() @@ -52,13 +52,13 @@ func TestGetList(t *testing.T) { cliOpts, _, err := configure.GetCliOpts(cfgPath, &mockRepository{}) require.NoError(t, err) - result := GetList(cliOpts, "tt") + result := GetAvailableVersions("tt", cliOpts.Env.BinDir) assert.Equal(result, []string{"1.2.3"}) - result = GetList(cliOpts, "tarantool") + result = GetAvailableVersions("tarantool", cliOpts.Env.BinDir) assert.Equal(result, []string{"1.2.10"}) - result = GetList(cliOpts, "tarantool-ee") + result = GetAvailableVersions("tarantool-ee", cliOpts.Env.BinDir) assert.Equal(result, []string{"master"}) } From 87c4e563de2baa472472dfac191fd5cb9030a2c2 Mon Sep 17 00:00:00 2001 From: Mikhail Elhimov Date: Thu, 23 Jan 2025 13:01:59 +0300 Subject: [PATCH 11/13] version: cut 'g' prefix from hash part of tarantool version --- cli/install/install.go | 6 ++---- cli/version/version_tools.go | 2 +- cli/version/version_tools_test.go | 10 +++++----- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/cli/install/install.go b/cli/install/install.go index ca120cf17..125ab8911 100644 --- a/cli/install/install.go +++ b/cli/install/install.go @@ -1255,13 +1255,11 @@ func isUpdatePossible(installCtx InstallCtx, if err != nil { return false, err } - // We need to trim first rune to get commit hash - // from string structure 'g'. - if len(binVersion.Hash) < 1 { + if len(binVersion.Hash) == 0 { return false, fmt.Errorf("could not get commit hash of the version"+ "of an installed %s", program) } - curBinHash = binVersion.Hash[1:] + curBinHash = binVersion.Hash } else if program == search.ProgramTt { ttVer, err := cmdcontext.GetTtVersion(pathToBin) if err != nil { diff --git a/cli/version/version_tools.go b/cli/version/version_tools.go index 13ae11ceb..2f383c742 100644 --- a/cli/version/version_tools.go +++ b/cli/version/version_tools.go @@ -85,7 +85,7 @@ func createVersionRegexp(isStrict bool) *regexp.Regexp { `v?(?:(?P\d+)){1}(?:\.(?P\d+)){1}(?:\.(?P\d+)){1}` + `(?:-(?Pentrypoint|rc|alpha|beta)(?P\d+)?)?` + `(?:-(?P\d+))?` + - `(?:-(?Pg[a-f0-9]+))?(?:-r(?P\d+))?(-gc64|-nogc64)?$` + `(?:-g(?P[a-f0-9]+))?(?:-r(?P\d+))?(-gc64|-nogc64)?$` if !isStrict { matchString = strings.Replace(matchString, "{1}", "?", 3) } diff --git a/cli/version/version_tools_test.go b/cli/version/version_tools_test.go index 92643b75b..ac098038e 100644 --- a/cli/version/version_tools_test.go +++ b/cli/version/version_tools_test.go @@ -24,7 +24,7 @@ func TestParseVersion(t *testing.T) { Patch: 42, Release: Release{Type: TypeAlpha, Num: 2, str: "alpha2"}, Additional: 91, - Hash: "g08c9b4963", + Hash: "08c9b4963", Revision: 482, Str: "2.10.42-alpha2-91-g08c9b4963-r482", }, @@ -38,7 +38,7 @@ func TestParseVersion(t *testing.T) { Patch: 13, Release: Release{Type: TypeRelease}, Additional: 48, - Hash: "ga3a42eec7", + Hash: "a3a42eec7", Revision: 496, Str: "1.10.13-48-ga3a42eec7-r496", }, @@ -52,7 +52,7 @@ func TestParseVersion(t *testing.T) { Patch: 0, Release: Release{Type: TypeRelease}, Additional: 0, - Hash: "gc9673ebb7", + Hash: "c9673ebb7", Revision: 575, Str: "2.11.0-0-gc9673ebb7-r575-nogc64", }, @@ -66,7 +66,7 @@ func TestParseVersion(t *testing.T) { Patch: 0, Release: Release{Type: TypeRelease}, Additional: 0, - Hash: "gc9673ebb7", + Hash: "c9673ebb7", Revision: 575, Str: "2.11.0-0-gc9673ebb7-r575-gc64", }, @@ -80,7 +80,7 @@ func TestParseVersion(t *testing.T) { Patch: 123, Release: Release{Type: TypeRC, Num: 1, str: "rc1"}, Additional: 100, - Hash: "g2ba6c0", + Hash: "2ba6c0", Str: "1.10.123-rc1-100-g2ba6c0", }, nil, From fcf64f7ff295bc4ca67d0654f9a150c050d8413b Mon Sep 17 00:00:00 2001 From: Mikhail Elhimov Date: Tue, 21 Jan 2025 01:05:46 +0300 Subject: [PATCH 12/13] uninstall: simplify `GetAvailableVersions` --- cli/uninstall/uninstall.go | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/cli/uninstall/uninstall.go b/cli/uninstall/uninstall.go index 7544cb5d7..049536dc7 100644 --- a/cli/uninstall/uninstall.go +++ b/cli/uninstall/uninstall.go @@ -208,30 +208,25 @@ func getDefault(program, dir string) (string, error) { } // GetAvailableVersions returns a list of the program's versions installed into -// the binDir directory. -func GetAvailableVersions(program string, binDir string) []string { - list := []string{} - re := regexp.MustCompile( - "^" + progRegexp + version.FsSeparator + verRegexp + "$", - ) - - if binDir == "" { +// the 'dir' directory. +func GetAvailableVersions(program string, dir string) []string { + if dir == "" { return nil } - installedPrograms, err := os.ReadDir(binDir) + versionPrefix := filepath.Join(dir, program+version.FsSeparator) + + programFiles, err := filepath.Glob(versionPrefix + "*") if err != nil { return nil } - for _, file := range installedPrograms { - matches := util.FindNamedMatches(re, file.Name()) - if len(matches) != 0 && matches["prog"] == program { - list = append(list, matches["ver"]) - } + versions := []string{} + for _, file := range programFiles { + versions = append(versions, file[len(versionPrefix):]) } - return list + return versions } // searchLatestVersion searches for the latest installed version of the program. From 1275a469b7716801041e99fe908140692ef6547d Mon Sep 17 00:00:00 2001 From: Mikhail Elhimov Date: Tue, 21 Jan 2025 01:00:53 +0300 Subject: [PATCH 13/13] uninstall: reuse `GetAvailableVersions` --- cli/cmd/uninstall.go | 4 +- cli/uninstall/uninstall.go | 137 ++++++++++--------------------- cli/uninstall/uninstall_test.go | 139 ++++++++++++++++++++------------ 3 files changed, 134 insertions(+), 146 deletions(-) diff --git a/cli/cmd/uninstall.go b/cli/cmd/uninstall.go index 51d056838..336aa73db 100644 --- a/cli/cmd/uninstall.go +++ b/cli/cmd/uninstall.go @@ -11,8 +11,8 @@ func uninstallValidArgsFunc(cmd *cobra.Command, args []string, toComplete string if len(args) > 0 { return []string{}, cobra.ShellCompDirectiveNoFileComp } - return uninstall.GetAvailableVersions(cmd.Name(), cliOpts.Env.BinDir), - cobra.ShellCompDirectiveNoFileComp + versions, _ := uninstall.GetAvailableVersions(cmd.Name(), cliOpts.Env.BinDir) + return versions, cobra.ShellCompDirectiveNoFileComp } // newUninstallTtCmd creates a command to install tt. diff --git a/cli/uninstall/uninstall.go b/cli/uninstall/uninstall.go index 049536dc7..ffdbfd2cf 100644 --- a/cli/uninstall/uninstall.go +++ b/cli/uninstall/uninstall.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" "regexp" + "slices" "strings" "github.com/tarantool/tt/cli/install" @@ -17,12 +18,6 @@ import ( ) const ( - progRegexp = "(?P" + - search.ProgramTt + "|" + - search.ProgramCe + "|" + - search.ProgramEe + ")" - verRegexp = "(?P.*)" - MajorMinorPatchRegexp = `^[0-9]+\.[0-9]+\.[0-9]+` ) @@ -180,45 +175,32 @@ func getAllTtVersionFormats(programName, ttVersion string) ([]string, error) { // getDefault returns a default version of an installed program. func getDefault(program, dir string) (string, error) { - var ver string - - re := regexp.MustCompile( - "^" + program + version.FsSeparator + verRegexp + "$", - ) - - installedPrograms, err := os.ReadDir(dir) + versions, err := GetAvailableVersions(program, dir) if err != nil { return "", err } - - for _, file := range installedPrograms { - matches := util.FindNamedMatches(re, file.Name()) - if ver != "" { - return "", fmt.Errorf("%s has more than one installed version, "+ - "please specify the version to uninstall", program) - } else { - ver = matches["ver"] - } - } - - if ver == "" { + if len(versions) == 0 { return "", fmt.Errorf("%s has no installed version", program) } - return ver, nil + if len(versions) > 1 { + return "", fmt.Errorf("%s has more than one installed version, "+ + "please specify the version to uninstall", program) + } + return versions[0], nil } // GetAvailableVersions returns a list of the program's versions installed into // the 'dir' directory. -func GetAvailableVersions(program string, dir string) []string { - if dir == "" { - return nil +func GetAvailableVersions(program string, dir string) ([]string, error) { + if !util.IsDir(dir) { + return nil, fmt.Errorf("%q is missing or not a directory", dir) } versionPrefix := filepath.Join(dir, program+version.FsSeparator) programFiles, err := filepath.Glob(versionPrefix + "*") if err != nil { - return nil + return nil, err } versions := []string{} @@ -226,86 +208,55 @@ func GetAvailableVersions(program string, dir string) []string { versions = append(versions, file[len(versionPrefix):]) } - return versions + return versions, nil } // searchLatestVersion searches for the latest installed version of the program. -func searchLatestVersion(linkName, binDst, headerDst string) (string, error) { - var programsToSearch []string - if linkName == "tarantool" { - programsToSearch = []string{search.ProgramCe, search.ProgramEe} - } else { - programsToSearch = []string{linkName} +func searchLatestVersion(program, binDst, headerDst string) (string, error) { + binVersions, err := GetAvailableVersions(program, binDst) + if err != nil { + return "", err } - programRegex := regexp.MustCompile( - "^" + progRegexp + version.FsSeparator + verRegexp + "$", - ) - - binaries, err := os.ReadDir(binDst) + headerVersions, err := GetAvailableVersions(program, headerDst) if err != nil { return "", err } - latestVersionInfo := version.Version{} - latestVersion := "" - hashFound := false - latestHash := "" - - for _, binary := range binaries { - if binary.IsDir() { - continue - } - binaryName := binary.Name() - matches := util.FindNamedMatches(programRegex, binaryName) + binPrefix := filepath.Join(binDst, program+version.FsSeparator) - // Need to match for the program and version. - if len(matches) != 2 { - log.Debugf("%q skipped: unexpected format", binaryName) + // Find intersection and convert to version.Version + versions := []version.Version{} + for _, binVersion := range binVersions { + if util.IsDir(binPrefix + binVersion) { continue } - programName := matches["prog"] - // Need to find the program in the list of suitable. - if util.Find(programsToSearch, programName) == -1 { - continue - } - isRightFormat, _ := util.IsValidCommitHash(matches["ver"]) - - if isRightFormat { - if hashFound { + if slices.Contains(headerVersions, binVersion) { + ver, err := version.Parse(binVersion) + if err != nil { continue } - if strings.Contains(programName, "tarantool") { - // Check for headers. - if _, err := os.Stat(filepath.Join(headerDst, binaryName)); os.IsNotExist(err) { - continue - } - } - hashFound = true - latestHash = binaryName - continue - } - ver, err := version.Parse(matches["ver"]) - if err != nil { - continue - } - if strings.Contains(programName, "tarantool") { - // Check for headers. - if _, err := os.Stat(filepath.Join(headerDst, binaryName)); os.IsNotExist(err) { - continue - } - } - // Update latest version. - if latestVersion == "" || version.IsLess(latestVersionInfo, ver) { - latestVersionInfo = ver - latestVersion = binaryName + versions = append(versions, ver) } } - if latestVersion != "" { - return latestVersion, nil + + if len(versions) == 0 { + return "", nil } - return latestHash, nil + + latestVersion := slices.MaxFunc(versions, func(a, b version.Version) int { + if a.Str == b.Str { + return 0 + } + isCommitHash, _ := util.IsValidCommitHash(a.Str) + if isCommitHash || version.IsLess(a, b) { + return -1 + } + return 1 + }) + + return program + version.FsSeparator + latestVersion.Str, nil } // switchProgramToLatestVersion switches the active version of the program to the latest installed. @@ -315,7 +266,7 @@ func switchProgramToLatestVersion(program, binDst, headerDst string) error { linkName = "tarantool" } - progToSwitch, err := searchLatestVersion(linkName, binDst, headerDst) + progToSwitch, err := searchLatestVersion(program, binDst, headerDst) if err != nil { return err } diff --git a/cli/uninstall/uninstall_test.go b/cli/uninstall/uninstall_test.go index 986b56e21..355689c6f 100644 --- a/cli/uninstall/uninstall_test.go +++ b/cli/uninstall/uninstall_test.go @@ -1,71 +1,108 @@ package uninstall import ( - "io" "os" "path/filepath" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tarantool/tt/cli/configure" "github.com/tarantool/tt/cli/search" "github.com/tarantool/tt/cli/version" ) -const testDirName = "uninstall-test-dir" - -type mockRepository struct{} - -func (mock *mockRepository) Read(path string) (io.ReadCloser, error) { - return os.Open(path) -} - -func (mock *mockRepository) ValidateAll() error { - return nil -} - func TestGetAvailableVersions(t *testing.T) { assert := assert.New(t) workDir := t.TempDir() - binDir := filepath.Join(workDir, "bin") - err := os.Mkdir(binDir, os.ModePerm) - require.NoError(t, err) - - cfgData := []byte("tt:\n app:\n bin_dir: " + binDir) - cfgPath := filepath.Join(workDir, "tt.yaml") - - err = os.WriteFile(cfgPath, cfgData, 0400) - require.NoError(t, err) - - files := []string{ - "tt" + version.FsSeparator + "1.2.3", - "tarantool" + version.FsSeparator + "1.2.10", - "tarantool-ee" + version.FsSeparator + "master", + type testCase struct { + name string + program string + dir string + expected []string + isErr bool } - for _, file := range files { - f, err := os.Create(filepath.Join(binDir, file)) - require.NoError(t, err) - f.Close() + base_cases := []testCase{ + { + program: search.ProgramTt, + expected: []string{ + "1.1.0", + "1.2.3", + "1.3.4", + "2.1.0", + }, + }, + { + program: search.ProgramCe, + expected: []string{ + "1.10.0", + "2.10.8", + "2.11.8", + "3.1.2", + "master", + "aaaaaaa", + "cececece", + }, + }, + { + program: search.ProgramEe, + expected: []string{ + "1.10.15-0-r543", + "2.8.4-0-r510", + "gc64-2.11.5-0-r662", + "gc64-3.3.0-0-r43", + "master", + "bbbbbbb", + "eeeeeee", + }, + }, } - cliOpts, _, err := configure.GetCliOpts(cfgPath, &mockRepository{}) - require.NoError(t, err) - result := GetAvailableVersions("tt", cliOpts.Env.BinDir) - assert.Equal(result, []string{"1.2.3"}) - - result = GetAvailableVersions("tarantool", cliOpts.Env.BinDir) - assert.Equal(result, []string{"1.2.10"}) + // Setup test cases + cases := []testCase{} + for _, set_name := range []string{"empty", "single", "multiple"} { + dir := filepath.Join(workDir, "dir_"+set_name) + err := os.Mkdir(dir, os.ModePerm) + require.NoError(t, err) + for _, base_case := range base_cases { + tc := base_case + tc.name = set_name + "_" + base_case.program + tc.dir = dir + switch set_name { + case "empty": + tc.expected = []string{} + case "single": + tc.expected = base_case.expected[0:1] + case "multiple": + tc.expected = base_case.expected + } + for _, ver := range tc.expected { + fileName := tc.program + version.FsSeparator + ver + f, err := os.Create(filepath.Join(dir, fileName)) + require.NoError(t, err) + f.Close() + } + cases = append(cases, tc) + } + } - result = GetAvailableVersions("tarantool-ee", cliOpts.Env.BinDir) - assert.Equal(result, []string{"master"}) + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + versions, err := GetAvailableVersions(tc.program, tc.dir) + if !tc.isErr { + assert.NoError(err) + assert.Equal(tc.expected, versions) + } else { + assert.Error(err) + } + }) + } } func TestSearchLatestVersion(t *testing.T) { type testCase struct { name string - linkName string + program string binDst string headerDst string expectedVer string @@ -75,42 +112,42 @@ func TestSearchLatestVersion(t *testing.T) { cases := []testCase{ { name: "basic", - linkName: "tarantool", + program: "tarantool", binDst: "./testdata/bin_basic", headerDst: "./testdata/inc_basic", expectedVer: "tarantool_3.0.0-entrypoint", }, { name: "no includes", - linkName: "tarantool", + program: "tarantool-ee", binDst: "./testdata/bin_basic", headerDst: "./testdata/inc_invalid", expectedVer: "tarantool-ee_2.8.4-0-r510", }, { name: "tarantool-dev", - linkName: "tarantool", + program: "tarantool-dev", binDst: "./testdata/bin_dev", headerDst: "./testdata/inc_basic", expectedVer: "", }, { name: "hash version", - linkName: "tarantool", + program: "tarantool", binDst: "./testdata/bin_hash", headerDst: "./testdata/inc_hash", expectedVer: "tarantool_aaaaaaa", }, { name: "hash invalid headers", - linkName: "tarantool", + program: "tarantool", binDst: "./testdata/bin_hash", headerDst: "./testdata/inc_invalid_hash", expectedVer: "tarantool_bbbbbbb", }, { name: "tt, include-dir basic", - linkName: "tt", + program: "tt", binDst: "./testdata/bin_basic", headerDst: "./testdata/inc_basic", expectedVer: "tt_2.0.0", @@ -118,14 +155,14 @@ func TestSearchLatestVersion(t *testing.T) { // Test that include dir doesn't affect the search for `tt`. { name: "tt, include-dir invalid", - linkName: "tt", + program: "tt", binDst: "./testdata/bin_basic", headerDst: "./testdata/inc_invalid", expectedVer: "tt_2.0.0", }, { name: "filename as a bin dir", - linkName: "tt", + program: "tt", binDst: "./testdata/bin_basic/tarantool", headerDst: "./testdata/inc_basic", isErr: true, @@ -134,7 +171,7 @@ func TestSearchLatestVersion(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - ver, err := searchLatestVersion(tc.linkName, tc.binDst, tc.headerDst) + ver, err := searchLatestVersion(tc.program, tc.binDst, tc.headerDst) if !tc.isErr { assert.NoError(t, err) assert.Equal(t, tc.expectedVer, ver)