From 71ce810f3a4e3f97c2fcf1fcbc06bb61be39829e Mon Sep 17 00:00:00 2001 From: vivekpatani <9080894+vivekpatani@users.noreply.github.com> Date: Wed, 20 Jul 2022 10:32:17 -0700 Subject: [PATCH] etcdserver,pkg: remove temp files in snap dir when etcdserver starting - Backporting: https://github.com/etcd-io/etcd/pull/12846 - Reference: https://github.com/etcd-io/etcd/issues/14232 Signed-off-by: vivekpatani <9080894+vivekpatani@users.noreply.github.com> --- etcdserver/server.go | 12 ++++++++++ pkg/fileutil/fileutil.go | 32 ++++++++++++++++++++++++++ pkg/fileutil/fileutil_test.go | 43 +++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/etcdserver/server.go b/etcdserver/server.go index 0733fd28547..1638719ffc6 100644 --- a/etcdserver/server.go +++ b/etcdserver/server.go @@ -25,6 +25,7 @@ import ( "os" "path" "regexp" + "strings" "sync" "sync/atomic" "time" @@ -323,6 +324,17 @@ func NewServer(cfg ServerConfig) (srv *EtcdServer, err error) { plog.Fatalf("create snapshot directory error: %v", err) } } + + if err = fileutil.RemoveMatchFile(cfg.Logger, cfg.SnapDir(), func(fileName string) bool { + return strings.HasPrefix(fileName, "tmp") + }); err != nil { + cfg.Logger.Error( + "failed to remove temp file(s) in snapshot directory", + zap.String("path", cfg.SnapDir()), + zap.Error(err), + ) + } + ss := snap.New(cfg.Logger, cfg.SnapDir()) bepath := cfg.backendPath() diff --git a/pkg/fileutil/fileutil.go b/pkg/fileutil/fileutil.go index f36136182b9..7052a808406 100644 --- a/pkg/fileutil/fileutil.go +++ b/pkg/fileutil/fileutil.go @@ -16,6 +16,7 @@ package fileutil import ( "fmt" + "go.uber.org/zap" "io" "io/ioutil" "os" @@ -127,3 +128,34 @@ func CheckDirPermission(dir string, perm os.FileMode) error { } return nil } + +// RemoveMatchFile deletes file if matchFunc is true on an existing dir +// Returns error if the dir does not exist or remove file fail +func RemoveMatchFile(lg *zap.Logger, dir string, matchFunc func(fileName string) bool) error { + if lg == nil { + lg = zap.NewNop() + } + if !Exist(dir) { + return fmt.Errorf("directory %s does not exist", dir) + } + fileNames, err := ReadDir(dir) + if err != nil { + return err + } + var removeFailedFiles []string + for _, fileName := range fileNames { + if matchFunc(fileName) { + file := filepath.Join(dir, fileName) + if err = os.Remove(file); err != nil { + removeFailedFiles = append(removeFailedFiles, fileName) + lg.Error("remove file failed", + zap.String("file", file), + zap.Error(err)) + } + } + } + if len(removeFailedFiles) != 0 { + return fmt.Errorf("remove file(s) %v error", removeFailedFiles) + } + return nil +} diff --git a/pkg/fileutil/fileutil_test.go b/pkg/fileutil/fileutil_test.go index 7cfac190e5c..f93c0d4ce36 100644 --- a/pkg/fileutil/fileutil_test.go +++ b/pkg/fileutil/fileutil_test.go @@ -26,6 +26,8 @@ import ( "strings" "testing" "time" + + "go.uber.org/zap/zaptest" ) func TestIsDirWriteable(t *testing.T) { @@ -166,3 +168,44 @@ func TestDirPermission(t *testing.T) { t.Errorf("expected error, got nil") } } + +func TestRemoveMatchFile(t *testing.T) { + tmpdir := t.TempDir() + f, err := os.CreateTemp(tmpdir, "tmp") + if err != nil { + t.Fatal(err) + } + f.Close() + f, err = os.CreateTemp(tmpdir, "foo.tmp") + if err != nil { + t.Fatal(err) + } + f.Close() + + err = RemoveMatchFile(zaptest.NewLogger(t), tmpdir, func(fileName string) bool { + return strings.HasPrefix(fileName, "tmp") + }) + if err != nil { + t.Errorf("expected nil, got error") + } + fnames, err := ReadDir(tmpdir) + if err != nil { + t.Fatal(err) + } + if len(fnames) != 1 { + t.Errorf("expected exist 1 files, got %d", len(fnames)) + } + + f, err = os.CreateTemp(tmpdir, "tmp") + if err != nil { + t.Fatal(err) + } + f.Close() + err = RemoveMatchFile(zaptest.NewLogger(t), tmpdir, func(fileName string) bool { + os.Remove(filepath.Join(tmpdir, fileName)) + return strings.HasPrefix(fileName, "tmp") + }) + if err == nil { + t.Errorf("expected error, got nil") + } +}