From f4078e1935065f77da28ed9d137054303e632b00 Mon Sep 17 00:00:00 2001 From: bergquist Date: Wed, 27 Dec 2017 15:04:32 +0100 Subject: [PATCH] tests: for skipping with hidden folders --- .../provisioning/dashboards/file_reader.go | 75 ++++--- .../dashboards/file_reader_test.go | 200 +++++++++++------- 2 files changed, 172 insertions(+), 103 deletions(-) diff --git a/pkg/services/provisioning/dashboards/file_reader.go b/pkg/services/provisioning/dashboards/file_reader.go index 22fe11b45c1..9c8120f6a8c 100644 --- a/pkg/services/provisioning/dashboards/file_reader.go +++ b/pkg/services/provisioning/dashboards/file_reader.go @@ -18,12 +18,18 @@ import ( gocache "github.com/patrickmn/go-cache" ) +var ( + checkDiskForChangesInterval time.Duration = time.Second * 3 +) + type fileReader struct { - Cfg *DashboardsAsConfig - Path string - log log.Logger - dashboardRepo dashboards.Repository - cache *gocache.Cache + Cfg *DashboardsAsConfig + Path string + FolderId int64 + log log.Logger + dashboardRepo dashboards.Repository + cache *gocache.Cache + createWalkFunc func(fr *fileReader) filepath.WalkFunc } func NewDashboardFileReader(cfg *DashboardsAsConfig, log log.Logger) (*fileReader, error) { @@ -37,34 +43,17 @@ func NewDashboardFileReader(cfg *DashboardsAsConfig, log log.Logger) (*fileReade } return &fileReader{ - Cfg: cfg, - Path: path, - log: log, - dashboardRepo: dashboards.GetRepository(), - cache: gocache.New(5*time.Minute, 30*time.Minute), + Cfg: cfg, + Path: path, + log: log, + dashboardRepo: dashboards.GetRepository(), + cache: gocache.New(5*time.Minute, 30*time.Minute), + createWalkFunc: createWalkFn, }, nil } -func (fr *fileReader) addCache(key string, json *dashboards.SaveDashboardItem) { - fr.cache.Add(key, json, time.Minute*10) -} - -func (fr *fileReader) getCache(key string) (*dashboards.SaveDashboardItem, bool) { - obj, exist := fr.cache.Get(key) - if !exist { - return nil, exist - } - - dash, ok := obj.(*dashboards.SaveDashboardItem) - if !ok { - return nil, ok - } - - return dash, ok -} - func (fr *fileReader) ReadAndListen(ctx context.Context) error { - ticker := time.NewTicker(time.Second * 3) + ticker := time.NewTicker(checkDiskForChangesInterval) if err := fr.walkFolder(); err != nil { fr.log.Error("failed to search for dashboards", "error", err) @@ -95,7 +84,11 @@ func (fr *fileReader) walkFolder() error { } } - return filepath.Walk(fr.Path, func(path string, fileInfo os.FileInfo, err error) error { + return filepath.Walk(fr.Path, fr.createWalkFunc(fr)) //omg this is so ugly :( +} + +func createWalkFn(fr *fileReader) filepath.WalkFunc { + return func(path string, fileInfo os.FileInfo, err error) error { if err != nil { return err } @@ -147,7 +140,7 @@ func (fr *fileReader) walkFolder() error { fr.log.Debug("loading dashboard from disk into database.", "file", path) _, err = fr.dashboardRepo.SaveDashboard(dash) return err - }) + } } func (fr *fileReader) readDashboardFromFile(path string) (*dashboards.SaveDashboardItem, error) { @@ -172,7 +165,25 @@ func (fr *fileReader) readDashboardFromFile(path string) (*dashboards.SaveDashbo return nil, err } - fr.addCache(path, dash) + fr.addDashboardCache(path, dash) return dash, nil } + +func (fr *fileReader) addDashboardCache(key string, json *dashboards.SaveDashboardItem) { + fr.cache.Add(key, json, time.Minute*10) +} + +func (fr *fileReader) getCache(key string) (*dashboards.SaveDashboardItem, bool) { + obj, exist := fr.cache.Get(key) + if !exist { + return nil, exist + } + + dash, ok := obj.(*dashboards.SaveDashboardItem) + if !ok { + return nil, ok + } + + return dash, ok +} diff --git a/pkg/services/provisioning/dashboards/file_reader_test.go b/pkg/services/provisioning/dashboards/file_reader_test.go index e91f278322a..84bdf6ee49d 100644 --- a/pkg/services/provisioning/dashboards/file_reader_test.go +++ b/pkg/services/provisioning/dashboards/file_reader_test.go @@ -2,6 +2,7 @@ package dashboards import ( "os" + "path/filepath" "testing" "time" @@ -22,99 +23,156 @@ var ( ) func TestDashboardFileReader(t *testing.T) { - Convey("Reading dashboards from disk", t, func() { - bus.ClearBusHandlers() - fakeRepo = &fakeDashboardRepo{} + Convey("Dashboard file reader", t, func() { + Convey("Reading dashboards from disk", func() { - bus.AddHandler("test", mockGetDashboardQuery) - dashboards.SetRepository(fakeRepo) - logger := log.New("test.logger") + bus.ClearBusHandlers() + fakeRepo = &fakeDashboardRepo{} - cfg := &DashboardsAsConfig{ - Name: "Default", - Type: "file", - OrgId: 1, - Folder: "", - Options: map[string]interface{}{}, - } + bus.AddHandler("test", mockGetDashboardQuery) + dashboards.SetRepository(fakeRepo) + logger := log.New("test.logger") - Convey("Can read default dashboard", func() { - cfg.Options["folder"] = defaultDashboards - - reader, err := NewDashboardFileReader(cfg, logger) - So(err, ShouldBeNil) - - err = reader.walkFolder() - So(err, ShouldBeNil) - - So(len(fakeRepo.inserted), ShouldEqual, 2) - }) - - Convey("Should not update dashboards when db is newer", func() { - cfg.Options["folder"] = oneDashboard - - fakeRepo.getDashboard = append(fakeRepo.getDashboard, &models.Dashboard{ - Updated: time.Now().Add(time.Hour), - Slug: "grafana", - }) - - reader, err := NewDashboardFileReader(cfg, logger) - So(err, ShouldBeNil) - - err = reader.walkFolder() - So(err, ShouldBeNil) - - So(len(fakeRepo.inserted), ShouldEqual, 0) - }) - - Convey("Can read default dashboard and replace old version in database", func() { - cfg.Options["folder"] = oneDashboard - - stat, _ := os.Stat(oneDashboard + "/dashboard1.json") - - fakeRepo.getDashboard = append(fakeRepo.getDashboard, &models.Dashboard{ - Updated: stat.ModTime().AddDate(0, 0, -1), - Slug: "grafana", - }) - - reader, err := NewDashboardFileReader(cfg, logger) - So(err, ShouldBeNil) - - err = reader.walkFolder() - So(err, ShouldBeNil) - - So(len(fakeRepo.inserted), ShouldEqual, 1) - }) - - Convey("Invalid configuration should return error", func() { cfg := &DashboardsAsConfig{ - Name: "Default", - Type: "file", - OrgId: 1, - Folder: "", + Name: "Default", + Type: "file", + OrgId: 1, + Folder: "", + Options: map[string]interface{}{}, } - _, err := NewDashboardFileReader(cfg, logger) - So(err, ShouldNotBeNil) + Convey("Can read default dashboard", func() { + cfg.Options["folder"] = defaultDashboards + + reader, err := NewDashboardFileReader(cfg, logger) + So(err, ShouldBeNil) + + err = reader.walkFolder() + So(err, ShouldBeNil) + + So(len(fakeRepo.inserted), ShouldEqual, 2) + }) + + Convey("Should not update dashboards when db is newer", func() { + cfg.Options["folder"] = oneDashboard + + fakeRepo.getDashboard = append(fakeRepo.getDashboard, &models.Dashboard{ + Updated: time.Now().Add(time.Hour), + Slug: "grafana", + }) + + reader, err := NewDashboardFileReader(cfg, logger) + So(err, ShouldBeNil) + + err = reader.walkFolder() + So(err, ShouldBeNil) + + So(len(fakeRepo.inserted), ShouldEqual, 0) + }) + + Convey("Can read default dashboard and replace old version in database", func() { + cfg.Options["folder"] = oneDashboard + + stat, _ := os.Stat(oneDashboard + "/dashboard1.json") + + fakeRepo.getDashboard = append(fakeRepo.getDashboard, &models.Dashboard{ + Updated: stat.ModTime().AddDate(0, 0, -1), + Slug: "grafana", + }) + + reader, err := NewDashboardFileReader(cfg, logger) + So(err, ShouldBeNil) + + err = reader.walkFolder() + So(err, ShouldBeNil) + + So(len(fakeRepo.inserted), ShouldEqual, 1) + }) + + Convey("Invalid configuration should return error", func() { + cfg := &DashboardsAsConfig{ + Name: "Default", + Type: "file", + OrgId: 1, + Folder: "", + } + + _, err := NewDashboardFileReader(cfg, logger) + So(err, ShouldNotBeNil) + }) + + Convey("Broken dashboards should not cause error", func() { + cfg := &DashboardsAsConfig{ + Name: "Default", + Type: "file", + OrgId: 1, + Folder: "", + Options: map[string]interface{}{ + "folder": brokenDashboards, + }, + } + + _, err := NewDashboardFileReader(cfg, logger) + So(err, ShouldBeNil) + }) }) - Convey("Broken dashboards should not cause error", func() { + Convey("Walking", func() { cfg := &DashboardsAsConfig{ Name: "Default", Type: "file", OrgId: 1, Folder: "", Options: map[string]interface{}{ - "folder": brokenDashboards, + "folder": defaultDashboards, }, } - _, err := NewDashboardFileReader(cfg, logger) + reader, err := NewDashboardFileReader(cfg, log.New("test-logger")) So(err, ShouldBeNil) + + Convey("should skip dirs that starts with .", func() { + shouldSkip := reader.createWalkFunc(reader)("path", &FakeFileInfo{isDirectory: true, name: ".folder"}, nil) + So(shouldSkip, ShouldEqual, filepath.SkipDir) + }) + + Convey("should keep walking if file is not .json", func() { + shouldSkip := reader.createWalkFunc(reader)("path", &FakeFileInfo{isDirectory: true, name: "folder"}, nil) + So(shouldSkip, ShouldBeNil) + }) }) }) } +type FakeFileInfo struct { + isDirectory bool + name string +} + +func (ffi *FakeFileInfo) IsDir() bool { + return ffi.isDirectory +} + +func (ffi FakeFileInfo) Size() int64 { + return 1 +} + +func (ffi FakeFileInfo) Mode() os.FileMode { + return 0777 +} + +func (ffi FakeFileInfo) Name() string { + return ffi.name +} + +func (ffi FakeFileInfo) ModTime() time.Time { + return time.Time{} +} + +func (ffi FakeFileInfo) Sys() interface{} { + return nil +} + type fakeDashboardRepo struct { inserted []*dashboards.SaveDashboardItem getDashboard []*models.Dashboard