diff --git a/e2e/etcdctlv3_test.go b/e2e/etcdctlv3_test.go index 84835e050..5894dae32 100644 --- a/e2e/etcdctlv3_test.go +++ b/e2e/etcdctlv3_test.go @@ -23,6 +23,22 @@ import ( "github.com/coreos/etcd/pkg/testutil" ) +func TestCtlV3Set(t *testing.T) { + testCtlV3Set(t, &configNoTLS, 3*time.Second, false) +} + +func TestCtlV3SetZeroTimeout(t *testing.T) { + testCtlV3Set(t, &configNoTLS, 0, false) +} + +func TestCtlV3SetTimeout(t *testing.T) { + testCtlV3Set(t, &configNoTLS, time.Nanosecond, false) +} + +func TestCtlV3SetPeerTLS(t *testing.T) { + testCtlV3Set(t, &configPeerTLS, 3*time.Second, false) +} + func TestCtlV3SetQuorum(t *testing.T) { testCtlV3Set(t, &configNoTLS, 3*time.Second, true) } @@ -105,12 +121,10 @@ func ctlV3Put(clus *etcdProcessCluster, key, value string, dialTimeout time.Dura } func ctlV3Get(clus *etcdProcessCluster, key, value string, dialTimeout time.Duration, quorum bool) error { - if !quorum { // TODO: add serialized option - panic("serialized option is not implemented") - } - cmdArgs := append(ctlV3PrefixArgs(clus, dialTimeout), "get", key) - + if !quorum { + cmdArgs = append(cmdArgs, "--consistency", "s") + } // TODO: match by value. Currently it prints out both key and value in multi-lines. return spawnWithExpectedString(cmdArgs, key) } @@ -122,10 +136,6 @@ func mustCtlV3(t *testing.T) { } func setupCtlV3Test(t *testing.T, cfg *etcdProcessClusterConfig, quorum bool) *etcdProcessCluster { - if !quorum { // TODO: add serialized option - panic("serialized option is not implemented") - } - mustCtlV3(t) if !quorum { cfg = configStandalone(*cfg) diff --git a/etcdctlv3/command/get_command.go b/etcdctlv3/command/get_command.go index 99746adbd..eb87ee0b0 100644 --- a/etcdctlv3/command/get_command.go +++ b/etcdctlv3/command/get_command.go @@ -24,11 +24,12 @@ import ( ) var ( - getLimit int64 - getSortOrder string - getSortTarget string - getPrefix bool - getFromKey bool + getConsistency string + getLimit int64 + getSortOrder string + getSortTarget string + getPrefix bool + getFromKey bool ) // NewGetCommand returns the cobra command for "get". @@ -39,12 +40,12 @@ func NewGetCommand() *cobra.Command { 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") - // TODO: add consistency. return cmd } @@ -69,6 +70,14 @@ func getGetOp(cmd *cobra.Command, args []string) (string, []clientv3.OpOption) { } opts := []clientv3.OpOption{} + switch getConsistency { + case "s": + opts = append(opts, clientv3.WithSerializable()) + case "l": + default: + ExitWithError(ExitBadFeature, fmt.Errorf("unknown consistency flag %q", getConsistency)) + } + key := args[0] if len(args) > 1 { if getPrefix || getFromKey {