|
@@ -76,9 +76,17 @@ func newEpHashKVCommand() *cobra.Command {
|
|
|
return hc
|
|
return hc
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+type epHealth struct {
|
|
|
|
|
+ Ep string `json:"endpoint"`
|
|
|
|
|
+ Health bool `json:"health"`
|
|
|
|
|
+ Took string `json:"took"`
|
|
|
|
|
+ Error string `json:"error,omitempty"`
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// epHealthCommandFunc executes the "endpoint-health" command.
|
|
// epHealthCommandFunc executes the "endpoint-health" command.
|
|
|
func epHealthCommandFunc(cmd *cobra.Command, args []string) {
|
|
func epHealthCommandFunc(cmd *cobra.Command, args []string) {
|
|
|
flags.SetPflagsFromEnv("ETCDCTL", cmd.InheritedFlags())
|
|
flags.SetPflagsFromEnv("ETCDCTL", cmd.InheritedFlags())
|
|
|
|
|
+ initDisplayFromCmd(cmd)
|
|
|
|
|
|
|
|
sec := secureCfgFromCmd(cmd)
|
|
sec := secureCfgFromCmd(cmd)
|
|
|
dt := dialTimeoutFromCmd(cmd)
|
|
dt := dialTimeoutFromCmd(cmd)
|
|
@@ -95,7 +103,7 @@ func epHealthCommandFunc(cmd *cobra.Command, args []string) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
var wg sync.WaitGroup
|
|
var wg sync.WaitGroup
|
|
|
- errc := make(chan error, len(cfgs))
|
|
|
|
|
|
|
+ hch := make(chan epHealth, len(cfgs))
|
|
|
for _, cfg := range cfgs {
|
|
for _, cfg := range cfgs {
|
|
|
wg.Add(1)
|
|
wg.Add(1)
|
|
|
go func(cfg *v3.Config) {
|
|
go func(cfg *v3.Config) {
|
|
@@ -103,7 +111,7 @@ func epHealthCommandFunc(cmd *cobra.Command, args []string) {
|
|
|
ep := cfg.Endpoints[0]
|
|
ep := cfg.Endpoints[0]
|
|
|
cli, err := v3.New(*cfg)
|
|
cli, err := v3.New(*cfg)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
- errc <- fmt.Errorf("%s is unhealthy: failed to connect: %v", ep, err)
|
|
|
|
|
|
|
+ hch <- epHealth{Ep: ep, Health: false, Error: err.Error()}
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
st := time.Now()
|
|
st := time.Now()
|
|
@@ -112,25 +120,29 @@ func epHealthCommandFunc(cmd *cobra.Command, args []string) {
|
|
|
ctx, cancel := commandCtx(cmd)
|
|
ctx, cancel := commandCtx(cmd)
|
|
|
_, err = cli.Get(ctx, "health")
|
|
_, err = cli.Get(ctx, "health")
|
|
|
cancel()
|
|
cancel()
|
|
|
|
|
+ eh := epHealth{Ep: ep, Health: false, Took: time.Since(st).String()}
|
|
|
// permission denied is OK since proposal goes through consensus to get it
|
|
// permission denied is OK since proposal goes through consensus to get it
|
|
|
if err == nil || err == rpctypes.ErrPermissionDenied {
|
|
if err == nil || err == rpctypes.ErrPermissionDenied {
|
|
|
- fmt.Printf("%s is healthy: successfully committed proposal: took = %v\n", ep, time.Since(st))
|
|
|
|
|
|
|
+ eh.Health = true
|
|
|
} else {
|
|
} else {
|
|
|
- errc <- fmt.Errorf("%s is unhealthy: failed to commit proposal: %v", ep, err)
|
|
|
|
|
|
|
+ eh.Error = err.Error()
|
|
|
}
|
|
}
|
|
|
|
|
+ hch <- eh
|
|
|
}(cfg)
|
|
}(cfg)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
wg.Wait()
|
|
wg.Wait()
|
|
|
- close(errc)
|
|
|
|
|
|
|
+ close(hch)
|
|
|
|
|
|
|
|
errs := false
|
|
errs := false
|
|
|
- for err := range errc {
|
|
|
|
|
- if err != nil {
|
|
|
|
|
|
|
+ healthList := []epHealth{}
|
|
|
|
|
+ for h := range hch {
|
|
|
|
|
+ healthList = append(healthList, h)
|
|
|
|
|
+ if h.Error != "" {
|
|
|
errs = true
|
|
errs = true
|
|
|
- fmt.Fprintln(os.Stderr, err)
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ display.EndpointHealth(healthList)
|
|
|
if errs {
|
|
if errs {
|
|
|
ExitWithError(ExitError, fmt.Errorf("unhealthy cluster"))
|
|
ExitWithError(ExitError, fmt.Errorf("unhealthy cluster"))
|
|
|
}
|
|
}
|