Compare commits

...

11 Commits

Author SHA1 Message Date
6f48bda7ac version: bump to v3.0.0 2016-06-30 10:04:59 -07:00
316534e09e *: remove beta from docs 2016-06-30 10:04:34 -07:00
3cecbdb464 hack: install goreman in tls-setup example 2016-06-30 09:33:19 -07:00
62f11e43ee hack: add tls-setup example generated certs to gitignore 2016-06-30 09:33:12 -07:00
064c1585ee Merge pull request #5822 from raoofm/patch-9
Doc: fix typo in dev-guide.md
2016-06-30 09:06:32 -07:00
15300a1eb8 Doc: fix typo in dev-guide.md 2016-06-30 10:36:50 -04:00
58dd047ee4 ctlv3: make flags, commands formats consistent
1. Capitalize first letter
2. Remove period at the end

(followed the pattern in linux coreutil man page)
2016-06-29 16:16:56 -07:00
4b42ea6cd7 clientv3: only use closeErr on watch when donec is closed
Fixes #5800
2016-06-28 17:48:44 -07:00
53c27ae621 benchmark: fix Compact request 2016-06-28 14:15:32 -07:00
269de67bde mvcc: do not hash consistent index 2016-06-28 12:29:36 -07:00
8bbccf1047 clientv3, ctl3, clientv3/integration: add compact response to compact 2016-06-28 12:29:32 -07:00
36 changed files with 154 additions and 133 deletions

1
.gitignore vendored
View File

@ -10,3 +10,4 @@
/hack/insta-discovery/.env
*.test
tools/functional-tester/docker/bin
hack/tls-setup/certs

View File

@ -4,5 +4,5 @@ For the most part, the etcd project is stable, but we are still moving fast! We
## The current experimental API/features are:
- v3 auth API: expect to be stale in 3.1 release
- etcd gateway: expect to be stable in 3.1 release
- v3 auth API: expect to be stable in 3.1 release
- etcd gateway: expect to be stable in 3.1 release

View File

@ -8,7 +8,7 @@ In order to expose the etcd API to clients outside of Docker host, use the host
```
# For each machine
ETCD_VERSION=v3.0.0-beta.0
ETCD_VERSION=v3.0.0
TOKEN=my-etcd-token
CLUSTER_STATE=new
NAME_1=etcd-node-0

View File

@ -210,7 +210,7 @@ func ExampleKV_compact() {
compRev := resp.Header.Revision // specify compact revision of your choice
ctx, cancel = context.WithTimeout(context.Background(), requestTimeout)
err = cli.Compact(ctx, compRev)
_, err = cli.Compact(ctx, compRev)
cancel()
if err != nil {
log.Fatal(err)

View File

@ -470,17 +470,17 @@ func TestKVCompactError(t *testing.T) {
t.Fatalf("couldn't put 'foo' (%v)", err)
}
}
err := kv.Compact(ctx, 6)
_, err := kv.Compact(ctx, 6)
if err != nil {
t.Fatalf("couldn't compact 6 (%v)", err)
}
err = kv.Compact(ctx, 6)
_, err = kv.Compact(ctx, 6)
if err != rpctypes.ErrCompacted {
t.Fatalf("expected %v, got %v", rpctypes.ErrCompacted, err)
}
err = kv.Compact(ctx, 100)
_, err = kv.Compact(ctx, 100)
if err != rpctypes.ErrFutureRev {
t.Fatalf("expected %v, got %v", rpctypes.ErrFutureRev, err)
}
@ -501,11 +501,11 @@ func TestKVCompact(t *testing.T) {
}
}
err := kv.Compact(ctx, 7)
_, err := kv.Compact(ctx, 7)
if err != nil {
t.Fatalf("couldn't compact kv space (%v)", err)
}
err = kv.Compact(ctx, 7)
_, err = kv.Compact(ctx, 7)
if err == nil || err != rpctypes.ErrCompacted {
t.Fatalf("error got %v, want %v", err, rpctypes.ErrCompacted)
}
@ -525,7 +525,7 @@ func TestKVCompact(t *testing.T) {
t.Fatalf("wchan got %v, expected closed", wr)
}
err = kv.Compact(ctx, 1000)
_, err = kv.Compact(ctx, 1000)
if err == nil || err != rpctypes.ErrFutureRev {
t.Fatalf("error got %v, want %v", err, rpctypes.ErrFutureRev)
}

View File

@ -375,7 +375,7 @@ func TestWatchResumeCompacted(t *testing.T) {
t.Fatal(err)
}
}
if err := kv.Compact(context.TODO(), 3); err != nil {
if _, err := kv.Compact(context.TODO(), 3); err != nil {
t.Fatal(err)
}
@ -414,7 +414,7 @@ func TestWatchCompactRevision(t *testing.T) {
w := clientv3.NewWatcher(clus.RandClient())
defer w.Close()
if err := kv.Compact(context.TODO(), 4); err != nil {
if _, err := kv.Compact(context.TODO(), 4); err != nil {
t.Fatal(err)
}
wch := w.Watch(context.Background(), "foo", clientv3.WithRev(2))

View File

@ -20,10 +20,11 @@ import (
)
type (
PutResponse pb.PutResponse
GetResponse pb.RangeResponse
DeleteResponse pb.DeleteRangeResponse
TxnResponse pb.TxnResponse
CompactResponse pb.CompactionResponse
PutResponse pb.PutResponse
GetResponse pb.RangeResponse
DeleteResponse pb.DeleteRangeResponse
TxnResponse pb.TxnResponse
)
type KV interface {
@ -47,7 +48,7 @@ type KV interface {
Delete(ctx context.Context, key string, opts ...OpOption) (*DeleteResponse, error)
// Compact compacts etcd KV history before the given rev.
Compact(ctx context.Context, rev int64, opts ...CompactOption) error
Compact(ctx context.Context, rev int64, opts ...CompactOption) (*CompactResponse, error)
// Do applies a single Op on KV without a transaction.
// Do is useful when declaring operations to be issued at a later time
@ -98,11 +99,12 @@ func (kv *kv) Delete(ctx context.Context, key string, opts ...OpOption) (*Delete
return r.del, toErr(ctx, err)
}
func (kv *kv) Compact(ctx context.Context, rev int64, opts ...CompactOption) error {
if _, err := kv.remote.Compact(ctx, OpCompact(rev, opts...).toRequest()); err != nil {
return toErr(ctx, err)
func (kv *kv) Compact(ctx context.Context, rev int64, opts ...CompactOption) (*CompactResponse, error) {
resp, err := kv.remote.Compact(ctx, OpCompact(rev, opts...).toRequest())
if err != nil {
return nil, toErr(ctx, err)
}
return nil
return (*CompactResponse)(resp), err
}
func (kv *kv) Txn(ctx context.Context) Txn {

View File

@ -505,6 +505,7 @@ func (w *watchGrpcStream) serveWatchClient(wc pb.Watch_WatchClient) {
// serveStream forwards watch responses from run() to the subscriber
func (w *watchGrpcStream) serveStream(ws *watcherStream) {
var closeErr error
emptyWr := &WatchResponse{}
wrs := []*WatchResponse{}
resuming := false
@ -569,13 +570,14 @@ func (w *watchGrpcStream) serveStream(ws *watcherStream) {
}
case <-w.donec:
closing = true
closeErr = w.closeErr
case <-ws.initReq.ctx.Done():
closing = true
}
}
// try to send off close error
if w.closeErr != nil {
if closeErr != nil {
select {
case ws.outc <- WatchResponse{closeErr: w.closeErr}:
case <-w.donec:

View File

@ -497,25 +497,25 @@ ENDPOINT STATUS does not support protobuf encoded output.
```bash
./etcdctl endpoint status
127.0.0.1:2379, 8211f1d0f64f3269, 3.0.0-beta.0+git, 25 kB, false, 2, 63
127.0.0.1:22379, 91bc3c398fb3c146, 3.0.0-beta.0+git, 25 kB, false, 2, 63
127.0.0.1:32379, fd422379fda50e48, 3.0.0-beta.0+git, 25 kB, true, 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
```
```bash
./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":"2.3.0+git","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":"2.3.0+git","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":"2.3.0+git","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}},{"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}}]
```
```bash
./etcdctl -w table endpoint status
+-----------------+------------------+------------------+---------+-----------+-----------+------------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+-----------------+------------------+------------------+---------+-----------+-----------+------------+
| 127.0.0.1:2379 | 8211f1d0f64f3269 | 3.0.0-beta.0+git | 25 kB | false | 2 | 52 |
| 127.0.0.1:22379 | 91bc3c398fb3c146 | 3.0.0-beta.0+git | 25 kB | false | 2 | 52 |
| 127.0.0.1:32379 | fd422379fda50e48 | 3.0.0-beta.0+git | 25 kB | true | 2 | 52 |
+-----------------+------------------+------------------+---------+-----------+-----------+------------+
+-----------------+------------------+---------+---------+-----------+-----------+------------+
| 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 |
| 127.0.0.1:22379 | 91bc3c398fb3c146 | 3.0.0 | 25 kB | false | 2 | 52 |
| 127.0.0.1:32379 | fd422379fda50e48 | 3.0.0 | 25 kB | true | 2 | 52 |
+-----------------+------------------+---------+---------+-----------+-----------+------------+
```
### LOCK \<lockname\>

View File

@ -25,7 +25,7 @@ import (
func NewAlarmCommand() *cobra.Command {
ac := &cobra.Command{
Use: "alarm <subcommand>",
Short: "alarm related command",
Short: "Alarm related commands",
}
ac.AddCommand(NewAlarmDisarmCommand())
@ -37,7 +37,7 @@ func NewAlarmCommand() *cobra.Command {
func NewAlarmDisarmCommand() *cobra.Command {
cmd := cobra.Command{
Use: "disarm",
Short: "disarm all alarms",
Short: "Disarms all alarms",
Run: alarmDisarmCommandFunc,
}
return &cmd
@ -60,7 +60,7 @@ func alarmDisarmCommandFunc(cmd *cobra.Command, args []string) {
func NewAlarmListCommand() *cobra.Command {
cmd := cobra.Command{
Use: "list",
Short: "list all alarms",
Short: "Lists all alarms",
Run: alarmListCommandFunc,
}
return &cmd

View File

@ -24,7 +24,7 @@ import (
func NewAuthCommand() *cobra.Command {
ac := &cobra.Command{
Use: "auth <enable or disable>",
Short: "Enable or disable authentication.",
Short: "Enable or disable authentication",
}
ac.AddCommand(newAuthEnableCommand())
@ -36,7 +36,7 @@ func NewAuthCommand() *cobra.Command {
func newAuthEnableCommand() *cobra.Command {
return &cobra.Command{
Use: "enable",
Short: "enable authentication",
Short: "Enables authentication",
Run: authEnableCommandFunc,
}
}
@ -60,7 +60,7 @@ func authEnableCommandFunc(cmd *cobra.Command, args []string) {
func newAuthDisableCommand() *cobra.Command {
return &cobra.Command{
Use: "disable",
Short: "disable authentication",
Short: "Disables authentication",
Run: authDisableCommandFunc,
}
}

View File

@ -28,10 +28,10 @@ var compactPhysical bool
func NewCompactionCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "compaction <revision>",
Short: "Compaction compacts the event history in etcd.",
Short: "Compacts the event history in etcd",
Run: compactionCommandFunc,
}
cmd.Flags().BoolVar(&compactPhysical, "physical", false, "'true' to wait for compaction to physically remove all old revisions.")
cmd.Flags().BoolVar(&compactPhysical, "physical", false, "'true' to wait for compaction to physically remove all old revisions")
return cmd
}
@ -53,7 +53,7 @@ func compactionCommandFunc(cmd *cobra.Command, args []string) {
c := mustClientFromCmd(cmd)
ctx, cancel := commandCtx(cmd)
cerr := c.Compact(ctx, rev, opts...)
_, cerr := c.Compact(ctx, rev, opts...)
cancel()
if cerr != nil {
ExitWithError(ExitError, cerr)

View File

@ -25,7 +25,7 @@ import (
func NewDefragCommand() *cobra.Command {
return &cobra.Command{
Use: "defrag",
Short: "defrag defragments the storage of the etcd members with given endpoints.",
Short: "Defragments the storage of the etcd members with given endpoints",
Run: defragCommandFunc,
}
}

View File

@ -29,7 +29,7 @@ var (
func NewDelCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "del [options] <key> [range_end]",
Short: "Removes the specified key or range of keys [key, range_end).",
Short: "Removes the specified key or range of keys [key, range_end)",
Run: delCommandFunc,
}

View File

@ -33,7 +33,7 @@ var (
func NewElectCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "elect <election-name> [proposal]",
Short: "elect observes and participates in leader election",
Short: "Observes and participates in leader election",
Run: electCommandFunc,
}
cmd.Flags().BoolVarP(&electListen, "listen", "l", false, "observation mode")

View File

@ -28,8 +28,8 @@ import (
// NewEndpointCommand returns the cobra command for "endpoint".
func NewEndpointCommand() *cobra.Command {
ec := &cobra.Command{
Use: "endpoint",
Short: "endpoint is used to check endpoints.",
Use: "endpoint <subcommand>",
Short: "Endpoint related commands",
}
ec.AddCommand(newEpHealthCommand())
@ -41,7 +41,7 @@ func NewEndpointCommand() *cobra.Command {
func newEpHealthCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "health",
Short: "health checks the healthiness of endpoints specified in `--endpoints` flag",
Short: "Checks the healthiness of endpoints specified in `--endpoints` flag",
Run: epHealthCommandFunc,
}
return cmd
@ -50,7 +50,7 @@ func newEpHealthCommand() *cobra.Command {
func newEpStatusCommand() *cobra.Command {
return &cobra.Command{
Use: "status",
Short: "status prints out the status of endpoints specified in `--endpoints` flag",
Short: "Prints out the status of endpoints specified in `--endpoints` flag",
Long: `When --write-out is set to simple, this command prints out comma-separated status lists for each endpoint.
The items in the lists are endpoint, ID, version, db size, is leader, raft term, raft index.
`,

View File

@ -37,18 +37,18 @@ var (
func NewGetCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "get [options] <key> [range_end]",
Short: "Get gets the key or a range of keys.",
Short: "Gets the key or a range of keys",
Run: getCommandFunc,
}
cmd.Flags().StringVar(&getConsistency, "consistency", "l", "Linearizable(l) or Serializable(s)")
cmd.Flags().StringVar(&getSortOrder, "order", "", "order of results; ASCEND or DESCEND")
cmd.Flags().StringVar(&getSortTarget, "sort-by", "", "sort target; CREATE, KEY, MODIFY, VALUE, or VERSION")
cmd.Flags().Int64Var(&getLimit, "limit", 0, "maximum number of results")
cmd.Flags().BoolVar(&getPrefix, "prefix", false, "get keys with matching prefix")
cmd.Flags().BoolVar(&getFromKey, "from-key", false, "get keys that are greater than or equal to the given key")
cmd.Flags().Int64Var(&getRev, "rev", 0, "specify the kv revision")
cmd.Flags().BoolVar(&getKeysOnly, "keys-only", false, "get only the keys")
cmd.Flags().StringVar(&getSortOrder, "order", "", "Order of results; ASCEND or DESCEND")
cmd.Flags().StringVar(&getSortTarget, "sort-by", "", "Sort target; CREATE, KEY, MODIFY, VALUE, or VERSION")
cmd.Flags().Int64Var(&getLimit, "limit", 0, "Maximum number of results")
cmd.Flags().BoolVar(&getPrefix, "prefix", false, "Get keys with matching prefix")
cmd.Flags().BoolVar(&getFromKey, "from-key", false, "Get keys that are greater than or equal to the given key")
cmd.Flags().Int64Var(&getRev, "rev", 0, "Specify the kv revision")
cmd.Flags().BoolVar(&getKeysOnly, "keys-only", false, "Get only the keys")
return cmd
}

View File

@ -26,8 +26,8 @@ import (
// NewLeaseCommand returns the cobra command for "lease".
func NewLeaseCommand() *cobra.Command {
lc := &cobra.Command{
Use: "lease",
Short: "lease is used to manage leases.",
Use: "lease <subcommand>",
Short: "Lease related commands",
}
lc.AddCommand(NewLeaseGrantCommand())
@ -41,7 +41,7 @@ func NewLeaseCommand() *cobra.Command {
func NewLeaseGrantCommand() *cobra.Command {
lc := &cobra.Command{
Use: "grant <ttl>",
Short: "grant is used to create leases.",
Short: "Creates leases",
Run: leaseGrantCommandFunc,
}
@ -73,7 +73,7 @@ func leaseGrantCommandFunc(cmd *cobra.Command, args []string) {
func NewLeaseRevokeCommand() *cobra.Command {
lc := &cobra.Command{
Use: "revoke <leaseID>",
Short: "revoke is used to revoke leases.",
Short: "Revokes leases",
Run: leaseRevokeCommandFunc,
}
@ -105,7 +105,7 @@ func leaseRevokeCommandFunc(cmd *cobra.Command, args []string) {
func NewLeaseKeepAliveCommand() *cobra.Command {
lc := &cobra.Command{
Use: "keep-alive <leaseID>",
Short: "keep-alive is used to keep leases alive.",
Short: "Keeps leases alive (renew)",
Run: leaseKeepAliveCommandFunc,
}

View File

@ -29,7 +29,7 @@ import (
func NewLockCommand() *cobra.Command {
c := &cobra.Command{
Use: "lock <lockname>",
Short: "lock acquires a named lock",
Short: "Acquires a named lock",
Run: lockCommandFunc,
}
return c

View File

@ -40,17 +40,17 @@ var (
func NewMakeMirrorCommand() *cobra.Command {
c := &cobra.Command{
Use: "make-mirror [options] <destination>",
Short: "make-mirror makes a mirror at the destination etcd cluster",
Short: "Makes a mirror at the destination etcd cluster",
Run: makeMirrorCommandFunc,
}
c.Flags().StringVar(&mmprefix, "prefix", "", "the key-value prefix to mirror")
c.Flags().StringVar(&mmprefix, "prefix", "", "Key-value prefix to mirror")
// TODO: add dest-prefix to mirror a prefix to a different prefix in the destination cluster?
c.Flags().StringVar(&mmcert, "dest-cert", "", "identify secure client using this TLS certificate file for the destination cluster")
c.Flags().StringVar(&mmkey, "dest-key", "", "identify secure client using this TLS key file")
c.Flags().StringVar(&mmcacert, "dest-cacert", "", "verify certificates of TLS enabled secure servers using this CA bundle")
c.Flags().StringVar(&mmcert, "dest-cert", "", "Identify secure client using this TLS certificate file for the destination cluster")
c.Flags().StringVar(&mmkey, "dest-key", "", "Identify secure client using this TLS key file")
c.Flags().StringVar(&mmcacert, "dest-cacert", "", "Verify certificates of TLS enabled secure servers using this CA bundle")
// TODO: secure by default when etcd enables secure gRPC by default.
c.Flags().BoolVar(&mminsecureTr, "dest-insecure-transport", true, "disable transport security for client connections")
c.Flags().BoolVar(&mminsecureTr, "dest-insecure-transport", true, "Disable transport security for client connections")
return c
}

View File

@ -27,8 +27,8 @@ var memberPeerURLs string
// NewMemberCommand returns the cobra command for "member".
func NewMemberCommand() *cobra.Command {
mc := &cobra.Command{
Use: "member",
Short: "member is used to manage membership in an etcd cluster.",
Use: "member <subcommand>",
Short: "Membership related commands",
}
mc.AddCommand(NewMemberAddCommand())
@ -43,7 +43,7 @@ func NewMemberCommand() *cobra.Command {
func NewMemberAddCommand() *cobra.Command {
cc := &cobra.Command{
Use: "add <memberName>",
Short: "add is used to add a member into the cluster",
Short: "Adds a member into the cluster",
Run: memberAddCommandFunc,
}
@ -57,7 +57,7 @@ func NewMemberAddCommand() *cobra.Command {
func NewMemberRemoveCommand() *cobra.Command {
cc := &cobra.Command{
Use: "remove <memberID>",
Short: "remove is used to remove a member from the cluster",
Short: "Removes a member from the cluster",
Run: memberRemoveCommandFunc,
}
@ -69,7 +69,7 @@ func NewMemberRemoveCommand() *cobra.Command {
func NewMemberUpdateCommand() *cobra.Command {
cc := &cobra.Command{
Use: "update <memberID>",
Short: "update is used to update a member in the cluster",
Short: "Updates a member in the cluster",
Run: memberUpdateCommandFunc,
}
@ -83,7 +83,7 @@ func NewMemberUpdateCommand() *cobra.Command {
func NewMemberListCommand() *cobra.Command {
cc := &cobra.Command{
Use: "list",
Short: "list is used to list all members in the cluster",
Short: "Lists all members in the cluster",
Long: `When --write-out is set to simple, this command prints out comma-separated member lists for each endpoint.
The items in the lists are ID, Status, Name, Peer Addrs, Client Addrs.
`,

View File

@ -51,13 +51,13 @@ var (
func NewMigrateCommand() *cobra.Command {
mc := &cobra.Command{
Use: "migrate",
Short: "migrates keys in a v2 store to a mvcc store",
Short: "Migrates keys in a v2 store to a mvcc store",
Run: migrateCommandFunc,
}
mc.Flags().StringVar(&migrateDatadir, "data-dir", "", "Path to the data directory.")
mc.Flags().StringVar(&migrateWALdir, "wal-dir", "", "Path to the WAL directory.")
mc.Flags().StringVar(&migrateTransformer, "transformer", "", "Path to the user-provided transformer program.")
mc.Flags().StringVar(&migrateDatadir, "data-dir", "", "Path to the data directory")
mc.Flags().StringVar(&migrateWALdir, "wal-dir", "", "Path to the WAL directory")
mc.Flags().StringVar(&migrateTransformer, "transformer", "", "Path to the user-provided transformer program")
return mc
}

View File

@ -31,9 +31,9 @@ var (
func NewPutCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "put [options] <key> <value> (<value> can also be given from stdin)",
Short: "Put puts the given key into the store.",
Short: "Puts the given key into the store",
Long: `
Put puts the given key into the store.
Puts the given key into the store.
When <value> begins with '-', <value> is interpreted as a flag.
Insert '--' for workaround:

View File

@ -26,7 +26,7 @@ import (
func NewRoleCommand() *cobra.Command {
ac := &cobra.Command{
Use: "role <subcommand>",
Short: "role related command",
Short: "Role related commands",
}
ac.AddCommand(newRoleAddCommand())
@ -42,7 +42,7 @@ func NewRoleCommand() *cobra.Command {
func newRoleAddCommand() *cobra.Command {
return &cobra.Command{
Use: "add <role name>",
Short: "add a new role",
Short: "Adds a new role",
Run: roleAddCommandFunc,
}
}
@ -50,7 +50,7 @@ func newRoleAddCommand() *cobra.Command {
func newRoleDeleteCommand() *cobra.Command {
return &cobra.Command{
Use: "delete <role name>",
Short: "delete a role",
Short: "Deletes a role",
Run: roleDeleteCommandFunc,
}
}
@ -58,7 +58,7 @@ func newRoleDeleteCommand() *cobra.Command {
func newRoleGetCommand() *cobra.Command {
return &cobra.Command{
Use: "get <role name>",
Short: "get detailed information of a role",
Short: "Gets detailed information of a role",
Run: roleGetCommandFunc,
}
}
@ -66,7 +66,7 @@ func newRoleGetCommand() *cobra.Command {
func newRoleListCommand() *cobra.Command {
return &cobra.Command{
Use: "list",
Short: "list up all roles",
Short: "Lists all roles",
Run: roleListCommandFunc,
}
}
@ -74,7 +74,7 @@ func newRoleListCommand() *cobra.Command {
func newRoleGrantPermissionCommand() *cobra.Command {
return &cobra.Command{
Use: "grant-permission <role name> <permission type> <key> [endkey]",
Short: "grant a key to a role",
Short: "Grants a key to a role",
Run: roleGrantPermissionCommandFunc,
}
}
@ -82,7 +82,7 @@ func newRoleGrantPermissionCommand() *cobra.Command {
func newRoleRevokePermissionCommand() *cobra.Command {
return &cobra.Command{
Use: "revoke-permission <role name> <key> [endkey]",
Short: "revoke a key from a role",
Short: "Revokes a key from a role",
Run: roleRevokePermissionCommandFunc,
}
}

View File

@ -58,8 +58,8 @@ var (
// NewSnapshotCommand returns the cobra command for "snapshot".
func NewSnapshotCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "snapshot",
Short: "snapshot manages etcd node snapshots.",
Use: "snapshot <subcommand>",
Short: "Manages etcd node snapshots",
}
cmd.AddCommand(NewSnapshotSaveCommand())
cmd.AddCommand(NewSnapshotRestoreCommand())
@ -70,7 +70,7 @@ func NewSnapshotCommand() *cobra.Command {
func NewSnapshotSaveCommand() *cobra.Command {
return &cobra.Command{
Use: "save <filename>",
Short: "save stores an etcd node backend snapshot to a given file.",
Short: "Stores an etcd node backend snapshot to a given file",
Run: snapshotSaveCommandFunc,
}
}
@ -78,7 +78,7 @@ func NewSnapshotSaveCommand() *cobra.Command {
func newSnapshotStatusCommand() *cobra.Command {
return &cobra.Command{
Use: "status <filename>",
Short: "status gets backend snapshot status of a given file.",
Short: "Gets backend snapshot status of a given file",
Long: `When --write-out is set to simple, this command prints out comma-separated status lists for each endpoint.
The items in the lists are hash, revision, total keys, total size.
`,
@ -89,15 +89,15 @@ The items in the lists are hash, revision, total keys, total size.
func NewSnapshotRestoreCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "restore <filename>",
Short: "restore an etcd member snapshot to an etcd directory",
Short: "Restores an etcd member snapshot to an etcd directory",
Run: snapshotRestoreCommandFunc,
}
cmd.Flags().StringVar(&restoreDataDir, "data-dir", "", "Path to the data directory.")
cmd.Flags().StringVar(&restoreCluster, "initial-cluster", initialClusterFromName(defaultName), "Initial cluster configuration for restore bootstrap.")
cmd.Flags().StringVar(&restoreClusterToken, "initial-cluster-token", "etcd-cluster", "Initial cluster token for the etcd cluster during restore bootstrap.")
cmd.Flags().StringVar(&restorePeerURLs, "initial-advertise-peer-urls", defaultInitialAdvertisePeerURLs, "List of this member's peer URLs to advertise to the rest of the cluster.")
cmd.Flags().StringVar(&restoreName, "name", defaultName, "Human-readable name for this member.")
cmd.Flags().BoolVar(&skipHashCheck, "skip-hash-check", false, "Ignore snapshot integrity hash value (required if copied from data directory).")
cmd.Flags().StringVar(&restoreDataDir, "data-dir", "", "Path to the data directory")
cmd.Flags().StringVar(&restoreCluster, "initial-cluster", initialClusterFromName(defaultName), "Initial cluster configuration for restore bootstrap")
cmd.Flags().StringVar(&restoreClusterToken, "initial-cluster-token", "etcd-cluster", "Initial cluster token for the etcd cluster during restore bootstrap")
cmd.Flags().StringVar(&restorePeerURLs, "initial-advertise-peer-urls", defaultInitialAdvertisePeerURLs, "List of this member's peer URLs to advertise to the rest of the cluster")
cmd.Flags().StringVar(&restoreName, "name", defaultName, "Human-readable name for this member")
cmd.Flags().BoolVar(&skipHashCheck, "skip-hash-check", false, "Ignore snapshot integrity hash value (required if copied from data directory)")
return cmd
}

View File

@ -34,10 +34,10 @@ var (
func NewTxnCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "txn [options]",
Short: "Txn processes all the requests in one transaction.",
Short: "Txn processes all the requests in one transaction",
Run: txnCommandFunc,
}
cmd.Flags().BoolVarP(&txnInteractive, "interactive", "i", false, "input transaction in interactive mode")
cmd.Flags().BoolVarP(&txnInteractive, "interactive", "i", false, "Input transaction in interactive mode")
return cmd
}

View File

@ -31,7 +31,7 @@ var (
func NewUserCommand() *cobra.Command {
ac := &cobra.Command{
Use: "user <subcommand>",
Short: "user related command",
Short: "User related commands",
}
ac.AddCommand(newUserAddCommand())
@ -52,11 +52,11 @@ var (
func newUserAddCommand() *cobra.Command {
cmd := cobra.Command{
Use: "add <user name>",
Short: "add a new user",
Short: "Adds a new user",
Run: userAddCommandFunc,
}
cmd.Flags().BoolVar(&passwordInteractive, "interactive", true, "read password from stdin instead of interactive terminal")
cmd.Flags().BoolVar(&passwordInteractive, "interactive", true, "Read password from stdin instead of interactive terminal")
return &cmd
}
@ -64,7 +64,7 @@ func newUserAddCommand() *cobra.Command {
func newUserDeleteCommand() *cobra.Command {
return &cobra.Command{
Use: "delete <user name>",
Short: "delete a user",
Short: "Deletes a user",
Run: userDeleteCommandFunc,
}
}
@ -72,11 +72,11 @@ func newUserDeleteCommand() *cobra.Command {
func newUserGetCommand() *cobra.Command {
cmd := cobra.Command{
Use: "get <user name>",
Short: "get detailed information of a user",
Short: "Gets detailed information of a user",
Run: userGetCommandFunc,
}
cmd.Flags().BoolVar(&userShowDetail, "detail", false, "show permissions of roles granted to the user")
cmd.Flags().BoolVar(&userShowDetail, "detail", false, "Show permissions of roles granted to the user")
return &cmd
}
@ -84,7 +84,7 @@ func newUserGetCommand() *cobra.Command {
func newUserListCommand() *cobra.Command {
return &cobra.Command{
Use: "list",
Short: "list up all users",
Short: "Lists all users",
Run: userListCommandFunc,
}
}
@ -92,11 +92,11 @@ func newUserListCommand() *cobra.Command {
func newUserChangePasswordCommand() *cobra.Command {
cmd := cobra.Command{
Use: "passwd <user name>",
Short: "change password of user",
Short: "Changes password of user",
Run: userChangePasswordCommandFunc,
}
cmd.Flags().BoolVar(&passwordInteractive, "interactive", true, "if true, read password from stdin instead of interactive terminal")
cmd.Flags().BoolVar(&passwordInteractive, "interactive", true, "If true, read password from stdin instead of interactive terminal")
return &cmd
}
@ -104,7 +104,7 @@ func newUserChangePasswordCommand() *cobra.Command {
func newUserGrantRoleCommand() *cobra.Command {
return &cobra.Command{
Use: "grant-role <user name> <role name>",
Short: "grant a role to a user",
Short: "Grants a role to a user",
Run: userGrantRoleCommandFunc,
}
}
@ -112,7 +112,7 @@ func newUserGrantRoleCommand() *cobra.Command {
func newUserRevokeRoleCommand() *cobra.Command {
return &cobra.Command{
Use: "revoke-role <user name> <role name>",
Short: "revoke a role from a user",
Short: "Revokes a role from a user",
Run: userRevokeRoleCommandFunc,
}
}

View File

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

View File

@ -35,13 +35,13 @@ var (
func NewWatchCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "watch [options] [key or prefix] [range_end]",
Short: "Watch watches events stream on keys or prefixes.",
Short: "Watches events stream on keys or prefixes",
Run: watchCommandFunc,
}
cmd.Flags().BoolVarP(&watchInteractive, "interactive", "i", false, "interactive mode")
cmd.Flags().BoolVar(&watchPrefix, "prefix", false, "watch on a prefix if prefix is set")
cmd.Flags().Int64Var(&watchRev, "rev", 0, "revision to start watching")
cmd.Flags().BoolVarP(&watchInteractive, "interactive", "i", false, "Interactive mode")
cmd.Flags().BoolVar(&watchPrefix, "prefix", false, "Watch on a prefix if prefix is set")
cmd.Flags().Int64Var(&watchRev, "rev", 0, "Revision to start watching")
return cmd
}

View File

@ -8,6 +8,7 @@ all: cfssl ca req
cfssl:
go get -u -tags nopkcs11 github.com/cloudflare/cfssl/cmd/cfssl
go get -u github.com/cloudflare/cfssl/cmd/cfssljson
go get -u github.com/mattn/goreman
ca:
mkdir -p certs

View File

@ -55,7 +55,7 @@ const (
type Backend interface {
BatchTx() BatchTx
Snapshot() Snapshot
Hash() (uint32, error)
Hash(ignores map[IgnoreKey]struct{}) (uint32, error)
// Size returns the current size of the backend.
Size() int64
Defrag() error
@ -144,7 +144,12 @@ func (b *backend) Snapshot() Snapshot {
return &snapshot{tx}
}
func (b *backend) Hash() (uint32, error) {
type IgnoreKey struct {
Bucket string
Key string
}
func (b *backend) Hash(ignores map[IgnoreKey]struct{}) (uint32, error) {
h := crc32.New(crc32.MakeTable(crc32.Castagnoli))
b.mu.RLock()
@ -158,8 +163,11 @@ func (b *backend) Hash() (uint32, error) {
}
h.Write(next)
b.ForEach(func(k, v []byte) error {
h.Write(k)
h.Write(v)
bk := IgnoreKey{Bucket: string(next), Key: string(k)}
if _, ok := ignores[bk]; !ok {
h.Write(k)
h.Write(v)
}
return nil
})
}

View File

@ -141,7 +141,7 @@ func TestBackendDefrag(t *testing.T) {
size := b.Size()
// shrink and check hash
oh, err := b.Hash()
oh, err := b.Hash(nil)
if err != nil {
t.Fatal(err)
}
@ -151,7 +151,7 @@ func TestBackendDefrag(t *testing.T) {
t.Fatal(err)
}
nh, err := b.Hash()
nh, err := b.Hash(nil)
if err != nil {
t.Fatal(err)
}

View File

@ -320,7 +320,14 @@ func (s *store) Hash() (uint32, int64, error) {
s.mu.Lock()
defer s.mu.Unlock()
h, err := s.b.Hash()
// ignore hash consistent index field for now.
// consistent index might be changed due to v2 internal sync, which
// is not controllable by the user.
ignores := make(map[backend.IgnoreKey]struct{})
bk := backend.IgnoreKey{Bucket: string(metaBucketName), Key: string(consistentIndexKeyName)}
ignores[bk] = struct{}{}
h, err := s.b.Hash(ignores)
rev := s.currentRev.main
return h, rev, err
}

View File

@ -593,13 +593,13 @@ type fakeBackend struct {
tx *fakeBatchTx
}
func (b *fakeBackend) BatchTx() backend.BatchTx { return b.tx }
func (b *fakeBackend) Hash() (uint32, error) { return 0, nil }
func (b *fakeBackend) Size() int64 { return 0 }
func (b *fakeBackend) Snapshot() backend.Snapshot { return nil }
func (b *fakeBackend) ForceCommit() {}
func (b *fakeBackend) Defrag() error { return nil }
func (b *fakeBackend) Close() error { return nil }
func (b *fakeBackend) BatchTx() backend.BatchTx { return b.tx }
func (b *fakeBackend) Hash(ignores map[backend.IgnoreKey]struct{}) (uint32, error) { return 0, nil }
func (b *fakeBackend) Size() int64 { return 0 }
func (b *fakeBackend) Snapshot() backend.Snapshot { return nil }
func (b *fakeBackend) ForceCommit() {}
func (b *fakeBackend) Defrag() error { return nil }
func (b *fakeBackend) Close() error { return nil }
type indexGetResp struct {
rev revision

View File

@ -143,7 +143,7 @@ func compactKV(clients []*v3.Client) {
revToCompact := max(0, curRev-compactIndexDelta)
for _, c := range clients {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
err := c.KV.Compact(ctx, revToCompact)
_, err := c.KV.Compact(ctx, revToCompact)
cancel()
if err != nil {
panic(err)

View File

@ -29,7 +29,7 @@ import (
var (
// MinClusterVersion is the min cluster version this etcd binary is compatible with.
MinClusterVersion = "2.3.0"
Version = "3.0.0-beta.0+git"
Version = "3.0.0"
// Git SHA Value will be set during build
GitSHA = "Not provided (use ./build instead of go build)"