Skip to content

Commit

Permalink
[commands] finish refactoring with working tests
Browse files Browse the repository at this point in the history
  • Loading branch information
shmel1k committed Jun 27, 2024
1 parent d175a2b commit fdf1970
Show file tree
Hide file tree
Showing 16 changed files with 287 additions and 239 deletions.
4 changes: 0 additions & 4 deletions cmd/maintenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,9 @@ func (r *MaintenanceCommand) RunCallback() func(*cobra.Command, []string) error
}

func NewMaintenanceCommand(
description *command.Description,
base *command.Base,
preRunCallback cli.PreRunCallback, // TODO(shmel1k@): change to validation callback name or smth
) command.Command {
return &MaintenanceCommand{
description: description,
preRunCallback: preRunCallback,
commandOptions: &options.RestartOptions{},
Base: base,
}
Expand Down
22 changes: 5 additions & 17 deletions cmd/maintenance/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,26 @@ import (
"github.com/spf13/cobra"

"github.com/ydb-platform/ydbops/pkg/cli"
"github.com/ydb-platform/ydbops/pkg/client"
"github.com/ydb-platform/ydbops/pkg/cmdutil"
"github.com/ydb-platform/ydbops/pkg/command"
"github.com/ydb-platform/ydbops/pkg/maintenance"
"github.com/ydb-platform/ydbops/pkg/options"
)

func NewHostCommand(
description *command.Description,
rootCommand *command.Base,
preRunCallback cli.PreRunCallback,
) command.Command {
return &HostCommand{
Base: rootCommand,
preRunCallback: preRunCallback,
commandOptions: &options.MaintenanceHostOpts{},
}
}

type HostCommand struct {
*command.Base
description *command.Description
preRunCallback cli.PreRunCallback
commandOptions *options.MaintenanceHostOpts
cobraCommand *cobra.Command
f cmdutil.Factory
}

func (h *HostCommand) ToCobraCommand() *cobra.Command {
Expand All @@ -42,7 +38,8 @@ func (h *HostCommand) ToCobraCommand() *cobra.Command {
Short: "Request host from the CMS (Cluster Management System)",
Long: `ydbops maintenance host:
Make a request to take the host out of the cluster.`,
RunE: h.RunCallback(),
RunE: h.RunCallback(),
PreRunE: cli.PopulateProfileDefaultsAndValidate(h.GetBaseOptions(), h.commandOptions),
}

return h.cobraCommand
Expand All @@ -61,16 +58,7 @@ func (h *HostCommand) RegisterSubcommands(c ...command.Command) {

func (h *HostCommand) RunCallback() func(*cobra.Command, []string) error {
return func(_ *cobra.Command, _ []string) error {
err := client.InitConnectionFactory(
*h.GetBaseOptions(),
options.Logger,
options.DefaultRetryCount,
)
if err != nil {
return err
}

taskId, err := maintenance.RequestHost(h.commandOptions)
taskId, err := maintenance.RequestHost(h.f.GetCMSClient(), h.commandOptions)
if err != nil {
return err
}
Expand Down
3 changes: 1 addition & 2 deletions cmd/restart.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,11 @@ type RestartCommand struct {
func NewRestartCommand(
description *command.Description,
rootCommand *command.Base,
preRunCallback cli.PreRunCallback,
f cmdutil.Factory,
) command.Command {
return &RestartCommand{
description: description,
preRunCallback: preRunCallback,
preRunCallback: cli.PopulateProfileDefaultsAndValidate,
commandOptions: &options.RestartOptions{},
Base: rootCommand,
}
Expand Down
21 changes: 12 additions & 9 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,29 @@ import (
"github.com/ydb-platform/ydbops/pkg/options"
"github.com/ydb-platform/ydbops/pkg/rolling"
"github.com/ydb-platform/ydbops/pkg/rolling/restarters"
"go.uber.org/zap"
)

type RunCommand struct {
*command.Base
description *command.Description
commandOptions *options.RunOptions
cobraCommand *cobra.Command
restarter *restarters.RunRestarter // TODO(shmel1k@): move to restarter interface.
f cmdutil.Factory
}

func NewRunCommand(
description *command.Description,
rootCommand *command.Base,
restarter *restarters.RunRestarter,
f cmdutil.Factory,
) command.Command {
return &RunCommand{
description: description,
commandOptions: &options.RunOptions{
RestartOptions: &options.RestartOptions{},
}, // TODO(shmel1k@): remove from options package.
restarter: restarters.NewRunRestarter(options.Logger), // TODO(shmel1k@): remove link to global variable
Base: rootCommand,
Base: rootCommand,
f: f,
}
}

Expand All @@ -55,17 +54,21 @@ func (r *RunCommand) RunCallback() func(*cobra.Command, []string) error {

bothUnspecified := !r.commandOptions.Storage && !r.commandOptions.Tenant

restarter := restarters.NewRunRestarter(zap.S(), &restarters.RunRestarterParams{
PayloadFilePath: r.commandOptions.PayloadFilePath,
})

var executer rolling.Executer
var err error
if r.commandOptions.Storage || bothUnspecified {
r.restarter.SetStorageOnly()
executer = rolling.NewExecuter(*r.commandOptions.RestartOptions, options.Logger, r.f.GetCMSClient(), r.f.GetDiscoveryClient(), r.restarter)
restarter.SetStorageOnly()
executer = rolling.NewExecuter(*r.commandOptions.RestartOptions, options.Logger, r.f.GetCMSClient(), r.f.GetDiscoveryClient(), restarter)
err = executer.Execute()
}

if err == nil && (r.commandOptions.Tenant || bothUnspecified) {
r.restarter.SetDynnodeOnly()
executer = rolling.NewExecuter(*r.commandOptions.RestartOptions, options.Logger, r.f.GetCMSClient(), r.f.GetDiscoveryClient(), r.restarter)
restarter.SetDynnodeOnly()
executer = rolling.NewExecuter(*r.commandOptions.RestartOptions, options.Logger, r.f.GetCMSClient(), r.f.GetDiscoveryClient(), restarter)
err = executer.Execute()
}

Expand All @@ -81,7 +84,7 @@ func (r *RunCommand) ToCobraCommand() *cobra.Command {
Use: r.description.GetUse(),
Short: r.description.GetShortDescription(),
Long: r.description.GetLongDescription(),
PreRunE: cli.PopulateProfileDefaultsAndValidate(r.GetBaseOptions(), r.restarter.Opts),
PreRunE: cli.PopulateProfileDefaultsAndValidate(r.GetBaseOptions(), r.commandOptions),
RunE: r.RunCallback(),
}
return r.cobraCommand
Expand Down
116 changes: 0 additions & 116 deletions examples/overridden_restarter/main.go

This file was deleted.

99 changes: 97 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@ package main
import (
"os"

"github.com/ydb-platform/ydbops/cmd"
"github.com/ydb-platform/ydbops/cmd/maintenance"
iCli "github.com/ydb-platform/ydbops/internal/cli"
"github.com/ydb-platform/ydbops/pkg/cli"
"github.com/ydb-platform/ydbops/pkg/client/auth/credentials"
"github.com/ydb-platform/ydbops/pkg/client/cms"
"github.com/ydb-platform/ydbops/pkg/client/connectionsfactory"
"github.com/ydb-platform/ydbops/pkg/client/discovery"
"github.com/ydb-platform/ydbops/pkg/cmdutil"
"github.com/ydb-platform/ydbops/pkg/command"
"github.com/ydb-platform/ydbops/pkg/options"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
Expand All @@ -24,8 +35,92 @@ func createLogger(level string) (zap.AtomicLevel, *zap.Logger) {
return atom, logger
}

var (
factory cmdutil.Factory
cmsClient cms.Client
discoveryClient discovery.Client
)

func initFactory() {
factory = cmdutil.New(cmsClient, discoveryClient)
}

func initClients(
cf connectionsfactory.Factory,
logger *zap.SugaredLogger,
cp credentials.Provider,
) {
cmsClient = cms.NewCMSClient(cf, logger, cp)
discoveryClient = discovery.NewDiscoveryClient(cf, logger, cp)
}

func initCommandTree(rootOptions *command.BaseOptions, logLevelSetter zap.AtomicLevel, logger *zap.SugaredLogger) (root command.Command) {
baseCommand := command.NewBase(rootOptions)
root = cmd.NewRootCommand(
command.NewDescription(
"ydbops",
"ydbops: a CLI tool for performing YDB cluster maintenance operations",
"ydbops: a CLI tool for performing YDB cluster maintenance operations",
),
baseCommand,
logLevelSetter,
logger,
)
root.RegisterOptions()
rootOptions.DefineFlags(root.ToCobraCommand().PersistentFlags())

restartCommand := cmd.NewRestartCommand(
cmd.RestartCommandDescription,
baseCommand,
factory,
)
root.RegisterSubcommands(restartCommand)
cli.SetDefaultsOn(root.ToCobraCommand())

runCommand := cmd.NewRunCommand(
command.NewDescription(
"run",
"Run an arbitrary executable (e.g. shell code) in the context of the local machine",
`ydbops restart run:
Run an arbitrary executable (e.g. shell code) in the context of the local machine
(where rolling-restart is launched). For example, if you want to execute ssh commands
on the ydb cluster node, you must write ssh commands yourself. See the examples.
For every node released by CMS, ydbops will execute this payload independently.
Restart will be treated as successful if your executable finished with a zero
return code.
Certain environment variable will be passed to your executable on each run:
$HOSTNAME: the fqdn of the node currently released by CMS.`,
),
baseCommand,
factory,
)
root.RegisterSubcommands(runCommand)

maintenanceCommand := cmd.NewMaintenanceCommand(baseCommand)
root.RegisterSubcommands(maintenanceCommand)
maintenanceCommand.RegisterSubcommands(maintenance.NewHostCommand(baseCommand))

root.ToCobraCommand().SetUsageTemplate(iCli.UsageTemplate)
return root
}

func main() {
rootOptions := &command.BaseOptions{}
cf := connectionsfactory.New(rootOptions)
logLevelSetter, logger := createLogger("info")
_ = logLevelSetter
_ = logger

options.Logger = logger.Sugar() // TODO(shmel1k@): tmp hack

credentialsProvider := credentials.New(rootOptions, cf, logger.Sugar(), nil)
initClients(cf, logger.Sugar(), credentialsProvider)
initFactory()

root := initCommandTree(rootOptions, logLevelSetter, logger.Sugar())
defer func() {
_ = logger.Sync()
}()
_ = root.ToCobraCommand().Execute()
}
2 changes: 1 addition & 1 deletion pkg/cli/cobra.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func PopulateProfileDefaultsAndValidate(rootOpts *command.BaseOptions, optsArgs
return fmt.Errorf("%w\nTry '--help' option for more info", err)
}
}
return nil
return rootOpts.Validate()
}
}

Expand Down
Loading

0 comments on commit fdf1970

Please sign in to comment.