浏览代码

*: combine etcdctl and etcdctlv3

Xiang Li 9 年之前
父节点
当前提交
87d9f06a45
共有 57 个文件被更改,包括 107 次插入66 次删除
  1. 0 1
      V3DemoProcfile
  2. 0 1
      build
  3. 5 9
      e2e/etcdctlv3_test.go
  4. 3 1
      etcdctl/READMEv3.md
  5. 0 0
      etcdctl/ctlv2/command/auth_commands.go
  6. 0 0
      etcdctl/ctlv2/command/backup_command.go
  7. 0 0
      etcdctl/ctlv2/command/cluster_health.go
  8. 0 0
      etcdctl/ctlv2/command/doc.go
  9. 0 0
      etcdctl/ctlv2/command/error.go
  10. 0 0
      etcdctl/ctlv2/command/exec_watch_command.go
  11. 0 0
      etcdctl/ctlv2/command/format.go
  12. 0 0
      etcdctl/ctlv2/command/get_command.go
  13. 0 0
      etcdctl/ctlv2/command/import_snap_command.go
  14. 0 0
      etcdctl/ctlv2/command/ls_command.go
  15. 0 0
      etcdctl/ctlv2/command/member_commands.go
  16. 0 0
      etcdctl/ctlv2/command/mk_command.go
  17. 0 0
      etcdctl/ctlv2/command/mkdir_command.go
  18. 0 0
      etcdctl/ctlv2/command/rm_command.go
  19. 0 0
      etcdctl/ctlv2/command/rmdir_command.go
  20. 0 0
      etcdctl/ctlv2/command/role_commands.go
  21. 0 0
      etcdctl/ctlv2/command/set_command.go
  22. 0 0
      etcdctl/ctlv2/command/set_dir_command.go
  23. 0 0
      etcdctl/ctlv2/command/update_command.go
  24. 0 0
      etcdctl/ctlv2/command/update_dir_command.go
  25. 0 0
      etcdctl/ctlv2/command/user_commands.go
  26. 0 0
      etcdctl/ctlv2/command/util.go
  27. 0 0
      etcdctl/ctlv2/command/util_test.go
  28. 0 0
      etcdctl/ctlv2/command/watch_command.go
  29. 70 0
      etcdctl/ctlv2/ctl.go
  30. 0 0
      etcdctl/ctlv3/command/auth_command.go
  31. 0 0
      etcdctl/ctlv3/command/compaction_command.go
  32. 0 0
      etcdctl/ctlv3/command/defrag_command.go
  33. 0 0
      etcdctl/ctlv3/command/del_command.go
  34. 0 0
      etcdctl/ctlv3/command/doc.go
  35. 0 0
      etcdctl/ctlv3/command/elect_command.go
  36. 0 0
      etcdctl/ctlv3/command/ep_health_command.go
  37. 0 0
      etcdctl/ctlv3/command/error.go
  38. 0 0
      etcdctl/ctlv3/command/get_command.go
  39. 0 0
      etcdctl/ctlv3/command/global.go
  40. 0 0
      etcdctl/ctlv3/command/lease_command.go
  41. 0 0
      etcdctl/ctlv3/command/lock_command.go
  42. 0 0
      etcdctl/ctlv3/command/make_mirror_command.go
  43. 0 0
      etcdctl/ctlv3/command/member_command.go
  44. 0 0
      etcdctl/ctlv3/command/printer.go
  45. 0 0
      etcdctl/ctlv3/command/put_command.go
  46. 0 0
      etcdctl/ctlv3/command/snapshot_command.go
  47. 0 0
      etcdctl/ctlv3/command/txn_command.go
  48. 0 0
      etcdctl/ctlv3/command/user_command.go
  49. 0 0
      etcdctl/ctlv3/command/util.go
  50. 1 1
      etcdctl/ctlv3/command/version_command.go
  51. 0 0
      etcdctl/ctlv3/command/watch_command.go
  52. 6 6
      etcdctl/ctlv3/ctl.go
  53. 1 1
      etcdctl/ctlv3/help.go
  54. 0 0
      etcdctl/doc/mirror_maker.md
  55. 20 44
      etcdctl/main.go
  56. 0 1
      etcdctlv3/.gitignore
  57. 1 1
      test

+ 0 - 1
V3DemoProcfile

@@ -1,5 +1,4 @@
 # Use goreman to run `go get github.com/mattn/goreman`
-# etcd1 is the default client server for etcdctlv3 commands
 etcd1: bin/etcd --name infra1 --listen-client-urls http://127.0.0.1:2379 --advertise-client-urls http://127.0.0.1:2379 --listen-peer-urls http://127.0.0.1:12380 --initial-advertise-peer-urls http://127.0.0.1:12380 --initial-cluster-token etcd-cluster-1 --initial-cluster 'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380' --initial-cluster-state new --enable-pprof
 etcd2: bin/etcd --name infra2 --listen-client-urls http://127.0.0.1:22379 --advertise-client-urls http://127.0.0.1:22379 --listen-peer-urls http://127.0.0.1:22380 --initial-advertise-peer-urls http://127.0.0.1:22380 --initial-cluster-token etcd-cluster-1 --initial-cluster 'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380' --initial-cluster-state new --enable-pprof
 etcd3: bin/etcd --name infra3 --listen-client-urls http://127.0.0.1:32379 --advertise-client-urls http://127.0.0.1:32379 --listen-peer-urls http://127.0.0.1:32380 --initial-advertise-peer-urls http://127.0.0.1:32380 --initial-cluster-token etcd-cluster-1 --initial-cluster 'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380' --initial-cluster-state new --enable-pprof

+ 0 - 1
build

@@ -32,4 +32,3 @@ fi
 # Static compilation is useful when etcd is run in a container
 CGO_ENABLED=0 go build $GO_BUILD_FLAGS -installsuffix cgo -ldflags "-s -X ${REPO_PATH}/version.GitSHA${LINK_OPERATOR}${GIT_SHA}" -o bin/etcd ${REPO_PATH}
 CGO_ENABLED=0 go build $GO_BUILD_FLAGS -installsuffix cgo -ldflags "-s" -o bin/etcdctl ${REPO_PATH}/etcdctl
-CGO_ENABLED=0 go build $GO_BUILD_FLAGS -installsuffix cgo -ldflags "-s" -o bin/etcdctlv3 ${REPO_PATH}/etcdctlv3

+ 5 - 9
e2e/etcdctlv3_test.go

@@ -15,11 +15,11 @@
 package e2e
 
 import (
+	"os"
 	"strings"
 	"testing"
 	"time"
 
-	"github.com/coreos/etcd/pkg/fileutil"
 	"github.com/coreos/etcd/pkg/testutil"
 )
 
@@ -58,8 +58,10 @@ func TestCtlV3SetPeerTLSQuorum(t *testing.T) {
 func testCtlV3Set(t *testing.T, cfg *etcdProcessClusterConfig, dialTimeout time.Duration, quorum bool) {
 	defer testutil.AfterTest(t)
 
+	os.Setenv("ETCDCTL_API", "3")
 	epc := setupCtlV3Test(t, cfg, quorum)
 	defer func() {
+		os.Unsetenv("ETCDCTL_API")
 		if errC := epc.Close(); errC != nil {
 			t.Fatalf("error closing etcd processes (%v)", errC)
 		}
@@ -108,7 +110,7 @@ func ctlV3PrefixArgs(clus *etcdProcessCluster, dialTimeout time.Duration) []stri
 		}
 		endpoints = strings.Join(es, ",")
 	}
-	cmdArgs := []string{"../bin/etcdctlv3", "--endpoints", endpoints, "--dial-timeout", dialTimeout.String()}
+	cmdArgs := []string{"../bin/etcdctl", "--endpoints", endpoints, "--dial-timeout", dialTimeout.String()}
 	if clus.cfg.clientTLS == clientTLS {
 		cmdArgs = append(cmdArgs, "--cacert", caPath, "--cert", certPath, "--key", privateKeyPath)
 	}
@@ -129,14 +131,8 @@ func ctlV3Get(clus *etcdProcessCluster, key, value string, dialTimeout time.Dura
 	return spawnWithExpectedString(cmdArgs, key)
 }
 
-func mustCtlV3(t *testing.T) {
-	if !fileutil.Exist("../bin/etcdctlv3") {
-		t.Fatalf("could not find etcdctlv3 binary")
-	}
-}
-
 func setupCtlV3Test(t *testing.T, cfg *etcdProcessClusterConfig, quorum bool) *etcdProcessCluster {
-	mustCtlV3(t)
+	mustEtcdctl(t)
 	if !quorum {
 		cfg = configStandalone(*cfg)
 	}

+ 3 - 1
etcdctlv3/README.md → etcdctl/READMEv3.md

@@ -1,6 +1,8 @@
 etcdctl
 ========
 
+TODO: merge into README.md.
+
 ## Commands
 
 ### PUT [options] \<key\> \<value\>
@@ -277,7 +279,7 @@ bar
 
 ### LOCK \<lockname\>
 
-LOCK acquires a distributed named mutex with a given name. Once the lock is acquired, it will be held until etcdctlv3 is terminated.
+LOCK acquires a distributed named mutex with a given name. Once the lock is acquired, it will be held until etcdctl is terminated.
 
 #### Return value
 

+ 0 - 0
etcdctl/command/auth_commands.go → etcdctl/ctlv2/command/auth_commands.go


+ 0 - 0
etcdctl/command/backup_command.go → etcdctl/ctlv2/command/backup_command.go


+ 0 - 0
etcdctl/command/cluster_health.go → etcdctl/ctlv2/command/cluster_health.go


+ 0 - 0
etcdctl/command/doc.go → etcdctl/ctlv2/command/doc.go


+ 0 - 0
etcdctl/command/error.go → etcdctl/ctlv2/command/error.go


+ 0 - 0
etcdctl/command/exec_watch_command.go → etcdctl/ctlv2/command/exec_watch_command.go


+ 0 - 0
etcdctl/command/format.go → etcdctl/ctlv2/command/format.go


+ 0 - 0
etcdctl/command/get_command.go → etcdctl/ctlv2/command/get_command.go


+ 0 - 0
etcdctl/command/import_snap_command.go → etcdctl/ctlv2/command/import_snap_command.go


+ 0 - 0
etcdctl/command/ls_command.go → etcdctl/ctlv2/command/ls_command.go


+ 0 - 0
etcdctl/command/member_commands.go → etcdctl/ctlv2/command/member_commands.go


+ 0 - 0
etcdctl/command/mk_command.go → etcdctl/ctlv2/command/mk_command.go


+ 0 - 0
etcdctl/command/mkdir_command.go → etcdctl/ctlv2/command/mkdir_command.go


+ 0 - 0
etcdctl/command/rm_command.go → etcdctl/ctlv2/command/rm_command.go


+ 0 - 0
etcdctl/command/rmdir_command.go → etcdctl/ctlv2/command/rmdir_command.go


+ 0 - 0
etcdctl/command/role_commands.go → etcdctl/ctlv2/command/role_commands.go


+ 0 - 0
etcdctl/command/set_command.go → etcdctl/ctlv2/command/set_command.go


+ 0 - 0
etcdctl/command/set_dir_command.go → etcdctl/ctlv2/command/set_dir_command.go


+ 0 - 0
etcdctl/command/update_command.go → etcdctl/ctlv2/command/update_command.go


+ 0 - 0
etcdctl/command/update_dir_command.go → etcdctl/ctlv2/command/update_dir_command.go


+ 0 - 0
etcdctl/command/user_commands.go → etcdctl/ctlv2/command/user_commands.go


+ 0 - 0
etcdctl/command/util.go → etcdctl/ctlv2/command/util.go


+ 0 - 0
etcdctl/command/util_test.go → etcdctl/ctlv2/command/util_test.go


+ 0 - 0
etcdctl/command/watch_command.go → etcdctl/ctlv2/command/watch_command.go


+ 70 - 0
etcdctl/ctlv2/ctl.go

@@ -0,0 +1,70 @@
+// 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 ctlv2 contains the main entry point for the etcdctl for v2 API.
+package ctlv2
+
+import (
+	"os"
+	"time"
+
+	"github.com/codegangsta/cli"
+	"github.com/coreos/etcd/etcdctl/ctlv2/command"
+	"github.com/coreos/etcd/version"
+)
+
+func Start() {
+	app := cli.NewApp()
+	app.Name = "etcdctl"
+	app.Version = version.Version
+	app.Usage = "A simple command line client for etcd."
+	app.Flags = []cli.Flag{
+		cli.BoolFlag{Name: "debug", Usage: "output cURL commands which can be used to reproduce the request"},
+		cli.BoolFlag{Name: "no-sync", Usage: "don't synchronize cluster information before sending request"},
+		cli.StringFlag{Name: "output, o", Value: "simple", Usage: "output response in the given format (`simple`, `extended` or `json`)"},
+		cli.StringFlag{Name: "discovery-srv, D", Usage: "domain name to query for SRV records describing cluster endpoints"},
+		cli.StringFlag{Name: "peers, C", Value: "", Usage: "DEPRECATED - \"--endpoints\" should be used instead"},
+		cli.StringFlag{Name: "endpoint", Value: "", Usage: "DEPRECATED - \"--endpoints\" should be used instead"},
+		cli.StringFlag{Name: "endpoints", Value: "", Usage: "a comma-delimited list of machine addresses in the cluster (default: \"http://127.0.0.1:2379,http://127.0.0.1:4001\")"},
+		cli.StringFlag{Name: "cert-file", Value: "", Usage: "identify HTTPS client using this SSL certificate file"},
+		cli.StringFlag{Name: "key-file", Value: "", Usage: "identify HTTPS client using this SSL key file"},
+		cli.StringFlag{Name: "ca-file", Value: "", Usage: "verify certificates of HTTPS-enabled servers using this CA bundle"},
+		cli.StringFlag{Name: "username, u", Value: "", Usage: "provide username[:password] and prompt if password is not supplied."},
+		cli.DurationFlag{Name: "timeout", Value: time.Second, Usage: "connection timeout per request"},
+		cli.DurationFlag{Name: "total-timeout", Value: 5 * time.Second, Usage: "timeout for the command execution (except watch)"},
+	}
+	app.Commands = []cli.Command{
+		command.NewBackupCommand(),
+		command.NewClusterHealthCommand(),
+		command.NewMakeCommand(),
+		command.NewMakeDirCommand(),
+		command.NewRemoveCommand(),
+		command.NewRemoveDirCommand(),
+		command.NewGetCommand(),
+		command.NewLsCommand(),
+		command.NewSetCommand(),
+		command.NewSetDirCommand(),
+		command.NewUpdateCommand(),
+		command.NewUpdateDirCommand(),
+		command.NewWatchCommand(),
+		command.NewExecWatchCommand(),
+		command.NewMemberCommand(),
+		command.NewImportSnapCommand(),
+		command.NewUserCommands(),
+		command.NewRoleCommands(),
+		command.NewAuthCommands(),
+	}
+
+	app.Run(os.Args)
+}

+ 0 - 0
etcdctlv3/command/auth_command.go → etcdctl/ctlv3/command/auth_command.go


+ 0 - 0
etcdctlv3/command/compaction_command.go → etcdctl/ctlv3/command/compaction_command.go


+ 0 - 0
etcdctlv3/command/defrag_command.go → etcdctl/ctlv3/command/defrag_command.go


+ 0 - 0
etcdctlv3/command/del_command.go → etcdctl/ctlv3/command/del_command.go


+ 0 - 0
etcdctlv3/command/doc.go → etcdctl/ctlv3/command/doc.go


+ 0 - 0
etcdctlv3/command/elect_command.go → etcdctl/ctlv3/command/elect_command.go


+ 0 - 0
etcdctlv3/command/ep_health_command.go → etcdctl/ctlv3/command/ep_health_command.go


+ 0 - 0
etcdctlv3/command/error.go → etcdctl/ctlv3/command/error.go


+ 0 - 0
etcdctlv3/command/get_command.go → etcdctl/ctlv3/command/get_command.go


+ 0 - 0
etcdctlv3/command/global.go → etcdctl/ctlv3/command/global.go


+ 0 - 0
etcdctlv3/command/lease_command.go → etcdctl/ctlv3/command/lease_command.go


+ 0 - 0
etcdctlv3/command/lock_command.go → etcdctl/ctlv3/command/lock_command.go


+ 0 - 0
etcdctlv3/command/make_mirror_command.go → etcdctl/ctlv3/command/make_mirror_command.go


+ 0 - 0
etcdctlv3/command/member_command.go → etcdctl/ctlv3/command/member_command.go


+ 0 - 0
etcdctlv3/command/printer.go → etcdctl/ctlv3/command/printer.go


+ 0 - 0
etcdctlv3/command/put_command.go → etcdctl/ctlv3/command/put_command.go


+ 0 - 0
etcdctlv3/command/snapshot_command.go → etcdctl/ctlv3/command/snapshot_command.go


+ 0 - 0
etcdctlv3/command/txn_command.go → etcdctl/ctlv3/command/txn_command.go


+ 0 - 0
etcdctlv3/command/user_command.go → etcdctl/ctlv3/command/user_command.go


+ 0 - 0
etcdctlv3/command/util.go → etcdctl/ctlv3/command/util.go


+ 1 - 1
etcdctlv3/command/version_command.go → etcdctl/ctlv3/command/version_command.go

@@ -25,7 +25,7 @@ import (
 func NewVersionCommand() *cobra.Command {
 	return &cobra.Command{
 		Use:   "version",
-		Short: "Print the version of etcdctlv3.",
+		Short: "Print the version of etcdctl.",
 		Run:   versionCommandFunc,
 	}
 }

+ 0 - 0
etcdctlv3/command/watch_command.go → etcdctl/ctlv3/command/watch_command.go


+ 6 - 6
etcdctlv3/main.go → etcdctl/ctlv3/ctl.go

@@ -12,19 +12,19 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// etcdctlv3 is a command line application that utilizes v3 API.
-package main
+// Package ctlv3 contains the main entry point for the etcdctl for v3 API.
+package ctlv3
 
 import (
 	"text/tabwriter"
 	"time"
 
-	"github.com/coreos/etcd/etcdctlv3/command"
+	"github.com/coreos/etcd/etcdctl/ctlv3/command"
 	"github.com/spf13/cobra"
 )
 
 const (
-	cliName        = "etcdctlv3"
+	cliName        = "etcdctl"
 	cliDescription = "A simple command line client for etcd3."
 
 	defaultDialTimeout    = 2 * time.Second
@@ -40,7 +40,7 @@ var (
 	rootCmd = &cobra.Command{
 		Use:        cliName,
 		Short:      cliDescription,
-		SuggestFor: []string{"etcctlv3", "etcdcltv3", "etlctlv3"},
+		SuggestFor: []string{"etcdctl"},
 	}
 )
 
@@ -85,7 +85,7 @@ func init() {
 	cobra.EnablePrefixMatching = true
 }
 
-func main() {
+func Start() {
 	rootCmd.SetUsageFunc(usageFunc)
 
 	// Make help just show the usage

+ 1 - 1
etcdctlv3/help.go → etcdctl/ctlv3/help.go

@@ -14,7 +14,7 @@
 
 // copied from https://github.com/coreos/rkt/blob/master/rkt/help.go
 
-package main
+package ctlv3
 
 import (
 	"bytes"

+ 0 - 0
etcdctlv3/doc/mirror_maker.md → etcdctl/doc/mirror_maker.md


+ 20 - 44
etcdctl/main.go

@@ -1,4 +1,4 @@
-// Copyright 2015 CoreOS, Inc.
+// Copyright 2016 CoreOS, Inc.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -16,55 +16,31 @@
 package main
 
 import (
+	"fmt"
 	"os"
-	"time"
 
-	"github.com/codegangsta/cli"
-	"github.com/coreos/etcd/etcdctl/command"
-	"github.com/coreos/etcd/version"
+	"github.com/coreos/etcd/etcdctl/ctlv2"
+	"github.com/coreos/etcd/etcdctl/ctlv3"
+)
+
+const (
+	apiEnv = "ETCDCTL_API"
 )
 
 func main() {
-	app := cli.NewApp()
-	app.Name = "etcdctl"
-	app.Version = version.Version
-	app.Usage = "A simple command line client for etcd."
-	app.Flags = []cli.Flag{
-		cli.BoolFlag{Name: "debug", Usage: "output cURL commands which can be used to reproduce the request"},
-		cli.BoolFlag{Name: "no-sync", Usage: "don't synchronize cluster information before sending request"},
-		cli.StringFlag{Name: "output, o", Value: "simple", Usage: "output response in the given format (`simple`, `extended` or `json`)"},
-		cli.StringFlag{Name: "discovery-srv, D", Usage: "domain name to query for SRV records describing cluster endpoints"},
-		cli.StringFlag{Name: "peers, C", Value: "", Usage: "DEPRECATED - \"--endpoints\" should be used instead"},
-		cli.StringFlag{Name: "endpoint", Value: "", Usage: "DEPRECATED - \"--endpoints\" should be used instead"},
-		cli.StringFlag{Name: "endpoints", Value: "", Usage: "a comma-delimited list of machine addresses in the cluster (default: \"http://127.0.0.1:2379,http://127.0.0.1:4001\")"},
-		cli.StringFlag{Name: "cert-file", Value: "", Usage: "identify HTTPS client using this SSL certificate file"},
-		cli.StringFlag{Name: "key-file", Value: "", Usage: "identify HTTPS client using this SSL key file"},
-		cli.StringFlag{Name: "ca-file", Value: "", Usage: "verify certificates of HTTPS-enabled servers using this CA bundle"},
-		cli.StringFlag{Name: "username, u", Value: "", Usage: "provide username[:password] and prompt if password is not supplied."},
-		cli.DurationFlag{Name: "timeout", Value: time.Second, Usage: "connection timeout per request"},
-		cli.DurationFlag{Name: "total-timeout", Value: 5 * time.Second, Usage: "timeout for the command execution (except watch)"},
+	apiv := os.Getenv(apiEnv)
+	// unset apiEnv to avoid side-effect for future env and flag parsing.
+	os.Unsetenv(apiv)
+	if len(apiv) == 0 || apiv == "2" {
+		ctlv2.Start()
+		return
 	}
-	app.Commands = []cli.Command{
-		command.NewBackupCommand(),
-		command.NewClusterHealthCommand(),
-		command.NewMakeCommand(),
-		command.NewMakeDirCommand(),
-		command.NewRemoveCommand(),
-		command.NewRemoveDirCommand(),
-		command.NewGetCommand(),
-		command.NewLsCommand(),
-		command.NewSetCommand(),
-		command.NewSetDirCommand(),
-		command.NewUpdateCommand(),
-		command.NewUpdateDirCommand(),
-		command.NewWatchCommand(),
-		command.NewExecWatchCommand(),
-		command.NewMemberCommand(),
-		command.NewImportSnapCommand(),
-		command.NewUserCommands(),
-		command.NewRoleCommands(),
-		command.NewAuthCommands(),
+
+	if apiv == "3" {
+		ctlv3.Start()
+		return
 	}
 
-	app.Run(os.Args)
+	fmt.Fprintln(os.Stderr, "unsupported API version", apiv)
+	os.Exit(1)
 }

+ 0 - 1
etcdctlv3/.gitignore

@@ -1 +0,0 @@
-etcdctlv3

+ 1 - 1
test

@@ -17,7 +17,7 @@ GO_BUILD_FLAGS=-a
 source ./build
 
 # Hack: gofmt ./ will recursively check the .git directory. So use *.go for gofmt.
-TESTABLE_AND_FORMATTABLE="client clientv3 discovery error etcdctl/command etcdmain etcdserver etcdserver/auth etcdserver/etcdhttp etcdserver/etcdhttp/httptypes pkg/fileutil pkg/flags pkg/idutil pkg/ioutil pkg/netutil pkg/osutil pkg/pbutil pkg/types pkg/transport pkg/wait proxy raft snap storage storage/backend store version wal"
+TESTABLE_AND_FORMATTABLE="client clientv3 discovery error etcdctl/ctlv2 etcdctl/ctlv3 etcdmain etcdserver etcdserver/auth etcdserver/etcdhttp etcdserver/etcdhttp/httptypes pkg/fileutil pkg/flags pkg/idutil pkg/ioutil pkg/netutil pkg/osutil pkg/pbutil pkg/types pkg/transport pkg/wait proxy raft snap storage storage/backend store version wal"
 # TODO: add it to race testing when the issue is resolved
 # https://github.com/golang/go/issues/9946
 NO_RACE_TESTABLE="rafthttp"