diff --git a/clientv3/maintenance.go b/clientv3/maintenance.go index 75c0df705..063426cdc 100644 --- a/clientv3/maintenance.go +++ b/clientv3/maintenance.go @@ -46,7 +46,7 @@ type Maintenance interface { // times with different endpoints. Defragment(ctx context.Context, endpoint string) (*DefragmentResponse, error) - // Status gets the status of the member. + // Status gets the status of the endpoint. Status(ctx context.Context, endpoint string) (*StatusResponse, error) // Snapshot provides a reader for a snapshot of a backend. diff --git a/e2e/ctl_v3_test.go b/e2e/ctl_v3_test.go index 5ac18ae05..db5ef1de2 100644 --- a/e2e/ctl_v3_test.go +++ b/e2e/ctl_v3_test.go @@ -532,7 +532,7 @@ func ctlV3Version(cx ctlCtx) error { } func ctlV3EpHealth(cx ctlCtx) error { - cmdArgs := append(ctlV3PrefixArgs(cx.epc, cx.dialTimeout), "endpoint-health") + cmdArgs := append(ctlV3PrefixArgs(cx.epc, cx.dialTimeout), "endpoint health") lines := make([]string, cx.epc.cfg.clusterSize) for i := range lines { lines[i] = "is healthy" diff --git a/etcdctl/ctlv3/command/ep_health_command.go b/etcdctl/ctlv3/command/ep_command.go similarity index 58% rename from etcdctl/ctlv3/command/ep_health_command.go rename to etcdctl/ctlv3/command/ep_command.go index 64a57bec3..27ac820d4 100644 --- a/etcdctl/ctlv3/command/ep_health_command.go +++ b/etcdctl/ctlv3/command/ep_command.go @@ -16,24 +16,45 @@ package command import ( "fmt" + "os" "sync" "time" - "github.com/coreos/etcd/clientv3" + v3 "github.com/coreos/etcd/clientv3" "github.com/coreos/etcd/pkg/flags" "github.com/spf13/cobra" ) -// NewEpHealthCommand returns the cobra command for "endpoint-health". -func NewEpHealthCommand() *cobra.Command { +// NewEndpointCommand returns the cobra command for "endpoint". +func NewEndpointCommand() *cobra.Command { + ec := &cobra.Command{ + Use: "endpoint", + Short: "endpoint is used to check endpoints.", + } + + ec.AddCommand(newEpHealthCommand()) + ec.AddCommand(newEpStatusCommand()) + + return ec +} + +func newEpHealthCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "endpoint-health", - Short: "endpoint-health checks the healthiness of endpoints specified in `--endpoints` flag", + Use: "health", + Short: "health checks the healthiness of endpoints specified in `--endpoints` flag", Run: epHealthCommandFunc, } return cmd } +func newEpStatusCommand() *cobra.Command { + return &cobra.Command{ + Use: "status", + Short: "status prints out the status of endpoints specified in `--endpoints` flag", + Run: epStatusCommandFunc, + } +} + // epHealthCommandFunc executes the "endpoint-health" command. func epHealthCommandFunc(cmd *cobra.Command, args []string) { flags.SetPflagsFromEnv("ETCDCTL", cmd.InheritedFlags()) @@ -44,7 +65,7 @@ func epHealthCommandFunc(cmd *cobra.Command, args []string) { sec := secureCfgFromCmd(cmd) dt := dialTimeoutFromCmd(cmd) - cfgs := []*clientv3.Config{} + cfgs := []*v3.Config{} for _, ep := range endpoints { cfg, err := newClientCfg([]string{ep}, dt, sec) if err != nil { @@ -57,10 +78,10 @@ func epHealthCommandFunc(cmd *cobra.Command, args []string) { for _, cfg := range cfgs { wg.Add(1) - go func(cfg *clientv3.Config) { + go func(cfg *v3.Config) { defer wg.Done() ep := cfg.Endpoints[0] - cli, err := clientv3.New(*cfg) + cli, err := v3.New(*cfg) if err != nil { fmt.Printf("%s is unhealthy: failed to connect: %v\n", ep, err) return @@ -81,3 +102,32 @@ func epHealthCommandFunc(cmd *cobra.Command, args []string) { wg.Wait() } + +type epStatus struct { + ep string + resp *v3.StatusResponse +} + +func epStatusCommandFunc(cmd *cobra.Command, args []string) { + c := mustClientFromCmd(cmd) + + statusList := []epStatus{} + var err error + for _, ep := range c.Endpoints() { + ctx, cancel := commandCtx(cmd) + resp, serr := c.Status(ctx, ep) + cancel() + if serr != nil { + err = serr + fmt.Fprintf(os.Stderr, "Failed to get the status of endpoint %s (%v)\n", ep, serr) + continue + } + statusList = append(statusList, epStatus{ep: ep, resp: resp}) + } + + display.EndpointStatus(statusList) + + if err != nil { + os.Exit(ExitError) + } +} diff --git a/etcdctl/ctlv3/command/printer.go b/etcdctl/ctlv3/command/printer.go index 59ccaad6c..7c6c8a485 100644 --- a/etcdctl/ctlv3/command/printer.go +++ b/etcdctl/ctlv3/command/printer.go @@ -37,7 +37,7 @@ type printer interface { MemberList(v3.MemberListResponse) - MemberStatus([]statusInfo) + EndpointStatus([]epStatus) Alarm(v3.AlarmResponse) DBStatus(dbstatus) @@ -129,7 +129,7 @@ func (s *simplePrinter) MemberList(resp v3.MemberListResponse) { table.Render() } -func (s *simplePrinter) MemberStatus(statusList []statusInfo) { +func (s *simplePrinter) EndpointStatus(statusList []epStatus) { table := tablewriter.NewWriter(os.Stdout) table.SetHeader([]string{"endpoint", "ID", "version", "db size", "is leader", "raft term", "raft index"}) @@ -175,7 +175,7 @@ func (p *jsonPrinter) Txn(r v3.TxnResponse) { printJSON(r) } func (p *jsonPrinter) Watch(r v3.WatchResponse) { printJSON(r) } func (p *jsonPrinter) Alarm(r v3.AlarmResponse) { printJSON(r) } func (p *jsonPrinter) MemberList(r v3.MemberListResponse) { printJSON(r) } -func (p *jsonPrinter) MemberStatus(r []statusInfo) { printJSON(r) } +func (p *jsonPrinter) EndpointStatus(r []epStatus) { printJSON(r) } func (p *jsonPrinter) DBStatus(r dbstatus) { printJSON(r) } func printJSON(v interface{}) { @@ -223,7 +223,7 @@ func (pb *pbPrinter) MemberList(r v3.MemberListResponse) { ExitWithError(ExitBadFeature, errors.New("only support simple or json as output format")) } -func (pb *pbPrinter) MemberStatus(r []statusInfo) { +func (pb *pbPrinter) EndpointStatus(statusList []epStatus) { ExitWithError(ExitBadFeature, errors.New("only support simple or json as output format")) } diff --git a/etcdctl/ctlv3/command/status_command.go b/etcdctl/ctlv3/command/status_command.go deleted file mode 100644 index c35fcb4ec..000000000 --- a/etcdctl/ctlv3/command/status_command.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2016 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package command - -import ( - "fmt" - "os" - - v3 "github.com/coreos/etcd/clientv3" - "github.com/spf13/cobra" -) - -// NewStatusCommand returns the cobra command for "Status". -func NewStatusCommand() *cobra.Command { - return &cobra.Command{ - Use: "status", - Short: "status prints out the statuses of the members with given endpoints.", - Run: statusCommandFunc, - } -} - -type statusInfo struct { - ep string - resp *v3.StatusResponse -} - -func statusCommandFunc(cmd *cobra.Command, args []string) { - c := mustClientFromCmd(cmd) - - statusList := []statusInfo{} - var err error - for _, ep := range c.Endpoints() { - ctx, cancel := commandCtx(cmd) - resp, serr := c.Status(ctx, ep) - cancel() - if serr != nil { - err = serr - fmt.Fprintf(os.Stderr, "Failed to get the status of endpoint %s (%v)", ep, serr) - continue - } - statusList = append(statusList, statusInfo{ep: ep, resp: resp}) - } - - display.MemberStatus(statusList) - - if err != nil { - os.Exit(ExitError) - } -} diff --git a/etcdctl/ctlv3/ctl.go b/etcdctl/ctlv3/ctl.go index 05a9b8749..017cbc562 100644 --- a/etcdctl/ctlv3/ctl.go +++ b/etcdctl/ctlv3/ctl.go @@ -66,12 +66,11 @@ func init() { command.NewCompactionCommand(), command.NewAlarmCommand(), command.NewDefragCommand(), - command.NewStatusCommand(), + command.NewEndpointCommand(), command.NewWatchCommand(), command.NewVersionCommand(), command.NewLeaseCommand(), command.NewMemberCommand(), - command.NewEpHealthCommand(), command.NewSnapshotCommand(), command.NewMakeMirrorCommand(), command.NewLockCommand(),