mirror of
https://github.com/grafana/grafana.git
synced 2025-01-27 00:37:04 -06:00
avoid infinite loop in the dashboard provisioner
if one dashboard with an uid is refered to by two provsioners each provsioner overwrite each other. filling up dashboard_versions quite fast if using default settings. ref #12864
This commit is contained in:
parent
dc9b83030f
commit
8880829eda
@ -4,6 +4,6 @@ providers:
|
||||
- name: 'gdev dashboards'
|
||||
folder: 'gdev dashboards'
|
||||
type: file
|
||||
updateIntervalSeconds: 15
|
||||
options:
|
||||
path: devenv/dev-dashboards
|
||||
|
||||
|
1674
devenv/dev-dashboards-without-uid/panel_tests_graph.json
Normal file
1674
devenv/dev-dashboards-without-uid/panel_tests_graph.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,510 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "gdev-testdata",
|
||||
"fill": 2,
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk",
|
||||
"target": ""
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [
|
||||
{
|
||||
"colorMode": "gray",
|
||||
"fill": true,
|
||||
"fillColor": "rgba(255, 255, 255, 0.03)",
|
||||
"from": "08:30",
|
||||
"fromDayOfWeek": 1,
|
||||
"line": false,
|
||||
"lineColor": "rgba(255, 255, 255, 0.2)",
|
||||
"op": "time",
|
||||
"to": "16:45",
|
||||
"toDayOfWeek": 5
|
||||
}
|
||||
],
|
||||
"timeShift": null,
|
||||
"title": "Business Hours",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "gdev-testdata",
|
||||
"fill": 2,
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 8
|
||||
},
|
||||
"id": 4,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk",
|
||||
"target": ""
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [
|
||||
{
|
||||
"colorMode": "red",
|
||||
"fill": true,
|
||||
"fillColor": "rgba(255, 255, 255, 0.03)",
|
||||
"from": "20:00",
|
||||
"fromDayOfWeek": 7,
|
||||
"line": false,
|
||||
"lineColor": "rgba(255, 255, 255, 0.2)",
|
||||
"op": "time",
|
||||
"to": "23:00",
|
||||
"toDayOfWeek": 7
|
||||
}
|
||||
],
|
||||
"timeShift": null,
|
||||
"title": "Sunday's 20-23",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {
|
||||
"A-series": "#d683ce"
|
||||
},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "gdev-testdata",
|
||||
"fill": 2,
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 16
|
||||
},
|
||||
"id": 3,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 0.5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk",
|
||||
"target": ""
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [
|
||||
{
|
||||
"colorMode": "custom",
|
||||
"fill": true,
|
||||
"fillColor": "rgba(255, 0, 0, 0.22)",
|
||||
"from": "",
|
||||
"fromDayOfWeek": 1,
|
||||
"line": true,
|
||||
"lineColor": "rgba(255, 0, 0, 0.32)",
|
||||
"op": "time",
|
||||
"to": "",
|
||||
"toDayOfWeek": 1
|
||||
},
|
||||
{
|
||||
"colorMode": "custom",
|
||||
"fill": true,
|
||||
"fillColor": "rgba(255, 127, 0, 0.22)",
|
||||
"fromDayOfWeek": 2,
|
||||
"line": true,
|
||||
"lineColor": "rgba(255, 127, 0, 0.32)",
|
||||
"op": "time",
|
||||
"toDayOfWeek": 2
|
||||
},
|
||||
{
|
||||
"colorMode": "custom",
|
||||
"fill": true,
|
||||
"fillColor": "rgba(255, 255, 0, 0.22)",
|
||||
"fromDayOfWeek": 3,
|
||||
"line": true,
|
||||
"lineColor": "rgba(255, 255, 0, 0.22)",
|
||||
"op": "time",
|
||||
"toDayOfWeek": 3
|
||||
},
|
||||
{
|
||||
"colorMode": "custom",
|
||||
"fill": true,
|
||||
"fillColor": "rgba(0, 255, 0, 0.22)",
|
||||
"fromDayOfWeek": 4,
|
||||
"line": true,
|
||||
"lineColor": "rgba(0, 255, 0, 0.32)",
|
||||
"op": "time",
|
||||
"toDayOfWeek": 4
|
||||
},
|
||||
{
|
||||
"colorMode": "custom",
|
||||
"fill": true,
|
||||
"fillColor": "rgba(0, 0, 255, 0.22)",
|
||||
"fromDayOfWeek": 5,
|
||||
"line": true,
|
||||
"lineColor": "rgba(0, 0, 255, 0.32)",
|
||||
"op": "time",
|
||||
"toDayOfWeek": 5
|
||||
},
|
||||
{
|
||||
"colorMode": "custom",
|
||||
"fill": true,
|
||||
"fillColor": "rgba(75, 0, 130, 0.22)",
|
||||
"fromDayOfWeek": 6,
|
||||
"line": true,
|
||||
"lineColor": "rgba(75, 0, 130, 0.32)",
|
||||
"op": "time",
|
||||
"toDayOfWeek": 6
|
||||
},
|
||||
{
|
||||
"colorMode": "custom",
|
||||
"fill": true,
|
||||
"fillColor": "rgba(148, 0, 211, 0.22)",
|
||||
"fromDayOfWeek": 7,
|
||||
"line": true,
|
||||
"lineColor": "rgba(148, 0, 211, 0.32)",
|
||||
"op": "time",
|
||||
"toDayOfWeek": 7
|
||||
}
|
||||
],
|
||||
"timeShift": null,
|
||||
"title": "Each day of week",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "gdev-testdata",
|
||||
"fill": 2,
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 24
|
||||
},
|
||||
"id": 5,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 2,
|
||||
"links": [],
|
||||
"nullPointMode": "null",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 1,
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk",
|
||||
"target": ""
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [
|
||||
{
|
||||
"colorMode": "red",
|
||||
"fill": false,
|
||||
"from": "05:00",
|
||||
"line": true,
|
||||
"op": "time"
|
||||
}
|
||||
],
|
||||
"timeShift": null,
|
||||
"title": "05:00",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"refresh": false,
|
||||
"schemaVersion": 16,
|
||||
"style": "dark",
|
||||
"tags": [
|
||||
"gdev",
|
||||
"panel-tests"
|
||||
],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-30d",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"refresh_intervals": [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
],
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "browser",
|
||||
"title": "Panel Tests - Graph (Time Regions)",
|
||||
"version": 1
|
||||
}
|
3342
devenv/dev-dashboards-without-uid/panel_tests_polystat.json
Normal file
3342
devenv/dev-dashboards-without-uid/panel_tests_polystat.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
||||
package dashboards
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -69,7 +70,7 @@ func (cr *configReader) readConfig() ([]*DashboardsAsConfig, error) {
|
||||
|
||||
parsedDashboards, err := cr.parseConfigs(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("could not parse provisioning config file: %s error: %v", file.Name(), err)
|
||||
}
|
||||
|
||||
if len(parsedDashboards) > 0 {
|
||||
|
@ -118,6 +118,7 @@ func (fr *fileReader) startWalkingDisk() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fr *fileReader) deleteDashboardIfFileIsMissing(provisionedDashboardRefs map[string]*models.DashboardProvisioning, filesFoundOnDisk map[string]os.FileInfo) {
|
||||
if fr.Cfg.DisableDeletion {
|
||||
return
|
||||
@ -180,7 +181,7 @@ func (fr *fileReader) saveDashboard(path string, folderId int64, fileInfo os.Fil
|
||||
dash.Dashboard.SetId(provisionedData.DashboardId)
|
||||
}
|
||||
|
||||
fr.log.Debug("saving new dashboard", "file", path)
|
||||
fr.log.Debug("saving new dashboard", "provisoner", fr.Cfg.Name, "file", path, "folderId", dash.Dashboard.FolderId)
|
||||
dp := &models.DashboardProvisioning{
|
||||
ExternalId: path,
|
||||
Name: fr.Cfg.Name,
|
||||
|
@ -166,6 +166,36 @@ func TestDashboardFileReader(t *testing.T) {
|
||||
_, err := NewDashboardFileReader(cfg, logger)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("Two dashboard providers should be able to provisioned the same dashboard without uid", func() {
|
||||
cfg1 := &DashboardsAsConfig{Name: "1", Type: "file", OrgId: 1, Folder: "f1", Options: map[string]interface{}{"path": containingId}}
|
||||
cfg2 := &DashboardsAsConfig{Name: "2", Type: "file", OrgId: 1, Folder: "f2", Options: map[string]interface{}{"path": containingId}}
|
||||
|
||||
reader1, err := NewDashboardFileReader(cfg1, logger)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader1.startWalkingDisk()
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
reader2, err := NewDashboardFileReader(cfg2, logger)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = reader2.startWalkingDisk()
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
var folderCount int
|
||||
var dashCount int
|
||||
for _, o := range fakeService.inserted {
|
||||
if o.Dashboard.IsFolder {
|
||||
folderCount++
|
||||
} else {
|
||||
dashCount++
|
||||
}
|
||||
}
|
||||
|
||||
So(folderCount, ShouldEqual, 2)
|
||||
So(dashCount, ShouldEqual, 2)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Should not create new folder if folder name is missing", func() {
|
||||
@ -256,7 +286,9 @@ func (ffi FakeFileInfo) Sys() interface{} {
|
||||
}
|
||||
|
||||
func mockDashboardProvisioningService() *fakeDashboardProvisioningService {
|
||||
mock := fakeDashboardProvisioningService{}
|
||||
mock := fakeDashboardProvisioningService{
|
||||
provisioned: map[string][]*models.DashboardProvisioning{},
|
||||
}
|
||||
dashboards.NewProvisioningService = func() dashboards.DashboardProvisioningService {
|
||||
return &mock
|
||||
}
|
||||
@ -265,17 +297,26 @@ func mockDashboardProvisioningService() *fakeDashboardProvisioningService {
|
||||
|
||||
type fakeDashboardProvisioningService struct {
|
||||
inserted []*dashboards.SaveDashboardDTO
|
||||
provisioned []*models.DashboardProvisioning
|
||||
provisioned map[string][]*models.DashboardProvisioning
|
||||
getDashboard []*models.Dashboard
|
||||
}
|
||||
|
||||
func (s *fakeDashboardProvisioningService) GetProvisionedDashboardData(name string) ([]*models.DashboardProvisioning, error) {
|
||||
return s.provisioned, nil
|
||||
if _, ok := s.provisioned[name]; !ok {
|
||||
s.provisioned[name] = []*models.DashboardProvisioning{}
|
||||
}
|
||||
|
||||
return s.provisioned[name], 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)
|
||||
|
||||
if _, ok := s.provisioned[provisioning.Name]; !ok {
|
||||
s.provisioned[provisioning.Name] = []*models.DashboardProvisioning{}
|
||||
}
|
||||
|
||||
s.provisioned[provisioning.Name] = append(s.provisioned[provisioning.Name], provisioning)
|
||||
return dto.Dashboard, nil
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ func SaveProvisionedDashboard(cmd *models.SaveProvisionedDashboardCommand) error
|
||||
func saveProvionedData(sess *DBSession, cmd *models.DashboardProvisioning, dashboard *models.Dashboard) error {
|
||||
result := &models.DashboardProvisioning{}
|
||||
|
||||
exist, err := sess.Where("dashboard_id=?", dashboard.Id).Get(result)
|
||||
exist, err := sess.Where("dashboard_id=? AND name = ?", dashboard.Id, cmd.Name).Get(result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user