|
|
@@ -2,6 +2,7 @@ package dashboards
|
|
|
|
|
|
import (
|
|
|
"os"
|
|
|
+ "path/filepath"
|
|
|
"testing"
|
|
|
"time"
|
|
|
|
|
|
@@ -22,7 +23,7 @@ var (
|
|
|
)
|
|
|
|
|
|
func TestDashboardFileReader(t *testing.T) {
|
|
|
- Convey("Reading dashboards from disk", t, func() {
|
|
|
+ Convey("Dashboard file reader", t, func() {
|
|
|
bus.ClearBusHandlers()
|
|
|
fakeRepo = &fakeDashboardRepo{}
|
|
|
|
|
|
@@ -30,91 +31,191 @@ func TestDashboardFileReader(t *testing.T) {
|
|
|
dashboards.SetRepository(fakeRepo)
|
|
|
logger := log.New("test.logger")
|
|
|
|
|
|
- cfg := &DashboardsAsConfig{
|
|
|
- Name: "Default",
|
|
|
- Type: "file",
|
|
|
- OrgId: 1,
|
|
|
- Folder: "",
|
|
|
- Options: map[string]interface{}{},
|
|
|
- }
|
|
|
+ Convey("Reading dashboards from disk", func() {
|
|
|
|
|
|
- Convey("Can read default dashboard", func() {
|
|
|
- cfg.Options["folder"] = defaultDashboards
|
|
|
+ cfg := &DashboardsAsConfig{
|
|
|
+ Name: "Default",
|
|
|
+ Type: "file",
|
|
|
+ OrgId: 1,
|
|
|
+ Folder: "",
|
|
|
+ Options: map[string]interface{}{},
|
|
|
+ }
|
|
|
|
|
|
- reader, err := NewDashboardFileReader(cfg, logger)
|
|
|
- So(err, ShouldBeNil)
|
|
|
+ Convey("Can read default dashboard", func() {
|
|
|
+ cfg.Options["folder"] = defaultDashboards
|
|
|
+ cfg.Folder = "Team A"
|
|
|
|
|
|
- err = reader.walkFolder()
|
|
|
- So(err, ShouldBeNil)
|
|
|
+ reader, err := NewDashboardFileReader(cfg, logger)
|
|
|
+ So(err, ShouldBeNil)
|
|
|
|
|
|
- So(len(fakeRepo.inserted), ShouldEqual, 2)
|
|
|
- })
|
|
|
+ err = reader.startWalkingDisk()
|
|
|
+ So(err, ShouldBeNil)
|
|
|
+
|
|
|
+ folders := 0
|
|
|
+ dashboards := 0
|
|
|
|
|
|
- Convey("Should not update dashboards when db is newer", func() {
|
|
|
- cfg.Options["folder"] = oneDashboard
|
|
|
+ for _, i := range fakeRepo.inserted {
|
|
|
+ if i.Dashboard.IsFolder {
|
|
|
+ folders++
|
|
|
+ } else {
|
|
|
+ dashboards++
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- fakeRepo.getDashboard = append(fakeRepo.getDashboard, &models.Dashboard{
|
|
|
- Updated: time.Now().Add(time.Hour),
|
|
|
- Slug: "grafana",
|
|
|
+ So(dashboards, ShouldEqual, 2)
|
|
|
+ So(folders, ShouldEqual, 1)
|
|
|
})
|
|
|
|
|
|
- reader, err := NewDashboardFileReader(cfg, logger)
|
|
|
- So(err, ShouldBeNil)
|
|
|
+ Convey("Should not update dashboards when db is newer", func() {
|
|
|
+ cfg.Options["folder"] = oneDashboard
|
|
|
|
|
|
- err = reader.walkFolder()
|
|
|
- So(err, ShouldBeNil)
|
|
|
+ fakeRepo.getDashboard = append(fakeRepo.getDashboard, &models.Dashboard{
|
|
|
+ Updated: time.Now().Add(time.Hour),
|
|
|
+ Slug: "grafana",
|
|
|
+ })
|
|
|
|
|
|
- So(len(fakeRepo.inserted), ShouldEqual, 0)
|
|
|
- })
|
|
|
+ reader, err := NewDashboardFileReader(cfg, logger)
|
|
|
+ So(err, ShouldBeNil)
|
|
|
+
|
|
|
+ err = reader.startWalkingDisk()
|
|
|
+ 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
|
|
|
|
|
|
- Convey("Can read default dashboard and replace old version in database", func() {
|
|
|
- cfg.Options["folder"] = oneDashboard
|
|
|
+ stat, _ := os.Stat(oneDashboard + "/dashboard1.json")
|
|
|
|
|
|
- stat, _ := os.Stat(oneDashboard + "/dashboard1.json")
|
|
|
+ fakeRepo.getDashboard = append(fakeRepo.getDashboard, &models.Dashboard{
|
|
|
+ Updated: stat.ModTime().AddDate(0, 0, -1),
|
|
|
+ Slug: "grafana",
|
|
|
+ })
|
|
|
|
|
|
- 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.startWalkingDisk()
|
|
|
+ So(err, ShouldBeNil)
|
|
|
+
|
|
|
+ So(len(fakeRepo.inserted), ShouldEqual, 1)
|
|
|
})
|
|
|
|
|
|
- reader, err := NewDashboardFileReader(cfg, logger)
|
|
|
- So(err, ShouldBeNil)
|
|
|
+ Convey("Invalid configuration should return error", func() {
|
|
|
+ cfg := &DashboardsAsConfig{
|
|
|
+ Name: "Default",
|
|
|
+ Type: "file",
|
|
|
+ OrgId: 1,
|
|
|
+ Folder: "",
|
|
|
+ }
|
|
|
|
|
|
- err = reader.walkFolder()
|
|
|
- So(err, ShouldBeNil)
|
|
|
+ _, err := NewDashboardFileReader(cfg, logger)
|
|
|
+ So(err, ShouldNotBeNil)
|
|
|
+ })
|
|
|
|
|
|
- So(len(fakeRepo.inserted), ShouldEqual, 1)
|
|
|
+ Convey("Broken dashboards should not cause error", func() {
|
|
|
+ cfg.Options["folder"] = brokenDashboards
|
|
|
+
|
|
|
+ _, err := NewDashboardFileReader(cfg, logger)
|
|
|
+ So(err, ShouldBeNil)
|
|
|
+ })
|
|
|
})
|
|
|
|
|
|
- Convey("Invalid configuration should return error", func() {
|
|
|
+ Convey("Should not create new folder if folder name is missing", func() {
|
|
|
cfg := &DashboardsAsConfig{
|
|
|
Name: "Default",
|
|
|
Type: "file",
|
|
|
OrgId: 1,
|
|
|
Folder: "",
|
|
|
+ Options: map[string]interface{}{
|
|
|
+ "folder": defaultDashboards,
|
|
|
+ },
|
|
|
}
|
|
|
|
|
|
- _, err := NewDashboardFileReader(cfg, logger)
|
|
|
- So(err, ShouldNotBeNil)
|
|
|
+ _, err := getOrCreateFolderId(cfg, fakeRepo)
|
|
|
+ So(err, ShouldEqual, ErrFolderNameMissing)
|
|
|
})
|
|
|
|
|
|
- Convey("Broken dashboards should not cause error", func() {
|
|
|
+ Convey("can get or Create dashboard folder", func() {
|
|
|
+ cfg := &DashboardsAsConfig{
|
|
|
+ Name: "Default",
|
|
|
+ Type: "file",
|
|
|
+ OrgId: 1,
|
|
|
+ Folder: "TEAM A",
|
|
|
+ Options: map[string]interface{}{
|
|
|
+ "folder": defaultDashboards,
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ folderId, err := getOrCreateFolderId(cfg, fakeRepo)
|
|
|
+ So(err, ShouldBeNil)
|
|
|
+ inserted := false
|
|
|
+ for _, d := range fakeRepo.inserted {
|
|
|
+ if d.Dashboard.IsFolder && d.Dashboard.Id == folderId {
|
|
|
+ inserted = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ So(len(fakeRepo.inserted), ShouldEqual, 1)
|
|
|
+ So(inserted, ShouldBeTrue)
|
|
|
+ })
|
|
|
+
|
|
|
+ Convey("Walking the folder with dashboards", 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.createWalk(reader, 0)("path", &FakeFileInfo{isDirectory: true, name: ".folder"}, nil)
|
|
|
+ So(shouldSkip, ShouldEqual, filepath.SkipDir)
|
|
|
+ })
|
|
|
+
|
|
|
+ Convey("should keep walking if file is not .json", func() {
|
|
|
+ shouldSkip := reader.createWalk(reader, 0)("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
|