Commit 243b9877 by Carl Bergquist Committed by GitHub

Merge pull request #10910 from bergquist/provisioning_disable_deleting_dashboards

provisioning: adds setting to disable dashboard deletes
parents 842f4c1d ad42883f
......@@ -184,11 +184,14 @@ providers:
orgId: 1
folder: ''
type: file
disableDeletion: false
editable: false
options:
folder: /var/lib/grafana/dashboards
path: /var/lib/grafana/dashboards
```
When Grafana starts, it will update/insert all dashboards available in the configured folders. If you modify the file, the dashboard will also be updated.
By default Grafana will delete dashboards in the database if the file is removed. You can disable this behavior using the `disableDeletion` setting.
> **Note.** Provisioning allows you to overwrite existing dashboards
> which leads to problems if you re-use settings that are supposed to be unique.
......
......@@ -67,6 +67,8 @@ func validateDashboardAsConfig(cfg []*DashboardsAsConfig) {
So(ds.Editable, ShouldBeTrue)
So(len(ds.Options), ShouldEqual, 1)
So(ds.Options["path"], ShouldEqual, "/var/lib/grafana/dashboards")
So(ds.DisableDeletion, ShouldBeTrue)
ds2 := cfg[1]
So(ds2.Name, ShouldEqual, "default")
So(ds2.Type, ShouldEqual, "file")
......@@ -75,4 +77,5 @@ func validateDashboardAsConfig(cfg []*DashboardsAsConfig) {
So(ds2.Editable, ShouldBeFalse)
So(len(ds2.Options), ShouldEqual, 1)
So(ds2.Options["path"], ShouldEqual, "/var/lib/grafana/dashboards")
So(ds2.DisableDeletion, ShouldBeFalse)
}
......@@ -105,6 +105,27 @@ func (fr *fileReader) startWalkingDisk() error {
return err
}
fr.deleteDashboardIfFileIsMissing(provisionedDashboardRefs, filesFoundOnDisk)
sanityChecker := newProvisioningSanityChecker(fr.Cfg.Name)
// save dashboards based on json files
for path, fileInfo := range filesFoundOnDisk {
provisioningMetadata, err := fr.saveDashboard(path, folderId, fileInfo, provisionedDashboardRefs)
sanityChecker.track(provisioningMetadata)
if err != nil {
fr.log.Error("failed to save dashboard", "error", err)
}
}
sanityChecker.logWarnings(fr.log)
return nil
}
func (fr *fileReader) deleteDashboardIfFileIsMissing(provisionedDashboardRefs map[string]*models.DashboardProvisioning, filesFoundOnDisk map[string]os.FileInfo) {
if fr.Cfg.DisableDeletion {
return
}
// find dashboards to delete since json file is missing
var dashboardToDelete []int64
for path, provisioningData := range provisionedDashboardRefs {
......@@ -113,7 +134,6 @@ func (fr *fileReader) startWalkingDisk() error {
dashboardToDelete = append(dashboardToDelete, provisioningData.DashboardId)
}
}
// delete dashboard that are missing json file
for _, dashboardId := range dashboardToDelete {
fr.log.Debug("deleting provisioned dashboard. missing on disk", "id", dashboardId)
......@@ -123,20 +143,6 @@ func (fr *fileReader) startWalkingDisk() error {
fr.log.Error("failed to delete dashboard", "id", cmd.Id)
}
}
sanityChecker := newProvisioningSanityChecker(fr.Cfg.Name)
// save dashboards based on json files
for path, fileInfo := range filesFoundOnDisk {
provisioningMetadata, err := fr.saveDashboard(path, folderId, fileInfo, provisionedDashboardRefs)
sanityChecker.track(provisioningMetadata)
if err != nil {
fr.log.Error("failed to save dashboard", "error", err)
}
}
sanityChecker.logWarnings(fr.log)
return nil
}
func (fr *fileReader) saveDashboard(path string, folderId int64, fileInfo os.FileInfo, provisionedDashboardRefs map[string]*models.DashboardProvisioning) (provisioningMetadata, error) {
......
......@@ -5,6 +5,7 @@ providers:
orgId: 2
folder: 'developers'
editable: true
disableDeletion: true
type: file
options:
path: /var/lib/grafana/dashboards
......
......@@ -2,6 +2,7 @@
org_id: 2
folder: 'developers'
editable: true
disableDeletion: true
type: file
options:
path: /var/lib/grafana/dashboards
......
......@@ -16,6 +16,7 @@ type DashboardsAsConfig struct {
Folder string
Editable bool
Options map[string]interface{}
DisableDeletion bool
}
type DashboardsAsConfigV0 struct {
......@@ -25,6 +26,7 @@ type DashboardsAsConfigV0 struct {
Folder string `json:"folder" yaml:"folder"`
Editable bool `json:"editable" yaml:"editable"`
Options map[string]interface{} `json:"options" yaml:"options"`
DisableDeletion bool `json:"disableDeletion" yaml:"disableDeletion"`
}
type ConfigVersion struct {
......@@ -42,6 +44,7 @@ type DashboardProviderConfigs struct {
Folder string `json:"folder" yaml:"folder"`
Editable bool `json:"editable" yaml:"editable"`
Options map[string]interface{} `json:"options" yaml:"options"`
DisableDeletion bool `json:"disableDeletion" yaml:"disableDeletion"`
}
func createDashboardJson(data *simplejson.Json, lastModified time.Time, cfg *DashboardsAsConfig, folderId int64) (*dashboards.SaveDashboardDTO, error) {
......@@ -74,6 +77,7 @@ func mapV0ToDashboardAsConfig(v0 []*DashboardsAsConfigV0) []*DashboardsAsConfig
Folder: v.Folder,
Editable: v.Editable,
Options: v.Options,
DisableDeletion: v.DisableDeletion,
})
}
......@@ -91,6 +95,7 @@ func (dc *DashboardAsConfigV1) mapToDashboardAsConfig() []*DashboardsAsConfig {
Folder: v.Folder,
Editable: v.Editable,
Options: v.Options,
DisableDeletion: v.DisableDeletion,
})
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment