diff --git a/Makefile b/Makefile index 378c1099..5c86390a 100644 --- a/Makefile +++ b/Makefile @@ -20,12 +20,12 @@ all: static-check birdwatcher birdwatcher: @echo "Compiling birdwatcher" @mkdir -p bin - @CGO_ENABLED=0 go build -o bin/birdwatcher main.go + @CGO_ENABLED=0 go build -o bin/birdwatcher cmd/birdwatcher/main.go birdwatcher_wkafka: @echo "Compiling birdwatcher with kafka(CGO_ENABLED)" @mkdir -p bin - @CGO_ENABLED=1 go build -o bin/birdwatcher_wkafka -tags WKAFKA main.go + @CGO_ENABLED=1 go build -o bin/birdwatcher_wkafka -tags WKAFKA cmd/birdwatcher/main.go getdeps: @mkdir -p $(INSTALL_PATH) diff --git a/bapps/app.go b/bapps/app.go index deaa0c82..f707b622 100644 --- a/bapps/app.go +++ b/bapps/app.go @@ -3,12 +3,12 @@ package bapps import ( "log" - "github.com/milvus-io/birdwatcher/states" + "github.com/milvus-io/birdwatcher/common" ) // BApp interface for birdwatcher application type BApp interface { - Run(states.State) + Run(common.State) } // AppOption application setup option function. diff --git a/bapps/go_prompt.go b/bapps/go_prompt.go index bacfe346..e7eb9da3 100644 --- a/bapps/go_prompt.go +++ b/bapps/go_prompt.go @@ -12,15 +12,15 @@ import ( "github.com/c-bata/go-prompt" "github.com/samber/lo" + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/configs" "github.com/milvus-io/birdwatcher/history" - "github.com/milvus-io/birdwatcher/states" ) // PromptApp wraps go-prompt as application. type PromptApp struct { exited bool - currentState states.State + currentState common.State sugguestHistory bool historyHelper *history.Helper logger *log.Logger @@ -71,7 +71,7 @@ func NewPromptApp(config *configs.Config, opts ...AppOption) BApp { return pa } -func (a *PromptApp) Run(start states.State) { +func (a *PromptApp) Run(start common.State) { a.currentState = start a.prompt.Run() } diff --git a/bapps/olc.go b/bapps/olc.go index 993940d0..9f58a26f 100644 --- a/bapps/olc.go +++ b/bapps/olc.go @@ -5,9 +5,8 @@ import ( "os" "strings" + "github.com/milvus-io/birdwatcher/common" "github.com/samber/lo" - - "github.com/milvus-io/birdwatcher/states" ) type olcApp struct { @@ -25,7 +24,7 @@ func NewOlcApp(script string) BApp { } } -func (a *olcApp) Run(start states.State) { +func (a *olcApp) Run(start common.State) { app := start cmds := a.parseScripts(a.script) var err error diff --git a/bapps/promptui.go b/bapps/promptui.go index dc08163b..dd20b10c 100644 --- a/bapps/promptui.go +++ b/bapps/promptui.go @@ -5,12 +5,12 @@ import ( "github.com/manifoldco/promptui" - "github.com/milvus-io/birdwatcher/states" + "github.com/milvus-io/birdwatcher/common" ) // simpleApp wraps promptui as BApp. type simpleApp struct { - currentState states.State + currentState common.State } func NewSimpleApp() BApp { @@ -18,7 +18,7 @@ func NewSimpleApp() BApp { } // Run starts BirdWatcher with promptui. (disable suggestion and history) -func (a *simpleApp) Run(start states.State) { +func (a *simpleApp) Run(start common.State) { app := start for { p := promptui.Prompt{ @@ -31,7 +31,7 @@ func (a *simpleApp) Run(start states.State) { line, err := p.Run() if err == nil { app, err = app.Process(line) - if errors.Is(err, states.ExitErr) { + if errors.Is(err, common.ExitErr) { break } if app.IsEnding() { diff --git a/bapps/webserver.go b/bapps/webserver.go index d2400749..d6d1af63 100644 --- a/bapps/webserver.go +++ b/bapps/webserver.go @@ -29,7 +29,7 @@ type InstanceInfo struct { RootPath string `form:"rootPath"` } -func (app *WebServerApp) Run(states.State) { +func (app *WebServerApp) Run(common.State) { r := gin.Default() etcdversion.SetVersion(models.GTEVersion2_2) @@ -42,7 +42,7 @@ func (app *WebServerApp) Run(states.State) { r.Run(fmt.Sprintf(":%d", app.port)) } -func (app *WebServerApp) ParseRouter(r *gin.Engine, s states.State) { +func (app *WebServerApp) ParseRouter(r *gin.Engine, s common.State) { v := reflect.ValueOf(s) tp := v.Type() @@ -106,7 +106,7 @@ func (app *WebServerApp) parseMethod(r *gin.Engine, mt reflect.Method, name stri // fmt.Println(mt.Name) cp := reflect.New(paramType.Elem()).Interface().(framework.CmdParam) - fUse, _ := states.GetCmdFromFlag(cp) + fUse, _ := common.GetCmdFromFlag(cp) if len(use) == 0 { use = fUse } @@ -115,7 +115,7 @@ func (app *WebServerApp) parseMethod(r *gin.Engine, mt reflect.Method, name stri fnName := mt.Name use = strings.ToLower(fnName[:len(fnName)-8]) } - uses := states.ParseUseSegments(use) + uses := common.ParseUseSegments(use) lastKw := uses[len(uses)-1] // hard code, show xxx command only if uses[0] != "show" { diff --git a/main.go b/cmd/birdwatcher/main.go similarity index 100% rename from main.go rename to cmd/birdwatcher/main.go diff --git a/common/exit.go b/common/exit.go new file mode 100644 index 00000000..5c7ba92a --- /dev/null +++ b/common/exit.go @@ -0,0 +1,13 @@ +package common + +// ExitState simple exit state. +type ExitState struct { + CmdState +} + +// SetupCommands setups the command. +// also called after each command run to reset flag values. +func (s *ExitState) SetupCommands() {} + +// IsEnding returns true for exit State +func (s *ExitState) IsEnding() bool { return true } diff --git a/states/states.go b/common/state.go similarity index 82% rename from states/states.go rename to common/state.go index ec14b1cf..b0a2db7b 100644 --- a/states/states.go +++ b/common/state.go @@ -1,4 +1,4 @@ -package states +package common import ( "context" @@ -18,6 +18,17 @@ import ( "github.com/milvus-io/birdwatcher/states/autocomplete" ) +// ExitErr is the error indicates user needs to exit application. +var ExitErr = exitErr{} + +// exitErr internal err type for comparing. +type exitErr struct{} + +// Error implements error. +func (e exitErr) Error() string { + return "exited" +} + // State is the interface for application state. type State interface { Ctx() (context.Context, context.CancelFunc) @@ -30,18 +41,18 @@ type State interface { IsEnding() bool } -// cmdState is the basic state to process input command. -type cmdState struct { - label string - rootCmd *cobra.Command - nextState State +// CmdState is the basic state to process input command. +type CmdState struct { + LabelStr string + RootCmd *cobra.Command + NextState State signal <-chan os.Signal - setupFn func() + SetupFn func() } // Ctx returns context which bind to sigint handler. -func (s *cmdState) Ctx() (context.Context, context.CancelFunc) { +func (s *CmdState) Ctx() (context.Context, context.CancelFunc) { ctx, cancel := context.WithCancel(context.Background()) go func() { defer cancel() @@ -54,24 +65,27 @@ func (s *cmdState) Ctx() (context.Context, context.CancelFunc) { } // SetupCommands perform command setup & reset. -func (s *cmdState) SetupCommands() { - if s.setupFn != nil { - s.setupFn() +func (s *CmdState) SetupCommands() { + if s.SetupFn != nil { + s.SetupFn() } } -// mergeFunctionCommands parses all member methods for provided state and add it into cmd. -func (s *cmdState) mergeFunctionCommands(cmd *cobra.Command, state State) { +// MergeFunctionCommands parses all member methods for provided state and add it into cmd. +func (s *CmdState) MergeFunctionCommands(cmd *cobra.Command, state State) { items := parseFunctionCommands(state) for _, item := range items { + // log.Println(item.kws, item.cmd.Use) target := cmd for _, kw := range item.kws { node, _, err := cmd.Find([]string{kw}) - if err != nil { + if err != nil || node.Use == "" { + // log.Println("not found", err) newNode := &cobra.Command{Use: kw} target.AddCommand(newNode) node = newNode } + // log.Println("[After find&check]", node.Use) target = node } target.AddCommand(item.cmd) @@ -79,19 +93,19 @@ func (s *cmdState) mergeFunctionCommands(cmd *cobra.Command, state State) { } // Label returns the display label for current cli. -func (s *cmdState) Label() string { - return s.label +func (s *CmdState) Label() string { + return s.LabelStr } -func (s *cmdState) Suggestions(input string) map[string]string { - return autocomplete.SuggestInputCommands(input, s.rootCmd.Commands()) +func (s *CmdState) Suggestions(input string) map[string]string { + return autocomplete.SuggestInputCommands(input, s.RootCmd.Commands()) } // Process is the main entry for processing command. -func (s *cmdState) Process(cmd string) (State, error) { +func (s *CmdState) Process(cmd string) (State, error) { args := strings.Split(cmd, " ") - target, _, err := s.rootCmd.Find(args) + target, _, err := s.RootCmd.Find(args) if err == nil && target != nil { defer target.SetArgs(nil) } @@ -101,18 +115,18 @@ func (s *cmdState) Process(cmd string) (State, error) { signal.Notify(c, syscall.SIGINT) s.signal = c - s.rootCmd.SetArgs(args) - err = s.rootCmd.Execute() + s.RootCmd.SetArgs(args) + err = s.RootCmd.Execute() signal.Reset(syscall.SIGINT) if errors.Is(err, ExitErr) { - return s.nextState, ExitErr + return s.NextState, ExitErr } if err != nil { return s, err } - if s.nextState != nil { - nextState := s.nextState - s.nextState = nil + if s.NextState != nil { + nextState := s.NextState + s.NextState = nil return nextState, nil } @@ -122,23 +136,31 @@ func (s *cmdState) Process(cmd string) (State, error) { } // SetNext simple method to set next state. -func (s *cmdState) SetNext(state State) { - s.nextState = state +func (s *CmdState) SetNext(state State) { + s.NextState = state } // Close empty method to implement State. -func (s *cmdState) Close() {} +func (s *CmdState) Close() {} // Check state is ending state. -func (s *cmdState) IsEnding() bool { return false } +func (s *CmdState) IsEnding() bool { return false } + +type PrintVerParam struct { + framework.ParamBase `use:"version" desc:"print version"` +} + +func (s *CmdState) PrintVersionCommand(ctx context.Context, _ *PrintVerParam) { + fmt.Println("Birdwatcher Version", Version) +} type exitParam struct { framework.ParamBase `use:"exit" desc:"Close this CLI tool"` } // ExitCommand returns exit command -func (s *cmdState) ExitCommand(ctx context.Context, _ *exitParam) { - s.SetNext(&exitState{}) +func (s *CmdState) ExitCommand(ctx context.Context, _ *exitParam) { + s.SetNext(&ExitState{}) } type commandItem struct { diff --git a/common/util.go b/common/util.go new file mode 100644 index 00000000..a40e4d1b --- /dev/null +++ b/common/util.go @@ -0,0 +1,49 @@ +package common + +import ( + "context" + "fmt" + "strconv" + "time" + + "github.com/milvus-io/birdwatcher/framework" +) + +const ( + logicalBits = 18 + logicalBitsMask = (1 << logicalBits) - 1 +) + +type ParseTSParam struct { + framework.ParamBase `use:"parse-ts" desc:"parse hybrid timestamp"` + args []string +} + +func (p *ParseTSParam) ParseArgs(args []string) error { + p.args = args + return nil +} + +func (s *CmdState) ParseTSCommand(ctx context.Context, p *ParseTSParam) { + if len(p.args) == 0 { + fmt.Println("no ts provided") + } + + for _, arg := range p.args { + ts, err := strconv.ParseUint(arg, 10, 64) + if err != nil { + fmt.Printf("failed to parse ts from %s, err: %s\n", arg, err.Error()) + continue + } + + t, _ := ParseTS(ts) + fmt.Printf("Parse ts result, ts:%d, time: %v\n", ts, t) + } +} + +func ParseTS(ts uint64) (time.Time, uint64) { + logical := ts & logicalBitsMask + physical := ts >> logicalBits + physicalTime := time.Unix(int64(physical/1000), int64(physical)%1000*time.Millisecond.Nanoseconds()) + return physicalTime, logical +} diff --git a/states/backup_mock_connect.go b/states/backup_mock_connect.go index b2bb57b6..15df03e6 100644 --- a/states/backup_mock_connect.go +++ b/states/backup_mock_connect.go @@ -17,6 +17,7 @@ import ( "go.etcd.io/etcd/server/v3/embed" "go.etcd.io/etcd/server/v3/etcdserver/api/v3client" + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/configs" "github.com/milvus-io/birdwatcher/models" "github.com/milvus-io/birdwatcher/states/etcd" @@ -30,7 +31,7 @@ const ( ) type embedEtcdMockState struct { - cmdState + common.CmdState *show.ComponentShow *remove.ComponentRemove *repair.ComponentRepair @@ -80,14 +81,14 @@ func (s *embedEtcdMockState) SetupCommands() { ) cmd.AddCommand(etcd.RawCommands(s.client)...) - s.mergeFunctionCommands(cmd, s) + s.MergeFunctionCommands(cmd, s) - s.cmdState.rootCmd = cmd - s.setupFn = s.SetupCommands + s.CmdState.RootCmd = cmd + s.SetupFn = s.SetupCommands } func (s *embedEtcdMockState) SetInstance(instanceName string) { - s.cmdState.label = fmt.Sprintf("Backup(%s)", instanceName) + s.CmdState.LabelStr = fmt.Sprintf("Backup(%s)", instanceName) s.instanceName = instanceName rootPath := path.Join(instanceName, metaPath) s.ComponentShow = show.NewComponent(s.client, s.config, rootPath) @@ -170,12 +171,12 @@ func (s *embedEtcdMockState) readWorkspaceMeta(path string) { s.SetInstance(meta.Instance) } -func getEmbedEtcdInstance(server *embed.Etcd, cli *clientv3.Client, instanceName string, config *configs.Config) State { +func getEmbedEtcdInstance(server *embed.Etcd, cli *clientv3.Client, instanceName string, config *configs.Config) common.State { basePath := path.Join(instanceName, metaPath) state := &embedEtcdMockState{ - cmdState: cmdState{ - label: fmt.Sprintf("Backup(%s)", instanceName), + CmdState: common.CmdState{ + LabelStr: fmt.Sprintf("Backup(%s)", instanceName), }, ComponentShow: show.NewComponent(cli, config, basePath), ComponentRemove: remove.NewComponent(cli, config, basePath), @@ -195,7 +196,7 @@ func getEmbedEtcdInstance(server *embed.Etcd, cli *clientv3.Client, instanceName func getEmbedEtcdInstanceV2(server *embed.Etcd, config *configs.Config) *embedEtcdMockState { client := v3client.New(server.Server) state := &embedEtcdMockState{ - cmdState: cmdState{}, + CmdState: common.CmdState{}, server: server, client: client, metrics: make(map[string][]byte), diff --git a/states/disconnected.go b/states/disconnected.go index 5979d9ec..f6fdecb6 100644 --- a/states/disconnected.go +++ b/states/disconnected.go @@ -3,27 +3,28 @@ package states import ( "github.com/spf13/cobra" + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/configs" ) type disconnectState struct { - cmdState + common.CmdState config *configs.Config } func (s *disconnectState) SetupCommands() { cmd := &cobra.Command{} - s.mergeFunctionCommands(cmd, s) + s.MergeFunctionCommands(cmd, s) - s.rootCmd = cmd - s.setupFn = s.SetupCommands + s.RootCmd = cmd + s.SetupFn = s.SetupCommands } -func getDisconnectedState(config *configs.Config) State { +func getDisconnectedState(config *configs.Config) common.State { state := &disconnectState{ - cmdState: cmdState{ - label: "Offline", + CmdState: common.CmdState{ + LabelStr: "Offline", }, config: config, } diff --git a/states/etcd_connect.go b/states/etcd_connect.go index 25fb1c64..cd553c4d 100644 --- a/states/etcd_connect.go +++ b/states/etcd_connect.go @@ -16,6 +16,7 @@ import ( "go.uber.org/zap" "google.golang.org/grpc" + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/configs" "github.com/milvus-io/birdwatcher/framework" ) @@ -175,7 +176,7 @@ func (s *disconnectState) ConnectCommand(ctx context.Context, cp *ConnectParams) } type etcdConnectedState struct { - cmdState + common.CmdState client *clientv3.Client addr string candidates []string @@ -187,17 +188,17 @@ type etcdConnectedState struct { func (s *etcdConnectedState) SetupCommands() { cmd := &cobra.Command{} - s.mergeFunctionCommands(cmd, s) + s.MergeFunctionCommands(cmd, s) - s.cmdState.rootCmd = cmd - s.setupFn = s.SetupCommands + s.CmdState.RootCmd = cmd + s.SetupFn = s.SetupCommands } // getEtcdConnectedState returns etcdConnectedState for unknown instance -func getEtcdConnectedState(cli *clientv3.Client, addr string, config *configs.Config) State { +func getEtcdConnectedState(cli *clientv3.Client, addr string, config *configs.Config) common.State { state := &etcdConnectedState{ - cmdState: cmdState{ - label: fmt.Sprintf("Etcd(%s)", addr), + CmdState: common.CmdState{ + LabelStr: fmt.Sprintf("Etcd(%s)", addr), }, client: cli, addr: addr, diff --git a/states/exit.go b/states/exit.go index f61fd237..626f4288 100644 --- a/states/exit.go +++ b/states/exit.go @@ -3,30 +3,19 @@ package states import ( "context" - "github.com/spf13/cobra" - + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/framework" + "github.com/spf13/cobra" ) -// ExitErr is the error indicates user needs to exit application. -var ExitErr = exitErr{} - -// exitErr internal err type for comparing. -type exitErr struct{} - -// Error implements error. -func (e exitErr) Error() string { - return "exited" -} - // getExitCmd returns exit command for input state. -func getExitCmd(state State) *cobra.Command { +func getExitCmd(state common.State) *cobra.Command { cmd := &cobra.Command{ Use: "exit", Short: "Closes the cli", Aliases: []string{"quit"}, RunE: func(*cobra.Command, []string) error { - state.SetNext(&exitState{}) + state.SetNext(&common.ExitState{}) // cannot return ExitErr here to avoid print help message return nil }, @@ -34,18 +23,6 @@ func getExitCmd(state State) *cobra.Command { return cmd } -// exitState simple exit state. -type exitState struct { - cmdState -} - -// SetupCommands setups the command. -// also called after each command run to reset flag values. -func (s *exitState) SetupCommands() {} - -// IsEnding returns true for exit State -func (s *exitState) IsEnding() bool { return true } - type DisconnectParam struct { framework.ParamBase `use:"disconnect" desc:"disconnect from current etcd instance"` } diff --git a/states/instance.go b/states/instance.go index 803e9097..0ecef2fe 100644 --- a/states/instance.go +++ b/states/instance.go @@ -9,6 +9,7 @@ import ( "github.com/spf13/cobra" clientv3 "go.etcd.io/etcd/client/v3" + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/configs" "github.com/milvus-io/birdwatcher/states/etcd" "github.com/milvus-io/birdwatcher/states/etcd/audit" @@ -20,7 +21,7 @@ import ( // InstanceState provides command for single milvus instance. type InstanceState struct { - cmdState + common.CmdState *show.ComponentShow *remove.ComponentRemove *repair.ComponentRepair @@ -29,7 +30,7 @@ type InstanceState struct { client clientv3.KV auditFile *os.File - etcdState State + etcdState common.State config *configs.Config basePath string } @@ -105,13 +106,13 @@ func (s *InstanceState) SetupCommands() { ) // cmd.AddCommand(etcd.RawCommands(cli)...) - s.mergeFunctionCommands(cmd, s) - s.cmdState.rootCmd = cmd - s.setupFn = s.SetupCommands + s.MergeFunctionCommands(cmd, s) + s.CmdState.RootCmd = cmd + s.SetupFn = s.SetupCommands } // getDryModeCmd enter dry-mode -func getDryModeCmd(state *InstanceState, etcdState State) *cobra.Command { +func getDryModeCmd(state *InstanceState, etcdState common.State) *cobra.Command { cmd := &cobra.Command{ Use: "dry-mode", Short: "enter dry mode to select instance", @@ -122,7 +123,7 @@ func getDryModeCmd(state *InstanceState, etcdState State) *cobra.Command { return cmd } -func getInstanceState(cli clientv3.KV, instanceName, metaPath string, etcdState State, config *configs.Config) State { +func getInstanceState(cli clientv3.KV, instanceName, metaPath string, etcdState common.State, config *configs.Config) common.State { var kv clientv3.KV name := fmt.Sprintf("audit_%s.log", time.Now().Format("2006_0102_150405")) file, err := os.OpenFile(name, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) @@ -137,8 +138,8 @@ func getInstanceState(cli clientv3.KV, instanceName, metaPath string, etcdState // use audit kv state := &InstanceState{ - cmdState: cmdState{ - label: fmt.Sprintf("Milvus(%s)", instanceName), + CmdState: common.CmdState{ + LabelStr: fmt.Sprintf("Milvus(%s)", instanceName), }, ComponentShow: show.NewComponent(cli, config, basePath), ComponentRemove: remove.NewComponent(cli, config, basePath), diff --git a/states/pulsarctl_connect.go b/states/pulsarctl_connect.go index 281a62cd..09e02fce 100644 --- a/states/pulsarctl_connect.go +++ b/states/pulsarctl_connect.go @@ -6,9 +6,10 @@ import ( "github.com/spf13/cobra" pulsarctl "github.com/streamnative/pulsarctl/pkg/pulsar" - "github.com/streamnative/pulsarctl/pkg/pulsar/common" + pulsarcommon "github.com/streamnative/pulsarctl/pkg/pulsar/common" "github.com/streamnative/pulsarctl/pkg/pulsar/utils" + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/framework" ) @@ -20,11 +21,11 @@ type PulsarctlParam struct { } func (s *disconnectState) PulsarctlCommand(ctx context.Context, p *PulsarctlParam) error { - config := common.Config{ + config := pulsarcommon.Config{ WebServiceURL: p.Address, AuthPlugin: p.AuthPlugin, AuthParams: p.AuthParam, - PulsarAPIVersion: common.V2, + PulsarAPIVersion: pulsarcommon.V2, } admin, err := pulsarctl.New(&config) if err != nil { @@ -37,7 +38,7 @@ func (s *disconnectState) PulsarctlCommand(ctx context.Context, p *PulsarctlPara return nil } -func getPulsarctlCmd(state State) *cobra.Command { +func getPulsarctlCmd(state common.State) *cobra.Command { cmd := &cobra.Command{ Use: "pulsarctl", Short: "connect to pulsar admin with pulsarctl", @@ -55,11 +56,11 @@ func getPulsarctlCmd(state State) *cobra.Command { fmt.Println(err.Error()) } - config := common.Config{ + config := pulsarcommon.Config{ WebServiceURL: address, AuthPlugin: authPlugin, AuthParams: authParams, - PulsarAPIVersion: common.V2, + PulsarAPIVersion: pulsarcommon.V2, } admin, err := pulsarctl.New(&config) if err != nil { @@ -78,10 +79,10 @@ func getPulsarctlCmd(state State) *cobra.Command { return cmd } -func getPulsarAdminState(admin pulsarctl.Client, addr string) State { +func getPulsarAdminState(admin pulsarctl.Client, addr string) common.State { state := &pulsarAdminState{ - cmdState: cmdState{ - label: fmt.Sprintf("PulsarAdmin(%s)", addr), + CmdState: common.CmdState{ + LabelStr: fmt.Sprintf("PulsarAdmin(%s)", addr), }, admin: admin, addr: addr, @@ -91,7 +92,7 @@ func getPulsarAdminState(admin pulsarctl.Client, addr string) State { } type pulsarAdminState struct { - cmdState + common.CmdState admin pulsarctl.Client addr string @@ -112,8 +113,8 @@ func (s *pulsarAdminState) SetupCommands() { getExitCmd(s), ) - s.cmdState.rootCmd = cmd - s.setupFn = s.SetupCommands + s.CmdState.RootCmd = cmd + s.SetupFn = s.SetupCommands } func getListTopicCmd(admin pulsarctl.Client) *cobra.Command { diff --git a/states/start.go b/states/start.go index bf9468dc..fbc7a984 100644 --- a/states/start.go +++ b/states/start.go @@ -1,13 +1,14 @@ package states import ( + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/configs" "github.com/milvus-io/birdwatcher/models" etcdversion "github.com/milvus-io/birdwatcher/states/etcd/version" ) // Start returns the first state - offline. -func Start(config *configs.Config) State { +func Start(config *configs.Config) common.State { app := &ApplicationState{ State: getDisconnectedState(config), config: config, @@ -22,7 +23,7 @@ func Start(config *configs.Config) State { // used for state switch/merging. type ApplicationState struct { // current state - State + common.State // config stores configuration items config *configs.Config diff --git a/states/util.go b/states/util.go index 2530bb3c..2df6529b 100644 --- a/states/util.go +++ b/states/util.go @@ -28,60 +28,11 @@ import ( clientv3 "go.etcd.io/etcd/client/v3" - "github.com/milvus-io/birdwatcher/common" - "github.com/milvus-io/birdwatcher/framework" "github.com/milvus-io/birdwatcher/models" "github.com/milvus-io/birdwatcher/proto/v2.0/datapb" stateCommon "github.com/milvus-io/birdwatcher/states/etcd/common" ) -const ( - logicalBits = 18 - logicalBitsMask = (1 << logicalBits) - 1 -) - -type ParseTSParam struct { - framework.ParamBase `use:"parse-ts" desc:"parse hybrid timestamp"` - args []string -} - -func (p *ParseTSParam) ParseArgs(args []string) error { - p.args = args - return nil -} - -func (s *cmdState) ParseTSCommand(ctx context.Context, p *ParseTSParam) { - if len(p.args) == 0 { - fmt.Println("no ts provided") - } - - for _, arg := range p.args { - ts, err := strconv.ParseUint(arg, 10, 64) - if err != nil { - fmt.Printf("failed to parse ts from %s, err: %s\n", arg, err.Error()) - continue - } - - t, _ := ParseTS(ts) - fmt.Printf("Parse ts result, ts:%d, time: %v\n", ts, t) - } -} - -type PrintVerParam struct { - framework.ParamBase `use:"version" desc:"print version"` -} - -func (s *cmdState) PrintVersionCommand(ctx context.Context, _ *PrintVerParam) { - fmt.Println("Birdwatcher Version", common.Version) -} - -func ParseTS(ts uint64) (time.Time, uint64) { - logical := ts & logicalBitsMask - physical := ts >> logicalBits - physicalTime := time.Unix(int64(physical/1000), int64(physical)%1000*time.Millisecond.Nanoseconds()) - return physicalTime, logical -} - // listSessions returns all session func listSessionsByPrefix(cli clientv3.KV, prefix string) ([]*models.Session, error) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) diff --git a/states/visit.go b/states/visit.go index 5779b740..355331a0 100644 --- a/states/visit.go +++ b/states/visit.go @@ -13,6 +13,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/models" "github.com/milvus-io/birdwatcher/proto/v2.0/commonpb" "github.com/milvus-io/birdwatcher/proto/v2.0/datapb" @@ -24,7 +25,7 @@ import ( datapbv2 "github.com/milvus-io/birdwatcher/proto/v2.2/datapb" internalpbv2 "github.com/milvus-io/birdwatcher/proto/v2.2/internalpb" milvuspbv2 "github.com/milvus-io/birdwatcher/proto/v2.2/milvuspb" - "github.com/milvus-io/birdwatcher/states/etcd/common" + etcdcommon "github.com/milvus-io/birdwatcher/states/etcd/common" ) func getSessionTypes() []string { @@ -39,7 +40,7 @@ func getSessionTypes() []string { } } -func getVisitCmd(state State, cli clientv3.KV, basePath string) *cobra.Command { +func getVisitCmd(state common.State, cli clientv3.KV, basePath string) *cobra.Command { callCmd := &cobra.Command{ Use: "visit", Short: "enter state that could visit some service of component", @@ -52,7 +53,7 @@ func getVisitCmd(state State, cli clientv3.KV, basePath string) *cobra.Command { return callCmd } -func setNextState(sessionType string, conn *grpc.ClientConn, statePtr *State, session *models.Session) { +func setNextState(sessionType string, conn *grpc.ClientConn, statePtr *common.State, session *models.Session) { state := *statePtr switch sessionType { case "datacoord": @@ -82,7 +83,7 @@ func setNextState(sessionType string, conn *grpc.ClientConn, statePtr *State, se func getSessionConnect(cli clientv3.KV, basePath string, id int64, sessionType string) (session *models.Session, conn *grpc.ClientConn, err error) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - sessions, err := common.ListSessions(ctx, cli, basePath) + sessions, err := etcdcommon.ListSessions(ctx, cli, basePath) if err != nil { fmt.Println("failed to list session, err:", err.Error()) return nil, nil, err @@ -107,7 +108,7 @@ func getSessionConnect(cli clientv3.KV, basePath string, id int64, sessionType s return nil, nil, errors.New("invalid id") } -func getVisitSessionCmds(state State, cli clientv3.KV, basePath string) []*cobra.Command { +func getVisitSessionCmds(state common.State, cli clientv3.KV, basePath string) []*cobra.Command { sessionCmds := make([]*cobra.Command, 0, len(getSessionTypes())) sessionTypes := getSessionTypes() diff --git a/states/visit_datacoord.go b/states/visit_datacoord.go index 335af6f5..f9babd51 100644 --- a/states/visit_datacoord.go +++ b/states/visit_datacoord.go @@ -6,18 +6,19 @@ import ( "github.com/spf13/cobra" "google.golang.org/grpc" + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/models" "github.com/milvus-io/birdwatcher/proto/v2.0/datapb" datapbv2 "github.com/milvus-io/birdwatcher/proto/v2.2/datapb" ) type dataCoordState struct { - cmdState + common.CmdState session *models.Session client datapb.DataCoordClient clientv2 datapbv2.DataCoordClient conn *grpc.ClientConn - prevState State + prevState common.State } // SetupCommands setups the command. @@ -39,16 +40,16 @@ func (s *dataCoordState) SetupCommands() { getExitCmd(s), ) - s.mergeFunctionCommands(cmd, s) + s.MergeFunctionCommands(cmd, s) - s.cmdState.rootCmd = cmd - s.setupFn = s.SetupCommands + s.CmdState.RootCmd = cmd + s.SetupFn = s.SetupCommands } -func getDataCoordState(client datapb.DataCoordClient, conn *grpc.ClientConn, prev State, session *models.Session) State { +func getDataCoordState(client datapb.DataCoordClient, conn *grpc.ClientConn, prev common.State, session *models.Session) common.State { state := &dataCoordState{ - cmdState: cmdState{ - label: fmt.Sprintf("DataCoord-%d(%s)", session.ServerID, session.Address), + CmdState: common.CmdState{ + LabelStr: fmt.Sprintf("DataCoord-%d(%s)", session.ServerID, session.Address), }, session: session, client: client, diff --git a/states/visit_datanode.go b/states/visit_datanode.go index ac3124be..f3560b80 100644 --- a/states/visit_datanode.go +++ b/states/visit_datanode.go @@ -6,18 +6,19 @@ import ( "github.com/spf13/cobra" "google.golang.org/grpc" + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/models" "github.com/milvus-io/birdwatcher/proto/v2.0/datapb" datapbv2 "github.com/milvus-io/birdwatcher/proto/v2.2/datapb" ) type dataNodeState struct { - cmdState + common.CmdState session *models.Session client datapb.DataNodeClient clientv2 datapbv2.DataNodeClient conn *grpc.ClientConn - prevState State + prevState common.State } // SetupCommands setups the command. @@ -35,16 +36,16 @@ func (s *dataNodeState) SetupCommands() { getExitCmd(s), ) - s.mergeFunctionCommands(cmd, s) + s.MergeFunctionCommands(cmd, s) - s.cmdState.rootCmd = cmd - s.setupFn = s.SetupCommands + s.CmdState.RootCmd = cmd + s.SetupFn = s.SetupCommands } -func getDataNodeState(client datapb.DataNodeClient, conn *grpc.ClientConn, prev State, session *models.Session) State { +func getDataNodeState(client datapb.DataNodeClient, conn *grpc.ClientConn, prev common.State, session *models.Session) common.State { state := &dataNodeState{ - cmdState: cmdState{ - label: fmt.Sprintf("DataNode-%d(%s)", session.ServerID, session.Address), + CmdState: common.CmdState{ + LabelStr: fmt.Sprintf("DataNode-%d(%s)", session.ServerID, session.Address), }, session: session, client: client, diff --git a/states/visit_indexcoord.go b/states/visit_indexcoord.go index 65562bb0..637743c7 100644 --- a/states/visit_indexcoord.go +++ b/states/visit_indexcoord.go @@ -7,19 +7,20 @@ import ( "github.com/spf13/cobra" "google.golang.org/grpc" + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/models" "github.com/milvus-io/birdwatcher/proto/v2.0/indexpb" indexpbv2 "github.com/milvus-io/birdwatcher/proto/v2.2/indexpb" - "github.com/milvus-io/birdwatcher/states/etcd/common" + etcdcommon "github.com/milvus-io/birdwatcher/states/etcd/common" ) type indexCoordState struct { - cmdState + common.CmdState session *models.Session client indexpb.IndexCoordClient clientv2 indexpbv2.IndexCoordClient conn *grpc.ClientConn - prevState State + prevState common.State } // SetupCommands setups the command. @@ -39,16 +40,16 @@ func (s *indexCoordState) SetupCommands() { getExitCmd(s), ) - s.mergeFunctionCommands(cmd, s) + s.MergeFunctionCommands(cmd, s) - s.cmdState.rootCmd = cmd - s.setupFn = s.SetupCommands + s.CmdState.RootCmd = cmd + s.SetupFn = s.SetupCommands } -func getIndexCoordState(client indexpb.IndexCoordClient, conn *grpc.ClientConn, prev State, session *models.Session) State { +func getIndexCoordState(client indexpb.IndexCoordClient, conn *grpc.ClientConn, prev common.State, session *models.Session) common.State { state := &indexCoordState{ - cmdState: cmdState{ - label: fmt.Sprintf("IndexCoord-%d(%s)", session.ServerID, session.Address), + CmdState: common.CmdState{ + LabelStr: fmt.Sprintf("IndexCoord-%d(%s)", session.ServerID, session.Address), }, session: session, client: client, @@ -95,9 +96,9 @@ func printIndexV2(index *indexpbv2.IndexInfo) { fmt.Printf("Total Rows: %d\n", index.GetTotalRows()) indexParams := index.GetIndexParams() fmt.Printf("Index Type: %s\tMetric Type: %s\n", - common.GetKVPair(indexParams, "index_type"), - common.GetKVPair(indexParams, "metric_type"), + etcdcommon.GetKVPair(indexParams, "index_type"), + etcdcommon.GetKVPair(indexParams, "metric_type"), ) - fmt.Printf("Index Params: %s\n", common.GetKVPair(index.GetUserIndexParams(), "params")) + fmt.Printf("Index Params: %s\n", etcdcommon.GetKVPair(index.GetUserIndexParams(), "params")) fmt.Println("==================================================================") } diff --git a/states/visit_indexnode.go b/states/visit_indexnode.go index 5ccb8dd1..dad50a68 100644 --- a/states/visit_indexnode.go +++ b/states/visit_indexnode.go @@ -6,18 +6,19 @@ import ( "github.com/spf13/cobra" "google.golang.org/grpc" + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/models" "github.com/milvus-io/birdwatcher/proto/v2.0/indexpb" indexpbv2 "github.com/milvus-io/birdwatcher/proto/v2.2/indexpb" ) type indexNodeState struct { - cmdState + common.CmdState session *models.Session client indexpb.IndexNodeClient clientv2 indexpbv2.IndexNodeClient conn *grpc.ClientConn - prevState State + prevState common.State } // SetupCommands setups the command. @@ -34,16 +35,16 @@ func (s *indexNodeState) SetupCommands() { // exit getExitCmd(s), ) - s.mergeFunctionCommands(cmd, s) + s.MergeFunctionCommands(cmd, s) - s.cmdState.rootCmd = cmd - s.setupFn = s.SetupCommands + s.CmdState.RootCmd = cmd + s.SetupFn = s.SetupCommands } -func getIndexNodeState(client indexpb.IndexNodeClient, conn *grpc.ClientConn, prev State, session *models.Session) State { +func getIndexNodeState(client indexpb.IndexNodeClient, conn *grpc.ClientConn, prev common.State, session *models.Session) common.State { state := &indexNodeState{ - cmdState: cmdState{ - label: fmt.Sprintf("IndexNode-%d(%s)", session.ServerID, session.Address), + CmdState: common.CmdState{ + LabelStr: fmt.Sprintf("IndexNode-%d(%s)", session.ServerID, session.Address), }, session: session, client: client, diff --git a/states/visit_querycoord.go b/states/visit_querycoord.go index e058814b..307963d2 100644 --- a/states/visit_querycoord.go +++ b/states/visit_querycoord.go @@ -11,6 +11,7 @@ import ( "github.com/spf13/cobra" "google.golang.org/grpc" + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/models" "github.com/milvus-io/birdwatcher/proto/v2.0/querypb" "github.com/milvus-io/birdwatcher/proto/v2.2/commonpb" @@ -18,12 +19,12 @@ import ( ) type queryCoordState struct { - cmdState + common.CmdState session *models.Session client querypb.QueryCoordClient clientv2 querypbv2.QueryCoordClient conn *grpc.ClientConn - prevState State + prevState common.State } // SetupCommands setups the command. @@ -41,10 +42,10 @@ func (s *queryCoordState) SetupCommands() { getExitCmd(s), checkerActivationCmd(s.clientv2, s.session.ServerID), ) - s.mergeFunctionCommands(cmd, s) + s.MergeFunctionCommands(cmd, s) - s.cmdState.rootCmd = cmd - s.setupFn = s.SetupCommands + s.CmdState.RootCmd = cmd + s.SetupFn = s.SetupCommands } /* @@ -79,10 +80,10 @@ func (s *queryCoordState) ShowCollectionCmd() *cobra.Command { return cmd }*/ -func getQueryCoordState(client querypb.QueryCoordClient, conn *grpc.ClientConn, prev State, session *models.Session) State { +func getQueryCoordState(client querypb.QueryCoordClient, conn *grpc.ClientConn, prev common.State, session *models.Session) common.State { state := &queryCoordState{ - cmdState: cmdState{ - label: fmt.Sprintf("QueryCoord-%d(%s)", session.ServerID, session.Address), + CmdState: common.CmdState{ + LabelStr: fmt.Sprintf("QueryCoord-%d(%s)", session.ServerID, session.Address), }, session: session, client: client, diff --git a/states/visit_querynode.go b/states/visit_querynode.go index 75e85f35..766ae79e 100644 --- a/states/visit_querynode.go +++ b/states/visit_querynode.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/cobra" "google.golang.org/grpc" + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/models" "github.com/milvus-io/birdwatcher/proto/v2.0/commonpb" "github.com/milvus-io/birdwatcher/proto/v2.0/querypb" @@ -16,12 +17,12 @@ import ( ) type queryNodeState struct { - cmdState + common.CmdState session *models.Session client querypb.QueryNodeClient clientv2 querypbv2.QueryNodeClient conn *grpc.ClientConn - prevState State + prevState common.State } // SetupCommands setups the command. @@ -45,16 +46,16 @@ func (s *queryNodeState) SetupCommands() { getExitCmd(s), ) - s.mergeFunctionCommands(cmd, s) + s.MergeFunctionCommands(cmd, s) - s.cmdState.rootCmd = cmd - s.setupFn = s.SetupCommands + s.CmdState.RootCmd = cmd + s.SetupFn = s.SetupCommands } -func getQueryNodeState(client querypb.QueryNodeClient, conn *grpc.ClientConn, prev State, session *models.Session) State { +func getQueryNodeState(client querypb.QueryNodeClient, conn *grpc.ClientConn, prev common.State, session *models.Session) common.State { state := &queryNodeState{ - cmdState: cmdState{ - label: fmt.Sprintf("QueryNode-%d(%s)", session.ServerID, session.Address), + CmdState: common.CmdState{ + LabelStr: fmt.Sprintf("QueryNode-%d(%s)", session.ServerID, session.Address), }, session: session, client: client, @@ -68,7 +69,7 @@ func getQueryNodeState(client querypb.QueryNodeClient, conn *grpc.ClientConn, pr return state } -func getBackCmd(state, prev State) *cobra.Command { +func getBackCmd(state, prev common.State) *cobra.Command { return &cobra.Command{ Use: "back", Run: func(cmd *cobra.Command, args []string) { diff --git a/states/visit_rootcoord.go b/states/visit_rootcoord.go index ff0ef325..4f48de18 100644 --- a/states/visit_rootcoord.go +++ b/states/visit_rootcoord.go @@ -6,18 +6,19 @@ import ( "github.com/spf13/cobra" "google.golang.org/grpc" + "github.com/milvus-io/birdwatcher/common" "github.com/milvus-io/birdwatcher/models" "github.com/milvus-io/birdwatcher/proto/v2.0/rootcoordpb" rootcoordpbv2 "github.com/milvus-io/birdwatcher/proto/v2.2/rootcoordpb" ) type rootCoordState struct { - cmdState + common.CmdState session *models.Session client rootcoordpb.RootCoordClient clientv2 rootcoordpbv2.RootCoordClient conn *grpc.ClientConn - prevState State + prevState common.State } // SetupCommands setups the command. @@ -34,17 +35,17 @@ func (s *rootCoordState) SetupCommands() { // exit getExitCmd(s), ) - s.mergeFunctionCommands(cmd, s) + s.MergeFunctionCommands(cmd, s) - s.cmdState.rootCmd = cmd - s.setupFn = s.SetupCommands + s.CmdState.RootCmd = cmd + s.SetupFn = s.SetupCommands } -func getRootCoordState(client rootcoordpb.RootCoordClient, conn *grpc.ClientConn, prev State, session *models.Session) State { +func getRootCoordState(client rootcoordpb.RootCoordClient, conn *grpc.ClientConn, prev common.State, session *models.Session) common.State { state := &rootCoordState{ session: session, - cmdState: cmdState{ - label: fmt.Sprintf("RootCoord-%d(%s)", session.ServerID, session.Address), + CmdState: common.CmdState{ + LabelStr: fmt.Sprintf("RootCoord-%d(%s)", session.ServerID, session.Address), }, client: client, clientv2: rootcoordpbv2.NewRootCoordClient(conn), diff --git a/states/web.go b/states/web.go index a879e1a2..c86f47a3 100644 --- a/states/web.go +++ b/states/web.go @@ -9,12 +9,13 @@ import ( "github.com/spf13/cobra" clientv3 "go.etcd.io/etcd/client/v3" - "github.com/milvus-io/birdwatcher/states/etcd/common" + "github.com/milvus-io/birdwatcher/common" + etcdcommon "github.com/milvus-io/birdwatcher/states/etcd/common" etcdversion "github.com/milvus-io/birdwatcher/states/etcd/version" ) // getCmdCmd returns exit command for input state. -func getWebCmd(state State, cli clientv3.KV, basePath string) *cobra.Command { +func getWebCmd(state common.State, cli clientv3.KV, basePath string) *cobra.Command { cmd := &cobra.Command{ Use: "web", Short: "start a web server to see more details on browser", @@ -44,7 +45,7 @@ func ginHandler(cli clientv3.KV, basePath string) http.Handler { c.String(http.StatusOK, "pong") }) r.GET("/collections", func(c *gin.Context) { - collections, err := common.ListCollectionsVersion(c, cli, basePath, etcdversion.GetVersion()) + collections, err := etcdcommon.ListCollectionsVersion(c, cli, basePath, etcdversion.GetVersion()) if err != nil { c.Error(err) return