Skip to content

Commit

Permalink
Merge pull request etcd-io#4020 from xiang90/ctl_04
Browse files Browse the repository at this point in the history
etcdctl: support etcd0.4
  • Loading branch information
xiang90 committed Dec 21, 2015
2 parents 7e26fe9 + 541f2e5 commit 2681137
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 12 deletions.
11 changes: 8 additions & 3 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,11 @@ type Client interface {
// this may differ from the initial Endpoints provided in the Config.
Endpoints() []string

// SetEndpoints sets the set of API endpoints used by Client to resolve
// HTTP requests. If the given endpoints are not valid, an error will be
// returned
SetEndpoints(eps []string) error

httpClient
}

Expand All @@ -176,7 +181,7 @@ func New(cfg Config) (Client, error) {
password: cfg.Password,
}
}
if err := c.reset(cfg.Endpoints); err != nil {
if err := c.SetEndpoints(cfg.Endpoints); err != nil {
return nil, err
}
return c, nil
Expand Down Expand Up @@ -219,7 +224,7 @@ type httpClusterClient struct {
rand *rand.Rand
}

func (c *httpClusterClient) reset(eps []string) error {
func (c *httpClusterClient) SetEndpoints(eps []string) error {
if len(eps) == 0 {
return ErrNoEndpoints
}
Expand Down Expand Up @@ -341,7 +346,7 @@ func (c *httpClusterClient) Sync(ctx context.Context) error {
return nil
}

return c.reset(eps)
return c.SetEndpoints(eps)
}

func (c *httpClusterClient) AutoSync(ctx context.Context, interval time.Duration) error {
Expand Down
16 changes: 8 additions & 8 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ func TestHTTPClusterClientSync(t *testing.T) {
clientFactory: cf,
rand: rand.New(rand.NewSource(0)),
}
err := hc.reset([]string{"http://127.0.0.1:2379"})
err := hc.SetEndpoints([]string{"http://127.0.0.1:2379"})
if err != nil {
t.Fatalf("unexpected error during setup: %#v", err)
}
Expand All @@ -728,7 +728,7 @@ func TestHTTPClusterClientSync(t *testing.T) {
t.Fatalf("incorrect endpoints post-Sync: want=%#v got=%#v", want, got)
}

err = hc.reset([]string{"http://127.0.0.1:4009"})
err = hc.SetEndpoints([]string{"http://127.0.0.1:4009"})
if err != nil {
t.Fatalf("unexpected error during reset: %#v", err)
}
Expand All @@ -749,7 +749,7 @@ func TestHTTPClusterClientSyncFail(t *testing.T) {
clientFactory: cf,
rand: rand.New(rand.NewSource(0)),
}
err := hc.reset([]string{"http://127.0.0.1:2379"})
err := hc.SetEndpoints([]string{"http://127.0.0.1:2379"})
if err != nil {
t.Fatalf("unexpected error during setup: %#v", err)
}
Expand Down Expand Up @@ -783,7 +783,7 @@ func TestHTTPClusterClientAutoSyncCancelContext(t *testing.T) {
clientFactory: cf,
rand: rand.New(rand.NewSource(0)),
}
err := hc.reset([]string{"http://127.0.0.1:2379"})
err := hc.SetEndpoints([]string{"http://127.0.0.1:2379"})
if err != nil {
t.Fatalf("unexpected error during setup: %#v", err)
}
Expand All @@ -805,7 +805,7 @@ func TestHTTPClusterClientAutoSyncFail(t *testing.T) {
clientFactory: cf,
rand: rand.New(rand.NewSource(0)),
}
err := hc.reset([]string{"http://127.0.0.1:2379"})
err := hc.SetEndpoints([]string{"http://127.0.0.1:2379"})
if err != nil {
t.Fatalf("unexpected error during setup: %#v", err)
}
Expand Down Expand Up @@ -838,7 +838,7 @@ func TestHTTPClusterClientSyncPinEndpoint(t *testing.T) {
clientFactory: cf,
rand: rand.New(rand.NewSource(0)),
}
err := hc.reset([]string{"http://127.0.0.1:4003", "http://127.0.0.1:2379", "http://127.0.0.1:4001", "http://127.0.0.1:4002"})
err := hc.SetEndpoints([]string{"http://127.0.0.1:4003", "http://127.0.0.1:2379", "http://127.0.0.1:4001", "http://127.0.0.1:4002"})
if err != nil {
t.Fatalf("unexpected error during setup: %#v", err)
}
Expand Down Expand Up @@ -867,7 +867,7 @@ func TestHTTPClusterClientResetFail(t *testing.T) {

for i, tt := range tests {
hc := &httpClusterClient{rand: rand.New(rand.NewSource(0))}
err := hc.reset(tt)
err := hc.SetEndpoints(tt)
if err == nil {
t.Errorf("#%d: expected non-nil error", i)
}
Expand All @@ -879,7 +879,7 @@ func TestHTTPClusterClientResetPinRandom(t *testing.T) {
pinNum := 0
for i := 0; i < round; i++ {
hc := &httpClusterClient{rand: rand.New(rand.NewSource(int64(i)))}
err := hc.reset([]string{"http://127.0.0.1:4001", "http://127.0.0.1:4002", "http://127.0.0.1:4003"})
err := hc.SetEndpoints([]string{"http://127.0.0.1:4001", "http://127.0.0.1:4002", "http://127.0.0.1:4003"})
if err != nil {
t.Fatalf("#%d: reset error (%v)", i, err)
}
Expand Down
54 changes: 53 additions & 1 deletion etcdctl/command/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,19 @@ func mustNewClient(c *cli.Context) client.Client {
if err == client.ErrNoEndpoints {
fmt.Fprintf(os.Stderr, "etcd cluster has no published client endpoints.\n")
fmt.Fprintf(os.Stderr, "Try '--no-sync' if you want to access non-published client endpoints(%s).\n", strings.Join(hc.Endpoints(), ","))
handleError(ExitServerError, err)
}

// fail-back to try sync cluster with peer API. this is for making etcdctl work with etcd 0.4.x.
// TODO: remove this when we deprecate the support for etcd 0.4.
eps, serr := syncWithPeerAPI(c, ctx, hc.Endpoints())
if serr != nil {
handleError(ExitServerError, serr)
}
err = hc.SetEndpoints(eps)
if err != nil {
handleError(ExitServerError, err)
}
handleError(ExitServerError, err)
}
if debug {
fmt.Fprintf(os.Stderr, "got endpoints(%s) after sync\n", strings.Join(hc.Endpoints(), ","))
Expand Down Expand Up @@ -271,3 +282,44 @@ func newClient(c *cli.Context) (client.Client, error) {
func contextWithTotalTimeout(c *cli.Context) (context.Context, context.CancelFunc) {
return context.WithTimeout(context.Background(), c.GlobalDuration("total-timeout"))
}

// syncWithPeerAPI syncs cluster with peer API defined at
// https://github.com/coreos/etcd/blob/v0.4.9/server/server.go#L311.
// This exists for backward compatibility with etcd 0.4.x.
func syncWithPeerAPI(c *cli.Context, ctx context.Context, knownPeers []string) ([]string, error) {
tr, err := getTransport(c)
if err != nil {
return nil, err
}

var (
body []byte
resp *http.Response
)
for _, p := range knownPeers {
var req *http.Request
req, err = http.NewRequest("GET", p+"/v2/peers", nil)
if err != nil {
continue
}
resp, err = tr.RoundTrip(req)
if err != nil {
continue
}
if resp.StatusCode != http.StatusOK {
resp.Body.Close()
continue
}
body, err = ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
continue
}
}
if err != nil {
return nil, err
}

// Parse the peers API format: https://github.com/coreos/etcd/blob/v0.4.9/server/server.go#L311
return strings.Split(string(body), ", "), nil
}

0 comments on commit 2681137

Please sign in to comment.