|
@@ -28,6 +28,7 @@ import (
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
var epClusterEndpoints bool
|
|
var epClusterEndpoints bool
|
|
|
|
|
+var epHashKVRev int64
|
|
|
|
|
|
|
|
// NewEndpointCommand returns the cobra command for "endpoint".
|
|
// NewEndpointCommand returns the cobra command for "endpoint".
|
|
|
func NewEndpointCommand() *cobra.Command {
|
|
func NewEndpointCommand() *cobra.Command {
|
|
@@ -39,6 +40,7 @@ func NewEndpointCommand() *cobra.Command {
|
|
|
ec.PersistentFlags().BoolVar(&epClusterEndpoints, "cluster", false, "use all endpoints from the cluster member list")
|
|
ec.PersistentFlags().BoolVar(&epClusterEndpoints, "cluster", false, "use all endpoints from the cluster member list")
|
|
|
ec.AddCommand(newEpHealthCommand())
|
|
ec.AddCommand(newEpHealthCommand())
|
|
|
ec.AddCommand(newEpStatusCommand())
|
|
ec.AddCommand(newEpStatusCommand())
|
|
|
|
|
+ ec.AddCommand(newEpHashKVCommand())
|
|
|
|
|
|
|
|
return ec
|
|
return ec
|
|
|
}
|
|
}
|
|
@@ -64,6 +66,16 @@ The items in the lists are endpoint, ID, version, db size, is leader, raft term,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func newEpHashKVCommand() *cobra.Command {
|
|
|
|
|
+ hc := &cobra.Command{
|
|
|
|
|
+ Use: "hashkv",
|
|
|
|
|
+ Short: "Prints the KV history hash for each endpoint in --endpoints",
|
|
|
|
|
+ Run: epHashKVCommandFunc,
|
|
|
|
|
+ }
|
|
|
|
|
+ hc.PersistentFlags().Int64Var(&epHashKVRev, "rev", 0, "maximum revision to hash (default: all revisions)")
|
|
|
|
|
+ return hc
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// 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())
|
|
@@ -151,6 +163,35 @@ func epStatusCommandFunc(cmd *cobra.Command, args []string) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+type epHashKV struct {
|
|
|
|
|
+ Ep string `json:"Endpoint"`
|
|
|
|
|
+ Resp *v3.HashKVResponse `json:"HashKV"`
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func epHashKVCommandFunc(cmd *cobra.Command, args []string) {
|
|
|
|
|
+ c := mustClientFromCmd(cmd)
|
|
|
|
|
+
|
|
|
|
|
+ hashList := []epHashKV{}
|
|
|
|
|
+ var err error
|
|
|
|
|
+ for _, ep := range endpointsFromCluster(cmd) {
|
|
|
|
|
+ ctx, cancel := commandCtx(cmd)
|
|
|
|
|
+ resp, serr := c.HashKV(ctx, ep, epHashKVRev)
|
|
|
|
|
+ cancel()
|
|
|
|
|
+ if serr != nil {
|
|
|
|
|
+ err = serr
|
|
|
|
|
+ fmt.Fprintf(os.Stderr, "Failed to get the hash of endpoint %s (%v)\n", ep, serr)
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+ hashList = append(hashList, epHashKV{Ep: ep, Resp: resp})
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ display.EndpointHashKV(hashList)
|
|
|
|
|
+
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ ExitWithError(ExitError, err)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func endpointsFromCluster(cmd *cobra.Command) []string {
|
|
func endpointsFromCluster(cmd *cobra.Command) []string {
|
|
|
if !epClusterEndpoints {
|
|
if !epClusterEndpoints {
|
|
|
endpoints, err := cmd.Flags().GetStringSlice("endpoints")
|
|
endpoints, err := cmd.Flags().GetStringSlice("endpoints")
|