mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
ObjectStore: add a kind registry (#56507)
This commit is contained in:
450
pkg/services/store/kind/dashboard/dashboard.go
Normal file
450
pkg/services/store/kind/dashboard/dashboard.go
Normal file
@@ -0,0 +1,450 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
)
|
||||
|
||||
func logf(format string, a ...interface{}) {
|
||||
//fmt.Printf(format, a...)
|
||||
}
|
||||
|
||||
type templateVariable struct {
|
||||
current struct {
|
||||
value interface{}
|
||||
}
|
||||
name string
|
||||
query interface{}
|
||||
variableType string
|
||||
}
|
||||
|
||||
type datasourceVariableLookup struct {
|
||||
variableNameToRefs map[string][]DataSourceRef
|
||||
dsLookup DatasourceLookup
|
||||
}
|
||||
|
||||
func (d *datasourceVariableLookup) getDsRefsByTemplateVariableValue(value string, datasourceType string) []DataSourceRef {
|
||||
switch value {
|
||||
case "default":
|
||||
// can be the default DS, or a DS with UID="default"
|
||||
candidateDs := d.dsLookup.ByRef(&DataSourceRef{UID: value})
|
||||
if candidateDs == nil {
|
||||
// get the actual default DS
|
||||
candidateDs = d.dsLookup.ByRef(nil)
|
||||
}
|
||||
|
||||
if candidateDs != nil {
|
||||
return []DataSourceRef{*candidateDs}
|
||||
}
|
||||
return []DataSourceRef{}
|
||||
case "$__all":
|
||||
// TODO: filter datasources by template variable's regex
|
||||
return d.dsLookup.ByType(datasourceType)
|
||||
case "":
|
||||
return []DataSourceRef{}
|
||||
case "No data sources found":
|
||||
return []DataSourceRef{}
|
||||
default:
|
||||
// some variables use `ds.name` rather `ds.uid`
|
||||
if ref := d.dsLookup.ByRef(&DataSourceRef{
|
||||
UID: value,
|
||||
}); ref != nil {
|
||||
return []DataSourceRef{*ref}
|
||||
}
|
||||
|
||||
// discard variable
|
||||
return []DataSourceRef{}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *datasourceVariableLookup) add(templateVariable templateVariable) {
|
||||
var refs []DataSourceRef
|
||||
|
||||
datasourceType, isDataSourceTypeValid := templateVariable.query.(string)
|
||||
if !isDataSourceTypeValid {
|
||||
d.variableNameToRefs[templateVariable.name] = refs
|
||||
return
|
||||
}
|
||||
|
||||
if values, multiValueVariable := templateVariable.current.value.([]interface{}); multiValueVariable {
|
||||
for _, value := range values {
|
||||
if valueAsString, ok := value.(string); ok {
|
||||
refs = append(refs, d.getDsRefsByTemplateVariableValue(valueAsString, datasourceType)...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if value, stringValue := templateVariable.current.value.(string); stringValue {
|
||||
refs = append(refs, d.getDsRefsByTemplateVariableValue(value, datasourceType)...)
|
||||
}
|
||||
|
||||
d.variableNameToRefs[templateVariable.name] = unique(refs)
|
||||
}
|
||||
|
||||
func unique(refs []DataSourceRef) []DataSourceRef {
|
||||
var uniqueRefs []DataSourceRef
|
||||
uidPresence := make(map[string]bool)
|
||||
for _, ref := range refs {
|
||||
if !uidPresence[ref.UID] {
|
||||
uidPresence[ref.UID] = true
|
||||
uniqueRefs = append(uniqueRefs, ref)
|
||||
}
|
||||
}
|
||||
return uniqueRefs
|
||||
}
|
||||
|
||||
func (d *datasourceVariableLookup) getDatasourceRefs(name string) []DataSourceRef {
|
||||
refs, ok := d.variableNameToRefs[name]
|
||||
if ok {
|
||||
return refs
|
||||
}
|
||||
|
||||
return []DataSourceRef{}
|
||||
}
|
||||
|
||||
func newDatasourceVariableLookup(dsLookup DatasourceLookup) *datasourceVariableLookup {
|
||||
return &datasourceVariableLookup{
|
||||
variableNameToRefs: make(map[string][]DataSourceRef),
|
||||
dsLookup: dsLookup,
|
||||
}
|
||||
}
|
||||
|
||||
// nolint:gocyclo
|
||||
// ReadDashboard will take a byte stream and return dashboard info
|
||||
func readDashboard(stream io.Reader, lookup DatasourceLookup) (*dashboardInfo, error) {
|
||||
dash := &dashboardInfo{}
|
||||
|
||||
iter := jsoniter.Parse(jsoniter.ConfigDefault, stream, 1024)
|
||||
|
||||
datasourceVariablesLookup := newDatasourceVariableLookup(lookup)
|
||||
|
||||
for l1Field := iter.ReadObject(); l1Field != ""; l1Field = iter.ReadObject() {
|
||||
// Skip null values so we don't need special int handling
|
||||
if iter.WhatIsNext() == jsoniter.NilValue {
|
||||
iter.Skip()
|
||||
continue
|
||||
}
|
||||
|
||||
switch l1Field {
|
||||
case "id":
|
||||
dash.ID = iter.ReadInt64()
|
||||
|
||||
case "uid":
|
||||
iter.ReadString()
|
||||
|
||||
case "title":
|
||||
dash.Title = iter.ReadString()
|
||||
|
||||
case "description":
|
||||
dash.Description = iter.ReadString()
|
||||
|
||||
case "schemaVersion":
|
||||
switch iter.WhatIsNext() {
|
||||
case jsoniter.NumberValue:
|
||||
dash.SchemaVersion = iter.ReadInt64()
|
||||
case jsoniter.StringValue:
|
||||
val := iter.ReadString()
|
||||
if v, err := strconv.ParseInt(val, 10, 64); err == nil {
|
||||
dash.SchemaVersion = v
|
||||
}
|
||||
default:
|
||||
iter.Skip()
|
||||
}
|
||||
case "timezone":
|
||||
dash.TimeZone = iter.ReadString()
|
||||
|
||||
case "editable":
|
||||
dash.ReadOnly = !iter.ReadBool()
|
||||
|
||||
case "refresh":
|
||||
nxt := iter.WhatIsNext()
|
||||
if nxt == jsoniter.StringValue {
|
||||
dash.Refresh = iter.ReadString()
|
||||
} else {
|
||||
iter.Skip()
|
||||
}
|
||||
|
||||
case "tags":
|
||||
for iter.ReadArray() {
|
||||
dash.Tags = append(dash.Tags, iter.ReadString())
|
||||
}
|
||||
|
||||
case "links":
|
||||
for iter.ReadArray() {
|
||||
iter.Skip()
|
||||
dash.LinkCount++
|
||||
}
|
||||
|
||||
case "time":
|
||||
obj, ok := iter.Read().(map[string]interface{})
|
||||
if ok {
|
||||
if timeFrom, ok := obj["from"].(string); ok {
|
||||
dash.TimeFrom = timeFrom
|
||||
}
|
||||
if timeTo, ok := obj["to"].(string); ok {
|
||||
dash.TimeTo = timeTo
|
||||
}
|
||||
}
|
||||
case "panels":
|
||||
for iter.ReadArray() {
|
||||
dash.Panels = append(dash.Panels, readpanelInfo(iter, lookup))
|
||||
}
|
||||
|
||||
case "rows":
|
||||
for iter.ReadArray() {
|
||||
v := iter.Read()
|
||||
logf("[DASHBOARD.ROW???] id=%s // %v\n", dash.ID, v)
|
||||
}
|
||||
|
||||
case "annotations":
|
||||
for sub := iter.ReadObject(); sub != ""; sub = iter.ReadObject() {
|
||||
if sub == "list" {
|
||||
for iter.ReadArray() {
|
||||
v := iter.Read()
|
||||
logf("[dash.anno] %v\n", v)
|
||||
}
|
||||
} else {
|
||||
iter.Skip()
|
||||
}
|
||||
}
|
||||
|
||||
case "templating":
|
||||
for sub := iter.ReadObject(); sub != ""; sub = iter.ReadObject() {
|
||||
if sub == "list" {
|
||||
for iter.ReadArray() {
|
||||
templateVariable := templateVariable{}
|
||||
|
||||
for k := iter.ReadObject(); k != ""; k = iter.ReadObject() {
|
||||
switch k {
|
||||
case "name":
|
||||
name := iter.ReadString()
|
||||
dash.TemplateVars = append(dash.TemplateVars, name)
|
||||
templateVariable.name = name
|
||||
case "type":
|
||||
templateVariable.variableType = iter.ReadString()
|
||||
case "query":
|
||||
templateVariable.query = iter.Read()
|
||||
case "current":
|
||||
for c := iter.ReadObject(); c != ""; c = iter.ReadObject() {
|
||||
if c == "value" {
|
||||
templateVariable.current.value = iter.Read()
|
||||
} else {
|
||||
iter.Skip()
|
||||
}
|
||||
}
|
||||
default:
|
||||
iter.Skip()
|
||||
}
|
||||
}
|
||||
|
||||
if templateVariable.variableType == "datasource" {
|
||||
datasourceVariablesLookup.add(templateVariable)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
iter.Skip()
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore these properties
|
||||
case "timepicker":
|
||||
fallthrough
|
||||
case "version":
|
||||
fallthrough
|
||||
case "iteration":
|
||||
iter.Skip()
|
||||
|
||||
default:
|
||||
v := iter.Read()
|
||||
logf("[DASHBOARD] support key: %s / %v\n", l1Field, v)
|
||||
}
|
||||
}
|
||||
|
||||
replaceDatasourceVariables(dash, datasourceVariablesLookup)
|
||||
fillDefaultDatasources(dash, lookup)
|
||||
filterOutSpecialDatasources(dash)
|
||||
|
||||
targets := newTargetInfo(lookup)
|
||||
for _, panel := range dash.Panels {
|
||||
targets.addPanel(panel)
|
||||
}
|
||||
dash.Datasource = targets.GetDatasourceInfo()
|
||||
|
||||
return dash, iter.Error
|
||||
}
|
||||
|
||||
func panelRequiresDatasource(panel panelInfo) bool {
|
||||
return panel.Type != "row"
|
||||
}
|
||||
|
||||
func fillDefaultDatasources(dash *dashboardInfo, lookup DatasourceLookup) {
|
||||
for i, panel := range dash.Panels {
|
||||
if len(panel.Datasource) != 0 || !panelRequiresDatasource(panel) {
|
||||
continue
|
||||
}
|
||||
|
||||
defaultDs := lookup.ByRef(nil)
|
||||
if defaultDs != nil {
|
||||
dash.Panels[i].Datasource = []DataSourceRef{*defaultDs}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func filterOutSpecialDatasources(dash *dashboardInfo) {
|
||||
for i, panel := range dash.Panels {
|
||||
var dsRefs []DataSourceRef
|
||||
|
||||
// partition into actual datasource references and variables
|
||||
for _, ds := range panel.Datasource {
|
||||
switch ds.UID {
|
||||
case "-- Mixed --":
|
||||
// The actual datasources used as targets will remain
|
||||
continue
|
||||
case "-- Dashboard --":
|
||||
// The `Dashboard` datasource refers to the results of the query used in another panel
|
||||
continue
|
||||
default:
|
||||
dsRefs = append(dsRefs, ds)
|
||||
}
|
||||
}
|
||||
|
||||
dash.Panels[i].Datasource = dsRefs
|
||||
}
|
||||
}
|
||||
|
||||
func replaceDatasourceVariables(dash *dashboardInfo, datasourceVariablesLookup *datasourceVariableLookup) {
|
||||
for i, panel := range dash.Panels {
|
||||
var dsVariableRefs []DataSourceRef
|
||||
var dsRefs []DataSourceRef
|
||||
|
||||
// partition into actual datasource references and variables
|
||||
for i := range panel.Datasource {
|
||||
uid := panel.Datasource[i].UID
|
||||
if isVariableRef(uid) {
|
||||
dsVariableRefs = append(dsVariableRefs, panel.Datasource[i])
|
||||
} else {
|
||||
dsRefs = append(dsRefs, panel.Datasource[i])
|
||||
}
|
||||
}
|
||||
|
||||
variables := findDatasourceRefsForVariables(dsVariableRefs, datasourceVariablesLookup)
|
||||
dash.Panels[i].Datasource = append(dsRefs, variables...)
|
||||
}
|
||||
}
|
||||
|
||||
func isSpecialDatasource(uid string) bool {
|
||||
return uid == "-- Mixed --" || uid == "-- Dashboard --"
|
||||
}
|
||||
|
||||
func isVariableRef(uid string) bool {
|
||||
return strings.HasPrefix(uid, "$")
|
||||
}
|
||||
|
||||
func getDataSourceVariableName(dsVariableRef DataSourceRef) string {
|
||||
if strings.HasPrefix(dsVariableRef.UID, "${") {
|
||||
return strings.TrimPrefix(strings.TrimSuffix(dsVariableRef.UID, "}"), "${")
|
||||
}
|
||||
|
||||
return strings.TrimPrefix(dsVariableRef.UID, "$")
|
||||
}
|
||||
|
||||
func findDatasourceRefsForVariables(dsVariableRefs []DataSourceRef, datasourceVariablesLookup *datasourceVariableLookup) []DataSourceRef {
|
||||
var referencedDs []DataSourceRef
|
||||
for _, dsVariableRef := range dsVariableRefs {
|
||||
variableName := getDataSourceVariableName(dsVariableRef)
|
||||
refs := datasourceVariablesLookup.getDatasourceRefs(variableName)
|
||||
referencedDs = append(referencedDs, refs...)
|
||||
}
|
||||
return referencedDs
|
||||
}
|
||||
|
||||
// will always return strings for now
|
||||
func readpanelInfo(iter *jsoniter.Iterator, lookup DatasourceLookup) panelInfo {
|
||||
panel := panelInfo{}
|
||||
|
||||
targets := newTargetInfo(lookup)
|
||||
|
||||
for l1Field := iter.ReadObject(); l1Field != ""; l1Field = iter.ReadObject() {
|
||||
if iter.WhatIsNext() == jsoniter.NilValue {
|
||||
if l1Field == "datasource" {
|
||||
targets.addDatasource(iter)
|
||||
continue
|
||||
}
|
||||
|
||||
// Skip null values so we don't need special int handling
|
||||
iter.Skip()
|
||||
continue
|
||||
}
|
||||
|
||||
switch l1Field {
|
||||
case "id":
|
||||
panel.ID = iter.ReadInt64()
|
||||
|
||||
case "type":
|
||||
panel.Type = iter.ReadString()
|
||||
|
||||
case "title":
|
||||
panel.Title = iter.ReadString()
|
||||
|
||||
case "description":
|
||||
panel.Description = iter.ReadString()
|
||||
|
||||
case "pluginVersion":
|
||||
panel.PluginVersion = iter.ReadString() // since 7x (the saved version for the plugin model)
|
||||
|
||||
case "datasource":
|
||||
targets.addDatasource(iter)
|
||||
|
||||
case "targets":
|
||||
switch iter.WhatIsNext() {
|
||||
case jsoniter.ArrayValue:
|
||||
for iter.ReadArray() {
|
||||
targets.addTarget(iter)
|
||||
}
|
||||
case jsoniter.ObjectValue:
|
||||
for f := iter.ReadObject(); f != ""; f = iter.ReadObject() {
|
||||
targets.addTarget(iter)
|
||||
}
|
||||
default:
|
||||
iter.Skip()
|
||||
}
|
||||
|
||||
case "transformations":
|
||||
for iter.ReadArray() {
|
||||
for sub := iter.ReadObject(); sub != ""; sub = iter.ReadObject() {
|
||||
if sub == "id" {
|
||||
panel.Transformer = append(panel.Transformer, iter.ReadString())
|
||||
} else {
|
||||
iter.Skip()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rows have nested panels
|
||||
case "panels":
|
||||
for iter.ReadArray() {
|
||||
panel.Collapsed = append(panel.Collapsed, readpanelInfo(iter, lookup))
|
||||
}
|
||||
|
||||
case "options":
|
||||
fallthrough
|
||||
|
||||
case "gridPos":
|
||||
fallthrough
|
||||
|
||||
case "fieldConfig":
|
||||
iter.Skip()
|
||||
|
||||
default:
|
||||
v := iter.Read()
|
||||
logf("[PANEL] support key: %s / %v\n", l1Field, v)
|
||||
}
|
||||
}
|
||||
|
||||
panel.Datasource = targets.GetDatasourceInfo()
|
||||
|
||||
return panel
|
||||
}
|
||||
126
pkg/services/store/kind/dashboard/dashboard_test.go
Normal file
126
pkg/services/store/kind/dashboard/dashboard_test.go
Normal file
@@ -0,0 +1,126 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func dsLookupForTests() DatasourceLookup {
|
||||
return CreateDatasourceLookup([]*DatasourceQueryResult{
|
||||
{
|
||||
UID: "P8045C56BDA891CB2",
|
||||
Type: "cloudwatch",
|
||||
Name: "cloudwatch-name",
|
||||
IsDefault: false,
|
||||
},
|
||||
{
|
||||
UID: "PD8C576611E62080A",
|
||||
Type: "testdata",
|
||||
Name: "gdev-testdata",
|
||||
IsDefault: false,
|
||||
},
|
||||
{
|
||||
UID: "dgd92lq7k",
|
||||
Type: "frser-sqlite-datasource",
|
||||
Name: "frser-sqlite-datasource-name",
|
||||
IsDefault: false,
|
||||
},
|
||||
{
|
||||
UID: "sqlite-1",
|
||||
Type: "sqlite-datasource",
|
||||
Name: "SQLite Grafana",
|
||||
IsDefault: false,
|
||||
},
|
||||
{
|
||||
UID: "sqlite-2",
|
||||
Type: "sqlite-datasource",
|
||||
Name: "SQLite Grafana2",
|
||||
IsDefault: false,
|
||||
},
|
||||
{
|
||||
UID: "default.uid",
|
||||
Type: "default.type",
|
||||
Name: "default.name",
|
||||
IsDefault: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestReadDashboard(t *testing.T) {
|
||||
inputs := []string{
|
||||
"check-string-datasource-id",
|
||||
"all-panels",
|
||||
"panel-graph/graph-shared-tooltips",
|
||||
"datasource-variable",
|
||||
"default-datasource-variable",
|
||||
"empty-datasource-variable",
|
||||
"repeated-datasource-variables",
|
||||
"string-datasource-variable",
|
||||
"datasource-variable-no-curly-braces",
|
||||
"all-selected-multi-datasource-variable",
|
||||
"all-selected-single-datasource-variable",
|
||||
"repeated-datasource-variables-with-default",
|
||||
"mixed-datasource-with-variable",
|
||||
"special-datasource-types",
|
||||
"panels-without-datasources",
|
||||
}
|
||||
|
||||
devdash := "../../../../../devenv/dev-dashboards/"
|
||||
|
||||
for _, input := range inputs {
|
||||
// nolint:gosec
|
||||
// We can ignore the gosec G304 warning because this is a test with hardcoded input values
|
||||
f, err := os.Open(filepath.Join(devdash, input) + ".json")
|
||||
if err == nil {
|
||||
input = "devdash-" + filepath.Base(input)
|
||||
}
|
||||
if err != nil {
|
||||
// nolint:gosec
|
||||
// We can ignore the gosec G304 warning because this is a test with hardcoded input values
|
||||
f, err = os.Open(filepath.Join("testdata", input) + ".json")
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
dash, err := readDashboard(f, dsLookupForTests())
|
||||
sortDatasources(dash)
|
||||
|
||||
require.NoError(t, err)
|
||||
out, err := json.MarshalIndent(dash, "", " ")
|
||||
require.NoError(t, err)
|
||||
|
||||
update := false
|
||||
savedPath := filepath.Join("testdata/", input+"-info.json")
|
||||
//nolint:gosec
|
||||
saved, err := os.ReadFile(savedPath)
|
||||
if err != nil {
|
||||
update = true
|
||||
assert.NoError(t, err)
|
||||
} else if !assert.JSONEq(t, string(saved), string(out)) {
|
||||
update = true
|
||||
}
|
||||
|
||||
if update {
|
||||
_ = os.WriteFile(savedPath, out, 0600)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// assure consistent ordering of datasources to prevent random failures of `assert.JSONEq`
|
||||
func sortDatasources(dash *dashboardInfo) {
|
||||
sort.Slice(dash.Datasource, func(i, j int) bool {
|
||||
return strings.Compare(dash.Datasource[i].UID, dash.Datasource[j].UID) > 0
|
||||
})
|
||||
|
||||
for panelId := range dash.Panels {
|
||||
sort.Slice(dash.Panels[panelId].Datasource, func(i, j int) bool {
|
||||
return strings.Compare(dash.Panels[panelId].Datasource[i].UID, dash.Panels[panelId].Datasource[j].UID) > 0
|
||||
})
|
||||
}
|
||||
}
|
||||
136
pkg/services/store/kind/dashboard/ds_lookup.go
Normal file
136
pkg/services/store/kind/dashboard/ds_lookup.go
Normal file
@@ -0,0 +1,136 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
)
|
||||
|
||||
type DataSourceRef struct {
|
||||
UID string `json:"uid,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
type DatasourceLookup interface {
|
||||
// ByRef will return the default DS given empty reference (nil ref, or empty ref.uid and ref.type)
|
||||
ByRef(ref *DataSourceRef) *DataSourceRef
|
||||
ByType(dsType string) []DataSourceRef
|
||||
}
|
||||
|
||||
type DatasourceQueryResult struct {
|
||||
UID string `xorm:"uid"`
|
||||
Type string `xorm:"type"`
|
||||
Name string `xorm:"name"`
|
||||
IsDefault bool `xorm:"is_default"`
|
||||
}
|
||||
|
||||
func CreateDatasourceLookup(rows []*DatasourceQueryResult) DatasourceLookup {
|
||||
byUID := make(map[string]*DataSourceRef, 50)
|
||||
byName := make(map[string]*DataSourceRef, 50)
|
||||
byType := make(map[string][]DataSourceRef, 50)
|
||||
var defaultDS *DataSourceRef
|
||||
|
||||
for _, row := range rows {
|
||||
ref := &DataSourceRef{
|
||||
UID: row.UID,
|
||||
Type: row.Type,
|
||||
}
|
||||
byUID[row.UID] = ref
|
||||
byName[row.Name] = ref
|
||||
if row.IsDefault {
|
||||
defaultDS = ref
|
||||
}
|
||||
|
||||
if _, ok := byType[row.Type]; !ok {
|
||||
byType[row.Type] = make([]DataSourceRef, 0)
|
||||
}
|
||||
byType[row.Type] = append(byType[row.Type], *ref)
|
||||
}
|
||||
|
||||
grafanaDs := &DataSourceRef{
|
||||
UID: "grafana",
|
||||
Type: "datasource",
|
||||
}
|
||||
if defaultDS == nil {
|
||||
// fallback replicated from /pkg/api/frontendsettings.go
|
||||
// https://github.com/grafana/grafana/blob/7ef21662f9ad74b80d832b9f2aa9db2fb4192741/pkg/api/frontendsettings.go#L51-L56
|
||||
defaultDS = grafanaDs
|
||||
}
|
||||
|
||||
if _, ok := byUID[grafanaDs.UID]; !ok {
|
||||
byUID[grafanaDs.UID] = grafanaDs
|
||||
}
|
||||
|
||||
grafanaDsName := "-- Grafana --"
|
||||
if _, ok := byName[grafanaDsName]; !ok {
|
||||
byName[grafanaDsName] = grafanaDs
|
||||
}
|
||||
|
||||
return &DsLookup{
|
||||
byName: byName,
|
||||
byUID: byUID,
|
||||
byType: byType,
|
||||
defaultDS: defaultDS,
|
||||
}
|
||||
}
|
||||
|
||||
type DsLookup struct {
|
||||
byName map[string]*DataSourceRef
|
||||
byUID map[string]*DataSourceRef
|
||||
byType map[string][]DataSourceRef
|
||||
defaultDS *DataSourceRef
|
||||
}
|
||||
|
||||
func (d *DsLookup) ByRef(ref *DataSourceRef) *DataSourceRef {
|
||||
if ref == nil {
|
||||
return d.defaultDS
|
||||
}
|
||||
|
||||
key := ""
|
||||
if ref.UID != "" {
|
||||
ds, ok := d.byUID[ref.UID]
|
||||
if ok {
|
||||
return ds
|
||||
}
|
||||
key = ref.UID
|
||||
}
|
||||
if key == "" {
|
||||
return d.defaultDS
|
||||
}
|
||||
ds, ok := d.byUID[key]
|
||||
if ok {
|
||||
return ds
|
||||
}
|
||||
|
||||
return d.byName[key]
|
||||
}
|
||||
|
||||
func (d *DsLookup) ByType(dsType string) []DataSourceRef {
|
||||
ds, ok := d.byType[dsType]
|
||||
if !ok {
|
||||
return make([]DataSourceRef, 0)
|
||||
}
|
||||
|
||||
return ds
|
||||
}
|
||||
|
||||
func LoadDatasourceLookup(ctx context.Context, orgID int64, sql *sqlstore.SQLStore) (DatasourceLookup, error) {
|
||||
rows := make([]*DatasourceQueryResult, 0)
|
||||
|
||||
if err := sql.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
sess.Table("data_source").
|
||||
Where("org_id = ?", orgID).
|
||||
Cols("uid", "name", "type", "is_default")
|
||||
|
||||
err := sess.Find(&rows)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return CreateDatasourceLookup(rows), nil
|
||||
}
|
||||
53
pkg/services/store/kind/dashboard/reference.go
Normal file
53
pkg/services/store/kind/dashboard/reference.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
// A reference accumulator can combine
|
||||
type ReferenceAccumulator interface {
|
||||
// Add references as we find them
|
||||
Add(kind string, subtype string, uid string)
|
||||
|
||||
// Returns the set of distinct references in a sorted order
|
||||
Get() []*models.ObjectExternalReference
|
||||
}
|
||||
|
||||
func NewReferenceAccumulator() ReferenceAccumulator {
|
||||
return &referenceAccumulator{
|
||||
refs: make(map[string]*models.ObjectExternalReference),
|
||||
}
|
||||
}
|
||||
|
||||
type referenceAccumulator struct {
|
||||
refs map[string]*models.ObjectExternalReference
|
||||
}
|
||||
|
||||
func (x *referenceAccumulator) Add(kind string, sub string, uid string) {
|
||||
key := fmt.Sprintf("%s/%s/%s", kind, sub, uid)
|
||||
_, ok := x.refs[key]
|
||||
if !ok {
|
||||
x.refs[key] = &models.ObjectExternalReference{
|
||||
Kind: kind,
|
||||
Type: sub,
|
||||
UID: uid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (x *referenceAccumulator) Get() []*models.ObjectExternalReference {
|
||||
keys := make([]string, 0, len(x.refs))
|
||||
for k := range x.refs {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
refs := make([]*models.ObjectExternalReference, len(keys))
|
||||
for i, key := range keys {
|
||||
refs[i] = x.refs[key]
|
||||
}
|
||||
return refs
|
||||
}
|
||||
99
pkg/services/store/kind/dashboard/summary.go
Normal file
99
pkg/services/store/kind/dashboard/summary.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
)
|
||||
|
||||
func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
return models.ObjectKindInfo{
|
||||
ID: models.StandardKindDashboard,
|
||||
Name: "Dashboard",
|
||||
Description: "Define a grafana dashboard layout",
|
||||
}
|
||||
}
|
||||
|
||||
func NewDashboardSummary(sql *sqlstore.SQLStore) models.ObjectSummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
// This just gets the orgID (that will soon/eventually be encoded in a GRN and passed instead of a UID)
|
||||
user := store.UserFromContext(ctx)
|
||||
if user == nil {
|
||||
return nil, nil, fmt.Errorf("can not find user in context")
|
||||
}
|
||||
|
||||
// Totally inefficient to look this up every time, but for the current use case that is OK
|
||||
// The lookup is currently structured to support searchV2, but I think should become a real fallback
|
||||
// that is only executed when we find a legacy dashboard ref
|
||||
lookup, err := LoadDatasourceLookup(ctx, user.OrgID, sql)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
builder := NewStaticDashboardSummaryBuilder(lookup)
|
||||
return builder(ctx, uid, body)
|
||||
}
|
||||
}
|
||||
|
||||
func NewStaticDashboardSummaryBuilder(lookup DatasourceLookup) models.ObjectSummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
summary := &models.ObjectSummary{
|
||||
Labels: make(map[string]string),
|
||||
Fields: make(map[string]interface{}),
|
||||
}
|
||||
stream := bytes.NewBuffer(body)
|
||||
dash, err := readDashboard(stream, lookup)
|
||||
if err != nil {
|
||||
summary.Error = &models.ObjectErrorInfo{
|
||||
Message: err.Error(),
|
||||
}
|
||||
return summary, body, err
|
||||
}
|
||||
|
||||
dashboardRefs := NewReferenceAccumulator()
|
||||
url := fmt.Sprintf("/d/%s/%s", uid, models.SlugifyTitle(dash.Title))
|
||||
summary.Name = dash.Title
|
||||
summary.Description = dash.Description
|
||||
summary.URL = url
|
||||
for _, v := range dash.Tags {
|
||||
summary.Labels[v] = ""
|
||||
}
|
||||
if len(dash.TemplateVars) > 0 {
|
||||
summary.Fields["hasTemplateVars"] = true
|
||||
}
|
||||
summary.Fields["schemaVersion"] = dash.SchemaVersion
|
||||
|
||||
for _, panel := range dash.Panels {
|
||||
panelRefs := NewReferenceAccumulator()
|
||||
p := &models.ObjectSummary{
|
||||
UID: uid + "#" + strconv.FormatInt(panel.ID, 10),
|
||||
Kind: "panel",
|
||||
}
|
||||
p.Name = panel.Title
|
||||
p.Description = panel.Description
|
||||
p.URL = fmt.Sprintf("%s?viewPanel=%d", url, panel.ID)
|
||||
p.Fields = make(map[string]interface{}, 0)
|
||||
|
||||
panelRefs.Add("panel", panel.Type, "")
|
||||
for _, v := range panel.Datasource {
|
||||
dashboardRefs.Add(models.StandardKindDataSource, v.Type, v.UID)
|
||||
panelRefs.Add(models.StandardKindDataSource, v.Type, v.UID)
|
||||
}
|
||||
|
||||
for _, v := range panel.Transformer {
|
||||
panelRefs.Add(models.StandardKindTransform, v, "")
|
||||
}
|
||||
|
||||
dashboardRefs.Add(models.StandardKindPanel, panel.Type, "")
|
||||
p.References = panelRefs.Get()
|
||||
summary.Nested = append(summary.Nested, p)
|
||||
}
|
||||
|
||||
summary.References = dashboardRefs.Get()
|
||||
return summary, body, nil
|
||||
}
|
||||
}
|
||||
67
pkg/services/store/kind/dashboard/summary_test.go
Normal file
67
pkg/services/store/kind/dashboard/summary_test.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestReadSummaries(t *testing.T) {
|
||||
devdash := "../../../../../devenv/dev-dashboards/panel-graph/"
|
||||
|
||||
ctx := context.Background()
|
||||
reader := NewStaticDashboardSummaryBuilder(dsLookupForTests())
|
||||
failed := make([]string, 0, 10)
|
||||
|
||||
err := filepath.Walk(devdash,
|
||||
func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !info.IsDir() && strings.HasSuffix(path, ".json") {
|
||||
// Ignore gosec warning G304 since it's a test
|
||||
// nolint:gosec
|
||||
body, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uid := path[len(devdash):]
|
||||
summary, _, err := reader(ctx, uid, body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := json.MarshalIndent(summary, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gpath := "testdata/gdev-walk-" + strings.ReplaceAll(uid, "/", "-")
|
||||
|
||||
// Ignore gosec warning G304 since it's a test
|
||||
// nolint:gosec
|
||||
golden, _ := os.ReadFile(gpath)
|
||||
|
||||
if !bytes.Equal(out, golden) {
|
||||
failed = append(failed, uid)
|
||||
err = os.WriteFile(gpath, out, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// accumulated in the walk test
|
||||
require.Equal(t, []string{}, failed)
|
||||
}
|
||||
91
pkg/services/store/kind/dashboard/targets.go
Normal file
91
pkg/services/store/kind/dashboard/targets.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
)
|
||||
|
||||
type targetInfo struct {
|
||||
lookup DatasourceLookup
|
||||
uids map[string]*DataSourceRef
|
||||
}
|
||||
|
||||
func newTargetInfo(lookup DatasourceLookup) targetInfo {
|
||||
return targetInfo{
|
||||
lookup: lookup,
|
||||
uids: make(map[string]*DataSourceRef),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *targetInfo) GetDatasourceInfo() []DataSourceRef {
|
||||
keys := make([]DataSourceRef, len(s.uids))
|
||||
i := 0
|
||||
for _, v := range s.uids {
|
||||
keys[i] = *v
|
||||
i++
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// the node will either be string (name|uid) OR ref
|
||||
func (s *targetInfo) addDatasource(iter *jsoniter.Iterator) {
|
||||
switch iter.WhatIsNext() {
|
||||
case jsoniter.StringValue:
|
||||
key := iter.ReadString()
|
||||
|
||||
dsRef := &DataSourceRef{UID: key}
|
||||
if !isVariableRef(dsRef.UID) && !isSpecialDatasource(dsRef.UID) {
|
||||
ds := s.lookup.ByRef(dsRef)
|
||||
s.addRef(ds)
|
||||
} else {
|
||||
s.addRef(dsRef)
|
||||
}
|
||||
|
||||
case jsoniter.NilValue:
|
||||
s.addRef(s.lookup.ByRef(nil))
|
||||
iter.Skip()
|
||||
|
||||
case jsoniter.ObjectValue:
|
||||
ref := &DataSourceRef{}
|
||||
iter.ReadVal(ref)
|
||||
|
||||
if !isVariableRef(ref.UID) && !isSpecialDatasource(ref.UID) {
|
||||
s.addRef(s.lookup.ByRef(ref))
|
||||
} else {
|
||||
s.addRef(ref)
|
||||
}
|
||||
|
||||
default:
|
||||
v := iter.Read()
|
||||
logf("[Panel.datasource.unknown] %v\n", v)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *targetInfo) addRef(ref *DataSourceRef) {
|
||||
if ref != nil && ref.UID != "" {
|
||||
s.uids[ref.UID] = ref
|
||||
}
|
||||
}
|
||||
|
||||
func (s *targetInfo) addTarget(iter *jsoniter.Iterator) {
|
||||
for l1Field := iter.ReadObject(); l1Field != ""; l1Field = iter.ReadObject() {
|
||||
switch l1Field {
|
||||
case "datasource":
|
||||
s.addDatasource(iter)
|
||||
|
||||
case "refId":
|
||||
iter.Skip()
|
||||
|
||||
default:
|
||||
v := iter.Read()
|
||||
logf("[Panel.TARGET] %s=%v\n", l1Field, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *targetInfo) addPanel(panel panelInfo) {
|
||||
for idx, v := range panel.Datasource {
|
||||
if v.UID != "" {
|
||||
s.uids[v.UID] = &panel.Datasource[idx]
|
||||
}
|
||||
}
|
||||
}
|
||||
61
pkg/services/store/kind/dashboard/testdata/all-selected-multi-datasource-variable-info.json
vendored
Normal file
61
pkg/services/store/kind/dashboard/testdata/all-selected-multi-datasource-variable-info.json
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"id": 209,
|
||||
"title": "ds-variables",
|
||||
"tags": null,
|
||||
"templateVars": [
|
||||
"sqllite"
|
||||
],
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "sqlite-2",
|
||||
"type": "sqlite-datasource"
|
||||
},
|
||||
{
|
||||
"uid": "sqlite-1",
|
||||
"type": "sqlite-datasource"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 7,
|
||||
"title": "Panel Title",
|
||||
"type": "timeseries",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "sqlite-2",
|
||||
"type": "sqlite-datasource"
|
||||
},
|
||||
{
|
||||
"uid": "sqlite-1",
|
||||
"type": "sqlite-datasource"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "Row title",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"title": "usersss!",
|
||||
"type": "table",
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "sqlite-2",
|
||||
"type": "sqlite-datasource"
|
||||
},
|
||||
{
|
||||
"uid": "sqlite-1",
|
||||
"type": "sqlite-datasource"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"linkCount": 0,
|
||||
"timeFrom": "now-6h",
|
||||
"timeTo": "now",
|
||||
"timezone": ""
|
||||
}
|
||||
230
pkg/services/store/kind/dashboard/testdata/all-selected-multi-datasource-variable.json
vendored
Normal file
230
pkg/services/store/kind/dashboard/testdata/all-selected-multi-datasource-variable.json
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 209,
|
||||
"iteration": 1656533909544,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "sqlite-datasource",
|
||||
"uid": "${sqllite}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 7,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"repeat": "sqllite",
|
||||
"repeatDirection": "h",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "sqlite-datasource",
|
||||
"uid": "${sqllite}"
|
||||
},
|
||||
"queryText": "\n SELECT CAST(strftime('%s', 'now', '-1 minute') as INTEGER) as time, 4 as value\n WHERE time >= 1234 and time < 134567\n ",
|
||||
"queryType": "table",
|
||||
"rawQueryText": "SELECT CAST(strftime('%s', 'now', '-1 minute') as INTEGER) as time, 4 as value \nWHERE time >= $__from / 1000 and time < $__to / 1000",
|
||||
"refId": "A",
|
||||
"timeColumns": [
|
||||
"time",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "Panel Title",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": {
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 8
|
||||
},
|
||||
"id": 3,
|
||||
"panels": [],
|
||||
"repeat": "sqllite",
|
||||
"repeatDirection": "h",
|
||||
"title": "Row title",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "sqlite-datasource",
|
||||
"uid": "${sqllite}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"align": "auto",
|
||||
"displayMode": "auto",
|
||||
"inspect": false
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 8,
|
||||
"y": 9
|
||||
},
|
||||
"id": 1,
|
||||
"options": {
|
||||
"footer": {
|
||||
"fields": "",
|
||||
"reducer": [
|
||||
"sum"
|
||||
],
|
||||
"show": false
|
||||
},
|
||||
"showHeader": true
|
||||
},
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "sqlite-datasource",
|
||||
"uid": "${sqllite}"
|
||||
},
|
||||
"queryText": "select * from user",
|
||||
"queryType": "table",
|
||||
"rawQueryText": "select * from user",
|
||||
"refId": "A",
|
||||
"timeColumns": [
|
||||
"time",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "usersss!",
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"allValue": "",
|
||||
"current": {
|
||||
"selected": true,
|
||||
"text": [
|
||||
"All"
|
||||
],
|
||||
"value": [
|
||||
"$__all"
|
||||
]
|
||||
},
|
||||
"hide": 0,
|
||||
"includeAll": true,
|
||||
"multi": true,
|
||||
"name": "sqllite",
|
||||
"options": [],
|
||||
"query": "sqlite-datasource",
|
||||
"queryValue": "",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"type": "datasource"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "ds-variables",
|
||||
"uid": "7BzWolqnk",
|
||||
"version": 36,
|
||||
"weekStart": ""
|
||||
}
|
||||
41
pkg/services/store/kind/dashboard/testdata/all-selected-single-datasource-variable-info.json
vendored
Normal file
41
pkg/services/store/kind/dashboard/testdata/all-selected-single-datasource-variable-info.json
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"id": 208,
|
||||
"title": "new-dashboard-var-ds-test",
|
||||
"tags": null,
|
||||
"templateVars": [
|
||||
"dsVariable"
|
||||
],
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "sqlite-2",
|
||||
"type": "sqlite-datasource"
|
||||
},
|
||||
{
|
||||
"uid": "sqlite-1",
|
||||
"type": "sqlite-datasource"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Panel Title",
|
||||
"type": "table",
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "sqlite-2",
|
||||
"type": "sqlite-datasource"
|
||||
},
|
||||
{
|
||||
"uid": "sqlite-1",
|
||||
"type": "sqlite-datasource"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"linkCount": 0,
|
||||
"timeFrom": "now-6h",
|
||||
"timeTo": "now",
|
||||
"timezone": ""
|
||||
}
|
||||
133
pkg/services/store/kind/dashboard/testdata/all-selected-single-datasource-variable.json
vendored
Normal file
133
pkg/services/store/kind/dashboard/testdata/all-selected-single-datasource-variable.json
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"target": {
|
||||
"limit": 100,
|
||||
"matchAny": false,
|
||||
"tags": [],
|
||||
"type": "dashboard"
|
||||
},
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 208,
|
||||
"iteration": 1657048248371,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "sqlite-datasource",
|
||||
"uid": "${dsVariable}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {
|
||||
"align": "auto",
|
||||
"displayMode": "auto",
|
||||
"inspect": false
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 16,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"options": {
|
||||
"footer": {
|
||||
"fields": "",
|
||||
"reducer": [
|
||||
"sum"
|
||||
],
|
||||
"show": false
|
||||
},
|
||||
"showHeader": true
|
||||
},
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"repeat": "dsVariable",
|
||||
"repeatDirection": "h",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "sqlite-datasource",
|
||||
"uid": "${dsVariable}"
|
||||
},
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Panel Title",
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"refresh": "",
|
||||
"schemaVersion": 36,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"current": {
|
||||
"selected": true,
|
||||
"text": "All",
|
||||
"value": "$__all"
|
||||
},
|
||||
"hide": 0,
|
||||
"includeAll": true,
|
||||
"multi": false,
|
||||
"name": "dsVariable",
|
||||
"options": [],
|
||||
"query": "sqlite-datasource",
|
||||
"queryValue": "",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"type": "datasource"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "new-dashboard-var-ds-test",
|
||||
"uid": "2HLX_B3nk",
|
||||
"version": 21,
|
||||
"weekStart": ""
|
||||
}
|
||||
30
pkg/services/store/kind/dashboard/testdata/check-string-datasource-id-info.json
vendored
Normal file
30
pkg/services/store/kind/dashboard/testdata/check-string-datasource-id-info.json
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"id": 250,
|
||||
"title": "fast streaming",
|
||||
"tags": null,
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "grafana",
|
||||
"type": "datasource"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 3,
|
||||
"title": "Panel Title",
|
||||
"type": "timeseries",
|
||||
"pluginVersion": "7.5.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "grafana",
|
||||
"type": "datasource"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 27,
|
||||
"linkCount": 0,
|
||||
"timeFrom": "now-30s",
|
||||
"timeTo": "now",
|
||||
"timezone": ""
|
||||
}
|
||||
67
pkg/services/store/kind/dashboard/testdata/check-string-datasource-id.json
vendored
Normal file
67
pkg/services/store/kind/dashboard/testdata/check-string-datasource-id.json
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations \u0026 Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"id": 250,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"datasource": "-- Grafana --",
|
||||
"fieldConfig": {},
|
||||
"gridPos": {},
|
||||
"id": 3,
|
||||
"options": {
|
||||
"graph": {},
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"tooltipOptions": {
|
||||
"mode": "single"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "7.5.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"channel": "stream/telegraf/cpu",
|
||||
"filter": {
|
||||
"fields": []
|
||||
},
|
||||
"queryType": "measurements",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Panel Title",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 27,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-30s",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "fast streaming",
|
||||
"uid": "K2X7hzwGk",
|
||||
"version": 8
|
||||
}
|
||||
33
pkg/services/store/kind/dashboard/testdata/datasource-variable-info.json
vendored
Normal file
33
pkg/services/store/kind/dashboard/testdata/datasource-variable-info.json
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"id": 209,
|
||||
"title": "ds-variables",
|
||||
"tags": null,
|
||||
"templateVars": [
|
||||
"sqllite"
|
||||
],
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "sqlite-1",
|
||||
"type": "sqlite-datasource"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "usersss!",
|
||||
"type": "table",
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "sqlite-1",
|
||||
"type": "sqlite-datasource"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"linkCount": 0,
|
||||
"timeFrom": "now-6h",
|
||||
"timeTo": "now",
|
||||
"timezone": ""
|
||||
}
|
||||
33
pkg/services/store/kind/dashboard/testdata/datasource-variable-no-curly-braces-info.json
vendored
Normal file
33
pkg/services/store/kind/dashboard/testdata/datasource-variable-no-curly-braces-info.json
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"id": 209,
|
||||
"title": "ds-variables",
|
||||
"tags": null,
|
||||
"templateVars": [
|
||||
"sqllite"
|
||||
],
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "sqlite-1",
|
||||
"type": "sqlite-datasource"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "usersss!",
|
||||
"type": "table",
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "sqlite-1",
|
||||
"type": "sqlite-datasource"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"linkCount": 0,
|
||||
"timeFrom": "now-6h",
|
||||
"timeTo": "now",
|
||||
"timezone": ""
|
||||
}
|
||||
134
pkg/services/store/kind/dashboard/testdata/datasource-variable-no-curly-braces.json
vendored
Normal file
134
pkg/services/store/kind/dashboard/testdata/datasource-variable-no-curly-braces.json
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"target": {
|
||||
"limit": 100,
|
||||
"matchAny": false,
|
||||
"tags": [],
|
||||
"type": "dashboard"
|
||||
},
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 209,
|
||||
"iteration": 1656508852566,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "sqlite-datasource",
|
||||
"uid": "$sqllite"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"align": "auto",
|
||||
"displayMode": "auto",
|
||||
"inspect": false
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"options": {
|
||||
"footer": {
|
||||
"fields": "",
|
||||
"reducer": [
|
||||
"sum"
|
||||
],
|
||||
"show": false
|
||||
},
|
||||
"showHeader": true
|
||||
},
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "sqlite-datasource",
|
||||
"uid": "$sqllite"
|
||||
},
|
||||
"queryText": "select * from user",
|
||||
"queryType": "table",
|
||||
"rawQueryText": "select * from user",
|
||||
"refId": "A",
|
||||
"timeColumns": [
|
||||
"time",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "usersss!",
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"current": {
|
||||
"selected": false,
|
||||
"text": "SQLite Grafana",
|
||||
"value": "SQLite Grafana"
|
||||
},
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"multi": false,
|
||||
"name": "sqllite",
|
||||
"options": [],
|
||||
"query": "sqlite-datasource",
|
||||
"queryValue": "",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"type": "datasource"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "ds-variables",
|
||||
"uid": "7BzWolqnk",
|
||||
"version": 13,
|
||||
"weekStart": ""
|
||||
}
|
||||
134
pkg/services/store/kind/dashboard/testdata/datasource-variable.json
vendored
Normal file
134
pkg/services/store/kind/dashboard/testdata/datasource-variable.json
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"target": {
|
||||
"limit": 100,
|
||||
"matchAny": false,
|
||||
"tags": [],
|
||||
"type": "dashboard"
|
||||
},
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 209,
|
||||
"iteration": 1656508852566,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "sqlite-datasource",
|
||||
"uid": "${sqllite}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"align": "auto",
|
||||
"displayMode": "auto",
|
||||
"inspect": false
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"options": {
|
||||
"footer": {
|
||||
"fields": "",
|
||||
"reducer": [
|
||||
"sum"
|
||||
],
|
||||
"show": false
|
||||
},
|
||||
"showHeader": true
|
||||
},
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "sqlite-datasource",
|
||||
"uid": "${sqllite}"
|
||||
},
|
||||
"queryText": "select * from user",
|
||||
"queryType": "table",
|
||||
"rawQueryText": "select * from user",
|
||||
"refId": "A",
|
||||
"timeColumns": [
|
||||
"time",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "usersss!",
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"current": {
|
||||
"selected": false,
|
||||
"text": "SQLite Grafana",
|
||||
"value": "SQLite Grafana"
|
||||
},
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"multi": false,
|
||||
"name": "sqllite",
|
||||
"options": [],
|
||||
"query": "sqlite-datasource",
|
||||
"queryValue": "",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"type": "datasource"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "ds-variables",
|
||||
"uid": "7BzWolqnk",
|
||||
"version": 13,
|
||||
"weekStart": ""
|
||||
}
|
||||
33
pkg/services/store/kind/dashboard/testdata/default-datasource-variable-info.json
vendored
Normal file
33
pkg/services/store/kind/dashboard/testdata/default-datasource-variable-info.json
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"id": 208,
|
||||
"title": "new-dashboard-var-ds-test",
|
||||
"tags": null,
|
||||
"templateVars": [
|
||||
"dsVariable"
|
||||
],
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Panel Title",
|
||||
"type": "table",
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"linkCount": 0,
|
||||
"timeFrom": "now-6h",
|
||||
"timeTo": "now",
|
||||
"timezone": ""
|
||||
}
|
||||
133
pkg/services/store/kind/dashboard/testdata/default-datasource-variable.json
vendored
Normal file
133
pkg/services/store/kind/dashboard/testdata/default-datasource-variable.json
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"target": {
|
||||
"limit": 100,
|
||||
"matchAny": false,
|
||||
"tags": [],
|
||||
"type": "dashboard"
|
||||
},
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 208,
|
||||
"iteration": 1657048248373,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "testdata",
|
||||
"uid": "${dsVariable}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {
|
||||
"align": "auto",
|
||||
"displayMode": "auto",
|
||||
"inspect": false
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 16,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"options": {
|
||||
"footer": {
|
||||
"fields": "",
|
||||
"reducer": [
|
||||
"sum"
|
||||
],
|
||||
"show": false
|
||||
},
|
||||
"showHeader": true
|
||||
},
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"repeat": "dsVariable",
|
||||
"repeatDirection": "h",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "testdata",
|
||||
"uid": "${dsVariable}"
|
||||
},
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Panel Title",
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"refresh": "",
|
||||
"schemaVersion": 36,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"current": {
|
||||
"selected": true,
|
||||
"text": "default",
|
||||
"value": "default"
|
||||
},
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"multi": false,
|
||||
"name": "dsVariable",
|
||||
"options": [],
|
||||
"query": "testdata",
|
||||
"queryValue": "",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"type": "datasource"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "new-dashboard-var-ds-test",
|
||||
"uid": "2HLX_B3nk",
|
||||
"version": 22,
|
||||
"weekStart": ""
|
||||
}
|
||||
236
pkg/services/store/kind/dashboard/testdata/devdash-all-panels-info.json
vendored
Normal file
236
pkg/services/store/kind/dashboard/testdata/devdash-all-panels-info.json
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
{
|
||||
"title": "Panel tests - All panels",
|
||||
"tags": [
|
||||
"gdev",
|
||||
"panel-tests",
|
||||
"all-panels"
|
||||
],
|
||||
"templateVars": [
|
||||
"query0",
|
||||
"query1",
|
||||
"text"
|
||||
],
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 34,
|
||||
"title": "",
|
||||
"type": "text",
|
||||
"pluginVersion": "8.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 35,
|
||||
"title": "",
|
||||
"type": "text",
|
||||
"pluginVersion": "8.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 32,
|
||||
"title": "Row title",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"id": 41,
|
||||
"title": "State timeline",
|
||||
"type": "state-timeline",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 62,
|
||||
"title": "Size, color mapped to different fields + share view",
|
||||
"type": "geomap",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"title": "Histogram",
|
||||
"type": "histogram",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 28,
|
||||
"title": "Logs",
|
||||
"type": "logs",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"title": "Dashboard list",
|
||||
"type": "dashlist",
|
||||
"pluginVersion": "8.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"title": "Alert list",
|
||||
"type": "alertlist",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"title": "Heatmap",
|
||||
"type": "heatmap",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"title": "Bar gauge",
|
||||
"type": "bargauge",
|
||||
"pluginVersion": "8.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"title": "Pie chart",
|
||||
"type": "piechart",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"title": "Gauge",
|
||||
"type": "gauge",
|
||||
"pluginVersion": "8.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"title": "Tabel",
|
||||
"type": "table",
|
||||
"pluginVersion": "8.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"title": "Annotation list",
|
||||
"type": "annolist",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"title": "Stat",
|
||||
"type": "stat",
|
||||
"pluginVersion": "8.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Graph NG",
|
||||
"type": "timeseries",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"title": "Bar chart",
|
||||
"type": "barchart",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"title": "News panel",
|
||||
"type": "news",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 33,
|
||||
"linkCount": 2,
|
||||
"timeFrom": "now-6h",
|
||||
"timeTo": "now",
|
||||
"timezone": ""
|
||||
}
|
||||
121
pkg/services/store/kind/dashboard/testdata/devdash-graph-shared-tooltips-info.json
vendored
Normal file
121
pkg/services/store/kind/dashboard/testdata/devdash-graph-shared-tooltips-info.json
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
{
|
||||
"title": "Panel Tests - shared tooltips",
|
||||
"tags": [
|
||||
"gdev",
|
||||
"panel-tests",
|
||||
"graph-ng"
|
||||
],
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 4,
|
||||
"title": "two units",
|
||||
"type": "timeseries",
|
||||
"pluginVersion": "7.5.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"title": "Speed vs Temperature (XY)",
|
||||
"type": "xychart",
|
||||
"pluginVersion": "7.5.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
],
|
||||
"transformer": [
|
||||
"seriesToColumns",
|
||||
"organize"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Cursor info",
|
||||
"type": "debug",
|
||||
"pluginVersion": "7.5.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"title": "Only temperature",
|
||||
"type": "timeseries",
|
||||
"pluginVersion": "7.5.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"title": "Only Speed",
|
||||
"type": "timeseries",
|
||||
"pluginVersion": "7.5.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"title": "Panel Title",
|
||||
"type": "timeseries",
|
||||
"pluginVersion": "7.5.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"title": "flot panel (temperature)",
|
||||
"type": "graph",
|
||||
"pluginVersion": "7.5.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"title": "flot panel (no units)",
|
||||
"type": "graph",
|
||||
"pluginVersion": "7.5.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 28,
|
||||
"linkCount": 0,
|
||||
"timeFrom": "2020-09-14T16:13:20.000Z",
|
||||
"timeTo": "2020-09-15T20:00:00.000Z",
|
||||
"timezone": ""
|
||||
}
|
||||
33
pkg/services/store/kind/dashboard/testdata/empty-datasource-variable-info.json
vendored
Normal file
33
pkg/services/store/kind/dashboard/testdata/empty-datasource-variable-info.json
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"id": 209,
|
||||
"title": "ds-variables",
|
||||
"tags": null,
|
||||
"templateVars": [
|
||||
"sqllite"
|
||||
],
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "usersss!",
|
||||
"type": "table",
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"linkCount": 0,
|
||||
"timeFrom": "now-6h",
|
||||
"timeTo": "now",
|
||||
"timezone": ""
|
||||
}
|
||||
134
pkg/services/store/kind/dashboard/testdata/empty-datasource-variable.json
vendored
Normal file
134
pkg/services/store/kind/dashboard/testdata/empty-datasource-variable.json
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"target": {
|
||||
"limit": 100,
|
||||
"matchAny": false,
|
||||
"tags": [],
|
||||
"type": "dashboard"
|
||||
},
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 209,
|
||||
"iteration": 1656513278471,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "sqlite-datasource",
|
||||
"uid": "${sqllite}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"align": "auto",
|
||||
"displayMode": "auto",
|
||||
"inspect": false
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"options": {
|
||||
"footer": {
|
||||
"fields": "",
|
||||
"reducer": [
|
||||
"sum"
|
||||
],
|
||||
"show": false
|
||||
},
|
||||
"showHeader": true
|
||||
},
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "sqlite-datasource",
|
||||
"uid": "${sqllite}"
|
||||
},
|
||||
"queryText": "select * from user",
|
||||
"queryType": "table",
|
||||
"rawQueryText": "select * from user",
|
||||
"refId": "A",
|
||||
"timeColumns": [
|
||||
"time",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "usersss!",
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"current": {
|
||||
"selected": false,
|
||||
"text": "No data sources found",
|
||||
"value": ""
|
||||
},
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"multi": false,
|
||||
"name": "sqllite",
|
||||
"options": [],
|
||||
"query": "sqlite-datasource",
|
||||
"queryValue": "",
|
||||
"refresh": 1,
|
||||
"regex": "asdgasd",
|
||||
"skipUrlSync": false,
|
||||
"type": "datasource"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "ds-variables",
|
||||
"uid": "7BzWolqnk",
|
||||
"version": 14,
|
||||
"weekStart": ""
|
||||
}
|
||||
93
pkg/services/store/kind/dashboard/testdata/gdev-walk-graph-gradient-area-fills.json
vendored
Normal file
93
pkg/services/store/kind/dashboard/testdata/gdev-walk-graph-gradient-area-fills.json
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"name": "Panel Tests - Graph - Gradient Area Fills",
|
||||
"labels": {
|
||||
"gdev": "",
|
||||
"graph": "",
|
||||
"panel-tests": ""
|
||||
},
|
||||
"URL": "/d/graph-gradient-area-fills.json/panel-tests-graph-gradient-area-fills",
|
||||
"fields": {
|
||||
"schemaVersion": 18
|
||||
},
|
||||
"nested": [
|
||||
{
|
||||
"uid": "graph-gradient-area-fills.json#2",
|
||||
"kind": "panel",
|
||||
"name": "Req/s",
|
||||
"URL": "/d/graph-gradient-area-fills.json/panel-tests-graph-gradient-area-fills?viewPanel=2",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph-gradient-area-fills.json#11",
|
||||
"kind": "panel",
|
||||
"name": "Req/s",
|
||||
"URL": "/d/graph-gradient-area-fills.json/panel-tests-graph-gradient-area-fills?viewPanel=11",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph-gradient-area-fills.json#7",
|
||||
"kind": "panel",
|
||||
"name": "Memory",
|
||||
"URL": "/d/graph-gradient-area-fills.json/panel-tests-graph-gradient-area-fills?viewPanel=7",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph-gradient-area-fills.json#10",
|
||||
"kind": "panel",
|
||||
"name": "Req/s",
|
||||
"URL": "/d/graph-gradient-area-fills.json/panel-tests-graph-gradient-area-fills?viewPanel=10",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
}
|
||||
181
pkg/services/store/kind/dashboard/testdata/gdev-walk-graph-shared-tooltips.json
vendored
Normal file
181
pkg/services/store/kind/dashboard/testdata/gdev-walk-graph-shared-tooltips.json
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
{
|
||||
"name": "Panel Tests - shared tooltips",
|
||||
"labels": {
|
||||
"gdev": "",
|
||||
"graph-ng": "",
|
||||
"panel-tests": ""
|
||||
},
|
||||
"URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips",
|
||||
"fields": {
|
||||
"schemaVersion": 28
|
||||
},
|
||||
"nested": [
|
||||
{
|
||||
"uid": "graph-shared-tooltips.json#4",
|
||||
"kind": "panel",
|
||||
"name": "two units",
|
||||
"URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=4",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "timeseries"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph-shared-tooltips.json#13",
|
||||
"kind": "panel",
|
||||
"name": "Speed vs Temperature (XY)",
|
||||
"URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=13",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "xychart"
|
||||
},
|
||||
{
|
||||
"kind": "transform",
|
||||
"type": "organize"
|
||||
},
|
||||
{
|
||||
"kind": "transform",
|
||||
"type": "seriesToColumns"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph-shared-tooltips.json#2",
|
||||
"kind": "panel",
|
||||
"name": "Cursor info",
|
||||
"URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=2",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "debug"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph-shared-tooltips.json#5",
|
||||
"kind": "panel",
|
||||
"name": "Only temperature",
|
||||
"URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=5",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "timeseries"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph-shared-tooltips.json#9",
|
||||
"kind": "panel",
|
||||
"name": "Only Speed",
|
||||
"URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=9",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "timeseries"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph-shared-tooltips.json#11",
|
||||
"kind": "panel",
|
||||
"name": "Panel Title",
|
||||
"URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=11",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "timeseries"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph-shared-tooltips.json#8",
|
||||
"kind": "panel",
|
||||
"name": "flot panel (temperature)",
|
||||
"URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=8",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph-shared-tooltips.json#10",
|
||||
"kind": "panel",
|
||||
"name": "flot panel (no units)",
|
||||
"URL": "/d/graph-shared-tooltips.json/panel-tests-shared-tooltips?viewPanel=10",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "debug"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "xychart"
|
||||
}
|
||||
]
|
||||
}
|
||||
110
pkg/services/store/kind/dashboard/testdata/gdev-walk-graph-time-regions.json
vendored
Normal file
110
pkg/services/store/kind/dashboard/testdata/gdev-walk-graph-time-regions.json
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
{
|
||||
"name": "Panel Tests - Graph Time Regions",
|
||||
"labels": {
|
||||
"gdev": "",
|
||||
"graph": "",
|
||||
"panel-tests": ""
|
||||
},
|
||||
"URL": "/d/graph-time-regions.json/panel-tests-graph-time-regions",
|
||||
"fields": {
|
||||
"schemaVersion": 18
|
||||
},
|
||||
"nested": [
|
||||
{
|
||||
"uid": "graph-time-regions.json#2",
|
||||
"kind": "panel",
|
||||
"name": "Business Hours",
|
||||
"URL": "/d/graph-time-regions.json/panel-tests-graph-time-regions?viewPanel=2",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph-time-regions.json#4",
|
||||
"kind": "panel",
|
||||
"name": "Sunday's 20-23",
|
||||
"URL": "/d/graph-time-regions.json/panel-tests-graph-time-regions?viewPanel=4",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph-time-regions.json#3",
|
||||
"kind": "panel",
|
||||
"name": "Each day of week",
|
||||
"URL": "/d/graph-time-regions.json/panel-tests-graph-time-regions?viewPanel=3",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph-time-regions.json#5",
|
||||
"kind": "panel",
|
||||
"name": "05:00",
|
||||
"URL": "/d/graph-time-regions.json/panel-tests-graph-time-regions?viewPanel=5",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph-time-regions.json#7",
|
||||
"kind": "panel",
|
||||
"name": "From 22:00 to 00:30 (crossing midnight)",
|
||||
"URL": "/d/graph-time-regions.json/panel-tests-graph-time-regions?viewPanel=7",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
}
|
||||
385
pkg/services/store/kind/dashboard/testdata/gdev-walk-graph_tests.json
vendored
Normal file
385
pkg/services/store/kind/dashboard/testdata/gdev-walk-graph_tests.json
vendored
Normal file
@@ -0,0 +1,385 @@
|
||||
{
|
||||
"name": "Panel Tests - Graph",
|
||||
"labels": {
|
||||
"gdev": "",
|
||||
"graph": "",
|
||||
"panel-tests": ""
|
||||
},
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph",
|
||||
"fields": {
|
||||
"schemaVersion": 16
|
||||
},
|
||||
"nested": [
|
||||
{
|
||||
"uid": "graph_tests.json#1",
|
||||
"kind": "panel",
|
||||
"name": "No Data Points Warning",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=1",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#2",
|
||||
"kind": "panel",
|
||||
"name": "Datapoints Outside Range Warning",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=2",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#3",
|
||||
"kind": "panel",
|
||||
"name": "Random walk series",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=3",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#4",
|
||||
"kind": "panel",
|
||||
"name": "Millisecond res x-axis and tooltip",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=4",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#6",
|
||||
"kind": "panel",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=6",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#5",
|
||||
"kind": "panel",
|
||||
"name": "2 yaxis and axis labels",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=5",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#7",
|
||||
"kind": "panel",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=7",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#8",
|
||||
"kind": "panel",
|
||||
"name": "null value connected",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=8",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#10",
|
||||
"kind": "panel",
|
||||
"name": "null value null as zero",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=10",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#13",
|
||||
"kind": "panel",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=13",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#9",
|
||||
"kind": "panel",
|
||||
"name": "Stacking value ontop of nulls",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=9",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#14",
|
||||
"kind": "panel",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=14",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#12",
|
||||
"kind": "panel",
|
||||
"name": "Stacking all series null segment",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=12",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#15",
|
||||
"kind": "panel",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=15",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#21",
|
||||
"kind": "panel",
|
||||
"name": "Null between points",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=21",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#22",
|
||||
"kind": "panel",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=22",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#20",
|
||||
"kind": "panel",
|
||||
"name": "Legend Table Single Series Should Take Minimum Height",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=20",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#16",
|
||||
"kind": "panel",
|
||||
"name": "Legend Table No Scroll Visible",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=16",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#17",
|
||||
"kind": "panel",
|
||||
"name": "Legend Table Should Scroll",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=17",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#18",
|
||||
"kind": "panel",
|
||||
"name": "Legend Table No Scroll Visible",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=18",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_tests.json#19",
|
||||
"kind": "panel",
|
||||
"name": "Legend Table No Scroll Visible",
|
||||
"URL": "/d/graph_tests.json/panel-tests-graph?viewPanel=19",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "testdata",
|
||||
"UID": "PD8C576611E62080A"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
}
|
||||
177
pkg/services/store/kind/dashboard/testdata/gdev-walk-graph_y_axis.json
vendored
Normal file
177
pkg/services/store/kind/dashboard/testdata/gdev-walk-graph_y_axis.json
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
{
|
||||
"name": "Panel Tests - Graph - Y axis ticks",
|
||||
"labels": {
|
||||
"gdev": "",
|
||||
"panel-tests": ""
|
||||
},
|
||||
"URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks",
|
||||
"fields": {
|
||||
"schemaVersion": 19
|
||||
},
|
||||
"nested": [
|
||||
{
|
||||
"uid": "graph_y_axis.json#7",
|
||||
"kind": "panel",
|
||||
"name": "Data from 0 - 10K (unit short)",
|
||||
"URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=7",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_y_axis.json#5",
|
||||
"kind": "panel",
|
||||
"name": "Data from 0 - 10K (unit bytes metric)",
|
||||
"URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=5",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_y_axis.json#4",
|
||||
"kind": "panel",
|
||||
"name": "Data from 0 - 10K (unit bytes IEC)",
|
||||
"URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=4",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_y_axis.json#2",
|
||||
"kind": "panel",
|
||||
"name": "Data from 0 - 10K (unit short)",
|
||||
"URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=2",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_y_axis.json#3",
|
||||
"kind": "panel",
|
||||
"name": "Data from 0.0002 - 0.001 (unit short)",
|
||||
"URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=3",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_y_axis.json#6",
|
||||
"kind": "panel",
|
||||
"name": "Data from 12000 - 30000 (unit ms)",
|
||||
"URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=6",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_y_axis.json#9",
|
||||
"kind": "panel",
|
||||
"name": "Data from 0 - 1B (unit short)",
|
||||
"URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=9",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_y_axis.json#10",
|
||||
"kind": "panel",
|
||||
"name": "Data from 0 - 1B (unit bytes)",
|
||||
"URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=10",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"uid": "graph_y_axis.json#8",
|
||||
"kind": "panel",
|
||||
"name": "Data from 12000 - 30000 (unit ms)",
|
||||
"URL": "/d/graph_y_axis.json/panel-tests-graph-y-axis-ticks?viewPanel=8",
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"kind": "ds",
|
||||
"type": "default.type",
|
||||
"UID": "default.uid"
|
||||
},
|
||||
{
|
||||
"kind": "panel",
|
||||
"type": "graph"
|
||||
}
|
||||
]
|
||||
}
|
||||
49
pkg/services/store/kind/dashboard/testdata/mixed-datasource-with-variable-info.json
vendored
Normal file
49
pkg/services/store/kind/dashboard/testdata/mixed-datasource-with-variable-info.json
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"id": 220,
|
||||
"title": "new-dashboard-mixed",
|
||||
"tags": null,
|
||||
"templateVars": [
|
||||
"dsVariable"
|
||||
],
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
},
|
||||
{
|
||||
"uid": "PD8C576611E62080A",
|
||||
"type": "testdata"
|
||||
},
|
||||
{
|
||||
"uid": "P8045C56BDA891CB2",
|
||||
"type": "cloudwatch"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Panel Title",
|
||||
"type": "table",
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
},
|
||||
{
|
||||
"uid": "PD8C576611E62080A",
|
||||
"type": "testdata"
|
||||
},
|
||||
{
|
||||
"uid": "P8045C56BDA891CB2",
|
||||
"type": "cloudwatch"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"linkCount": 0,
|
||||
"timeFrom": "now-6h",
|
||||
"timeTo": "now",
|
||||
"timezone": ""
|
||||
}
|
||||
139
pkg/services/store/kind/dashboard/testdata/mixed-datasource-with-variable.json
vendored
Normal file
139
pkg/services/store/kind/dashboard/testdata/mixed-datasource-with-variable.json
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
{
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 220,
|
||||
"iteration": 1658225888559,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "-- Mixed --"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {
|
||||
"align": "auto",
|
||||
"displayMode": "auto",
|
||||
"inspect": false
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 16,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"options": {
|
||||
"footer": {
|
||||
"fields": "",
|
||||
"reducer": [
|
||||
"sum"
|
||||
],
|
||||
"show": false
|
||||
},
|
||||
"showHeader": true
|
||||
},
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"repeat": "dsVariable",
|
||||
"repeatDirection": "h",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "testdata",
|
||||
"uid": "${dsVariable}"
|
||||
},
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "cloudwatch",
|
||||
"uid": "P8045C56BDA891CB2"
|
||||
},
|
||||
"dimensions": {},
|
||||
"expression": "",
|
||||
"hide": false,
|
||||
"id": "",
|
||||
"label": "",
|
||||
"matchExact": true,
|
||||
"metricEditorMode": 0,
|
||||
"metricName": "",
|
||||
"metricQueryType": 0,
|
||||
"namespace": "",
|
||||
"period": "",
|
||||
"queryMode": "Metrics",
|
||||
"refId": "B",
|
||||
"region": "default",
|
||||
"sqlExpression": "",
|
||||
"statistic": "Average"
|
||||
}
|
||||
],
|
||||
"title": "Panel Title",
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"refresh": "",
|
||||
"schemaVersion": 36,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"current": {
|
||||
"selected": true,
|
||||
"text": [
|
||||
"gdev-testdata",
|
||||
"default"
|
||||
],
|
||||
"value": [
|
||||
"gdev-testdata",
|
||||
"default"
|
||||
]
|
||||
},
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"multi": false,
|
||||
"name": "dsVariable",
|
||||
"options": [],
|
||||
"query": "testdata",
|
||||
"queryValue": "",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"type": "datasource"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "new-dashboard-mixed",
|
||||
"uid": "NV5PypgVz",
|
||||
"version": 2,
|
||||
"weekStart": ""
|
||||
}
|
||||
54
pkg/services/store/kind/dashboard/testdata/panels-without-datasources-info.json
vendored
Normal file
54
pkg/services/store/kind/dashboard/testdata/panels-without-datasources-info.json
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"title": "Datasource tests - Shared Queries",
|
||||
"tags": [
|
||||
"gdev",
|
||||
"datasource-test"
|
||||
],
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Raw Data Graph",
|
||||
"type": "graph",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"title": "Last non-null",
|
||||
"type": "gauge",
|
||||
"pluginVersion": "6.4.0-pre"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"title": "min",
|
||||
"type": "gauge",
|
||||
"pluginVersion": "6.4.0-pre"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"title": "Max",
|
||||
"type": "bargauge",
|
||||
"pluginVersion": "6.4.0-pre"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"title": "Panel Title",
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 19,
|
||||
"linkCount": 0,
|
||||
"timeFrom": "now-6h",
|
||||
"timeTo": "now",
|
||||
"timezone": ""
|
||||
}
|
||||
346
pkg/services/store/kind/dashboard/testdata/panels-without-datasources.json
vendored
Normal file
346
pkg/services/store/kind/dashboard/testdata/panels-without-datasources.json
vendored
Normal file
@@ -0,0 +1,346 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations \u0026 Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"fill": 0,
|
||||
"fillGradient": 6,
|
||||
"gridPos": {
|
||||
"h": 15,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"dataLinks": []
|
||||
},
|
||||
"percentage": false,
|
||||
"pointradius": 2,
|
||||
"points": true,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"scenarioId": "csv_metric_values",
|
||||
"stringInput": "1,20,90,30,5,0,100"
|
||||
},
|
||||
{
|
||||
"refId": "B",
|
||||
"scenarioId": "csv_metric_values",
|
||||
"stringInput": "1,20,90,30,5,-100,200"
|
||||
},
|
||||
{
|
||||
"refId": "C",
|
||||
"scenarioId": "csv_metric_values",
|
||||
"stringInput": "2.5,3.5,4.5,10.5,20.5,21.5,19.5"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Raw Data Graph",
|
||||
"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
|
||||
}
|
||||
},
|
||||
{
|
||||
"datasource": "-- Dashboard --",
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 0
|
||||
},
|
||||
"id": 4,
|
||||
"options": {
|
||||
"fieldOptions": {
|
||||
"calcs": [
|
||||
"lastNotNull"
|
||||
],
|
||||
"defaults": {
|
||||
"mappings": [],
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"thresholds": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
},
|
||||
"override": {},
|
||||
"values": false
|
||||
},
|
||||
"orientation": "auto",
|
||||
"showThresholdLabels": false,
|
||||
"showThresholdMarkers": true
|
||||
},
|
||||
"pluginVersion": "6.4.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"panelId": 2,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Last non-null",
|
||||
"type": "gauge"
|
||||
},
|
||||
{
|
||||
"datasource": "-- Dashboard --",
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 5
|
||||
},
|
||||
"id": 6,
|
||||
"options": {
|
||||
"fieldOptions": {
|
||||
"calcs": [
|
||||
"min"
|
||||
],
|
||||
"defaults": {
|
||||
"mappings": [],
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"thresholds": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
},
|
||||
"override": {},
|
||||
"values": false
|
||||
},
|
||||
"orientation": "auto",
|
||||
"showThresholdLabels": false,
|
||||
"showThresholdMarkers": true
|
||||
},
|
||||
"pluginVersion": "6.4.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"panelId": 2,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "min",
|
||||
"type": "gauge"
|
||||
},
|
||||
{
|
||||
"datasource": "-- Dashboard --",
|
||||
"gridPos": {
|
||||
"h": 5,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 10
|
||||
},
|
||||
"id": 5,
|
||||
"options": {
|
||||
"displayMode": "basic",
|
||||
"fieldOptions": {
|
||||
"calcs": [
|
||||
"max"
|
||||
],
|
||||
"defaults": {
|
||||
"mappings": [],
|
||||
"max": 200,
|
||||
"min": 0,
|
||||
"thresholds": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "blue",
|
||||
"value": 40
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 120
|
||||
}
|
||||
]
|
||||
},
|
||||
"override": {},
|
||||
"values": false
|
||||
},
|
||||
"orientation": "vertical"
|
||||
},
|
||||
"pluginVersion": "6.4.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"panelId": 2,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Max",
|
||||
"type": "bargauge"
|
||||
},
|
||||
{
|
||||
"columns": [],
|
||||
"datasource": "-- Dashboard --",
|
||||
"fontSize": "100%",
|
||||
"gridPos": {
|
||||
"h": 10,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 15
|
||||
},
|
||||
"id": 8,
|
||||
"options": {},
|
||||
"pageSize": null,
|
||||
"showHeader": true,
|
||||
"sort": {
|
||||
"col": 0,
|
||||
"desc": true
|
||||
},
|
||||
"styles": [
|
||||
{
|
||||
"alias": "Time",
|
||||
"dateFormat": "YYYY-MM-DD HH:mm:ss",
|
||||
"pattern": "Time",
|
||||
"type": "date"
|
||||
},
|
||||
{
|
||||
"alias": "",
|
||||
"colorMode": null,
|
||||
"colors": [
|
||||
"rgba(245, 54, 54, 0.9)",
|
||||
"rgba(237, 129, 40, 0.89)",
|
||||
"rgba(50, 172, 45, 0.97)"
|
||||
],
|
||||
"decimals": 2,
|
||||
"pattern": "/.*/",
|
||||
"thresholds": [],
|
||||
"type": "number",
|
||||
"unit": "short"
|
||||
}
|
||||
],
|
||||
"targets": [
|
||||
{
|
||||
"panelId": 2,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Panel Title",
|
||||
"transform": "timeseries_to_columns",
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 19,
|
||||
"style": "dark",
|
||||
"tags": [
|
||||
"gdev",
|
||||
"datasource-test"
|
||||
],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"refresh_intervals": [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
]
|
||||
},
|
||||
"timezone": "",
|
||||
"title": "Datasource tests - Shared Queries",
|
||||
"uid": "ZqZnVvFZz",
|
||||
"version": 1
|
||||
}
|
||||
41
pkg/services/store/kind/dashboard/testdata/repeated-datasource-variables-info.json
vendored
Normal file
41
pkg/services/store/kind/dashboard/testdata/repeated-datasource-variables-info.json
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"id": 209,
|
||||
"title": "ds-variables",
|
||||
"tags": null,
|
||||
"templateVars": [
|
||||
"sqllite"
|
||||
],
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "sqlite-2",
|
||||
"type": "sqlite-datasource"
|
||||
},
|
||||
{
|
||||
"uid": "sqlite-1",
|
||||
"type": "sqlite-datasource"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "usersss!",
|
||||
"type": "table",
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "sqlite-2",
|
||||
"type": "sqlite-datasource"
|
||||
},
|
||||
{
|
||||
"uid": "sqlite-1",
|
||||
"type": "sqlite-datasource"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"linkCount": 0,
|
||||
"timeFrom": "now-6h",
|
||||
"timeTo": "now",
|
||||
"timezone": ""
|
||||
}
|
||||
41
pkg/services/store/kind/dashboard/testdata/repeated-datasource-variables-with-default-info.json
vendored
Normal file
41
pkg/services/store/kind/dashboard/testdata/repeated-datasource-variables-with-default-info.json
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"id": 208,
|
||||
"title": "new-dashboard-var-ds-test",
|
||||
"tags": null,
|
||||
"templateVars": [
|
||||
"dsVariable"
|
||||
],
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
},
|
||||
{
|
||||
"uid": "PD8C576611E62080A",
|
||||
"type": "testdata"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 2,
|
||||
"title": "Panel Title",
|
||||
"type": "table",
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "default.uid",
|
||||
"type": "default.type"
|
||||
},
|
||||
{
|
||||
"uid": "PD8C576611E62080A",
|
||||
"type": "testdata"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"linkCount": 0,
|
||||
"timeFrom": "now-6h",
|
||||
"timeTo": "now",
|
||||
"timezone": ""
|
||||
}
|
||||
139
pkg/services/store/kind/dashboard/testdata/repeated-datasource-variables-with-default.json
vendored
Normal file
139
pkg/services/store/kind/dashboard/testdata/repeated-datasource-variables-with-default.json
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"target": {
|
||||
"limit": 100,
|
||||
"matchAny": false,
|
||||
"tags": [],
|
||||
"type": "dashboard"
|
||||
},
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 208,
|
||||
"iteration": 1657048248365,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "testdata",
|
||||
"uid": "${dsVariable}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"custom": {
|
||||
"align": "auto",
|
||||
"displayMode": "auto",
|
||||
"inspect": false
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 16,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"options": {
|
||||
"footer": {
|
||||
"fields": "",
|
||||
"reducer": [
|
||||
"sum"
|
||||
],
|
||||
"show": false
|
||||
},
|
||||
"showHeader": true
|
||||
},
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"repeat": "dsVariable",
|
||||
"repeatDirection": "h",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "testdata",
|
||||
"uid": "${dsVariable}"
|
||||
},
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Panel Title",
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"refresh": "",
|
||||
"schemaVersion": 36,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"current": {
|
||||
"selected": true,
|
||||
"text": [
|
||||
"gdev-testdata",
|
||||
"default"
|
||||
],
|
||||
"value": [
|
||||
"gdev-testdata",
|
||||
"default"
|
||||
]
|
||||
},
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"multi": true,
|
||||
"name": "dsVariable",
|
||||
"options": [],
|
||||
"query": "testdata",
|
||||
"queryValue": "",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"type": "datasource"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "new-dashboard-var-ds-test",
|
||||
"uid": "2HLX_B3nk",
|
||||
"version": 19,
|
||||
"weekStart": ""
|
||||
}
|
||||
143
pkg/services/store/kind/dashboard/testdata/repeated-datasource-variables.json
vendored
Normal file
143
pkg/services/store/kind/dashboard/testdata/repeated-datasource-variables.json
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"target": {
|
||||
"limit": 100,
|
||||
"matchAny": false,
|
||||
"tags": [],
|
||||
"type": "dashboard"
|
||||
},
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 209,
|
||||
"iteration": 1656507534777,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "sqlite-datasource",
|
||||
"uid": "${sqllite}"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"align": "auto",
|
||||
"displayMode": "auto",
|
||||
"inspect": false
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"options": {
|
||||
"footer": {
|
||||
"fields": "",
|
||||
"reducer": [
|
||||
"sum"
|
||||
],
|
||||
"show": false
|
||||
},
|
||||
"showHeader": true
|
||||
},
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"repeat": "sqllite",
|
||||
"repeatDirection": "h",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "sqlite-datasource",
|
||||
"uid": "${sqllite}"
|
||||
},
|
||||
"key": "Q-7ab4ab1a-3c70-41f4-9a45-19919e1c2193-0",
|
||||
"queryText": "select * from user",
|
||||
"queryType": "table",
|
||||
"rawQueryText": "select * from user",
|
||||
"refId": "A",
|
||||
"timeColumns": [
|
||||
"time",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "usersss!",
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"current": {
|
||||
"selected": false,
|
||||
"text": [
|
||||
"SQLite Grafana",
|
||||
"SQLite Grafana2"
|
||||
],
|
||||
"value": [
|
||||
"SQLite Grafana",
|
||||
"SQLite Grafana2"
|
||||
]
|
||||
},
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"multi": true,
|
||||
"name": "sqllite",
|
||||
"options": [],
|
||||
"query": "sqlite-datasource",
|
||||
"queryValue": "",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"type": "datasource"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "ds-variables",
|
||||
"uid": "7BzWolqnk",
|
||||
"version": 8,
|
||||
"weekStart": ""
|
||||
}
|
||||
77
pkg/services/store/kind/dashboard/testdata/special-datasource-types-info.json
vendored
Normal file
77
pkg/services/store/kind/dashboard/testdata/special-datasource-types-info.json
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"id": 221,
|
||||
"title": "special ds",
|
||||
"tags": null,
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "grafana",
|
||||
"type": "datasource"
|
||||
},
|
||||
{
|
||||
"uid": "dgd92lq7k",
|
||||
"type": "frser-sqlite-datasource"
|
||||
},
|
||||
{
|
||||
"uid": "PD8C576611E62080A",
|
||||
"type": "testdata"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 10,
|
||||
"title": "mixed ds with grafana ds",
|
||||
"type": "timeseries",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "grafana",
|
||||
"type": "datasource"
|
||||
},
|
||||
{
|
||||
"uid": "dgd92lq7k",
|
||||
"type": "frser-sqlite-datasource"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"title": "Row title",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"title": "dashboard ds",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"title": "grafana ds",
|
||||
"type": "timeseries",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "grafana",
|
||||
"type": "datasource"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "mixed ds",
|
||||
"type": "timeseries",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "dgd92lq7k",
|
||||
"type": "frser-sqlite-datasource"
|
||||
},
|
||||
{
|
||||
"uid": "PD8C576611E62080A",
|
||||
"type": "testdata"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"linkCount": 0,
|
||||
"timeFrom": "now-6h",
|
||||
"timeTo": "now",
|
||||
"timezone": ""
|
||||
}
|
||||
310
pkg/services/store/kind/dashboard/testdata/special-datasource-types.json
vendored
Normal file
310
pkg/services/store/kind/dashboard/testdata/special-datasource-types.json
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
{
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 221,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "-- Mixed --"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 10,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "grafana"
|
||||
},
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "frser-sqlite-datasource",
|
||||
"uid": "dgd92lq7k"
|
||||
},
|
||||
"hide": false,
|
||||
"queryText": "\n SELECT CAST(strftime('%s', 'now', '-1 minute') as INTEGER) as time, 4 as value\n WHERE time >= 1234 and time < 134567\n ",
|
||||
"queryType": "table",
|
||||
"rawQueryText": "SELECT CAST(strftime('%s', 'now', '-1 minute') as INTEGER) as time, 4 as value \nWHERE time >= $__from / 1000 and time < $__to / 1000",
|
||||
"refId": "B",
|
||||
"timeColumns": [
|
||||
"time",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "mixed ds with grafana ds",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"gridPos": {
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 8
|
||||
},
|
||||
"id": 8,
|
||||
"title": "Row title",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "-- Dashboard --"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 9
|
||||
},
|
||||
"id": 4,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "-- Dashboard --"
|
||||
},
|
||||
"panelId": 2,
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "dashboard ds",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "grafana"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 9
|
||||
},
|
||||
"id": 6,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "grafana"
|
||||
},
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "grafana ds",
|
||||
"type": "timeseries"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "datasource",
|
||||
"uid": "-- Mixed --"
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 9,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 17
|
||||
},
|
||||
"id": 2,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"tooltip": {
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "testdata",
|
||||
"uid": "PD8C576611E62080A"
|
||||
},
|
||||
"refId": "A"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "frser-sqlite-datasource",
|
||||
"uid": "dgd92lq7k"
|
||||
},
|
||||
"hide": false,
|
||||
"queryText": "\n SELECT CAST(strftime('%s', 'now', '-1 minute') as INTEGER) as time, 4 as value\n WHERE time >= 1234 and time < 134567\n ",
|
||||
"queryType": "table",
|
||||
"rawQueryText": "SELECT CAST(strftime('%s', 'now', '-1 minute') as INTEGER) as time, 4 as value \nWHERE time >= $__from / 1000 and time < $__to / 1000",
|
||||
"refId": "B",
|
||||
"timeColumns": [
|
||||
"time",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "mixed ds",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "special ds",
|
||||
"uid": "mocpwtR4k",
|
||||
"version": 1,
|
||||
"weekStart": ""
|
||||
}
|
||||
33
pkg/services/store/kind/dashboard/testdata/string-datasource-variable-info.json
vendored
Normal file
33
pkg/services/store/kind/dashboard/testdata/string-datasource-variable-info.json
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"id": 209,
|
||||
"title": "ds-variables",
|
||||
"tags": null,
|
||||
"templateVars": [
|
||||
"sqllite"
|
||||
],
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "sqlite-1",
|
||||
"type": "sqlite-datasource"
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "usersss!",
|
||||
"type": "table",
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"datasource": [
|
||||
{
|
||||
"uid": "sqlite-1",
|
||||
"type": "sqlite-datasource"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"linkCount": 0,
|
||||
"timeFrom": "now-6h",
|
||||
"timeTo": "now",
|
||||
"timezone": ""
|
||||
}
|
||||
109
pkg/services/store/kind/dashboard/testdata/string-datasource-variable.json
vendored
Normal file
109
pkg/services/store/kind/dashboard/testdata/string-datasource-variable.json
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
{
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 209,
|
||||
"iteration": 1656508852566,
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"panels": [
|
||||
{
|
||||
"datasource": "${sqllite}",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {
|
||||
"align": "auto",
|
||||
"displayMode": "auto",
|
||||
"inspect": false
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 1,
|
||||
"options": {
|
||||
"footer": {
|
||||
"fields": "",
|
||||
"reducer": [
|
||||
"sum"
|
||||
],
|
||||
"show": false
|
||||
},
|
||||
"showHeader": true
|
||||
},
|
||||
"pluginVersion": "9.1.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "sqlite-datasource",
|
||||
"uid": "${sqllite}"
|
||||
},
|
||||
"queryText": "select * from user",
|
||||
"queryType": "table",
|
||||
"rawQueryText": "select * from user",
|
||||
"refId": "A",
|
||||
"timeColumns": [
|
||||
"time",
|
||||
"ts"
|
||||
]
|
||||
}
|
||||
],
|
||||
"title": "usersss!",
|
||||
"type": "table"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"current": {
|
||||
"selected": false,
|
||||
"text": "SQLite Grafana",
|
||||
"value": "SQLite Grafana"
|
||||
},
|
||||
"hide": 0,
|
||||
"includeAll": false,
|
||||
"multi": false,
|
||||
"name": "sqllite",
|
||||
"options": [],
|
||||
"query": "sqlite-datasource",
|
||||
"queryValue": "",
|
||||
"refresh": 1,
|
||||
"regex": "",
|
||||
"skipUrlSync": false,
|
||||
"type": "datasource"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "ds-variables",
|
||||
"uid": "7BzWolqnk",
|
||||
"version": 13,
|
||||
"weekStart": ""
|
||||
}
|
||||
32
pkg/services/store/kind/dashboard/types.go
Normal file
32
pkg/services/store/kind/dashboard/types.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package dashboard
|
||||
|
||||
type panelInfo struct {
|
||||
ID int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Type string `json:"type,omitempty"` // PluginID
|
||||
PluginVersion string `json:"pluginVersion,omitempty"`
|
||||
Datasource []DataSourceRef `json:"datasource,omitempty"` // UIDs
|
||||
Transformer []string `json:"transformer,omitempty"` // ids of the transformation steps
|
||||
|
||||
// Rows define panels as sub objects
|
||||
Collapsed []panelInfo `json:"collapsed,omitempty"`
|
||||
}
|
||||
|
||||
type dashboardInfo struct {
|
||||
UID string `json:"uid,omitempty"`
|
||||
ID int64 `json:"id,omitempty"` // internal ID
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Tags []string `json:"tags"`
|
||||
TemplateVars []string `json:"templateVars,omitempty"` // the keys used
|
||||
Datasource []DataSourceRef `json:"datasource,omitempty"` // UIDs
|
||||
Panels []panelInfo `json:"panels"` // nesed documents
|
||||
SchemaVersion int64 `json:"schemaVersion"`
|
||||
LinkCount int64 `json:"linkCount"`
|
||||
TimeFrom string `json:"timeFrom"`
|
||||
TimeTo string `json:"timeTo"`
|
||||
TimeZone string `json:"timezone"`
|
||||
Refresh string `json:"refresh,omitempty"`
|
||||
ReadOnly bool `json:"readOnly,omitempty"` // editable = false
|
||||
}
|
||||
4
pkg/services/store/kind/dummy/doc.go
Normal file
4
pkg/services/store/kind/dummy/doc.go
Normal file
@@ -0,0 +1,4 @@
|
||||
// Package dummy provides a dummy kind useful for testing
|
||||
//
|
||||
// The dummy kind returns a complicated summary that can exercise most of the storage options
|
||||
package dummy
|
||||
61
pkg/services/store/kind/dummy/summary.go
Normal file
61
pkg/services/store/kind/dummy/summary.go
Normal file
@@ -0,0 +1,61 @@
|
||||
package dummy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func GetObjectKindInfo(kind string) models.ObjectKindInfo {
|
||||
return models.ObjectKindInfo{
|
||||
ID: kind,
|
||||
Name: kind,
|
||||
Description: "Dummy kind used for testing.",
|
||||
IsRaw: true,
|
||||
}
|
||||
}
|
||||
|
||||
func GetObjectSummaryBuilder(kind string) models.ObjectSummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
summary := &models.ObjectSummary{
|
||||
Name: fmt.Sprintf("Dummy: %s", kind),
|
||||
Kind: kind,
|
||||
Description: fmt.Sprintf("Wrote at %s", time.Now().Local().String()),
|
||||
Labels: map[string]string{
|
||||
"hello": "world",
|
||||
"tag1": "",
|
||||
"tag2": "",
|
||||
},
|
||||
Fields: map[string]interface{}{
|
||||
"field1": "a string",
|
||||
"field2": 1.224,
|
||||
"field4": true,
|
||||
},
|
||||
Error: nil, // ignore for now
|
||||
Nested: nil, // ignore for now
|
||||
References: []*models.ObjectExternalReference{
|
||||
{
|
||||
Kind: "ds",
|
||||
Type: "influx",
|
||||
UID: "xyz",
|
||||
},
|
||||
{
|
||||
Kind: "panel",
|
||||
Type: "heatmap",
|
||||
},
|
||||
{
|
||||
Kind: "panel",
|
||||
Type: "timeseries",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if summary.UID != "" && uid != summary.UID {
|
||||
return summary, nil, fmt.Errorf("internal UID mismatch")
|
||||
}
|
||||
|
||||
return summary, body, nil
|
||||
}
|
||||
}
|
||||
67
pkg/services/store/kind/playlist/summary.go
Normal file
67
pkg/services/store/kind/playlist/summary.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package playlist
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana/pkg/coremodel/playlist"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
return models.ObjectKindInfo{
|
||||
ID: models.StandardKindPlaylist,
|
||||
Name: "Playlist",
|
||||
Description: "Cycle though a collection of dashboards automatically",
|
||||
}
|
||||
}
|
||||
|
||||
func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
return summaryBuilder
|
||||
}
|
||||
|
||||
func summaryBuilder(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
obj := &playlist.Model{}
|
||||
err := json.Unmarshal(body, obj)
|
||||
if err != nil {
|
||||
return nil, nil, err // unable to read object
|
||||
}
|
||||
|
||||
// TODO: fix model so this is not possible
|
||||
if obj.Items == nil {
|
||||
temp := make([]playlist.PlaylistItem, 0)
|
||||
obj.Items = &temp
|
||||
}
|
||||
|
||||
summary := &models.ObjectSummary{
|
||||
UID: obj.Uid,
|
||||
Name: obj.Name,
|
||||
Description: fmt.Sprintf("%d items, refreshed every %s", len(*obj.Items), obj.Interval),
|
||||
}
|
||||
|
||||
for _, item := range *obj.Items {
|
||||
switch item.Type {
|
||||
case playlist.PlaylistItemTypeDashboardByUid:
|
||||
summary.References = append(summary.References, &models.ObjectExternalReference{
|
||||
Kind: "dashboard",
|
||||
UID: item.Value,
|
||||
})
|
||||
|
||||
case playlist.PlaylistItemTypeDashboardByTag:
|
||||
if summary.Labels == nil {
|
||||
summary.Labels = make(map[string]string, 0)
|
||||
}
|
||||
summary.Labels[item.Value] = ""
|
||||
|
||||
case playlist.PlaylistItemTypeDashboardById:
|
||||
// obviously insufficient long term... but good to have an example :)
|
||||
summary.Error = &models.ObjectErrorInfo{
|
||||
Message: "Playlist uses deprecated internal id system",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out, err := json.Marshal(obj)
|
||||
return summary, out, err
|
||||
}
|
||||
39
pkg/services/store/kind/playlist/summary_test.go
Normal file
39
pkg/services/store/kind/playlist/summary_test.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package playlist
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/coremodel/playlist"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPlaylistSummary(t *testing.T) {
|
||||
builder := GetObjectSummaryBuilder()
|
||||
|
||||
// Do not parse invalid input
|
||||
_, _, err := builder(context.Background(), "abc", []byte("{invalid json"))
|
||||
require.Error(t, err)
|
||||
|
||||
playlist := playlist.Model{
|
||||
Interval: "30s",
|
||||
Name: "test",
|
||||
Items: &[]playlist.PlaylistItem{
|
||||
{Type: playlist.PlaylistItemTypeDashboardByUid, Value: "D1"},
|
||||
{Type: playlist.PlaylistItemTypeDashboardByTag, Value: "tagA"},
|
||||
{Type: playlist.PlaylistItemTypeDashboardByUid, Value: "D3"},
|
||||
},
|
||||
}
|
||||
out, err := json.Marshal(playlist)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, out)
|
||||
|
||||
// Do not parse invalid input
|
||||
summary, body, err := builder(context.Background(), "abc", out)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "test", summary.Name)
|
||||
require.Equal(t, 2, len(summary.References))
|
||||
require.Equal(t, map[string]string{"tagA": ""}, summary.Labels)
|
||||
require.True(t, json.Valid(body))
|
||||
}
|
||||
55
pkg/services/store/kind/png/summary.go
Normal file
55
pkg/services/store/kind/png/summary.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package png
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"image/png"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
return models.ObjectKindInfo{
|
||||
ID: models.StandardKindPNG,
|
||||
Name: "PNG",
|
||||
Description: "PNG Image file",
|
||||
IsRaw: true,
|
||||
FileExtension: "png",
|
||||
MimeType: "image/png",
|
||||
}
|
||||
}
|
||||
|
||||
// SVG sanitizer based on the rendering service
|
||||
func GetObjectSummaryBuilder() models.ObjectSummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
img, err := png.Decode(bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
size := img.Bounds().Size()
|
||||
summary := &models.ObjectSummary{
|
||||
Kind: models.StandardKindSVG,
|
||||
Name: guessNameFromUID(uid),
|
||||
UID: uid,
|
||||
Fields: map[string]interface{}{
|
||||
"width": int64(size.X),
|
||||
"height": int64(size.Y),
|
||||
},
|
||||
}
|
||||
return summary, body, nil
|
||||
}
|
||||
}
|
||||
|
||||
func guessNameFromUID(uid string) string {
|
||||
sidx := strings.LastIndex(uid, "/") + 1
|
||||
didx := strings.LastIndex(uid, ".")
|
||||
if didx > sidx && didx != sidx {
|
||||
return uid[sidx:didx]
|
||||
}
|
||||
if sidx > 0 {
|
||||
return uid[sidx:]
|
||||
}
|
||||
return uid
|
||||
}
|
||||
33
pkg/services/store/kind/png/summary_test.go
Normal file
33
pkg/services/store/kind/png/summary_test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package png
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPNGSummary(t *testing.T) {
|
||||
const gopher = `iVBORw0KGgoAAAANSUhEUgAAAEsAAAA8CAAAAAALAhhPAAAFfUlEQVRYw62XeWwUVRzHf2+OPbo9d7tsWyiyaZti6eWGAhISoIGKECEKCAiJJkYTiUgTMYSIosYYBBIUIxoSPIINEBDi2VhwkQrVsj1ESgu9doHWdrul7ba73WNm3vOPtsseM9MdwvvrzTs+8/t95ze/33sI5BqiabU6m9En8oNjduLnAEDLUsQXFF8tQ5oxK3vmnNmDSMtrncks9Hhtt/qeWZapHb1ha3UqYSWVl2ZmpWgaXMXGohQAvmeop3bjTRtv6SgaK/Pb9/bFzUrYslbFAmHPp+3WhAYdr+7GN/YnpN46Opv55VDsJkoEpMrY/vO2BIYQ6LLvm0ThY3MzDzzeSJeeWNyTkgnIE5ePKsvKlcg/0T9QMzXalwXMlj54z4c0rh/mzEfr+FgWEz2w6uk8dkzFAgcARAgNp1ZYef8bH2AgvuStbc2/i6CiWGj98y2tw2l4FAXKkQBIf+exyRnteY83LfEwDQAYCoK+P6bxkZm/0966LxcAAILHB56kgD95PPxltuYcMtFTWw/FKkY/6Opf3GGd9ZF+Qp6mzJxzuRSractOmJrH1u8XTvWFHINNkLQLMR+XHXvfPPHw967raE1xxwtA36IMRfkAAG29/7mLuQcb2WOnsJReZGfpiHsSBX81cvMKywYZHhX5hFPtOqPGWZCXnhWGAu6lX91ElKXSalcLXu3UaOXVay57ZSe5f6Gpx7J2MXAsi7EqSp09b/MirKSyJfnfEEgeDjl8FgDAfvewP03zZ+AJ0m9aFRM8eEHBDRKjfcreDXnZdQuAxXpT2NRJ7xl3UkLBhuVGU16gZiGOgZmrSbRdqkILuL/yYoSXHHkl9KXgqNu3PB8oRg0geC5vFmLjad6mUyTKLmF3OtraWDIfACyXqmephaDABawfpi6tqqBZytfQMqOz6S09iWXhktrRaB8Xz4Yi/8gyABDm5NVe6qq/3VzPrcjELWrebVuyY2T7ar4zQyybUCtsQ5Es1FGaZVrRVQwAgHGW2ZCRZshI5bGQi7HesyE972pOSeMM0dSktlzxRdrlqb3Osa6CCS8IJoQQQgBAbTAa5l5epO34rJszibJI8rxLfGzcp1dRosutGeb2VDNgqYrwTiPNsLxXiPi3dz7LiS1WBRBDBOnqEjyy3aQb+/bLiJzz9dIkscVBBLxMfSEac7kO4Fpkngi0ruNBeSOal+u8jgOuqPz12nryMLCniEjtOOOmpt+KEIqsEdocJjYXwrh9OZqWJQyPCTo67LNS/TdxLAv6R5ZNK9npEjbYdT33gRo4o5oTqR34R+OmaSzDBWsAIPhuRcgyoteNi9gF0KzNYWVItPf2TLoXEg+7isNC7uJkgo1iQWOfRSP9NR11RtbZZ3OMG/VhL6jvx+J1m87+RCfJChAtEBQkSBX2PnSiihc/Twh3j0h7qdYQAoRVsRGmq7HU2QRbaxVGa1D6nIOqaIWRjyRZpHMQKWKpZM5feA+lzC4ZFultV8S6T0mzQGhQohi5I8iw+CsqBSxhFMuwyLgSwbghGb0AiIKkSDmGZVmJSiKihsiyOAUs70UkywooYP0bii9GdH4sfr1UNysd3fUyLLMQN+rsmo3grHl9VNJHbbwxoa47Vw5gupIqrZcjPh9R4Nye3nRDk199V+aetmvVtDRE8/+cbgAAgMIWGb3UA0MGLE9SCbWX670TDy1y98c3D27eppUjsZ6fql3jcd5rUe7+ZIlLNQny3Rd+E5Tct3WVhTM5RBCEdiEK0b6B+/ca2gYU393nFj/n1AygRQxPIUA043M42u85+z2SnssKrPl8Mx76NL3E6eXc3be7OD+H4WHbJkKI8AU8irbITQjZ+0hQcPEgId/Fn/pl9crKH02+5o2b9T/eMx7pKoskYgAAAABJRU5ErkJggg==`
|
||||
img, err := base64.StdEncoding.DecodeString(gopher)
|
||||
require.NoError(t, err)
|
||||
|
||||
summary, out, err := GetObjectSummaryBuilder()(context.Background(), "hello.png", img)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, img, out) // same image
|
||||
|
||||
asjson, err := json.MarshalIndent(summary, "", " ")
|
||||
//fmt.Printf(string(asjson))
|
||||
require.NoError(t, err)
|
||||
require.JSONEq(t, `{
|
||||
"uid": "hello.png",
|
||||
"kind": "svg",
|
||||
"name": "hello",
|
||||
"fields": {
|
||||
"height": 60,
|
||||
"width": 75
|
||||
}
|
||||
}`, string(asjson))
|
||||
}
|
||||
144
pkg/services/store/kind/registry.go
Normal file
144
pkg/services/store/kind/registry.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package kind
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/rendering"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/store/kind/dashboard"
|
||||
"github.com/grafana/grafana/pkg/services/store/kind/dummy"
|
||||
"github.com/grafana/grafana/pkg/services/store/kind/playlist"
|
||||
"github.com/grafana/grafana/pkg/services/store/kind/png"
|
||||
"github.com/grafana/grafana/pkg/services/store/kind/svg"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
type KindRegistry interface {
|
||||
Register(info models.ObjectKindInfo, builder models.ObjectSummaryBuilder) error
|
||||
GetSummaryBuilder(kind string) models.ObjectSummaryBuilder
|
||||
GetInfo(kind string) (models.ObjectKindInfo, error)
|
||||
GetKinds() []models.ObjectKindInfo
|
||||
}
|
||||
|
||||
func NewKindRegistry() KindRegistry {
|
||||
kinds := make(map[string]*kindValues)
|
||||
kinds[models.StandardKindPlaylist] = &kindValues{
|
||||
info: playlist.GetObjectKindInfo(),
|
||||
builder: playlist.GetObjectSummaryBuilder(),
|
||||
}
|
||||
kinds[models.StandardKindPNG] = &kindValues{
|
||||
info: png.GetObjectKindInfo(),
|
||||
builder: png.GetObjectSummaryBuilder(),
|
||||
}
|
||||
|
||||
// FIXME -- these are registered because existing tests use them
|
||||
for _, k := range []string{"dummy", "kind1", "kind2", "kind3"} {
|
||||
kinds[k] = &kindValues{
|
||||
info: dummy.GetObjectKindInfo(k),
|
||||
builder: dummy.GetObjectSummaryBuilder(k),
|
||||
}
|
||||
}
|
||||
|
||||
// create a registry
|
||||
reg := ®istry{
|
||||
mutex: sync.RWMutex{},
|
||||
kinds: kinds,
|
||||
}
|
||||
reg.updateInfoArray()
|
||||
return reg
|
||||
}
|
||||
|
||||
// TODO? This could be a zero dependency service that others are responsible for configuring
|
||||
func ProvideService(cfg *setting.Cfg, renderer rendering.Service, sql *sqlstore.SQLStore) KindRegistry {
|
||||
reg := NewKindRegistry()
|
||||
|
||||
// Register Dashboard support
|
||||
//-----------------------
|
||||
_ = reg.Register(dashboard.GetObjectKindInfo(), dashboard.NewDashboardSummary(sql))
|
||||
|
||||
// Register SVG support
|
||||
//-----------------------
|
||||
info := svg.GetObjectKindInfo()
|
||||
allowUnsanitizedSvgUpload := cfg != nil && cfg.Storage.AllowUnsanitizedSvgUpload
|
||||
support := svg.GetObjectSummaryBuilder(allowUnsanitizedSvgUpload, renderer)
|
||||
_ = reg.Register(info, support)
|
||||
|
||||
return reg
|
||||
}
|
||||
|
||||
type kindValues struct {
|
||||
info models.ObjectKindInfo
|
||||
builder models.ObjectSummaryBuilder
|
||||
}
|
||||
|
||||
type registry struct {
|
||||
mutex sync.RWMutex
|
||||
kinds map[string]*kindValues
|
||||
info []models.ObjectKindInfo
|
||||
}
|
||||
|
||||
func (r *registry) updateInfoArray() {
|
||||
info := make([]models.ObjectKindInfo, 0, len(r.kinds))
|
||||
for _, v := range r.kinds {
|
||||
info = append(info, v.info)
|
||||
}
|
||||
sort.Slice(info, func(i, j int) bool {
|
||||
return info[i].ID < info[j].ID
|
||||
})
|
||||
r.info = info
|
||||
}
|
||||
|
||||
func (r *registry) Register(info models.ObjectKindInfo, builder models.ObjectSummaryBuilder) error {
|
||||
if info.ID == "" || builder == nil {
|
||||
return fmt.Errorf("invalid kind")
|
||||
}
|
||||
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
|
||||
if r.kinds[info.ID] != nil {
|
||||
return fmt.Errorf("already exits")
|
||||
}
|
||||
|
||||
r.kinds[info.ID] = &kindValues{
|
||||
info: info,
|
||||
builder: builder,
|
||||
}
|
||||
r.updateInfoArray()
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSummaryBuilder returns a builder or nil if not found
|
||||
func (r *registry) GetSummaryBuilder(kind string) models.ObjectSummaryBuilder {
|
||||
r.mutex.RLock()
|
||||
defer r.mutex.RUnlock()
|
||||
|
||||
v, ok := r.kinds[kind]
|
||||
if ok {
|
||||
return v.builder
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetInfo returns the registered info
|
||||
func (r *registry) GetInfo(kind string) (models.ObjectKindInfo, error) {
|
||||
r.mutex.RLock()
|
||||
defer r.mutex.RUnlock()
|
||||
|
||||
v, ok := r.kinds[kind]
|
||||
if ok {
|
||||
return v.info, nil
|
||||
}
|
||||
return models.ObjectKindInfo{}, fmt.Errorf("not found")
|
||||
}
|
||||
|
||||
// GetSummaryBuilder returns a builder or nil if not found
|
||||
func (r *registry) GetKinds() []models.ObjectKindInfo {
|
||||
r.mutex.RLock()
|
||||
defer r.mutex.RUnlock()
|
||||
|
||||
return r.info // returns a copy of the array
|
||||
}
|
||||
42
pkg/services/store/kind/registry_test.go
Normal file
42
pkg/services/store/kind/registry_test.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package kind
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/store/kind/dummy"
|
||||
)
|
||||
|
||||
func TestKindRegistry(t *testing.T) {
|
||||
registry := NewKindRegistry()
|
||||
err := registry.Register(dummy.GetObjectKindInfo("test"), dummy.GetObjectSummaryBuilder("test"))
|
||||
require.NoError(t, err)
|
||||
|
||||
ids := []string{}
|
||||
for _, k := range registry.GetKinds() {
|
||||
ids = append(ids, k.ID)
|
||||
}
|
||||
require.Equal(t, []string{
|
||||
"dummy",
|
||||
"kind1",
|
||||
"kind2",
|
||||
"kind3",
|
||||
"playlist",
|
||||
"png",
|
||||
"test",
|
||||
}, ids)
|
||||
|
||||
// Check playlist exists
|
||||
info, err := registry.GetInfo(models.StandardKindPlaylist)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "Playlist", info.Name)
|
||||
require.False(t, info.IsRaw)
|
||||
|
||||
// Check that we registered a test item
|
||||
info, err = registry.GetInfo("test")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "test", info.Name)
|
||||
require.True(t, info.IsRaw)
|
||||
}
|
||||
66
pkg/services/store/kind/svg/summary.go
Normal file
66
pkg/services/store/kind/svg/summary.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package svg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/rendering"
|
||||
)
|
||||
|
||||
func GetObjectKindInfo() models.ObjectKindInfo {
|
||||
return models.ObjectKindInfo{
|
||||
ID: models.StandardKindSVG,
|
||||
Name: "SVG",
|
||||
Description: "Scalable Vector Graphics",
|
||||
IsRaw: true,
|
||||
FileExtension: "svg",
|
||||
MimeType: "image/svg+xml",
|
||||
}
|
||||
}
|
||||
|
||||
// SVG sanitizer based on the rendering service
|
||||
func GetObjectSummaryBuilder(allowUnsanitizedSvgUpload bool, renderer rendering.Service) models.ObjectSummaryBuilder {
|
||||
return func(ctx context.Context, uid string, body []byte) (*models.ObjectSummary, []byte, error) {
|
||||
if !IsSVG(body) {
|
||||
return nil, nil, fmt.Errorf("invalid svg")
|
||||
}
|
||||
|
||||
// When a renderer exists, we can return a sanitized version
|
||||
var sanitized []byte
|
||||
if renderer != nil {
|
||||
rsp, err := renderer.SanitizeSVG(ctx, &rendering.SanitizeSVGRequest{
|
||||
Content: body,
|
||||
})
|
||||
if err != nil && !allowUnsanitizedSvgUpload {
|
||||
return nil, nil, err
|
||||
}
|
||||
sanitized = rsp.Sanitized
|
||||
}
|
||||
if sanitized == nil {
|
||||
if !allowUnsanitizedSvgUpload {
|
||||
return nil, nil, fmt.Errorf("unable to sanitize svg")
|
||||
}
|
||||
sanitized = body
|
||||
}
|
||||
|
||||
return &models.ObjectSummary{
|
||||
Kind: models.StandardKindSVG,
|
||||
Name: guessNameFromUID(uid),
|
||||
UID: uid,
|
||||
}, sanitized, nil
|
||||
}
|
||||
}
|
||||
|
||||
func guessNameFromUID(uid string) string {
|
||||
sidx := strings.LastIndex(uid, "/") + 1
|
||||
didx := strings.LastIndex(uid, ".")
|
||||
if didx > sidx && didx != sidx {
|
||||
return uid[sidx:didx]
|
||||
}
|
||||
if sidx > 0 {
|
||||
return uid[sidx:]
|
||||
}
|
||||
return uid
|
||||
}
|
||||
56
pkg/services/store/kind/svg/svg.go
Normal file
56
pkg/services/store/kind/svg/svg.go
Normal file
@@ -0,0 +1,56 @@
|
||||
// The MIT License
|
||||
//
|
||||
//Copyright (c) 2016 Tomas Aparicio
|
||||
//
|
||||
//Permission is hereby granted, free of charge, to any person
|
||||
//obtaining a copy of this software and associated documentation
|
||||
//files (the "Software"), to deal in the Software without
|
||||
//restriction, including without limitation the rights to use,
|
||||
//copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
//copies of the Software, and to permit persons to whom the
|
||||
//Software is furnished to do so, subject to the following
|
||||
//conditions:
|
||||
//
|
||||
//The above copyright notice and this permission notice shall be
|
||||
//included in all copies or substantial portions of the Software.
|
||||
//
|
||||
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
//EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
//OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
//NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
//HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
//WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
//FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
//OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
package svg
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var (
|
||||
// nolint:gosimple
|
||||
htmlCommentRegex = regexp.MustCompile("(?i)<!--([\\s\\S]*?)-->")
|
||||
svgRegex = regexp.MustCompile(`(?i)^\s*(?:<\?xml[^>]*>\s*)?(?:<!doctype svg[^>]*>\s*)?<svg[^>]*>[^*]*<\/svg>\s*$`)
|
||||
)
|
||||
|
||||
// isBinary checks if the given buffer is a binary file.
|
||||
func isBinary(buf []byte) bool {
|
||||
if len(buf) < 24 {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < 24; i++ {
|
||||
charCode, _ := utf8.DecodeRuneInString(string(buf[i]))
|
||||
if charCode == 65533 || charCode <= 8 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Is returns true if the given buffer is a valid SVG image.
|
||||
func IsSVG(buf []byte) bool {
|
||||
return !isBinary(buf) && svgRegex.Match(htmlCommentRegex.ReplaceAll(buf, []byte{}))
|
||||
}
|
||||
Reference in New Issue
Block a user