mirror of
https://github.com/grafana/grafana.git
synced 2024-11-30 12:44:10 -06:00
296 lines
7.4 KiB
Go
296 lines
7.4 KiB
Go
package dashboards
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/grafana/grafana/pkg/bus"
|
|
"github.com/grafana/grafana/pkg/models"
|
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
|
|
|
"github.com/grafana/grafana/pkg/log"
|
|
. "github.com/smartystreets/goconvey/convey"
|
|
)
|
|
|
|
var (
|
|
defaultDashboards = "testdata/test-dashboards/folder-one"
|
|
brokenDashboards = "testdata/test-dashboards/broken-dashboards"
|
|
oneDashboard = "testdata/test-dashboards/one-dashboard"
|
|
containingId = "testdata/test-dashboards/containing-id"
|
|
|
|
fakeService *fakeDashboardProvisioningService
|
|
)
|
|
|
|
func TestCreatingNewDashboardFileReader(t *testing.T) {
|
|
Convey("creating new dashboard file reader", t, func() {
|
|
cfg := &DashboardsAsConfig{
|
|
Name: "Default",
|
|
Type: "file",
|
|
OrgId: 1,
|
|
Folder: "",
|
|
Options: map[string]interface{}{},
|
|
}
|
|
|
|
Convey("using path parameter", func() {
|
|
cfg.Options["path"] = defaultDashboards
|
|
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"))
|
|
So(err, ShouldBeNil)
|
|
So(reader.Path, ShouldNotEqual, "")
|
|
})
|
|
|
|
Convey("using folder as options", func() {
|
|
cfg.Options["folder"] = defaultDashboards
|
|
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"))
|
|
So(err, ShouldBeNil)
|
|
So(reader.Path, ShouldNotEqual, "")
|
|
})
|
|
|
|
Convey("using full path", func() {
|
|
fullPath := "/var/lib/grafana/dashboards"
|
|
if runtime.GOOS == "windows" {
|
|
fullPath = `c:\var\lib\grafana`
|
|
}
|
|
|
|
cfg.Options["folder"] = fullPath
|
|
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"))
|
|
So(err, ShouldBeNil)
|
|
|
|
So(reader.Path, ShouldEqual, fullPath)
|
|
So(filepath.IsAbs(reader.Path), ShouldBeTrue)
|
|
})
|
|
|
|
Convey("using relative path", func() {
|
|
cfg.Options["folder"] = defaultDashboards
|
|
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"))
|
|
So(err, ShouldBeNil)
|
|
|
|
So(filepath.IsAbs(reader.Path), ShouldBeTrue)
|
|
})
|
|
})
|
|
}
|
|
|
|
func TestDashboardFileReader(t *testing.T) {
|
|
Convey("Dashboard file reader", t, func() {
|
|
bus.ClearBusHandlers()
|
|
origNewDashboardProvisioningService := dashboards.NewProvisioningService
|
|
fakeService = mockDashboardProvisioningService()
|
|
|
|
bus.AddHandler("test", mockGetDashboardQuery)
|
|
logger := log.New("test.logger")
|
|
|
|
Convey("Reading dashboards from disk", func() {
|
|
|
|
cfg := &DashboardsAsConfig{
|
|
Name: "Default",
|
|
Type: "file",
|
|
OrgId: 1,
|
|
Folder: "",
|
|
Options: map[string]interface{}{},
|
|
}
|
|
|
|
Convey("Can read default dashboard", func() {
|
|
cfg.Options["path"] = defaultDashboards
|
|
cfg.Folder = "Team A"
|
|
|
|
reader, err := NewDashboardFileReader(cfg, logger)
|
|
So(err, ShouldBeNil)
|
|
|
|
err = reader.startWalkingDisk()
|
|
So(err, ShouldBeNil)
|
|
|
|
folders := 0
|
|
dashboards := 0
|
|
|
|
for _, i := range fakeService.inserted {
|
|
if i.Dashboard.IsFolder {
|
|
folders++
|
|
} else {
|
|
dashboards++
|
|
}
|
|
}
|
|
|
|
So(folders, ShouldEqual, 1)
|
|
So(dashboards, ShouldEqual, 2)
|
|
})
|
|
|
|
Convey("Can read default dashboard and replace old version in database", func() {
|
|
cfg.Options["path"] = oneDashboard
|
|
|
|
stat, _ := os.Stat(oneDashboard + "/dashboard1.json")
|
|
|
|
fakeService.getDashboard = append(fakeService.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(fakeService.inserted), ShouldEqual, 1)
|
|
})
|
|
|
|
Convey("Overrides id from dashboard.json files", func() {
|
|
cfg.Options["path"] = containingId
|
|
|
|
reader, err := NewDashboardFileReader(cfg, logger)
|
|
So(err, ShouldBeNil)
|
|
|
|
err = reader.startWalkingDisk()
|
|
So(err, ShouldBeNil)
|
|
|
|
So(len(fakeService.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.Options["path"] = brokenDashboards
|
|
|
|
_, err := NewDashboardFileReader(cfg, logger)
|
|
So(err, ShouldBeNil)
|
|
})
|
|
})
|
|
|
|
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 := getOrCreateFolderId(cfg, fakeService)
|
|
So(err, ShouldEqual, ErrFolderNameMissing)
|
|
})
|
|
|
|
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, fakeService)
|
|
So(err, ShouldBeNil)
|
|
inserted := false
|
|
for _, d := range fakeService.inserted {
|
|
if d.Dashboard.IsFolder && d.Dashboard.Id == folderId {
|
|
inserted = true
|
|
}
|
|
}
|
|
So(len(fakeService.inserted), ShouldEqual, 1)
|
|
So(inserted, ShouldBeTrue)
|
|
})
|
|
|
|
Convey("Walking the folder with dashboards", func() {
|
|
noFiles := map[string]os.FileInfo{}
|
|
|
|
Convey("should skip dirs that starts with .", func() {
|
|
shouldSkip := createWalkFn(noFiles)("path", &FakeFileInfo{isDirectory: true, name: ".folder"}, nil)
|
|
So(shouldSkip, ShouldEqual, filepath.SkipDir)
|
|
})
|
|
|
|
Convey("should keep walking if file is not .json", func() {
|
|
shouldSkip := createWalkFn(noFiles)("path", &FakeFileInfo{isDirectory: true, name: "folder"}, nil)
|
|
So(shouldSkip, ShouldBeNil)
|
|
})
|
|
})
|
|
|
|
Reset(func() {
|
|
dashboards.NewProvisioningService = origNewDashboardProvisioningService
|
|
})
|
|
})
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
func mockDashboardProvisioningService() *fakeDashboardProvisioningService {
|
|
mock := fakeDashboardProvisioningService{}
|
|
dashboards.NewProvisioningService = func() dashboards.DashboardProvisioningService {
|
|
return &mock
|
|
}
|
|
return &mock
|
|
}
|
|
|
|
type fakeDashboardProvisioningService struct {
|
|
inserted []*dashboards.SaveDashboardDTO
|
|
provisioned []*models.DashboardProvisioning
|
|
getDashboard []*models.Dashboard
|
|
}
|
|
|
|
func (s *fakeDashboardProvisioningService) GetProvisionedDashboardData(name string) ([]*models.DashboardProvisioning, error) {
|
|
return s.provisioned, nil
|
|
}
|
|
|
|
func (s *fakeDashboardProvisioningService) SaveProvisionedDashboard(dto *dashboards.SaveDashboardDTO, provisioning *models.DashboardProvisioning) (*models.Dashboard, error) {
|
|
s.inserted = append(s.inserted, dto)
|
|
s.provisioned = append(s.provisioned, provisioning)
|
|
return dto.Dashboard, nil
|
|
}
|
|
|
|
func (s *fakeDashboardProvisioningService) SaveFolderForProvisionedDashboards(dto *dashboards.SaveDashboardDTO) (*models.Dashboard, error) {
|
|
s.inserted = append(s.inserted, dto)
|
|
return dto.Dashboard, nil
|
|
}
|
|
|
|
func mockGetDashboardQuery(cmd *models.GetDashboardQuery) error {
|
|
for _, d := range fakeService.getDashboard {
|
|
if d.Slug == cmd.Slug {
|
|
cmd.Result = d
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return models.ErrDashboardNotFound
|
|
}
|