Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
6e3e0dea
Unverified
Commit
6e3e0dea
authored
Sep 11, 2020
by
Maksim Nabokikh
Committed by
GitHub
Sep 11, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Provisioning: Remove provisioned dashboards without parental reader (#26143)
parent
0132bca9
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
133 additions
and
41 deletions
+133
-41
pkg/models/dashboards.go
+4
-0
pkg/services/provisioning/dashboards/dashboard.go
+16
-0
pkg/services/provisioning/dashboards/dashboard_mock.go
+3
-0
pkg/services/provisioning/provisioning.go
+4
-2
pkg/services/sqlstore/dashboard.go
+43
-39
pkg/services/sqlstore/dashboard_provisioning.go
+26
-0
pkg/services/sqlstore/dashboard_provisioning_test.go
+37
-0
No files found.
pkg/models/dashboards.go
View file @
6e3e0dea
...
...
@@ -384,6 +384,10 @@ type ValidateDashboardBeforeSaveCommand struct {
Result
*
ValidateDashboardBeforeSaveResult
}
type
DeleteOrphanedProvisionedDashboardsCommand
struct
{
ReaderNames
[]
string
}
//
// QUERIES
//
...
...
pkg/services/provisioning/dashboards/dashboard.go
View file @
6e3e0dea
...
...
@@ -5,7 +5,9 @@ import (
"fmt"
"os"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/util/errutil"
)
...
...
@@ -16,6 +18,7 @@ type DashboardProvisioner interface {
PollChanges
(
ctx
context
.
Context
)
GetProvisionerResolvedPath
(
name
string
)
string
GetAllowUIUpdatesFromConfig
(
name
string
)
bool
CleanUpOrphanedDashboards
()
}
// DashboardProvisionerFactory creates DashboardProvisioners based on input
...
...
@@ -71,6 +74,19 @@ func (provider *Provisioner) Provision() error {
return
nil
}
// CleanUpOrphanedDashboards deletes provisioned dashboards missing a linked reader.
func
(
provider
*
Provisioner
)
CleanUpOrphanedDashboards
()
{
currentReaders
:=
make
([]
string
,
len
(
provider
.
fileReaders
))
for
index
,
reader
:=
range
provider
.
fileReaders
{
currentReaders
[
index
]
=
reader
.
Cfg
.
Name
}
if
err
:=
bus
.
Dispatch
(
&
models
.
DeleteOrphanedProvisionedDashboardsCommand
{
ReaderNames
:
currentReaders
});
err
!=
nil
{
provider
.
log
.
Warn
(
"Failed to delete orphaned provisioned dashboards"
,
"err"
,
err
)
}
}
// PollChanges starts polling for changes in dashboard definition files. It creates goroutine for each provider
// defined in the config.
func
(
provider
*
Provisioner
)
PollChanges
(
ctx
context
.
Context
)
{
...
...
pkg/services/provisioning/dashboards/dashboard_mock.go
View file @
6e3e0dea
...
...
@@ -60,3 +60,6 @@ func (dpm *ProvisionerMock) GetAllowUIUpdatesFromConfig(name string) bool {
}
return
false
}
// CleanUpOrphanedDashboards not implemented for mocks
func
(
dpm
*
ProvisionerMock
)
CleanUpOrphanedDashboards
()
{}
pkg/services/provisioning/provisioning.go
View file @
6e3e0dea
...
...
@@ -143,9 +143,11 @@ func (ps *provisioningServiceImpl) ProvisionDashboards() error {
defer
ps
.
mutex
.
Unlock
()
ps
.
cancelPolling
()
dashProvisioner
.
CleanUpOrphanedDashboards
()
if
err
:=
dashProvisioner
.
Provision
();
err
!=
nil
{
// If we fail to provision with the new provisioner, mutex will unlock and the polling we restart with the
err
=
dashProvisioner
.
Provision
()
if
err
!=
nil
{
// If we fail to provision with the new provisioner, the mutex will unlock and the polling will restart with the
// old provisioner as we did not switch them yet.
return
errutil
.
Wrap
(
"Failed to provision dashboards"
,
err
)
}
...
...
pkg/services/sqlstore/dashboard.go
View file @
6e3e0dea
...
...
@@ -353,57 +353,61 @@ func GetDashboardTags(query *models.GetDashboardTagsQuery) error {
func
DeleteDashboard
(
cmd
*
models
.
DeleteDashboardCommand
)
error
{
return
inTransaction
(
func
(
sess
*
DBSession
)
error
{
dashboard
:=
models
.
Dashboard
{
Id
:
cmd
.
Id
,
OrgId
:
cmd
.
OrgId
}
has
,
err
:=
sess
.
Get
(
&
dashboard
)
return
deleteDashboard
(
cmd
,
sess
)
})
}
func
deleteDashboard
(
cmd
*
models
.
DeleteDashboardCommand
,
sess
*
DBSession
)
error
{
dashboard
:=
models
.
Dashboard
{
Id
:
cmd
.
Id
,
OrgId
:
cmd
.
OrgId
}
has
,
err
:=
sess
.
Get
(
&
dashboard
)
if
err
!=
nil
{
return
err
}
else
if
!
has
{
return
models
.
ErrDashboardNotFound
}
deletes
:=
[]
string
{
"DELETE FROM dashboard_tag WHERE dashboard_id = ? "
,
"DELETE FROM star WHERE dashboard_id = ? "
,
"DELETE FROM dashboard WHERE id = ?"
,
"DELETE FROM playlist_item WHERE type = 'dashboard_by_id' AND value = ?"
,
"DELETE FROM dashboard_version WHERE dashboard_id = ?"
,
"DELETE FROM annotation WHERE dashboard_id = ?"
,
"DELETE FROM dashboard_provisioning WHERE dashboard_id = ?"
,
}
if
dashboard
.
IsFolder
{
deletes
=
append
(
deletes
,
"DELETE FROM dashboard_provisioning WHERE dashboard_id in (select id from dashboard where folder_id = ?)"
)
deletes
=
append
(
deletes
,
"DELETE FROM dashboard WHERE folder_id = ?"
)
dashIds
:=
[]
struct
{
Id
int64
}{}
err
:=
sess
.
SQL
(
"select id from dashboard where folder_id = ?"
,
dashboard
.
Id
)
.
Find
(
&
dashIds
)
if
err
!=
nil
{
return
err
}
else
if
!
has
{
return
models
.
ErrDashboardNotFound
}
deletes
:=
[]
string
{
"DELETE FROM dashboard_tag WHERE dashboard_id = ? "
,
"DELETE FROM star WHERE dashboard_id = ? "
,
"DELETE FROM dashboard WHERE id = ?"
,
"DELETE FROM playlist_item WHERE type = 'dashboard_by_id' AND value = ?"
,
"DELETE FROM dashboard_version WHERE dashboard_id = ?"
,
"DELETE FROM annotation WHERE dashboard_id = ?"
,
"DELETE FROM dashboard_provisioning WHERE dashboard_id = ?"
,
}
if
dashboard
.
IsFolder
{
deletes
=
append
(
deletes
,
"DELETE FROM dashboard_provisioning WHERE dashboard_id in (select id from dashboard where folder_id = ?)"
)
deletes
=
append
(
deletes
,
"DELETE FROM dashboard WHERE folder_id = ?"
)
dashIds
:=
[]
struct
{
Id
int64
}{}
err
:=
sess
.
SQL
(
"select id from dashboard where folder_id = ?"
,
dashboard
.
Id
)
.
Find
(
&
dashIds
)
if
err
!=
nil
{
for
_
,
id
:=
range
dashIds
{
if
err
:=
deleteAlertDefinition
(
id
.
Id
,
sess
);
err
!=
nil
{
return
err
}
for
_
,
id
:=
range
dashIds
{
if
err
:=
deleteAlertDefinition
(
id
.
Id
,
sess
);
err
!=
nil
{
return
err
}
}
}
}
if
err
:=
deleteAlertDefinition
(
dashboard
.
Id
,
sess
);
err
!=
nil
{
return
err
}
if
err
:=
deleteAlertDefinition
(
dashboard
.
Id
,
sess
);
err
!=
nil
{
return
err
}
for
_
,
sql
:=
range
deletes
{
_
,
err
:=
sess
.
Exec
(
sql
,
dashboard
.
Id
)
for
_
,
sql
:=
range
deletes
{
_
,
err
:=
sess
.
Exec
(
sql
,
dashboard
.
Id
)
if
err
!=
nil
{
return
err
}
if
err
!=
nil
{
return
err
}
}
return
nil
})
return
nil
}
func
GetDashboards
(
query
*
models
.
GetDashboardsQuery
)
error
{
...
...
pkg/services/sqlstore/dashboard_provisioning.go
View file @
6e3e0dea
package
sqlstore
import
(
"errors"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/models"
)
...
...
@@ -10,6 +12,7 @@ func init() {
bus
.
AddHandler
(
"sql"
,
SaveProvisionedDashboard
)
bus
.
AddHandler
(
"sql"
,
GetProvisionedDataByDashboardId
)
bus
.
AddHandler
(
"sql"
,
UnprovisionDashboard
)
bus
.
AddHandler
(
"sql"
,
DeleteOrphanedProvisionedDashboards
)
}
type
DashboardExtras
struct
{
...
...
@@ -88,3 +91,26 @@ func UnprovisionDashboard(cmd *models.UnprovisionDashboardCommand) error {
}
return
nil
}
func
DeleteOrphanedProvisionedDashboards
(
cmd
*
models
.
DeleteOrphanedProvisionedDashboardsCommand
)
error
{
var
result
[]
*
models
.
DashboardProvisioning
convertedReaderNames
:=
make
([]
interface
{},
len
(
cmd
.
ReaderNames
))
for
index
,
readerName
:=
range
cmd
.
ReaderNames
{
convertedReaderNames
[
index
]
=
readerName
}
err
:=
x
.
NotIn
(
"name"
,
convertedReaderNames
...
)
.
Find
(
&
result
)
if
err
!=
nil
{
return
err
}
for
_
,
deleteDashCommand
:=
range
result
{
err
:=
DeleteDashboard
(
&
models
.
DeleteDashboardCommand
{
Id
:
deleteDashCommand
.
DashboardId
})
if
err
!=
nil
&&
!
errors
.
Is
(
err
,
models
.
ErrDashboardNotFound
)
{
return
err
}
}
return
nil
}
pkg/services/sqlstore/dashboard_provisioning_test.go
View file @
6e3e0dea
...
...
@@ -54,6 +54,43 @@ func TestDashboardProvisioningTest(t *testing.T) {
So
(
cmd
.
Result
.
Id
,
ShouldNotEqual
,
0
)
dashId
:=
cmd
.
Result
.
Id
Convey
(
"Deleting orphaned provisioned dashboards"
,
func
()
{
anotherCmd
:=
&
models
.
SaveProvisionedDashboardCommand
{
DashboardCmd
:
&
models
.
SaveDashboardCommand
{
OrgId
:
1
,
IsFolder
:
false
,
FolderId
:
folderCmd
.
Result
.
Id
,
Dashboard
:
simplejson
.
NewFromAny
(
map
[
string
]
interface
{}{
"id"
:
nil
,
"title"
:
"another_dashboard"
,
}),
},
DashboardProvisioning
:
&
models
.
DashboardProvisioning
{
Name
:
"another_reader"
,
ExternalId
:
"/var/grafana.json"
,
Updated
:
now
.
Unix
(),
},
}
err
:=
SaveProvisionedDashboard
(
anotherCmd
)
So
(
err
,
ShouldBeNil
)
query
:=
&
models
.
GetDashboardsQuery
{
DashboardIds
:
[]
int64
{
anotherCmd
.
Result
.
Id
}}
err
=
GetDashboards
(
query
)
So
(
err
,
ShouldBeNil
)
So
(
query
.
Result
,
ShouldNotBeNil
)
deleteCmd
:=
&
models
.
DeleteOrphanedProvisionedDashboardsCommand
{
ReaderNames
:
[]
string
{
"default"
}}
So
(
DeleteOrphanedProvisionedDashboards
(
deleteCmd
),
ShouldBeNil
)
query
=
&
models
.
GetDashboardsQuery
{
DashboardIds
:
[]
int64
{
cmd
.
Result
.
Id
,
anotherCmd
.
Result
.
Id
}}
err
=
GetDashboards
(
query
)
So
(
err
,
ShouldBeNil
)
So
(
len
(
query
.
Result
),
ShouldEqual
,
1
)
So
(
query
.
Result
[
0
]
.
Id
,
ShouldEqual
,
dashId
)
})
Convey
(
"Can query for provisioned dashboards"
,
func
()
{
query
:=
&
models
.
GetProvisionedDashboardDataQuery
{
Name
:
"default"
}
err
:=
GetProvisionedDashboardDataQuery
(
query
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment