Merge pull request #2910 from xiang90/etcdctl

etcdctl: cleanup
This commit is contained in:
Xiang Li
2015-06-03 10:53:13 -07:00
13 changed files with 100 additions and 80 deletions

View File

@@ -27,11 +27,11 @@ func NewClusterHealthCommand() cli.Command {
func handleClusterHealth(c *cli.Context) {
endpoints, err := getEndpoints(c)
if err != nil {
handleError(ErrorFromEtcd, err)
handleError(ExitServerError, err)
}
tr, err := getTransport(c)
if err != nil {
handleError(ErrorFromEtcd, err)
handleError(ExitServerError, err)
}
client := etcd.NewClient(endpoints)
@@ -42,7 +42,7 @@ func handleClusterHealth(c *cli.Context) {
}
if ok := client.SyncCluster(); !ok {
handleError(FailedToConnectToHost, errors.New("cannot sync with the cluster using endpoints "+strings.Join(endpoints, ", ")))
handleError(ExitBadConnection, errors.New("cannot sync with the cluster using endpoints "+strings.Join(endpoints, ", ")))
}
// do we have a leader?

View File

@@ -20,11 +20,11 @@ import (
)
const (
SUCCESS = iota
MalformedEtcdctlArguments
FailedToConnectToHost
FailedToAuth
ErrorFromEtcd
ExitSuccess = iota
ExitBadArgs
ExitBadConnection
ExitBadAuth
ExitServerError
)
func handleError(code int, err error) {

74
etcdctl/command/format.go Normal file
View File

@@ -0,0 +1,74 @@
// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package command
import (
"encoding/json"
"fmt"
"os"
"github.com/coreos/etcd/Godeps/_workspace/src/github.com/coreos/go-etcd/etcd"
)
// printKey writes the etcd response to STDOUT in the given format.
func printKey(resp *etcd.Response, format string) {
// printKey is only for keys, error on directories
if resp.Node.Dir == true {
fmt.Fprintln(os.Stderr, fmt.Sprintf("Cannot print key [%s: Is a directory]", resp.Node.Key))
os.Exit(1)
}
printKeyOnly(resp, format)
}
// printAll prints the etcd response in the given format in its best efforts.
func printAll(resp *etcd.Response, format string) {
if resp.Node.Dir == true {
return
}
printKeyOnly(resp, format)
}
// printKeyOnly only supports to print key correctly.
func printKeyOnly(resp *etcd.Response, format string) {
// Format the result.
switch format {
case "simple":
fmt.Println(resp.Node.Value)
case "extended":
// Extended prints in a rfc2822 style format
fmt.Println("Key:", resp.Node.Key)
fmt.Println("Created-Index:", resp.Node.CreatedIndex)
fmt.Println("Modified-Index:", resp.Node.ModifiedIndex)
if resp.PrevNode != nil {
fmt.Println("PrevNode.Value:", resp.PrevNode.Value)
}
fmt.Println("TTL:", resp.Node.TTL)
fmt.Println("Etcd-Index:", resp.EtcdIndex)
fmt.Println("Raft-Index:", resp.RaftIndex)
fmt.Println("Raft-Term:", resp.RaftTerm)
fmt.Println("")
fmt.Println(resp.Node.Value)
case "json":
b, err := json.Marshal(resp)
if err != nil {
panic(err)
}
fmt.Println(string(b))
default:
fmt.Fprintln(os.Stderr, "Unsupported output format:", format)
}
}

View File

@@ -55,7 +55,7 @@ func printGet(resp *etcd.Response, format string) {
// getCommandFunc executes the "get" command.
func getCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, error) {
if len(c.Args()) == 0 {
return nil, errors.New("Key required")
return nil, errors.New("key required")
}
key := c.Args()[0]
sorted := c.Bool("sort")

View File

@@ -15,7 +15,6 @@
package command
import (
"encoding/json"
"errors"
"fmt"
"os"
@@ -60,7 +59,7 @@ func rawhandle(c *cli.Context, fn handlerFunc) (*etcd.Response, error) {
// Sync cluster.
if !c.GlobalBool("no-sync") {
if ok := client.SyncCluster(); !ok {
handleError(FailedToConnectToHost, errors.New("cannot sync with the cluster using endpoints "+strings.Join(endpoints, ", ")))
handleError(ExitBadConnection, errors.New("cannot sync with the cluster using endpoints "+strings.Join(endpoints, ", ")))
}
}
@@ -79,7 +78,7 @@ func handlePrint(c *cli.Context, fn handlerFunc, pFn printFunc) {
// Print error and exit, if necessary.
if err != nil {
handleError(ErrorFromEtcd, err)
handleError(ExitServerError, err)
}
if resp != nil && pFn != nil {
@@ -92,7 +91,7 @@ func handleContextualPrint(c *cli.Context, fn handlerFunc, pFn contextualPrintFu
resp, err := rawhandle(c, fn)
if err != nil {
handleError(ErrorFromEtcd, err)
handleError(ExitServerError, err)
}
if resp != nil && pFn != nil {
@@ -114,54 +113,3 @@ func handleKey(c *cli.Context, fn handlerFunc) {
func handleAll(c *cli.Context, fn handlerFunc) {
handlePrint(c, fn, printAll)
}
// printKey writes the etcd response to STDOUT in the given format.
func printKey(resp *etcd.Response, format string) {
// printKey is only for keys, error on directories
if resp.Node.Dir == true {
fmt.Fprintln(os.Stderr, fmt.Sprintf("Cannot print key [%s: Is a directory]", resp.Node.Key))
os.Exit(1)
}
printKeyOnly(resp, format)
}
// printAll prints the etcd response in the given format in its best efforts.
func printAll(resp *etcd.Response, format string) {
if resp.Node.Dir == true {
return
}
printKeyOnly(resp, format)
}
// printKeyOnly only supports to print key correctly.
func printKeyOnly(resp *etcd.Response, format string) {
// Format the result.
switch format {
case "simple":
fmt.Println(resp.Node.Value)
case "extended":
// Extended prints in a rfc2822 style format
fmt.Println("Key:", resp.Node.Key)
fmt.Println("Created-Index:", resp.Node.CreatedIndex)
fmt.Println("Modified-Index:", resp.Node.ModifiedIndex)
if resp.PrevNode != nil {
fmt.Println("PrevNode.Value:", resp.PrevNode.Value)
}
fmt.Println("TTL:", resp.Node.TTL)
fmt.Println("Etcd-Index:", resp.EtcdIndex)
fmt.Println("Raft-Index:", resp.RaftIndex)
fmt.Println("Raft-Term:", resp.RaftTerm)
fmt.Println("")
fmt.Println(resp.Node.Value)
case "json":
b, err := json.Marshal(resp)
if err != nil {
panic(err)
}
fmt.Println(string(b))
default:
fmt.Fprintln(os.Stderr, "Unsupported output format:", format)
}
}

View File

@@ -53,11 +53,11 @@ func handleImportSnap(c *cli.Context) {
endpoints, err := getEndpoints(c)
if err != nil {
handleError(ErrorFromEtcd, err)
handleError(ExitServerError, err)
}
tr, err := getTransport(c)
if err != nil {
handleError(ErrorFromEtcd, err)
handleError(ExitServerError, err)
}
wg := &sync.WaitGroup{}
@@ -73,7 +73,7 @@ func handleImportSnap(c *cli.Context) {
}
if ok := client.SyncCluster(); !ok {
handleError(FailedToConnectToHost, errors.New("cannot sync with the cluster using endpoints "+strings.Join(endpoints, ", ")))
handleError(ExitBadConnection, errors.New("cannot sync with the cluster using endpoints "+strings.Join(endpoints, ", ")))
}
wg.Add(1)
go runSet(client, setc, wg)
@@ -81,7 +81,7 @@ func handleImportSnap(c *cli.Context) {
all, err := st.Get("/", true, true)
if err != nil {
handleError(ErrorFromEtcd, err)
handleError(ExitServerError, err)
}
n := copyKeys(all.Node, setc)
@@ -89,7 +89,7 @@ func handleImportSnap(c *cli.Context) {
for _, h := range hiddens {
allh, err := st.Get(h, true, true)
if err != nil {
handleError(ErrorFromEtcd, err)
handleError(ExitServerError, err)
}
n += copyKeys(allh.Node, setc)
}

View File

@@ -39,12 +39,12 @@ func NewMakeCommand() cli.Command {
// makeCommandFunc executes the "make" command.
func makeCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, error) {
if len(c.Args()) == 0 {
return nil, errors.New("Key required")
return nil, errors.New("key required")
}
key := c.Args()[0]
value, err := argOrStdin(c.Args(), os.Stdin, 1)
if err != nil {
return nil, errors.New("Value required")
return nil, errors.New("value required")
}
ttl := c.Int("ttl")

View File

@@ -38,7 +38,7 @@ func NewMakeDirCommand() cli.Command {
// makeDirCommandFunc executes the "mkdir" command.
func makeDirCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, error) {
if len(c.Args()) == 0 {
return nil, errors.New("Key required")
return nil, errors.New("key required")
}
key := c.Args()[0]
ttl := c.Int("ttl")

View File

@@ -41,7 +41,7 @@ func NewRemoveCommand() cli.Command {
// removeCommandFunc executes the "rm" command.
func removeCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, error) {
if len(c.Args()) == 0 {
return nil, errors.New("Key required")
return nil, errors.New("key required")
}
key := c.Args()[0]
recursive := c.Bool("recursive")

View File

@@ -35,7 +35,7 @@ func NewRemoveDirCommand() cli.Command {
// removeDirCommandFunc executes the "rmdir" command.
func removeDirCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, error) {
if len(c.Args()) == 0 {
return nil, errors.New("Key required")
return nil, errors.New("key required")
}
key := c.Args()[0]

View File

@@ -41,12 +41,12 @@ func NewSetCommand() cli.Command {
// setCommandFunc executes the "set" command.
func setCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, error) {
if len(c.Args()) == 0 {
return nil, errors.New("Key required")
return nil, errors.New("key required")
}
key := c.Args()[0]
value, err := argOrStdin(c.Args(), os.Stdin, 1)
if err != nil {
return nil, errors.New("Value required")
return nil, errors.New("value required")
}
ttl := c.Int("ttl")
@@ -55,7 +55,6 @@ func setCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, error)
if prevValue == "" && prevIndex == 0 {
return client.Set(key, value, uint64(ttl))
} else {
return client.CompareAndSwap(key, value, uint64(ttl), prevValue, uint64(prevIndex))
}
return client.CompareAndSwap(key, value, uint64(ttl), prevValue, uint64(prevIndex))
}

View File

@@ -111,5 +111,4 @@ func getTransport(c *cli.Context) (*http.Transport, error) {
KeyFile: keyfile,
}
return transport.NewTransport(tls)
}

View File

@@ -86,7 +86,7 @@ func watchCommandFunc(c *cli.Context, client *etcd.Client) (*etcd.Response, erro
resp, err = client.Watch(key, uint64(index), recursive, nil, nil)
if err != nil {
handleError(ErrorFromEtcd, err)
handleError(ExitServerError, err)
}
if err != nil {