etcdctl: support basic operations with etcd 0.4.

For CoreOS users, they will get a updated version of etcdctl without updating
the etcd server version. And the users cannot really control this behavior.
We do not want to suddenly break them without enough communication.

So we still want the most basic opeartions like get, set, watch of etcdctl2 work
with etcd 0.4. This patches solve the incompability issue.
This commit is contained in:
Xiang Li 2015-12-17 18:56:30 -08:00
parent 916106c3a2
commit 6751727809

View File

@ -203,9 +203,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)
os.Exit(1)
}
if debug {
fmt.Fprintf(os.Stderr, "got endpoints(%s) after sync\n", strings.Join(hc.Endpoints(), ","))
@ -267,3 +277,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
}