From 2092b5b1a94e1366cd80c7b34a3638d7b12a9875 Mon Sep 17 00:00:00 2001 From: zhanwang Date: Sun, 5 Apr 2020 05:41:19 +0800 Subject: [PATCH] pkg, clientv3: etcdctl snaprestore when data-dir empty (#11648) --- clientv3/snapshot/v3_snapshot.go | 4 ++-- pkg/fileutil/fileutil.go | 6 ++++++ pkg/fileutil/fileutil_test.go | 25 +++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/clientv3/snapshot/v3_snapshot.go b/clientv3/snapshot/v3_snapshot.go index 5eefdbaac..5c11bf8ee 100644 --- a/clientv3/snapshot/v3_snapshot.go +++ b/clientv3/snapshot/v3_snapshot.go @@ -268,8 +268,8 @@ func (s *v3Manager) Restore(cfg RestoreConfig) error { if dataDir == "" { dataDir = cfg.Name + ".etcd" } - if fileutil.Exist(dataDir) { - return fmt.Errorf("data-dir %q exists", dataDir) + if fileutil.Exist(dataDir) && !fileutil.DirEmpty(dataDir) { + return fmt.Errorf("data-dir %q not empty or could not be read", dataDir) } walDir := cfg.OutputWALDir diff --git a/pkg/fileutil/fileutil.go b/pkg/fileutil/fileutil.go index 03d82ee71..bc8b92c26 100644 --- a/pkg/fileutil/fileutil.go +++ b/pkg/fileutil/fileutil.go @@ -76,6 +76,12 @@ func Exist(name string) bool { return err == nil } +// DirEmpty returns true if a directory empty and can access. +func DirEmpty(name string) bool { + ns, err := ReadDir(name) + return len(ns) == 0 && err == nil +} + // ZeroToEnd zeros a file starting from SEEK_CUR to its SEEK_END. May temporarily // shorten the length of the file. func ZeroToEnd(f *os.File) error { diff --git a/pkg/fileutil/fileutil_test.go b/pkg/fileutil/fileutil_test.go index a76d87ddc..58da3fe33 100644 --- a/pkg/fileutil/fileutil_test.go +++ b/pkg/fileutil/fileutil_test.go @@ -105,6 +105,31 @@ func TestExist(t *testing.T) { } } +func TestDirEmpty(t *testing.T) { + dir, err := ioutil.TempDir(os.TempDir(), "empty_dir") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + if !DirEmpty(dir) { + t.Fatalf("expected DirEmpty true, got %v", DirEmpty(dir)) + } + + file, err := ioutil.TempFile(dir, "new_file") + if err != nil { + t.Fatal(err) + } + file.Close() + + if DirEmpty(dir) { + t.Fatalf("expected DirEmpty false, got %v", DirEmpty(dir)) + } + if DirEmpty(file.Name()) { + t.Fatalf("expected DirEmpty false, got %v", DirEmpty(file.Name())) + } +} + func TestZeroToEnd(t *testing.T) { f, err := ioutil.TempFile(os.TempDir(), "fileutil") if err != nil {