mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
provisioning: only update dashboard if hash of json changed
This commit is contained in:
parent
44f5b92fbc
commit
c817aecd66
@ -5,7 +5,7 @@ bulkDashboard() {
|
|||||||
requiresJsonnet
|
requiresJsonnet
|
||||||
|
|
||||||
COUNTER=0
|
COUNTER=0
|
||||||
MAX=400
|
MAX=4
|
||||||
while [ $COUNTER -lt $MAX ]; do
|
while [ $COUNTER -lt $MAX ]; do
|
||||||
jsonnet -o "dashboards/bulk-testing/dashboard${COUNTER}.json" -e "local bulkDash = import 'dashboards/bulk-testing/bulkdash.jsonnet'; bulkDash + { uid: 'uid-${COUNTER}', title: 'title-${COUNTER}' }"
|
jsonnet -o "dashboards/bulk-testing/dashboard${COUNTER}.json" -e "local bulkDash = import 'dashboards/bulk-testing/bulkdash.jsonnet'; bulkDash + { uid: 'uid-${COUNTER}', title: 'title-${COUNTER}' }"
|
||||||
let COUNTER=COUNTER+1
|
let COUNTER=COUNTER+1
|
||||||
|
@ -254,6 +254,7 @@ type DashboardProvisioning struct {
|
|||||||
DashboardId int64
|
DashboardId int64
|
||||||
Name string
|
Name string
|
||||||
ExternalId string
|
ExternalId string
|
||||||
|
CheckSum string
|
||||||
Updated int64
|
Updated int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,14 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||||
|
"github.com/grafana/grafana/pkg/util"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/bus"
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
|
|
||||||
@ -161,13 +163,18 @@ func (fr *fileReader) saveDashboard(path string, folderId int64, fileInfo os.Fil
|
|||||||
provisionedData, alreadyProvisioned := provisionedDashboardRefs[path]
|
provisionedData, alreadyProvisioned := provisionedDashboardRefs[path]
|
||||||
upToDate := alreadyProvisioned && provisionedData.Updated >= resolvedFileInfo.ModTime().Unix()
|
upToDate := alreadyProvisioned && provisionedData.Updated >= resolvedFileInfo.ModTime().Unix()
|
||||||
|
|
||||||
dash, err := fr.readDashboardFromFile(path, resolvedFileInfo.ModTime(), folderId)
|
jsonFile, err := fr.readDashboardFromFile(path, resolvedFileInfo.ModTime(), folderId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fr.log.Error("failed to load dashboard from ", "file", path, "error", err)
|
fr.log.Error("failed to load dashboard from ", "file", path, "error", err)
|
||||||
return provisioningMetadata, nil
|
return provisioningMetadata, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if provisionedData != nil && jsonFile.checkSum == provisionedData.CheckSum {
|
||||||
|
upToDate = true
|
||||||
|
}
|
||||||
|
|
||||||
// keeps track of what uid's and title's we have already provisioned
|
// keeps track of what uid's and title's we have already provisioned
|
||||||
|
dash := jsonFile.dashboard
|
||||||
provisioningMetadata.uid = dash.Dashboard.Uid
|
provisioningMetadata.uid = dash.Dashboard.Uid
|
||||||
provisioningMetadata.title = dash.Dashboard.Title
|
provisioningMetadata.title = dash.Dashboard.Title
|
||||||
|
|
||||||
@ -185,7 +192,13 @@ func (fr *fileReader) saveDashboard(path string, folderId int64, fileInfo os.Fil
|
|||||||
}
|
}
|
||||||
|
|
||||||
fr.log.Debug("saving new dashboard", "file", path)
|
fr.log.Debug("saving new dashboard", "file", path)
|
||||||
dp := &models.DashboardProvisioning{ExternalId: path, Name: fr.Cfg.Name, Updated: resolvedFileInfo.ModTime().Unix()}
|
dp := &models.DashboardProvisioning{
|
||||||
|
ExternalId: path,
|
||||||
|
Name: fr.Cfg.Name,
|
||||||
|
Updated: resolvedFileInfo.ModTime().Unix(),
|
||||||
|
CheckSum: jsonFile.checkSum,
|
||||||
|
}
|
||||||
|
|
||||||
_, err = fr.dashboardService.SaveProvisionedDashboard(dash, dp)
|
_, err = fr.dashboardService.SaveProvisionedDashboard(dash, dp)
|
||||||
return provisioningMetadata, err
|
return provisioningMetadata, err
|
||||||
}
|
}
|
||||||
@ -283,14 +296,30 @@ func validateWalkablePath(fileInfo os.FileInfo) (bool, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *fileReader) readDashboardFromFile(path string, lastModified time.Time, folderId int64) (*dashboards.SaveDashboardDTO, error) {
|
type dashboardJsonFile struct {
|
||||||
|
dashboard *dashboards.SaveDashboardDTO
|
||||||
|
checkSum string
|
||||||
|
lastModified time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *fileReader) readDashboardFromFile(path string, lastModified time.Time, folderId int64) (*dashboardJsonFile, error) {
|
||||||
reader, err := os.Open(path)
|
reader, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer reader.Close()
|
defer reader.Close()
|
||||||
|
|
||||||
data, err := simplejson.NewFromReader(reader)
|
all, err := ioutil.ReadAll(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
checkSum, err := util.Md5SumString(string(all))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := simplejson.NewJson(all)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -300,7 +329,11 @@ func (fr *fileReader) readDashboardFromFile(path string, lastModified time.Time,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return dash, nil
|
return &dashboardJsonFile{
|
||||||
|
dashboard: dash,
|
||||||
|
checkSum: checkSum,
|
||||||
|
lastModified: lastModified,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type provisioningMetadata struct {
|
type provisioningMetadata struct {
|
||||||
@ -328,7 +361,6 @@ func (checker provisioningSanityChecker) track(pm provisioningMetadata) {
|
|||||||
if len(pm.title) > 0 {
|
if len(pm.title) > 0 {
|
||||||
checker.titleUsage[pm.title] += 1
|
checker.titleUsage[pm.title] += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (checker provisioningSanityChecker) logWarnings(log log.Logger) {
|
func (checker provisioningSanityChecker) logWarnings(log log.Logger) {
|
||||||
@ -343,5 +375,4 @@ func (checker provisioningSanityChecker) logWarnings(log log.Logger) {
|
|||||||
log.Error("the same 'title' is used more than once", "title", title, "provider", checker.provisioningProvider)
|
log.Error("the same 'title' is used more than once", "title", title, "provider", checker.provisioningProvider)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -211,4 +211,8 @@ func addDashboardMigration(mg *Migrator) {
|
|||||||
"name": "name",
|
"name": "name",
|
||||||
"external_id": "external_id",
|
"external_id": "external_id",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
mg.AddMigration("Add check_sum column", NewAddColumnMigration(dashboardExtrasTableV2, &Column{
|
||||||
|
Name: "check_sum", Type: DB_NVarchar, Length: 32, Nullable: true,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
26
pkg/util/md5.go
Normal file
26
pkg/util/md5.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Md5Sum calculates the md5sum of a stream
|
||||||
|
func Md5Sum(reader io.Reader) (string, error) {
|
||||||
|
var returnMD5String string
|
||||||
|
hash := md5.New()
|
||||||
|
if _, err := io.Copy(hash, reader); err != nil {
|
||||||
|
return returnMD5String, err
|
||||||
|
}
|
||||||
|
hashInBytes := hash.Sum(nil)[:16]
|
||||||
|
returnMD5String = hex.EncodeToString(hashInBytes)
|
||||||
|
return returnMD5String, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Md5Sum calculates the md5sum of a string
|
||||||
|
func Md5SumString(input string) (string, error) {
|
||||||
|
buffer := strings.NewReader(input)
|
||||||
|
return Md5Sum(buffer)
|
||||||
|
}
|
17
pkg/util/md5_test.go
Normal file
17
pkg/util/md5_test.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestMd5Sum(t *testing.T) {
|
||||||
|
input := "dont hash passwords with md5"
|
||||||
|
|
||||||
|
have, err := Md5SumString(input)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("expected err to be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
want := "2d6a56c82d09d374643b926d3417afba"
|
||||||
|
if have != want {
|
||||||
|
t.Fatalf("expected: %s got: %s", want, have)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user