etcdctl: --cluster flag using cluster endpoints for endpoint commands

Queries the cluster for endpoints to use for the endpoint commands.

Fixes #8117
release-3.3
Anthony Romano 2017-06-20 15:24:50 -07:00
parent a40cdc7baa
commit 1a2be432c5
2 changed files with 62 additions and 19 deletions

View File

@ -565,6 +565,10 @@ Prints a humanized table of the member IDs, statuses, names, peer addresses, and
ENDPOINT provides commands for querying individual endpoints. ENDPOINT provides commands for querying individual endpoints.
#### Options
- cluster -- fetch and use all endpoints from the etcd cluster member list
### ENDPOINT HEALTH ### ENDPOINT HEALTH
ENDPOINT HEALTH checks the health of the list of endpoints with respect to cluster. An endpoint is unhealthy ENDPOINT HEALTH checks the health of the list of endpoints with respect to cluster. An endpoint is unhealthy
@ -576,11 +580,20 @@ If an endpoint can participate in consensus, prints a message indicating the end
#### Example #### Example
Check the default endpoint's health:
```bash ```bash
./etcdctl endpoint health ./etcdctl endpoint health
# 127.0.0.1:32379 is healthy: successfully committed proposal: took = 2.130877ms
# 127.0.0.1:2379 is healthy: successfully committed proposal: took = 2.095242ms # 127.0.0.1:2379 is healthy: successfully committed proposal: took = 2.095242ms
# 127.0.0.1:22379 is healthy: successfully committed proposal: took = 2.083263ms ```
Check all endpoints for the cluster associated with the default endpoint:
```bash
./etcdctl endpoint --cluster health
# http://127.0.0.1:2379 is healthy: successfully committed proposal: took = 1.060091ms
# http://127.0.0.1:22379 is healthy: successfully committed proposal: took = 903.138µs
# http://127.0.0.1:32379 is healthy: successfully committed proposal: took = 1.113848ms
``` ```
### ENDPOINT STATUS ### ENDPOINT STATUS
@ -599,27 +612,31 @@ Prints a line of JSON encoding each endpoint URL, ID, version, database size, le
#### Examples #### Examples
Get the status for the default endpoint:
```bash ```bash
./etcdctl endpoint status ./etcdctl endpoint status
# 127.0.0.1:2379, 8211f1d0f64f3269, 3.0.0, 25 kB, false, 2, 63 # 127.0.0.1:2379, 8211f1d0f64f3269, 3.0.0, 25 kB, false, 2, 63
# 127.0.0.1:22379, 91bc3c398fb3c146, 3.0.0, 25 kB, false, 2, 63
# 127.0.0.1:32379, fd422379fda50e48, 3.0.0, 25 kB, true, 2, 63
``` ```
Get the status for the default endpoint as JSON:
```bash ```bash
./etcdctl -w json endpoint status ./etcdctl -w json endpoint status
# [{"Endpoint":"127.0.0.1:2379","Status":{"header":{"cluster_id":17237436991929493444,"member_id":9372538179322589801,"revision":2,"raft_term":2},"version":"3.0.0","dbSize":24576,"leader":18249187646912138824,"raftIndex":32623,"raftTerm":2}},{"Endpoint":"127.0.0.1:22379","Status":{"header":{"cluster_id":17237436991929493444,"member_id":10501334649042878790,"revision":2,"raft_term":2},"version":"3.0.0","dbSize":24576,"leader":18249187646912138824,"raftIndex":32623,"raftTerm":2}},{"Endpoint":"127.0.0.1:32379","Status":{"header":{"cluster_id":17237436991929493444,"member_id":18249187646912138824,"revision":2,"raft_term":2},"version":"3.0.0","dbSize":24576,"leader":18249187646912138824,"raftIndex":32623,"raftTerm":2}}] # [{"Endpoint":"127.0.0.1:2379","Status":{"header":{"cluster_id":17237436991929493444,"member_id":9372538179322589801,"revision":2,"raft_term":2},"version":"3.0.0","dbSize":24576,"leader":18249187646912138824,"raftIndex":32623,"raftTerm":2}}]
``` ```
Get the status for all endpoints in the cluster associated with the default endpoint:
```bash ```bash
./etcdctl -w table endpoint status ./etcdctl -w table endpoint --cluster status
+-----------------+------------------+---------+---------+-----------+-----------+------------+ +------------------------+------------------+----------------+---------+-----------+-----------+------------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX | | ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+-----------------+------------------+---------+---------+-----------+-----------+------------+ +------------------------+------------------+----------------+---------+-----------+-----------+------------+
| 127.0.0.1:2379 | 8211f1d0f64f3269 | 3.0.0 | 25 kB | false | 2 | 52 | | http://127.0.0.1:2379 | 8211f1d0f64f3269 | 3.2.0-rc.1+git | 25 kB | false | 2 | 8 |
| 127.0.0.1:22379 | 91bc3c398fb3c146 | 3.0.0 | 25 kB | false | 2 | 52 | | http://127.0.0.1:22379 | 91bc3c398fb3c146 | 3.2.0-rc.1+git | 25 kB | false | 2 | 8 |
| 127.0.0.1:32379 | fd422379fda50e48 | 3.0.0 | 25 kB | true | 2 | 52 | | http://127.0.0.1:32379 | fd422379fda50e48 | 3.2.0-rc.1+git | 25 kB | true | 2 | 8 |
+-----------------+------------------+---------+---------+-----------+-----------+------------+ +------------------------+------------------+----------------+---------+-----------+-----------+------------+
``` ```
### ALARM \<subcommand\> ### ALARM \<subcommand\>

View File

@ -27,6 +27,8 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var epClusterEndpoints bool
// NewEndpointCommand returns the cobra command for "endpoint". // NewEndpointCommand returns the cobra command for "endpoint".
func NewEndpointCommand() *cobra.Command { func NewEndpointCommand() *cobra.Command {
ec := &cobra.Command{ ec := &cobra.Command{
@ -34,6 +36,7 @@ func NewEndpointCommand() *cobra.Command {
Short: "Endpoint related commands", Short: "Endpoint related commands",
} }
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())
@ -64,16 +67,12 @@ The items in the lists are endpoint, ID, version, db size, is leader, raft term,
// 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())
endpoints, err := cmd.Flags().GetStringSlice("endpoints")
if err != nil {
ExitWithError(ExitError, err)
}
sec := secureCfgFromCmd(cmd) sec := secureCfgFromCmd(cmd)
dt := dialTimeoutFromCmd(cmd) dt := dialTimeoutFromCmd(cmd)
auth := authCfgFromCmd(cmd) auth := authCfgFromCmd(cmd)
cfgs := []*v3.Config{} cfgs := []*v3.Config{}
for _, ep := range endpoints { for _, ep := range endpointsFromCluster(cmd) {
cfg, err := newClientCfg([]string{ep}, dt, sec, auth) cfg, err := newClientCfg([]string{ep}, dt, sec, auth)
if err != nil { if err != nil {
ExitWithError(ExitBadArgs, err) ExitWithError(ExitBadArgs, err)
@ -121,7 +120,7 @@ func epStatusCommandFunc(cmd *cobra.Command, args []string) {
statusList := []epStatus{} statusList := []epStatus{}
var err error var err error
for _, ep := range c.Endpoints() { for _, ep := range endpointsFromCluster(cmd) {
ctx, cancel := commandCtx(cmd) ctx, cancel := commandCtx(cmd)
resp, serr := c.Status(ctx, ep) resp, serr := c.Status(ctx, ep)
cancel() cancel()
@ -139,3 +138,30 @@ func epStatusCommandFunc(cmd *cobra.Command, args []string) {
os.Exit(ExitError) os.Exit(ExitError)
} }
} }
func endpointsFromCluster(cmd *cobra.Command) []string {
if !epClusterEndpoints {
endpoints, err := cmd.Flags().GetStringSlice("endpoints")
if err != nil {
ExitWithError(ExitError, err)
}
return endpoints
}
c := mustClientFromCmd(cmd)
ctx, cancel := commandCtx(cmd)
defer func() {
c.Close()
cancel()
}()
membs, err := c.MemberList(ctx)
if err != nil {
err = fmt.Errorf("failed to fetch endpoints from etcd cluster member list: %v", err)
ExitWithError(ExitError, err)
}
ret := []string{}
for _, m := range membs.Members {
ret = append(ret, m.ClientURLs...)
}
return ret
}