Browse Source

etcdserver: Fix v2v3api set to create parent directly if not exists

When a new file is created under an non existent directly,
the v2 API automatically create the parent directly.
This commit aligns the behaviour of v2v3 emulation to comply with the v2
API.
Iwasaki Yudai 7 years ago
parent
commit
3c25465855
2 changed files with 29 additions and 6 deletions
  1. 14 4
      etcdserver/api/v2v3/store.go
  2. 15 2
      etcdserver/v2store/store_test.go

+ 14 - 4
etcdserver/api/v2v3/store.go

@@ -143,10 +143,20 @@ func (s *v2v3Store) Set(
 
 	ecode := 0
 	applyf := func(stm concurrency.STM) error {
-		parent := path.Dir(nodePath)
-		if !isRoot(parent) && stm.Rev(s.mkPath(parent)+"/") == 0 {
-			ecode = v2error.EcodeKeyNotFound
-			return nil
+		// build path if any directories in path do not exist
+		dirs := []string{}
+		for p := path.Dir(nodePath); !isRoot(p); p = path.Dir(p) {
+			pp := s.mkPath(p)
+			if stm.Rev(pp) > 0 {
+				ecode = v2error.EcodeNotDir
+				return nil
+			}
+			if stm.Rev(pp+"/") == 0 {
+				dirs = append(dirs, pp+"/")
+			}
+		}
+		for _, d := range dirs {
+			stm.Put(d, "")
 		}
 
 		key := s.mkPath(nodePath)

+ 15 - 2
etcdserver/v2store/store_test.go

@@ -145,8 +145,21 @@ func TestSet(t *testing.T) {
 	testutil.AssertEqual(t, *e.PrevNode.Value, "bar")
 	testutil.AssertEqual(t, e.PrevNode.ModifiedIndex, uint64(2))
 
-	// Set /dir as a directory
+	// Set /a/b/c/d="efg"
 	eidx = 4
+	e, err = s.Set("/a/b/c/d", false, "efg", v2store.TTLOptionSet{ExpireTime: v2store.Permanent})
+	testutil.AssertNil(t, err)
+	testutil.AssertEqual(t, e.EtcdIndex, eidx)
+	testutil.AssertEqual(t, e.Node.Key, "/a/b/c/d")
+	testutil.AssertFalse(t, e.Node.Dir)
+	testutil.AssertEqual(t, *e.Node.Value, "efg")
+	testutil.AssertNil(t, e.Node.Nodes)
+	testutil.AssertNil(t, e.Node.Expiration)
+	testutil.AssertEqual(t, e.Node.TTL, int64(0))
+	testutil.AssertEqual(t, e.Node.ModifiedIndex, uint64(4))
+
+	// Set /dir as a directory
+	eidx = 5
 	e, err = s.Set("/dir", true, "", v2store.TTLOptionSet{ExpireTime: v2store.Permanent})
 	testutil.AssertNil(t, err)
 	testutil.AssertEqual(t, e.EtcdIndex, eidx)
@@ -157,7 +170,7 @@ func TestSet(t *testing.T) {
 	testutil.AssertNil(t, e.Node.Nodes)
 	testutil.AssertNil(t, e.Node.Expiration)
 	testutil.AssertEqual(t, e.Node.TTL, int64(0))
-	testutil.AssertEqual(t, e.Node.ModifiedIndex, uint64(4))
+	testutil.AssertEqual(t, e.Node.ModifiedIndex, uint64(5))
 }
 
 // Ensure that the store can create a new key if it doesn't already exist.