diff --git a/pkg/services/provisioning/dashboards/file_reader.go b/pkg/services/provisioning/dashboards/file_reader.go index 3005de9a390..dbbb44f15b8 100644 --- a/pkg/services/provisioning/dashboards/file_reader.go +++ b/pkg/services/provisioning/dashboards/file_reader.go @@ -30,7 +30,7 @@ type fileReader struct { log log.Logger dashboardRepo dashboards.Repository cache *dashboardCache - createWalk func(fr *fileReader, folderId int64) filepath.WalkFunc + createWalk func(fr *fileReader, folderId int64, provisionedDashboards map[string]*models.DashboardProvisioning) filepath.WalkFunc } func NewDashboardFileReader(cfg *DashboardsAsConfig, log log.Logger) (*fileReader, error) { @@ -98,7 +98,26 @@ func (fr *fileReader) startWalkingDisk() error { return err } - return filepath.Walk(fr.Path, fr.createWalk(fr, folderId)) + byPath, err := getProvisionedDashboardByPath(fr.dashboardRepo, fr.Cfg.Name) + if err != nil { + return err + } + + return filepath.Walk(fr.Path, fr.createWalk(fr, folderId, byPath)) +} + +func getProvisionedDashboardByPath(repo dashboards.Repository, name string) (map[string]*models.DashboardProvisioning, error) { + arr, err := repo.GetProvisionedDashboardData(name) + if err != nil { + return nil, err + } + + byPath := map[string]*models.DashboardProvisioning{} + for _, pd := range arr { + byPath[pd.ExternalId] = pd + } + + return byPath, nil } func getOrCreateFolderId(cfg *DashboardsAsConfig, repo dashboards.Repository) (int64, error) { @@ -150,7 +169,7 @@ func resolveSymlink(fileinfo os.FileInfo, path string) (os.FileInfo, error) { return fileinfo, err } -func createWalkFn(fr *fileReader, folderId int64) filepath.WalkFunc { +func createWalkFn(fr *fileReader, folderId int64, provisionedDashboards map[string]*models.DashboardProvisioning) filepath.WalkFunc { return func(path string, fileInfo os.FileInfo, err error) error { if err != nil { return err @@ -177,18 +196,31 @@ func createWalkFn(fr *fileReader, folderId int64) filepath.WalkFunc { return nil } - if dash.Dashboard.Id != 0 { - fr.log.Error("Cannot provision dashboard. Please remove the id property from the json file") - return nil + var dbDashboard *models.Dashboard + cmd := &models.GetDashboardQuery{} + provisionedData, allReadyProvisioned := provisionedDashboards[path] + + // see if the + if allReadyProvisioned { + dash.Dashboard.Id = provisionedData.DashboardId + dash.Dashboard.Data.Set("id", provisionedData.DashboardId) + cmd.Id = provisionedData.DashboardId + } else { + if dash.Dashboard.Id != 0 { + fr.log.Error("Cannot provision dashboard. Please remove the id property from the json file") + return nil + } + + cmd.Slug = dash.Dashboard.Slug } - cmd := &models.GetDashboardQuery{Slug: dash.Dashboard.Slug} err = bus.Dispatch(cmd) + dbDashboard = cmd.Result // if we don't have the dashboard in the db, save it! if err == models.ErrDashboardNotFound { fr.log.Debug("saving new dashboard", "file", path) - err = saveDashboard(fr, path, dash, fileInfo.ModTime()) + err = saveDashboard(fr, path, dash) return err } @@ -198,24 +230,30 @@ func createWalkFn(fr *fileReader, folderId int64) filepath.WalkFunc { } // break if db version is newer then fil version - if cmd.Result.Updated.Unix() >= resolvedFileInfo.ModTime().Unix() { + if dbDashboard.Updated.Unix() >= resolvedFileInfo.ModTime().Unix() { return nil } fr.log.Debug("loading dashboard from disk into database.", "file", path) - err = saveDashboard(fr, path, dash, fileInfo.ModTime()) + err = saveDashboard(fr, path, dash) return err } } -func saveDashboard(fr *fileReader, path string, dash *dashboards.SaveDashboardDTO, modTime time.Time) error { + +func saveDashboard(fr *fileReader, path string, dash *dashboards.SaveDashboardDTO) error { d := &models.DashboardProvisioning{ ExternalId: path, Name: fr.Cfg.Name, } - _, err := fr.dashboardRepo.SaveProvisionedDashboard(dash, d) - return err + _, err := fr.dashboardRepo.SaveProvisionedDashboard(dash, d) + if err != nil { + return err + } + + fr.cache.addDashboardCache(path, dash) + return nil } func validateWalkablePath(fileInfo os.FileInfo) (bool, error) { diff --git a/pkg/services/provisioning/dashboards/file_reader_test.go b/pkg/services/provisioning/dashboards/file_reader_test.go index 5c90e573f80..390190e29af 100644 --- a/pkg/services/provisioning/dashboards/file_reader_test.go +++ b/pkg/services/provisioning/dashboards/file_reader_test.go @@ -174,13 +174,15 @@ func TestDashboardFileReader(t *testing.T) { reader, err := NewDashboardFileReader(cfg, log.New("test-logger")) So(err, ShouldBeNil) + emptyProvisioned := map[string]*models.DashboardProvisioning{} + Convey("should skip dirs that starts with .", func() { - shouldSkip := reader.createWalk(reader, 0)("path", &FakeFileInfo{isDirectory: true, name: ".folder"}, nil) + shouldSkip := reader.createWalk(reader, 0, emptyProvisioned)("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) + shouldSkip := reader.createWalk(reader, 0, emptyProvisioned)("path", &FakeFileInfo{isDirectory: true, name: "folder"}, nil) So(shouldSkip, ShouldBeNil) }) }) diff --git a/pkg/services/sqlstore/dashboard.go b/pkg/services/sqlstore/dashboard.go index 4c72e3423be..2b94f0e089c 100644 --- a/pkg/services/sqlstore/dashboard.go +++ b/pkg/services/sqlstore/dashboard.go @@ -31,7 +31,6 @@ func saveDashboard(sess *DBSession, cmd *m.SaveDashboardCommand) error { // try get existing dashboard var existing, sameTitle m.Dashboard - if dash.Id > 0 { dashWithIdExists, err := sess.Where("id=? AND org_id=?", dash.Id, dash.OrgId).Get(&existing) if err != nil {