etcdctl: move endpoint-heath and status into endpoint command

release-3.0
Xiang Li 2016-04-12 15:57:24 -07:00
parent a8b7d0b63c
commit ae9b251d99
6 changed files with 65 additions and 77 deletions

View File

@ -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.

View File

@ -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"

View File

@ -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)
}
}

View File

@ -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"))
}

View File

@ -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)
}
}

View File

@ -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(),