mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
namespace: check IsWithFromKey if keyLen equal 0. (#12307)
* namespace: check IsWithFromKey if keyLen equal 0. Rename function isWithFromKey/isWithPrefix to IsOptsWithFromKey/IsOptsWithPrefix. fixes: #12282 * integration: add test while WithFromKey/WithPrefix called in opts.
This commit is contained in:
parent
2c66612e0e
commit
11ba1a6109
@ -48,7 +48,7 @@ func (kv *kvPrefix) Put(ctx context.Context, key, val string, opts ...clientv3.O
|
||||
}
|
||||
|
||||
func (kv *kvPrefix) Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) {
|
||||
if len(key) == 0 {
|
||||
if len(key) == 0 && !(clientv3.IsOptsWithFromKey(opts) || clientv3.IsOptsWithPrefix(opts)) {
|
||||
return nil, rpctypes.ErrEmptyKey
|
||||
}
|
||||
r, err := kv.KV.Do(ctx, kv.prefixOp(clientv3.OpGet(key, opts...)))
|
||||
@ -61,7 +61,7 @@ func (kv *kvPrefix) Get(ctx context.Context, key string, opts ...clientv3.OpOpti
|
||||
}
|
||||
|
||||
func (kv *kvPrefix) Delete(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.DeleteResponse, error) {
|
||||
if len(key) == 0 {
|
||||
if len(key) == 0 && !(clientv3.IsOptsWithFromKey(opts) || clientv3.IsOptsWithPrefix(opts)) {
|
||||
return nil, rpctypes.ErrEmptyKey
|
||||
}
|
||||
r, err := kv.KV.Do(ctx, kv.prefixOp(clientv3.OpDelete(key, opts...)))
|
||||
|
@ -219,7 +219,7 @@ func (op Op) isWrite() bool {
|
||||
// OpGet returns "get" operation based on given key and operation options.
|
||||
func OpGet(key string, opts ...OpOption) Op {
|
||||
// WithPrefix and WithFromKey are not supported together
|
||||
if isWithPrefix(opts) && isWithFromKey(opts) {
|
||||
if IsOptsWithPrefix(opts) && IsOptsWithFromKey(opts) {
|
||||
panic("`WithPrefix` and `WithFromKey` cannot be set at the same time, choose one")
|
||||
}
|
||||
ret := Op{t: tRange, key: []byte(key)}
|
||||
@ -230,7 +230,7 @@ func OpGet(key string, opts ...OpOption) Op {
|
||||
// OpDelete returns "delete" operation based on given key and operation options.
|
||||
func OpDelete(key string, opts ...OpOption) Op {
|
||||
// WithPrefix and WithFromKey are not supported together
|
||||
if isWithPrefix(opts) && isWithFromKey(opts) {
|
||||
if IsOptsWithPrefix(opts) && IsOptsWithFromKey(opts) {
|
||||
panic("`WithPrefix` and `WithFromKey` cannot be set at the same time, choose one")
|
||||
}
|
||||
ret := Op{t: tDeleteRange, key: []byte(key)}
|
||||
@ -553,8 +553,8 @@ func toLeaseTimeToLiveRequest(id LeaseID, opts ...LeaseOption) *pb.LeaseTimeToLi
|
||||
return &pb.LeaseTimeToLiveRequest{ID: int64(id), Keys: ret.attachedKeys}
|
||||
}
|
||||
|
||||
// isWithPrefix returns true if WithPrefix is being called in the op
|
||||
func isWithPrefix(opts []OpOption) bool { return isOpFuncCalled("WithPrefix", opts) }
|
||||
// IsOptsWithPrefix returns true if WithPrefix option is called in the given opts.
|
||||
func IsOptsWithPrefix(opts []OpOption) bool { return isOpFuncCalled("WithPrefix", opts) }
|
||||
|
||||
// isWithFromKey returns true if WithFromKey is being called in the op
|
||||
func isWithFromKey(opts []OpOption) bool { return isOpFuncCalled("WithFromKey", opts) }
|
||||
// IsOptsWithFromKey returns true if WithFromKey option is called in the given opts.
|
||||
func IsOptsWithFromKey(opts []OpOption) bool { return isOpFuncCalled("WithFromKey", opts) }
|
||||
|
88
integration/v3_kv_test.go
Normal file
88
integration/v3_kv_test.go
Normal file
@ -0,0 +1,88 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"go.etcd.io/etcd/v3/clientv3"
|
||||
"go.etcd.io/etcd/v3/clientv3/namespace"
|
||||
"go.etcd.io/etcd/v3/embed"
|
||||
"go.etcd.io/etcd/v3/etcdserver/api/v3client"
|
||||
"go.etcd.io/etcd/v3/pkg/testutil"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestKVWithEmptyValue ensures that a get/delete with an empty value, and with WithFromKey/WithPrefix function will return an empty error.
|
||||
func TestKVWithEmptyValue(t *testing.T) {
|
||||
defer testutil.AfterTest(t)
|
||||
|
||||
cfg := embed.NewConfig()
|
||||
|
||||
// Use temporary data directory.
|
||||
dir, err := ioutil.TempDir("", "etcd-")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
cfg.Dir = dir
|
||||
|
||||
// Suppress server log to keep output clean.
|
||||
//cfg.Logger = "zap"
|
||||
//cfg.LogLevel = "error"
|
||||
|
||||
etcd, err := embed.StartEtcd(cfg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer etcd.Close()
|
||||
<-etcd.Server.ReadyNotify()
|
||||
|
||||
client := v3client.New(etcd.Server)
|
||||
defer client.Close()
|
||||
|
||||
_, err = client.Put(context.Background(), "my-namespace/foobar", "data")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = client.Put(context.Background(), "my-namespace/foobar1", "data")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = client.Put(context.Background(), "namespace/foobar1", "data")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Range over all keys.
|
||||
resp, err := client.Get(context.Background(), "", clientv3.WithFromKey())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, kv := range resp.Kvs {
|
||||
t.Log(string(kv.Key), "=", string(kv.Value))
|
||||
}
|
||||
|
||||
// Range over all keys in a namespace.
|
||||
client.KV = namespace.NewKV(client.KV, "my-namespace/")
|
||||
resp, err = client.Get(context.Background(), "", clientv3.WithFromKey())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, kv := range resp.Kvs {
|
||||
t.Log(string(kv.Key), "=", string(kv.Value))
|
||||
}
|
||||
|
||||
//Remove all keys without WithFromKey/WithPrefix func
|
||||
respDel, err := client.Delete(context.Background(), "")
|
||||
if err == nil {
|
||||
// fatal error duo to without WithFromKey/WithPrefix func called.
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
respDel, err = client.Delete(context.Background(), "", clientv3.WithFromKey())
|
||||
if err != nil {
|
||||
// fatal error duo to with WithFromKey/WithPrefix func called.
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("delete keys:%d", respDel.Deleted)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user