From 13a89d4ae3f1f4ccdb98edc9b42f3c35522d2dfa Mon Sep 17 00:00:00 2001 From: Stephanie Hingtgen Date: Thu, 10 Jul 2025 13:58:33 -0500 Subject: [PATCH] =?UTF-8?q?Revert:=20Future-proofing=20query=20and=20data?= =?UTF-8?q?=20source=20model=20in=20Dashboard=20Sche=E2=80=A6=20(#107985)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Revert: Future-proofing query and data source model in Dashboard Schema v2 --------- Co-authored-by: Ryan McKinley --- apps/alerting/notifications/Makefile | 5 +- apps/dashboard/Makefile | 2 +- .../kinds/v2alpha1/dashboard_spec.cue | 18 +- .../dashboard/v2alpha1/dashboard_spec.cue | 18 +- .../dashboard/v2alpha1/dashboard_spec_gen.go | 96 +-- .../v2alpha1/zz_generated.openapi.go | 79 +-- apps/iam/pkg/apis/iam_manifest.go | 2 + conf/provisioning/sample/dashboard-v2.json | 604 +----------------- e2e/dashboards/TestV2Dashboard.json | 67 +- e2e/utils/flows/scenes/importDashboard.ts | 4 - go.work.sum | 9 + .../src/schema/dashboard/v2_examples.ts | 68 +- .../dashboard/v2alpha1/types.spec.gen.ts | 42 +- .../dashboard.grafana.app-v2alpha1.json | 45 +- .../DashboardScenePageStateManager.test.ts | 52 +- .../scene/export/exporters.test.ts | 20 +- .../dashboard-scene/scene/export/exporters.ts | 5 +- .../DashboardSceneSerializer.test.ts | 29 +- .../serialization/DashboardSceneSerializer.ts | 6 +- ...sformSceneToSaveModelSchemaV2.test.ts.snap | 47 +- .../layoutSerializers/utils.test.ts | 62 +- .../serialization/layoutSerializers/utils.ts | 45 +- .../sceneVariablesSetToVariables.test.ts | 137 ++-- .../sceneVariablesSetToVariables.ts | 22 +- .../transformSaveModelSchemaV2ToScene.test.ts | 88 +-- .../transformSaveModelSchemaV2ToScene.ts | 47 +- .../transformSceneToSaveModelSchemaV2.test.ts | 61 +- .../transformSceneToSaveModelSchemaV2.ts | 67 +- .../v2schema/ImportDashboardOverviewV2.tsx | 39 +- .../dashboard-scene/v2schema/test-helpers.ts | 3 +- .../api/ResponseTransformers.test.ts | 57 +- .../dashboard/api/ResponseTransformers.ts | 38 +- .../manage-dashboards/state/actions.test.ts | 25 +- .../manage-dashboards/state/actions.ts | 59 +- 34 files changed, 517 insertions(+), 1451 deletions(-) diff --git a/apps/alerting/notifications/Makefile b/apps/alerting/notifications/Makefile index 2c50dee3970..d745632abf9 100644 --- a/apps/alerting/notifications/Makefile +++ b/apps/alerting/notifications/Makefile @@ -19,6 +19,9 @@ update-app-sdk: ## Update the Grafana App SDK dependency in go.mod go mod tidy .PHONY: generate -generate: install-app-sdk update-app-sdk +generate: do-generate ## Run Grafana App SDK code generation + +.PHONY: do-generate +do-generate: install-app-sdk update-app-sdk ## --defencoding=none and noschemasinmanifest are needed to avoid infinite loop while generating recursive models (see routingtree.cue) @$(APP_SDK_BIN) generate --grouping=group --gogenpath=./pkg/apis --defencoding=none --postprocess --noschemasinmanifest diff --git a/apps/dashboard/Makefile b/apps/dashboard/Makefile index 701b1d0854e..1a948f1b9a8 100644 --- a/apps/dashboard/Makefile +++ b/apps/dashboard/Makefile @@ -1,4 +1,4 @@ -APP_SDK_VERSION := v0.39.2 +APP_SDK_VERSION := v0.39.0 APP_SDK_DIR := $(shell go env GOPATH)/bin/app-sdk-$(APP_SDK_VERSION) APP_SDK_BIN := $(APP_SDK_DIR)/grafana-app-sdk diff --git a/apps/dashboard/kinds/v2alpha1/dashboard_spec.cue b/apps/dashboard/kinds/v2alpha1/dashboard_spec.cue index 180cc985669..ccce02984c8 100644 --- a/apps/dashboard/kinds/v2alpha1/dashboard_spec.cue +++ b/apps/dashboard/kinds/v2alpha1/dashboard_spec.cue @@ -111,8 +111,6 @@ DashboardLink: { keepTime: bool | *false } -// Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec -// This type is widely used in the codebase and changing it will have a big impact DataSourceRef: { // The plugin type-id type?: string @@ -387,7 +385,8 @@ VizConfigKind: { } AnnotationQuerySpec: { - query: DataQueryKind + datasource?: DataSourceRef + query?: DataQueryKind enable: bool hide: bool iconColor: string @@ -413,19 +412,15 @@ QueryOptionsSpec: { } DataQueryKind: { - kind: "DataQuery" - group: string - version: string | *"v0" - // New type for datasource reference - // Not creating a new type until we figure out how to handle DS refs for group by, adhoc, and every place that uses DataSourceRef in TS. - datasource?: { - name?: string - } + // The kind of a DataQueryKind is the datasource type + kind: string spec: [string]: _ } PanelQuerySpec: { query: DataQueryKind + datasource?: DataSourceRef + refId: string hidden: bool } @@ -728,6 +723,7 @@ QueryVariableSpec: { refresh: VariableRefresh skipUrlSync: bool | *false description?: string + datasource?: DataSourceRef query: DataQueryKind regex: string | *"" sort: VariableSort diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec.cue b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec.cue index 50306a06aa0..98fc8804de6 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec.cue +++ b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec.cue @@ -115,8 +115,6 @@ DashboardLink: { keepTime: bool | *false } -// Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec -// This type is widely used in the codebase and changing it will have a big impact DataSourceRef: { // The plugin type-id type?: string @@ -391,7 +389,8 @@ VizConfigKind: { } AnnotationQuerySpec: { - query: DataQueryKind + datasource?: DataSourceRef + query?: DataQueryKind enable: bool hide: bool iconColor: string @@ -417,19 +416,15 @@ QueryOptionsSpec: { } DataQueryKind: { - kind: "DataQuery" - group: string - version: string | *"v0" - // New type for datasource reference - // Not creating a new type until we figure out how to handle DS refs for group by, adhoc, and every place that uses DataSourceRef in TS. - datasource?: { - name?: string - } + // The kind of a DataQueryKind is the datasource type + kind: string spec: [string]: _ } PanelQuerySpec: { query: DataQueryKind + datasource?: DataSourceRef + refId: string hidden: bool } @@ -732,6 +727,7 @@ QueryVariableSpec: { refresh: VariableRefresh skipUrlSync: bool | *false description?: string + datasource?: DataSourceRef query: DataQueryKind regex: string | *"" sort: VariableSort diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec_gen.go b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec_gen.go index 79d77c4de74..5b599cb414e 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v2alpha1/dashboard_spec_gen.go @@ -23,13 +23,14 @@ func NewDashboardAnnotationQueryKind() *DashboardAnnotationQueryKind { // +k8s:openapi-gen=true type DashboardAnnotationQuerySpec struct { - Query DashboardDataQueryKind `json:"query"` - Enable bool `json:"enable"` - Hide bool `json:"hide"` - IconColor string `json:"iconColor"` - Name string `json:"name"` - BuiltIn *bool `json:"builtIn,omitempty"` - Filter *DashboardAnnotationPanelFilter `json:"filter,omitempty"` + Datasource *DashboardDataSourceRef `json:"datasource,omitempty"` + Query *DashboardDataQueryKind `json:"query,omitempty"` + Enable bool `json:"enable"` + Hide bool `json:"hide"` + IconColor string `json:"iconColor"` + Name string `json:"name"` + BuiltIn *bool `json:"builtIn,omitempty"` + Filter *DashboardAnnotationPanelFilter `json:"filter,omitempty"` // Catch-all field for datasource-specific properties LegacyOptions map[string]interface{} `json:"legacyOptions,omitempty"` } @@ -37,28 +38,34 @@ type DashboardAnnotationQuerySpec struct { // NewDashboardAnnotationQuerySpec creates a new DashboardAnnotationQuerySpec object. func NewDashboardAnnotationQuerySpec() *DashboardAnnotationQuerySpec { return &DashboardAnnotationQuerySpec{ - Query: *NewDashboardDataQueryKind(), BuiltIn: (func(input bool) *bool { return &input })(false), } } +// +k8s:openapi-gen=true +type DashboardDataSourceRef struct { + // The plugin type-id + Type *string `json:"type,omitempty"` + // Specific datasource instance + Uid *string `json:"uid,omitempty"` +} + +// NewDashboardDataSourceRef creates a new DashboardDataSourceRef object. +func NewDashboardDataSourceRef() *DashboardDataSourceRef { + return &DashboardDataSourceRef{} +} + // +k8s:openapi-gen=true type DashboardDataQueryKind struct { - Kind string `json:"kind"` - Group string `json:"group"` - Version string `json:"version"` - // New type for datasource reference - // Not creating a new type until we figure out how to handle DS refs for group by, adhoc, and every place that uses DataSourceRef in TS. - Datasource *DashboardV2alpha1DataQueryKindDatasource `json:"datasource,omitempty"` - Spec map[string]interface{} `json:"spec"` + // The kind of a DataQueryKind is the datasource type + Kind string `json:"kind"` + Spec map[string]interface{} `json:"spec"` } // NewDashboardDataQueryKind creates a new DashboardDataQueryKind object. func NewDashboardDataQueryKind() *DashboardDataQueryKind { return &DashboardDataQueryKind{ - Kind: "DataQuery", - Version: "v0", - Spec: map[string]interface{}{}, + Spec: map[string]interface{}{}, } } @@ -192,9 +199,10 @@ func NewDashboardPanelQueryKind() *DashboardPanelQueryKind { // +k8s:openapi-gen=true type DashboardPanelQuerySpec struct { - Query DashboardDataQueryKind `json:"query"` - RefId string `json:"refId"` - Hidden bool `json:"hidden"` + Query DashboardDataQueryKind `json:"query"` + Datasource *DashboardDataSourceRef `json:"datasource,omitempty"` + RefId string `json:"refId"` + Hidden bool `json:"hidden"` } // NewDashboardPanelQuerySpec creates a new DashboardPanelQuerySpec object. @@ -755,9 +763,7 @@ type DashboardRepeatOptions struct { // NewDashboardRepeatOptions creates a new DashboardRepeatOptions object. func NewDashboardRepeatOptions() *DashboardRepeatOptions { - return &DashboardRepeatOptions{ - Mode: DashboardRepeatMode, - } + return &DashboardRepeatOptions{} } // other repeat modes will be added in the future: label, frame @@ -932,9 +938,7 @@ type DashboardRowRepeatOptions struct { // NewDashboardRowRepeatOptions creates a new DashboardRowRepeatOptions object. func NewDashboardRowRepeatOptions() *DashboardRowRepeatOptions { - return &DashboardRowRepeatOptions{ - Mode: DashboardRepeatMode, - } + return &DashboardRowRepeatOptions{} } // +k8s:openapi-gen=true @@ -1007,9 +1011,7 @@ type DashboardAutoGridRepeatOptions struct { // NewDashboardAutoGridRepeatOptions creates a new DashboardAutoGridRepeatOptions object. func NewDashboardAutoGridRepeatOptions() *DashboardAutoGridRepeatOptions { - return &DashboardAutoGridRepeatOptions{ - Mode: DashboardRepeatMode, - } + return &DashboardAutoGridRepeatOptions{} } // +k8s:openapi-gen=true @@ -1075,9 +1077,7 @@ type DashboardTabRepeatOptions struct { // NewDashboardTabRepeatOptions creates a new DashboardTabRepeatOptions object. func NewDashboardTabRepeatOptions() *DashboardTabRepeatOptions { - return &DashboardTabRepeatOptions{ - Mode: DashboardRepeatMode, - } + return &DashboardTabRepeatOptions{} } // Links with references to other dashboards or external resources @@ -1221,6 +1221,7 @@ type DashboardQueryVariableSpec struct { Refresh DashboardVariableRefresh `json:"refresh"` SkipUrlSync bool `json:"skipUrlSync"` Description *string `json:"description,omitempty"` + Datasource *DashboardDataSourceRef `json:"datasource,omitempty"` Query DashboardDataQueryKind `json:"query"` Regex string `json:"regex"` Sort DashboardVariableSort `json:"sort"` @@ -1626,21 +1627,6 @@ func NewDashboardGroupByVariableSpec() *DashboardGroupByVariableSpec { } } -// Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec -// This type is widely used in the codebase and changing it will have a big impact -// +k8s:openapi-gen=true -type DashboardDataSourceRef struct { - // The plugin type-id - Type *string `json:"type,omitempty"` - // Specific datasource instance - Uid *string `json:"uid,omitempty"` -} - -// NewDashboardDataSourceRef creates a new DashboardDataSourceRef object. -func NewDashboardDataSourceRef() *DashboardDataSourceRef { - return &DashboardDataSourceRef{} -} - // Adhoc variable kind // +k8s:openapi-gen=true type DashboardAdhocVariableKind struct { @@ -1701,9 +1687,7 @@ type DashboardAdHocFilterWithLabels struct { // NewDashboardAdHocFilterWithLabels creates a new DashboardAdHocFilterWithLabels object. func NewDashboardAdHocFilterWithLabels() *DashboardAdHocFilterWithLabels { - return &DashboardAdHocFilterWithLabels{ - Origin: DashboardFilterOrigin, - } + return &DashboardAdHocFilterWithLabels{} } // Determine the origin of the adhoc variable filter @@ -1774,16 +1758,6 @@ func NewDashboardSpec() *DashboardSpec { } } -// +k8s:openapi-gen=true -type DashboardV2alpha1DataQueryKindDatasource struct { - Name *string `json:"name,omitempty"` -} - -// NewDashboardV2alpha1DataQueryKindDatasource creates a new DashboardV2alpha1DataQueryKindDatasource object. -func NewDashboardV2alpha1DataQueryKindDatasource() *DashboardV2alpha1DataQueryKindDatasource { - return &DashboardV2alpha1DataQueryKindDatasource{} -} - // +k8s:openapi-gen=true type DashboardV2alpha1FieldConfigSourceOverrides struct { Matcher DashboardMatcherConfig `json:"matcher"` diff --git a/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi.go b/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi.go index 4e55caae3c6..85b5a6f65cb 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi.go +++ b/apps/dashboard/pkg/apis/dashboard/v2alpha1/zz_generated.openapi.go @@ -109,7 +109,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardTimeRangeOption": schema_pkg_apis_dashboard_v2alpha1_DashboardTimeRangeOption(ref), "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardTimeSettingsSpec": schema_pkg_apis_dashboard_v2alpha1_DashboardTimeSettingsSpec(ref), "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardTransformationKind": schema_pkg_apis_dashboard_v2alpha1_DashboardTransformationKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1DataQueryKindDatasource": schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1DataQueryKindDatasource(ref), "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1FieldConfigSourceOverrides": schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1FieldConfigSourceOverrides(ref), "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1RangeMapOptions": schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1RangeMapOptions(ref), "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1RegexMapOptions": schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1RegexMapOptions(ref), @@ -596,10 +595,14 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardAnnotationQuerySpec(ref common. SchemaProps: spec.SchemaProps{ Type: []string{"object"}, Properties: map[string]spec.Schema{ + "datasource": { + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"), + }, + }, "query": { SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind"), + Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind"), }, }, "enable": { @@ -657,11 +660,11 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardAnnotationQuerySpec(ref common. }, }, }, - Required: []string{"query", "enable", "hide", "iconColor", "name"}, + Required: []string{"enable", "hide", "iconColor", "name"}, }, }, Dependencies: []string{ - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardAnnotationPanelFilter", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind"}, + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardAnnotationPanelFilter", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"}, } } @@ -1502,29 +1505,10 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardDataQueryKind(ref common.Refere Properties: map[string]spec.Schema{ "kind": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "group": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "version": { - SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", - }, - }, - "datasource": { - SchemaProps: spec.SchemaProps{ - Description: "New type for datasource reference Not creating a new type until we figure out how to handle DS refs for group by, adhoc, and every place that uses DataSourceRef in TS.", - Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1DataQueryKindDatasource"), + Description: "The kind of a DataQueryKind is the datasource type", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "spec": { @@ -1542,11 +1526,9 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardDataQueryKind(ref common.Refere }, }, }, - Required: []string{"kind", "group", "version", "spec"}, + Required: []string{"kind", "spec"}, }, }, - Dependencies: []string{ - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardV2alpha1DataQueryKindDatasource"}, } } @@ -1554,8 +1536,7 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardDataSourceRef(ref common.Refere return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec This type is widely used in the codebase and changing it will have a big impact", - Type: []string{"object"}, + Type: []string{"object"}, Properties: map[string]spec.Schema{ "type": { SchemaProps: spec.SchemaProps{ @@ -2909,6 +2890,11 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardPanelQuerySpec(ref common.Refer Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind"), }, }, + "datasource": { + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"), + }, + }, "refId": { SchemaProps: spec.SchemaProps{ Default: "", @@ -2928,7 +2914,7 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardPanelQuerySpec(ref common.Refer }, }, Dependencies: []string{ - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind"}, + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"}, } } @@ -3264,6 +3250,11 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardQueryVariableSpec(ref common.Re Format: "", }, }, + "datasource": { + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef"), + }, + }, "query": { SchemaProps: spec.SchemaProps{ Default: map[string]interface{}{}, @@ -3341,7 +3332,7 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardQueryVariableSpec(ref common.Re }, }, Dependencies: []string{ - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardVariableOption"}, + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardDataSourceRef", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1.DashboardVariableOption"}, } } @@ -4329,24 +4320,6 @@ func schema_pkg_apis_dashboard_v2alpha1_DashboardTransformationKind(ref common.R } } -func schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1DataQueryKindDatasource(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "name": { - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", - }, - }, - }, - }, - }, - } -} - func schema_pkg_apis_dashboard_v2alpha1_DashboardV2alpha1FieldConfigSourceOverrides(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/apps/iam/pkg/apis/iam_manifest.go b/apps/iam/pkg/apis/iam_manifest.go index 667b7a10354..8f144c3cd27 100644 --- a/apps/iam/pkg/apis/iam_manifest.go +++ b/apps/iam/pkg/apis/iam_manifest.go @@ -14,6 +14,8 @@ import ( v0alpha1 "github.com/grafana/grafana/apps/iam/pkg/apis/iam/v0alpha1" ) +var () + var appManifestData = app.ManifestData{ AppName: "iam", Group: "iam.grafana.app", diff --git a/conf/provisioning/sample/dashboard-v2.json b/conf/provisioning/sample/dashboard-v2.json index 73592fd09f6..ad4671943c3 100644 --- a/conf/provisioning/sample/dashboard-v2.json +++ b/conf/provisioning/sample/dashboard-v2.json @@ -10,44 +10,14 @@ "kind": "AnnotationQuery", "spec": { "builtIn": true, - "enable": true, - "filter": { - "exclude": false, - "ids": [1] + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" }, + "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations \u0026 Alerts", - "query": { - "group": "grafana", - "kind": "DataQuery", - "spec": {}, - "version": "v0" - } - } - }, - { - "kind": "AnnotationQuery", - "spec": { - "query": { - "kind": "DataQuery", - "group": "grafana-testdata-datasource", - "version": "v0", - "spec": { - "lines": 10, - "refId": "Anno", - "scenarioId": "annotations" - } - }, - "enable": true, - "hide": false, - "iconColor": "red", - "name": "Test data annotations", - "builtIn": false, - "filter": { - "exclude": false, - "ids": [1] - } + "name": "Annotations \u0026 Alerts" } } ], @@ -67,16 +37,8 @@ "spec": { "hidden": false, "query": { - "datasource": { - "name": "gdev-testdata" - }, - "group": "grafana-testdata-datasource", - "kind": "DataQuery", - "spec": { - "scenarioId": "random_walk", - "seriesCount": 3 - }, - "version": "v0" + "kind": "grafana-testdata-datasource", + "spec": {} }, "refId": "A" } @@ -89,7 +51,7 @@ "description": "", "id": 1, "links": [], - "title": "Simple timeseries (WITH DS REF)", + "title": "Simle timeseries", "vizConfig": { "kind": "timeseries", "spec": { @@ -131,12 +93,12 @@ "mode": "off" } }, + "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { - "color": "green", - "value": 0 + "color": "green" }, { "color": "red", @@ -160,7 +122,7 @@ "sort": "none" } }, - "pluginVersion": "12.1.0-pre" + "pluginVersion": "12.0.0-pre" } } } @@ -177,13 +139,8 @@ "spec": { "hidden": false, "query": { - "group": "grafana-testdata-datasource", - "kind": "DataQuery", - "spec": { - "scenarioId": "random_walk", - "seriesCount": 4 - }, - "version": "v0" + "kind": "grafana-testdata-datasource", + "spec": {} }, "refId": "A" } @@ -196,7 +153,7 @@ "description": "", "id": 2, "links": [], - "title": "Simple stat (NO DS REF)", + "title": "Simple stat", "vizConfig": { "kind": "stat", "spec": { @@ -205,12 +162,12 @@ "color": { "mode": "thresholds" }, + "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { - "color": "green", - "value": 0 + "color": "green" }, { "color": "red", @@ -236,496 +193,7 @@ "textMode": "auto", "wideLayout": true }, - "pluginVersion": "12.1.0-pre" - } - } - } - }, - "panel-3": { - "kind": "Panel", - "spec": { - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "hidden": false, - "query": { - "group": "prometheus", - "kind": "DataQuery", - "spec": { - "disableTextWrap": false, - "editorMode": "builder", - "expr": "rate(counters_requests[$__rate_interval])", - "fullMetaSearch": false, - "includeNullMetadata": false, - "instant": false, - "legendFormat": "__auto", - "range": true, - "useBackend": false - }, - "version": "v0" - }, - "refId": "A" - } - } - ], - "queryOptions": {}, - "transformations": [] - } - }, - "description": "", - "id": 3, - "links": [], - "title": "Panel with NO REF to gdev-prometheus", - "vizConfig": { - "kind": "timeseries", - "spec": { - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": 0 - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.1.0-pre" - } - } - } - }, - "panel-4": { - "kind": "Panel", - "spec": { - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "hidden": false, - "query": { - "datasource": { - "name": "gdev-prometheus" - }, - "group": "prometheus", - "kind": "DataQuery", - "spec": { - "disableTextWrap": false, - "editorMode": "builder", - "expr": "rate(counters_requests[$__rate_interval])", - "fullMetaSearch": false, - "includeNullMetadata": false, - "instant": false, - "legendFormat": "__auto", - "range": true, - "useBackend": false - }, - "version": "v0" - }, - "refId": "A" - } - } - ], - "queryOptions": {}, - "transformations": [] - } - }, - "description": "", - "id": 4, - "links": [], - "title": "Panel with ref to gdev-prometheus", - "vizConfig": { - "kind": "timeseries", - "spec": { - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": 0 - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.1.0-pre" - } - } - } - }, - "panel-5": { - "kind": "Panel", - "spec": { - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "hidden": false, - "query": { - "datasource": { - "name": "gdev-prometheus" - }, - "group": "prometheus", - "kind": "DataQuery", - "spec": { - "disableTextWrap": false, - "editorMode": "builder", - "expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])", - "fullMetaSearch": false, - "includeNullMetadata": false, - "legendFormat": "__auto", - "range": true, - "useBackend": false - }, - "version": "v0" - }, - "refId": "A" - } - }, - { - "kind": "PanelQuery", - "spec": { - "hidden": false, - "query": { - "datasource": { - "name": "gdev-testdata" - }, - "group": "grafana-testdata-datasource", - "kind": "DataQuery", - "spec": {}, - "version": "v0" - }, - "refId": "B" - } - } - ], - "queryOptions": {}, - "transformations": [] - } - }, - "description": "", - "id": 5, - "links": [], - "title": "Mixed DS WITH REFS", - "vizConfig": { - "kind": "timeseries", - "spec": { - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": 0 - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.1.0-pre" - } - } - } - }, - "panel-6": { - "kind": "Panel", - "spec": { - "data": { - "kind": "QueryGroup", - "spec": { - "queries": [ - { - "kind": "PanelQuery", - "spec": { - "hidden": false, - "query": { - "group": "prometheus", - "kind": "DataQuery", - "spec": { - "disableTextWrap": false, - "editorMode": "builder", - "expr": "rate(counters_requests{server=\"backend-01\"}[$__rate_interval])", - "fullMetaSearch": false, - "includeNullMetadata": false, - "legendFormat": "__auto", - "range": true, - "useBackend": false - }, - "version": "v0" - }, - "refId": "A" - } - }, - { - "kind": "PanelQuery", - "spec": { - "hidden": false, - "query": { - "group": "grafana-testdata-datasource", - "kind": "DataQuery", - "spec": {}, - "version": "v0" - }, - "refId": "B" - } - } - ], - "queryOptions": {}, - "transformations": [] - } - }, - "description": "", - "id": 6, - "links": [], - "title": "Mixed DS WITHOUT REFS", - "vizConfig": { - "kind": "timeseries", - "spec": { - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": 0 - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "12.1.0-pre" + "pluginVersion": "12.0.0-pre" } } } @@ -736,24 +204,6 @@ "spec": { "columnWidthMode": "standard", "items": [ - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-3" - } - } - }, - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-4" - } - } - }, { "kind": "AutoGridLayoutItem", "spec": { @@ -771,24 +221,6 @@ "name": "panel-1" } } - }, - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-5" - } - } - }, - { - "kind": "AutoGridLayoutItem", - "spec": { - "element": { - "kind": "ElementReference", - "name": "panel-6" - } - } } ], "maxColumnCount": 3, @@ -803,7 +235,7 @@ "autoRefresh": "", "autoRefreshIntervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"], "fiscalYearStartMonth": 0, - "from": "now-5m", + "from": "now-6h", "hideTimepicker": false, "timezone": "browser", "to": "now" diff --git a/e2e/dashboards/TestV2Dashboard.json b/e2e/dashboards/TestV2Dashboard.json index 13e86f6c66a..da89762c3a6 100644 --- a/e2e/dashboards/TestV2Dashboard.json +++ b/e2e/dashboards/TestV2Dashboard.json @@ -2,11 +2,21 @@ "apiVersion": "dashboard.grafana.app/v2alpha1", "kind": "Dashboard", "metadata": { - "name": "fa400625-2a44-4add-a369-e6c972eb4bd6", + "name": "admjzp8", + "namespace": "default", + "uid": "hrbekBWXeM7nC7GtouIbcngFyuqt8Xx7KlE4AnTwV7AX", + "resourceVersion": "1", "generation": 1, - "creationTimestamp": "2025-05-27T11:40:22Z", - "labels": {}, - "annotations": {} + "creationTimestamp": "2025-05-16T09:41:56Z", + "labels": { + "grafana.app/deprecatedInternalID": "182" + }, + "annotations": { + "grafana.app/createdBy": "user:cejvsh18uudxcf", + "grafana.app/updatedBy": "user:cejvsh18uudxcf", + "grafana.app/updatedTimestamp": "2025-05-16T09:41:56Z", + "grafana.app/folder": "" + } }, "spec": { "annotations": [ @@ -14,20 +24,19 @@ "kind": "AnnotationQuery", "spec": { "builtIn": true, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "query": { - "group": "grafana", - "kind": "DataQuery", - "spec": {}, - "version": "v0" - } + "name": "Annotations & Alerts" } } ], "cursorSync": "Off", + "description": "", "editable": true, "elements": { "panel-1": { @@ -40,12 +49,14 @@ { "kind": "PanelQuery", "spec": { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, "hidden": false, "query": { - "group": "grafana-testdata-datasource", - "kind": "DataQuery", - "spec": {}, - "version": "v0" + "kind": "grafana-testdata-datasource", + "spec": {} }, "refId": "A" } @@ -144,12 +155,14 @@ { "kind": "PanelQuery", "spec": { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, "hidden": false, "query": { - "group": "grafana-testdata-datasource", - "kind": "DataQuery", - "spec": {}, - "version": "v0" + "kind": "grafana-testdata-datasource", + "spec": {} }, "refId": "A" } @@ -248,12 +261,14 @@ { "kind": "PanelQuery", "spec": { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, "hidden": false, "query": { - "group": "grafana-testdata-datasource", - "kind": "DataQuery", - "spec": {}, - "version": "v0" + "kind": "grafana-testdata-datasource", + "spec": {} }, "refId": "A" } @@ -365,7 +380,7 @@ "spec": { "element": { "kind": "ElementReference", - "name": "panel-3" + "name": "panel-2" }, "height": 8, "width": 12, @@ -378,7 +393,7 @@ "spec": { "element": { "kind": "ElementReference", - "name": "panel-2" + "name": "panel-3" }, "height": 8, "width": 12, @@ -402,7 +417,7 @@ "timezone": "browser", "to": "now" }, - "title": "Test V2 Dashboard", + "title": "New Test V2 Dashboard", "variables": [] }, "status": {} diff --git a/e2e/utils/flows/scenes/importDashboard.ts b/e2e/utils/flows/scenes/importDashboard.ts index a916f733d06..e0b0a8ae929 100644 --- a/e2e/utils/flows/scenes/importDashboard.ts +++ b/e2e/utils/flows/scenes/importDashboard.ts @@ -17,9 +17,5 @@ export const importV2Dashboard = ({ title }: ImportDashboardConfig) => { if (title) { e2e.components.ImportDashboardForm.name().clear().type(title); } - - e2e.components.DataSourcePicker.inputV2().click(); - cy.get('div[data-testid="data-source-card"]').first().click(); - e2e.components.ImportDashboardForm.submit().click(); }; diff --git a/go.work.sum b/go.work.sum index 273fa901a4b..f371854b77f 100644 --- a/go.work.sum +++ b/go.work.sum @@ -347,6 +347,7 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV github.com/RaveNoX/go-jsoncommentstrip v1.0.0 h1:t527LHHE3HmiHrq74QMpNPZpGCIJzTx+apLkMKt4HC0= github.com/RoaringBitmap/gocroaring v0.4.0 h1:5nufXUgWpBEUNEJXw7926YAA58ZAQRpWPrQV1xCoSjc= github.com/RoaringBitmap/real-roaring-datasets v0.0.0-20190726190000-eb7c87156f76 h1:ZYlhPbqQFU+AHfgtCdHGDTtRW1a8geZyiE8c6Q+Sl1s= +github.com/RoaringBitmap/real-roaring-datasets v0.0.0-20190726190000-eb7c87156f76/go.mod h1:oM0MHmQ3nDsq609SS36p+oYbRi16+oVvU2Bw4Ipv0SE= github.com/Sereal/Sereal/Go/sereal v0.0.0-20231009093132-b9187f1a92c6 h1:5kUcJJAKWWI82Xnp/CaU0eu5hLlHkmm9acjowSkwCd0= github.com/Sereal/Sereal/Go/sereal v0.0.0-20231009093132-b9187f1a92c6/go.mod h1:JwrycNnC8+sZPDyzM3MQ86LvaGzSpfxg885KOOwFRW4= github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0= @@ -570,6 +571,7 @@ github.com/envoyproxy/go-control-plane v0.13.1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQ github.com/envoyproxy/go-control-plane/envoy v1.32.3/go.mod h1:F6hWupPfh75TBXGKA++MCT/CZHFq5r9/uwt/kQYkZfE= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= +github.com/expr-lang/expr v1.16.9/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4= github.com/expr-lang/expr v1.17.0/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= @@ -679,6 +681,8 @@ github.com/grafana/alerting v0.0.0-20250403153742-418bc7118d05 h1:hMzOzI/S0nkZt0 github.com/grafana/alerting v0.0.0-20250403153742-418bc7118d05/go.mod h1:K3YAJumchx5EEZItGv4D3pCv/Ux796hmoOibP/p/eYk= github.com/grafana/alerting v0.0.0-20250429131604-de176b4a0309 h1:H2p3XKDHnTBGkMXLCgXiqb2dFnHbQ4zPDXOwKK4Ne3Y= github.com/grafana/alerting v0.0.0-20250429131604-de176b4a0309/go.mod h1:pMfhRxL2LZ3Pm8iy7VcVsb9CLYuBtjFYbf1oxgx7yFA= +github.com/grafana/alerting v0.0.0-20250701210250-cea2d1683945 h1:3imTbxFpZSVI6IBIB9mn+Xc40lUweWjfMaBSgXR7rLs= +github.com/grafana/alerting v0.0.0-20250701210250-cea2d1683945/go.mod h1:gtR7agmxVfJOmNKV/n2ZULgOYTYNL+PDKYB5N48tQ7Q= github.com/grafana/authlib v0.0.0-20250123104008-e99947858901/go.mod h1:/gYfphsNu9v1qYWXxpv1NSvMEMSwvdf8qb8YlgwIRl8= github.com/grafana/authlib/types v0.0.0-20250120144156-d6737a7dc8f5/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM= github.com/grafana/authlib/types v0.0.0-20250120145936-5f0e28e7a87c/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM= @@ -693,6 +697,8 @@ github.com/grafana/grafana-app-sdk/logging v0.39.0 h1:3GgN5+dUZYqq74Q+GT9/ET+yo+ github.com/grafana/grafana-app-sdk/logging v0.39.0/go.mod h1:WhDENSnaGHtyVVwZGVnAR7YLvh2xlLDYR3D7E6h7XVk= github.com/grafana/grafana-aws-sdk v0.38.2 h1:TzQD0OpWsNjtldi5G5TLDlBRk8OyDf+B5ujcoAu4Dp0= github.com/grafana/grafana-aws-sdk v0.38.2/go.mod h1:j3vi+cXYHEFqjhBGrI6/lw1TNM+dl0Y3f0cSnDOPy+s= +github.com/grafana/grafana-aws-sdk v1.0.2 h1:98eBuHYFmgvH0xO9kKf4RBsEsgQRp8EOA/9yhDIpkss= +github.com/grafana/grafana-aws-sdk v1.0.2/go.mod h1:hO7q7yWV+t6dmiyJjMa3IbuYnYkBua+G/IAlOPVIYKE= github.com/grafana/grafana-plugin-sdk-go v0.263.0/go.mod h1:U43Cnrj/9DNYyvFcNdeUWNjMXTKNB0jcTcQGpWKd2gw= github.com/grafana/grafana-plugin-sdk-go v0.267.0/go.mod h1:OuwS4c/JYgn0rr/w5zhJBpLo4gKm/vw15RsfpYAvK9Q= github.com/grafana/grafana-plugin-sdk-go v0.269.1/go.mod h1:yv2KbO4mlr9WuDK2f+2gHAMTwwLmLuqaEnrPXTRU+OI= @@ -1270,6 +1276,7 @@ golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhp golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs= golang.org/x/mod v0.6.0-dev.0.20220818022119-ed83ed61efb9/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -1297,6 +1304,7 @@ golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc= gonum.org/v1/plot v0.15.2 h1:Tlfh/jBk2tqjLZ4/P8ZIwGrLEWQSPDLRm/SNWKNXiGI= gonum.org/v1/plot v0.15.2/go.mod h1:DX+x+DWso3LTha+AdkJEv5Txvi+Tql3KAGkehP0/Ubg= @@ -1382,6 +1390,7 @@ k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7 h1:2OX19X59HxDprNCVrWi6jb7LW1 k8s.io/gengo/v2 v2.0.0-20250207200755-1244d31929d7/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/kms v0.33.2/go.mod h1:C1I8mjFFBNzfUZXYt9FZVJ8MJl7ynFbGgZFbBzkBJ3E= lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= modernc.org/cc/v3 v3.36.3 h1:uISP3F66UlixxWEcKuIWERa4TwrZENHSL8tWxZz8bHg= modernc.org/ccgo/v3 v3.16.9 h1:AXquSwg7GuMk11pIdw7fmO1Y/ybgazVkMhsZWCV0mHM= diff --git a/packages/grafana-schema/src/schema/dashboard/v2_examples.ts b/packages/grafana-schema/src/schema/dashboard/v2_examples.ts index 7944cfae117..4bf078783cb 100644 --- a/packages/grafana-schema/src/schema/dashboard/v2_examples.ts +++ b/packages/grafana-schema/src/schema/dashboard/v2_examples.ts @@ -1,4 +1,4 @@ -import { defaultDataQueryKind, Spec } from './v2alpha1/types.spec.gen'; +import { Spec } from './v2alpha1/types.spec.gen'; export const handyTestingSchema: Spec = { title: 'Default Dashboard', @@ -37,16 +37,15 @@ export const handyTestingSchema: Spec = { spec: { builtIn: false, query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'prometheus', - datasource: { - name: 'uid', - }, + kind: 'prometheus', spec: { expr: 'test-query', }, }, + datasource: { + type: 'prometheus', + uid: 'uid', + }, filter: { ids: [1] }, enable: true, hide: false, @@ -58,16 +57,15 @@ export const handyTestingSchema: Spec = { kind: 'AnnotationQuery', spec: { builtIn: false, + datasource: { + type: 'grafana-testdata-datasource', + uid: 'uid', + }, enable: true, iconColor: 'red', name: 'Enabled', query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'grafana-testdata-datasource', - datasource: { - name: 'uid', - }, + kind: 'grafana-testdata-datasource', spec: { lines: 4, refId: 'Anno', @@ -81,16 +79,15 @@ export const handyTestingSchema: Spec = { kind: 'AnnotationQuery', spec: { builtIn: false, + datasource: { + type: 'grafana-testdata-datasource', + uid: 'uid', + }, enable: false, iconColor: 'yellow', name: 'Disabled', query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'grafana-testdata-datasource', - datasource: { - name: 'uid', - }, + kind: 'grafana-testdata-datasource', spec: { lines: 5, refId: 'Anno', scenarioId: 'annotations' }, }, hide: false, @@ -100,17 +97,16 @@ export const handyTestingSchema: Spec = { kind: 'AnnotationQuery', spec: { builtIn: false, + datasource: { + type: 'grafana-testdata-datasource', + uid: 'uid', + }, enable: true, hide: true, iconColor: 'dark-purple', name: 'Hidden', query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'grafana-testdata-datasource', - datasource: { - name: 'uid', - }, + kind: 'grafana-testdata-datasource', spec: { lines: 6, refId: 'Anno', @@ -132,13 +128,12 @@ export const handyTestingSchema: Spec = { kind: 'PanelQuery', spec: { refId: 'A', + datasource: { + type: 'prometheus', + uid: 'datasource1', + }, query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'prometheus', - datasource: { - name: 'datasource1', - }, + kind: 'prometheus', spec: { expr: 'test-query', }, @@ -270,6 +265,10 @@ export const handyTestingSchema: Spec = { text: 'text1', value: 'value1', }, + datasource: { + type: 'prometheus', + uid: 'datasource1', + }, definition: 'definition1', description: 'A query variable', hide: 'dontHide', @@ -279,12 +278,7 @@ export const handyTestingSchema: Spec = { name: 'queryVar', options: [], query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'prometheus', - datasource: { - name: 'datasource1', - }, + kind: 'prometheus', spec: { expr: 'test-query', refId: 'A', diff --git a/packages/grafana-schema/src/schema/dashboard/v2alpha1/types.spec.gen.ts b/packages/grafana-schema/src/schema/dashboard/v2alpha1/types.spec.gen.ts index 0075a197ffa..34ee46e0cff 100644 --- a/packages/grafana-schema/src/schema/dashboard/v2alpha1/types.spec.gen.ts +++ b/packages/grafana-schema/src/schema/dashboard/v2alpha1/types.spec.gen.ts @@ -11,7 +11,8 @@ export const defaultAnnotationQueryKind = (): AnnotationQueryKind => ({ }); export interface AnnotationQuerySpec { - query: DataQueryKind; + datasource?: DataSourceRef; + query?: DataQueryKind; enable: boolean; hide: boolean; iconColor: string; @@ -23,7 +24,6 @@ export interface AnnotationQuerySpec { } export const defaultAnnotationQuerySpec = (): AnnotationQuerySpec => ({ - query: defaultDataQueryKind(), enable: false, hide: false, iconColor: "", @@ -31,22 +31,24 @@ export const defaultAnnotationQuerySpec = (): AnnotationQuerySpec => ({ builtIn: false, }); +export interface DataSourceRef { + // The plugin type-id + type?: string; + // Specific datasource instance + uid?: string; +} + +export const defaultDataSourceRef = (): DataSourceRef => ({ +}); + export interface DataQueryKind { - kind: "DataQuery"; - group: string; - version: string; - // New type for datasource reference - // Not creating a new type until we figure out how to handle DS refs for group by, adhoc, and every place that uses DataSourceRef in TS. - datasource?: { - name?: string; - }; + // The kind of a DataQueryKind is the datasource type + kind: string; spec: Record; } export const defaultDataQueryKind = (): DataQueryKind => ({ - kind: "DataQuery", - group: "", - version: "v0", + kind: "", spec: {}, }); @@ -149,6 +151,7 @@ export const defaultPanelQueryKind = (): PanelQueryKind => ({ export interface PanelQuerySpec { query: DataQueryKind; + datasource?: DataSourceRef; refId: string; hidden: boolean; } @@ -991,6 +994,7 @@ export interface QueryVariableSpec { refresh: VariableRefresh; skipUrlSync: boolean; description?: string; + datasource?: DataSourceRef; query: DataQueryKind; regex: string; sort: VariableSort; @@ -1279,18 +1283,6 @@ export const defaultGroupByVariableSpec = (): GroupByVariableSpec => ({ skipUrlSync: false, }); -// Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec -// This type is widely used in the codebase and changing it will have a big impact -export interface DataSourceRef { - // The plugin type-id - type?: string; - // Specific datasource instance - uid?: string; -} - -export const defaultDataSourceRef = (): DataSourceRef => ({ -}); - // Adhoc variable kind export interface AdhocVariableKind { kind: "AdhocVariable"; diff --git a/pkg/tests/apis/openapi_snapshots/dashboard.grafana.app-v2alpha1.json b/pkg/tests/apis/openapi_snapshots/dashboard.grafana.app-v2alpha1.json index a5262d3e078..2f4dafbaa16 100644 --- a/pkg/tests/apis/openapi_snapshots/dashboard.grafana.app-v2alpha1.json +++ b/pkg/tests/apis/openapi_snapshots/dashboard.grafana.app-v2alpha1.json @@ -1250,7 +1250,6 @@ "com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardAnnotationQuerySpec": { "type": "object", "required": [ - "query", "enable", "hide", "iconColor", @@ -1260,6 +1259,9 @@ "builtIn": { "type": "boolean" }, + "datasource": { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardDataSourceRef" + }, "enable": { "type": "boolean", "default": false @@ -1287,12 +1289,7 @@ "default": "" }, "query": { - "default": {}, - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardDataQueryKind" - } - ] + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardDataQueryKind" } } }, @@ -1868,24 +1865,11 @@ "type": "object", "required": [ "kind", - "group", - "version", "spec" ], "properties": { - "datasource": { - "description": "New type for datasource reference Not creating a new type until we figure out how to handle DS refs for group by, adhoc, and every place that uses DataSourceRef in TS.", - "allOf": [ - { - "$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardV2alpha1DataQueryKindDatasource" - } - ] - }, - "group": { - "type": "string", - "default": "" - }, "kind": { + "description": "The kind of a DataQueryKind is the datasource type", "type": "string", "default": "" }, @@ -1894,15 +1878,10 @@ "additionalProperties": { "type": "object" } - }, - "version": { - "type": "string", - "default": "" } } }, "com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardDataSourceRef": { - "description": "Keeping this for backwards compatibility for GroupByVariableSpec and AdhocVariableSpec This type is widely used in the codebase and changing it will have a big impact", "type": "object", "properties": { "type": { @@ -2764,6 +2743,9 @@ "hidden" ], "properties": { + "datasource": { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardDataSourceRef" + }, "hidden": { "type": "boolean", "default": false @@ -3011,6 +2993,9 @@ } ] }, + "datasource": { + "$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardDataSourceRef" + }, "definition": { "type": "string" }, @@ -3740,14 +3725,6 @@ } } }, - "com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardV2alpha1DataQueryKindDatasource": { - "type": "object", - "properties": { - "name": { - "type": "string" - } - } - }, "com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardV2alpha1FieldConfigSourceOverrides": { "type": "object", "required": [ diff --git a/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.test.ts b/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.test.ts index 1b971c981ee..c6a484837c9 100644 --- a/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.test.ts +++ b/public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.test.ts @@ -37,39 +37,6 @@ jest.mock('@grafana/runtime', () => { ...original.config.featureToggles, dashboardNewLayouts: false, // Default value }, - - bootData: { - ...original.config.bootData, - settings: { - ...original.config.bootData.settings, - datasources: { - 'gdev-testdata': { - id: 7, - uid: 'abc', - type: 'grafana-testdata-datasource', - name: 'gdev-testdata', - meta: { - id: 'grafana-testdata-datasource', - type: 'datasource', - name: 'TestData', - aliasIDs: ['testdata'], - }, - }, - '-- Grafana --': { - id: -1, - uid: 'grafana', - type: 'datasource', - name: '-- Grafana --', - meta: { - id: 'grafana', - type: 'datasource', - name: '-- Grafana --', - }, - }, - }, - defaultDatasource: 'gdev-testdata', - }, - }, }, }; }); @@ -1621,11 +1588,9 @@ const v2ProvisionedDashboardResource = { kind: 'AnnotationQuery', spec: { builtIn: true, - query: { - kind: 'DataQuery', - group: 'grafana', - spec: {}, - version: 'v0', + datasource: { + type: 'grafana', + uid: '-- Grafana --', }, enable: true, hide: true, @@ -1648,14 +1613,13 @@ const v2ProvisionedDashboardResource = { { kind: 'PanelQuery', spec: { + datasource: { + type: 'grafana-testdata-datasource', + uid: 'PD8C576611E62080A', + }, hidden: false, query: { - kind: 'DataQuery', - group: 'grafana-testdata-datasource', - version: 'v0', - datasource: { - name: 'PD8C576611E62080A', - }, + kind: 'grafana-testdata-datasource', spec: { scenarioId: 'random_walk', seriesCount: 2, diff --git a/public/app/features/dashboard-scene/scene/export/exporters.test.ts b/public/app/features/dashboard-scene/scene/export/exporters.test.ts index 90b71e9c044..9f9028e2c41 100644 --- a/public/app/features/dashboard-scene/scene/export/exporters.test.ts +++ b/public/app/features/dashboard-scene/scene/export/exporters.test.ts @@ -549,12 +549,13 @@ describe('dashboard exporter v2', () => { { kind: 'PanelQuery', spec: { + datasource: { + type: 'prometheus', + uid: '${datasourceVar}', + }, hidden: false, query: { - datasource: { - name: '${datasourceVar}', - }, - group: 'prometheus', + kind: 'prometheus', spec: { editorMode: 'builder', expr: 'go_goroutines{job="prometheus"}', @@ -582,7 +583,7 @@ describe('dashboard exporter v2', () => { it('should replace datasource in a query variable', async () => { const { dashboard } = await setup(); const variable = dashboard.variables[0] as QueryVariableKind; - expect(variable.spec.query.datasource?.name).toBeUndefined(); + expect(variable.spec.datasource?.uid).toBeUndefined(); }); it('do not expose datasource name and id in datasource variable', async () => { @@ -596,7 +597,7 @@ describe('dashboard exporter v2', () => { const { dashboard } = await setup(); const annotationQuery = dashboard.annotations[0]; - expect(annotationQuery.spec.query?.datasource?.name).toBeUndefined(); + expect(annotationQuery.spec.datasource?.uid).toBeUndefined(); }); it('should remove library panels from layout', async () => { @@ -615,8 +616,11 @@ describe('dashboard exporter v2', () => { if (panel.kind !== 'Panel') { throw new Error('Panel should be a Panel'); } - expect(panel.spec.data.spec.queries[0].spec.query.datasource?.name).toBe('${datasourceVar}'); - expect(panel.spec.data.spec.queries[0].spec.query.group).toBe('prometheus'); + + expect(panel.spec.data.spec.queries[0].spec.datasource).toEqual({ + type: 'prometheus', + uid: '${datasourceVar}', + }); }); }); diff --git a/public/app/features/dashboard-scene/scene/export/exporters.ts b/public/app/features/dashboard-scene/scene/export/exporters.ts index 7dfc76eea96..4ef9f5a4cbd 100644 --- a/public/app/features/dashboard-scene/scene/export/exporters.ts +++ b/public/app/features/dashboard-scene/scene/export/exporters.ts @@ -344,8 +344,7 @@ export async function makeExportableV2(dashboard: DashboardV2Spec) { const removeDataSourceRefs = ( obj: AnnotationQueryKind['spec'] | QueryVariableKind['spec'] | PanelQueryKind['spec'] ) => { - const datasourceUid = obj.query?.datasource?.name; - + const datasourceUid = obj.datasource?.uid; if (datasourceUid?.startsWith('${') && datasourceUid?.endsWith('}')) { const varName = datasourceUid.slice(2, -1); // if there's a match we don't want to remove the datasource ref @@ -355,7 +354,7 @@ export async function makeExportableV2(dashboard: DashboardV2Spec) { } } - obj.query && (obj.query.datasource = undefined); + obj.datasource = undefined; }; const processPanel = (panel: PanelKind) => { diff --git a/public/app/features/dashboard-scene/serialization/DashboardSceneSerializer.test.ts b/public/app/features/dashboard-scene/serialization/DashboardSceneSerializer.test.ts index ab99200417d..0e39748c270 100644 --- a/public/app/features/dashboard-scene/serialization/DashboardSceneSerializer.test.ts +++ b/public/app/features/dashboard-scene/serialization/DashboardSceneSerializer.test.ts @@ -10,7 +10,6 @@ import { Dashboard, VariableModel } from '@grafana/schema'; import { Spec as DashboardV2Spec, defaultSpec as defaultDashboardV2Spec, - defaultDataQueryKind, defaultPanelSpec, defaultTimeSettingsSpec, GridLayoutKind, @@ -724,14 +723,9 @@ describe('DashboardSceneSerializer', () => { spec: { builtIn: true, name: 'Annotations & Alerts', - query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'grafana', - datasource: { - name: '-- Grafana --', - }, - spec: {}, + datasource: { + uid: '-- Grafana --', + type: 'grafana', }, enable: true, hide: true, @@ -1020,7 +1014,7 @@ describe('DashboardSceneSerializer', () => { refId: 'A', hidden: false, // No datasource defined - query: { kind: 'DataQuery', version: defaultDataQueryKind().version, group: 'sql', spec: {} }, + query: { kind: 'sql', spec: {} }, }, }, { @@ -1028,15 +1022,8 @@ describe('DashboardSceneSerializer', () => { spec: { refId: 'B', hidden: false, - query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'prometheus', - datasource: { - name: 'datasource-1', - }, - spec: {}, - }, + datasource: { uid: 'datasource-1', type: 'prometheus' }, + query: { kind: 'prometheus', spec: {} }, }, }, ], @@ -1071,7 +1058,7 @@ describe('DashboardSceneSerializer', () => { refId: 'C', hidden: false, // No datasource defined - query: { kind: 'DataQuery', version: defaultDataQueryKind().version, group: 'sql', spec: {} }, + query: { kind: 'sql', spec: {} }, }, }, ], @@ -1119,7 +1106,7 @@ describe('DashboardSceneSerializer', () => { kind: 'AnnotationQuery', spec: { name: 'Annotation 1', - query: { kind: 'DataQuery', version: defaultDataQueryKind().version, group: 'prometheus', spec: {} }, + query: { kind: 'prometheus', spec: {} }, enable: true, hide: false, iconColor: 'red', diff --git a/public/app/features/dashboard-scene/serialization/DashboardSceneSerializer.ts b/public/app/features/dashboard-scene/serialization/DashboardSceneSerializer.ts index 9e73bed659e..66d73dd2ff9 100644 --- a/public/app/features/dashboard-scene/serialization/DashboardSceneSerializer.ts +++ b/public/app/features/dashboard-scene/serialization/DashboardSceneSerializer.ts @@ -288,7 +288,7 @@ export class V2DashboardSerializer const panelQueries = elementPanel.spec.data.spec.queries; for (const query of panelQueries) { - if (!query.spec.query.datasource?.name) { + if (!query.spec.datasource) { const elementId = this.getElementIdForPanel(elementPanel.spec.id); if (!this.defaultDsReferencesMap.panels.has(elementId)) { this.defaultDsReferencesMap.panels.set(elementId, new Set()); @@ -306,7 +306,7 @@ export class V2DashboardSerializer if (saveModel?.variables) { for (const variable of saveModel.variables) { // for query variables that dont have a ds defined add them to the list - if (variable.kind === 'QueryVariable' && !variable.spec.query.datasource?.name) { + if (variable.kind === 'QueryVariable' && !variable.spec.datasource) { this.defaultDsReferencesMap.variables.add(variable.spec.name); } } @@ -315,7 +315,7 @@ export class V2DashboardSerializer // initialize annotations ds references map if (saveModel?.annotations) { for (const annotation of saveModel.annotations) { - if (!annotation.spec.query?.datasource?.name) { + if (!annotation.spec.datasource) { this.defaultDsReferencesMap.annotations.add(annotation.spec.name); } } diff --git a/public/app/features/dashboard-scene/serialization/__snapshots__/transformSceneToSaveModelSchemaV2.test.ts.snap b/public/app/features/dashboard-scene/serialization/__snapshots__/transformSceneToSaveModelSchemaV2.test.ts.snap index 420a02a228a..cc3a40896c7 100644 --- a/public/app/features/dashboard-scene/serialization/__snapshots__/transformSceneToSaveModelSchemaV2.test.ts.snap +++ b/public/app/features/dashboard-scene/serialization/__snapshots__/transformSceneToSaveModelSchemaV2.test.ts.snap @@ -7,38 +7,38 @@ exports[`transformSceneToSaveModelSchemaV2 should transform scene to save model "kind": "AnnotationQuery", "spec": { "builtIn": false, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --", + }, "enable": true, "hide": false, "iconColor": "red", "name": "query1", - "query": { - "datasource": { - "name": "-- Grafana --", - }, - "group": "grafana", - "kind": "DataQuery", - "spec": {}, - "version": "v0", - }, }, }, { "kind": "AnnotationQuery", "spec": { "builtIn": false, + "datasource": { + "type": "prometheus", + "uid": "abcdef", + }, "enable": true, "hide": true, "iconColor": "blue", "name": "query2", - "query": { - "datasource": { - "name": "abcdef", - }, - "group": "prometheus", - "kind": "DataQuery", - "spec": {}, - "version": "v0", - }, + }, + }, + { + "kind": "AnnotationQuery", + "spec": { + "builtIn": false, + "enable": true, + "hide": true, + "iconColor": "green", + "name": "query3", }, }, ], @@ -152,6 +152,10 @@ exports[`transformSceneToSaveModelSchemaV2 should transform scene to save model "text": "text1", "value": "value1", }, + "datasource": { + "type": "prometheus", + "uid": "datasource1", + }, "definition": "definition1", "description": "A query variable", "hide": "hideLabel", @@ -161,16 +165,11 @@ exports[`transformSceneToSaveModelSchemaV2 should transform scene to save model "name": "queryVar", "options": [], "query": { - "datasource": { - "name": "datasource1", - }, - "group": "prometheus", - "kind": "DataQuery", + "kind": "prometheus", "spec": { "expr": "label_values(node_boot_time_seconds)", "refId": "A", }, - "version": "v0", }, "refresh": "onDashboardLoad", "regex": "regex1", diff --git a/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.test.ts b/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.test.ts index 2c71a63a03d..b5f9950b5f6 100644 --- a/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.test.ts +++ b/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.test.ts @@ -1,7 +1,4 @@ -import { - defaultDataQueryKind, - PanelQueryKind, -} from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen'; +import { PanelQueryKind } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen'; import { getRuntimePanelDataSource } from './utils'; @@ -32,12 +29,6 @@ jest.mock('@grafana/runtime', () => ({ meta: { id: 'loki' }, type: 'datasource', }, - '-- Grafana --': { - uid: 'grafana', - name: 'Grafana', - meta: { id: 'grafana' }, - type: 'datasource', - }, }, }, }, @@ -51,23 +42,22 @@ describe('getRuntimePanelDataSource', () => { spec: { refId: 'A', hidden: false, + datasource: { + uid: 'test-ds-uid', + type: 'test-ds-type', + }, query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'prometheus', - datasource: { - name: 'prometheus-uid', - }, + kind: 'prometheus', spec: {}, }, }, }; - const result = getRuntimePanelDataSource(query.spec.query); + const result = getRuntimePanelDataSource(query); expect(result).toEqual({ - uid: 'prometheus-uid', - type: 'prometheus', + uid: 'test-ds-uid', + type: 'test-ds-type', }); }); @@ -77,16 +67,15 @@ describe('getRuntimePanelDataSource', () => { spec: { refId: 'A', hidden: false, + datasource: undefined, query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'prometheus', + kind: 'prometheus', spec: {}, }, }, }; - const result = getRuntimePanelDataSource(query.spec.query); + const result = getRuntimePanelDataSource(query); expect(result).toEqual({ uid: 'default-prometheus-uid', @@ -100,16 +89,15 @@ describe('getRuntimePanelDataSource', () => { spec: { refId: 'A', hidden: false, + datasource: undefined, query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'loki', + kind: 'loki', spec: {}, }, }, }; - const result = getRuntimePanelDataSource(query.spec.query); + const result = getRuntimePanelDataSource(query); expect(result).toEqual({ uid: 'loki-uid', @@ -124,16 +112,15 @@ describe('getRuntimePanelDataSource', () => { spec: { refId: 'A', hidden: false, + datasource: undefined, query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'unknown-type', + kind: 'unknown-type', spec: {}, }, }, }; - const result = getRuntimePanelDataSource(query.spec.query); + const result = getRuntimePanelDataSource(query); expect(result).toEqual({ uid: 'default-prometheus-uid', @@ -151,19 +138,18 @@ describe('getRuntimePanelDataSource', () => { spec: { refId: 'A', hidden: false, + datasource: { + uid: '', + type: 'test-ds-type', + }, query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'prometheus', - datasource: { - name: '', - }, + kind: 'prometheus', spec: {}, }, }, }; - const result = getRuntimePanelDataSource(query.spec.query); + const result = getRuntimePanelDataSource(query); expect(result).toEqual({ uid: 'default-prometheus-uid', diff --git a/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.ts b/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.ts index 0f8e0750083..c8018a98be0 100644 --- a/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.ts +++ b/public/app/features/dashboard-scene/serialization/layoutSerializers/utils.ts @@ -19,7 +19,6 @@ import { PanelQueryKind, QueryVariableKind, TabsLayoutTabKind, - DataQueryKind, } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; @@ -186,15 +185,12 @@ function getPanelDataSource(panel: PanelKind): DataSourceRef | undefined { panel.spec.data.spec.queries.forEach((query) => { if (!datasource) { - if (!query.spec.query.datasource?.name) { - datasource = getRuntimePanelDataSource(query.spec.query); + if (!query.spec.datasource?.uid) { + datasource = getRuntimePanelDataSource(query); } else { - datasource = { - uid: query.spec.query.datasource?.name, - type: query.spec.query.group, - }; + datasource = query.spec.datasource; } - } else if (datasource.uid !== query.spec.query.datasource?.name || datasource.type !== query.spec.query.group) { + } else if (datasource.uid !== query.spec.datasource?.uid || datasource.type !== query.spec.datasource?.type) { isMixedDatasource = true; } }); @@ -203,19 +199,11 @@ function getPanelDataSource(panel: PanelKind): DataSourceRef | undefined { } export function getRuntimeVariableDataSource(variable: QueryVariableKind): DataSourceRef | undefined { - const ds: DataSourceRef = { - uid: variable.spec.query.datasource?.name, - type: variable.spec.query.group, - }; - return getDataSourceForQuery(ds, variable.spec.query.group); + return getDataSourceForQuery(variable.spec.datasource, variable.spec.query.kind); } -export function getRuntimePanelDataSource(query: DataQueryKind): DataSourceRef { - const ds: DataSourceRef = { - uid: query.datasource?.name, - type: query.group, - }; - return getDataSourceForQuery(ds, query.group); +export function getRuntimePanelDataSource(query: PanelQueryKind): DataSourceRef | undefined { + return getDataSourceForQuery(query.spec.datasource, query.spec.query.kind); } /** @@ -223,7 +211,10 @@ export function getRuntimePanelDataSource(query: DataQueryKind): DataSourceRef { * @param queryKind - The kind of query being performed * @returns The resolved DataSourceRef */ -function getDataSourceForQuery(querySpecDS: DataSourceRef | undefined | null, queryKind: string): DataSourceRef { +function getDataSourceForQuery( + querySpecDS: DataSourceRef | undefined | null, + queryKind: string +): DataSourceRef | undefined { // If datasource is specified and has a uid, use it if (querySpecDS?.uid) { return querySpecDS; @@ -262,22 +253,14 @@ function getDataSourceForQuery(querySpecDS: DataSourceRef | undefined | null, qu }; } - if (dsList && !dsList[defaultDatasource]) { - throw new Error(`Default datasource ${defaultDatasource} not found in datasource list`); - } - - // In the datasource list from bootData "id" is the type and the uid could be uid or the name - // in cases like grafana, dashboard or mixed datasource - return { - uid: dsList[defaultDatasource].uid || dsList[defaultDatasource].name, - type: dsList[defaultDatasource].meta.id, - }; + // If we don't find a default datasource, return undefined + return undefined; } function panelQueryKindToSceneQuery(query: PanelQueryKind): SceneDataQuery { return { refId: query.spec.refId, - datasource: getRuntimePanelDataSource(query.spec.query), + datasource: getRuntimePanelDataSource(query), hide: query.spec.hidden, ...query.spec.query.spec, }; diff --git a/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.test.ts b/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.test.ts index 701d992d3b1..72cc20f2943 100644 --- a/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.test.ts +++ b/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.test.ts @@ -45,8 +45,8 @@ const getDataSourceMock = jest.fn(); const fakeDsMock: DataSourceApi = { name: 'fake-std', - type: 'fake-type', - getRef: () => ({ type: 'fake-type', uid: 'fake-uid' }), + type: 'fake-std', + getRef: () => ({ type: 'fake-std', uid: 'fake-std' }), query: () => Promise.resolve({ data: [], @@ -74,7 +74,7 @@ const fakeDsMock: DataSourceApi = { toDataQuery: (q) => ({ ...q, refId: 'FakeDataSource-refId' }), }, id: 1, - uid: 'fake-uid', + uid: 'fake-std', }; jest.mock('@grafana/runtime', () => ({ @@ -95,7 +95,7 @@ describe('sceneVariablesSetToVariables', () => { description: 'test-desc', value: ['selected-value'], text: ['selected-value-text'], - datasource: { uid: 'fake-uid', type: 'fake-type' }, + datasource: { uid: 'fake-std', type: 'fake-std' }, query: 'query', includeAll: true, allowCustomValue: true, @@ -123,8 +123,8 @@ describe('sceneVariablesSetToVariables', () => { ], }, "datasource": { - "type": "fake-type", - "uid": "fake-uid", + "type": "fake-std", + "uid": "fake-std", }, "definition": undefined, "description": "test-desc", @@ -148,7 +148,7 @@ describe('sceneVariablesSetToVariables', () => { description: 'test-desc', value: ['selected-value'], text: ['selected-value-text'], - datasource: { uid: 'fake-uid', type: 'fake-type' }, + datasource: { uid: 'fake-std', type: 'fake-std' }, query: 'query', definition: 'query', includeAll: true, @@ -176,8 +176,8 @@ describe('sceneVariablesSetToVariables', () => { ], }, "datasource": { - "type": "fake-type", - "uid": "fake-uid", + "type": "fake-std", + "uid": "fake-std", }, "definition": "query", "description": "test-desc", @@ -201,7 +201,7 @@ describe('sceneVariablesSetToVariables', () => { description: 'test-desc', value: ['selected-value'], text: ['selected-value-text'], - datasource: { uid: 'fake-uid', type: 'fake-type' }, + datasource: { uid: 'fake-std', type: 'fake-std' }, query: 'query', options: [ { label: 'test', value: 'test' }, @@ -228,7 +228,7 @@ describe('sceneVariablesSetToVariables', () => { description: 'test-desc', value: ['test'], text: ['test'], - datasource: { uid: 'fake-uid', type: 'fake-type' }, + datasource: { uid: 'fake-std', type: 'fake-std' }, query: 'query', options: [ { label: 'test', value: 'test' }, @@ -499,7 +499,7 @@ describe('sceneVariablesSetToVariables', () => { allowCustomValue: true, label: 'test-label', description: 'test-desc', - datasource: { uid: 'fake-uid', type: 'fake-type' }, + datasource: { uid: 'fake-std', type: 'fake-std' }, filters: [ { key: 'filterTest', @@ -533,8 +533,8 @@ describe('sceneVariablesSetToVariables', () => { }, ], "datasource": { - "type": "fake-type", - "uid": "fake-uid", + "type": "fake-std", + "uid": "fake-std", }, "defaultKeys": undefined, "description": "test-desc", @@ -662,7 +662,7 @@ describe('sceneVariablesSetToVariables', () => { allowCustomValue: true, label: 'test-label', description: 'test-desc', - datasource: { uid: 'fake-uid', type: 'fake-type' }, + datasource: { uid: 'fake-std', type: 'fake-std' }, defaultKeys: [ { text: 'some', @@ -710,8 +710,8 @@ describe('sceneVariablesSetToVariables', () => { }, ], "datasource": { - "type": "fake-type", - "uid": "fake-uid", + "type": "fake-std", + "uid": "fake-std", }, "defaultKeys": [ { @@ -757,7 +757,7 @@ describe('sceneVariablesSetToVariables', () => { label: 'test-label', description: 'test-desc', allowCustomValue: true, - datasource: { uid: 'fake-uid', type: 'fake-type' }, + datasource: { uid: 'fake-std', type: 'fake-std' }, defaultOptions: [ { text: 'Foo', @@ -784,8 +784,8 @@ describe('sceneVariablesSetToVariables', () => { "value": [], }, "datasource": { - "type": "fake-type", - "uid": "fake-uid", + "type": "fake-std", + "uid": "fake-std", }, "defaultValue": undefined, "description": "test-desc", @@ -813,7 +813,7 @@ describe('sceneVariablesSetToVariables', () => { name: 'test', label: 'test-label', description: 'test-desc', - datasource: { uid: 'fake-uid', type: 'fake-type' }, + datasource: { uid: 'fake-std', type: 'fake-std' }, defaultOptions: [ { text: 'Foo', @@ -841,7 +841,7 @@ describe('sceneVariablesSetToVariables', () => { description: 'test-desc', value: ['selected-value'], text: ['selected-value-text'], - datasource: { uid: 'fake-uid', type: 'fake-type' }, + datasource: { uid: 'fake-std', type: 'fake-std' }, query: 'query', includeAll: true, allValue: 'test-all', @@ -856,45 +856,44 @@ describe('sceneVariablesSetToVariables', () => { expect(result).toHaveLength(1); expect(result[0]).toMatchInlineSnapshot(` - { - "kind": "QueryVariable", + { + "kind": "QueryVariable", + "spec": { + "allValue": "test-all", + "allowCustomValue": true, + "current": { + "text": [ + "selected-value-text", + ], + "value": [ + "selected-value", + ], + }, + "datasource": { + "type": "fake-std", + "uid": "fake-std", + }, + "definition": undefined, + "description": "test-desc", + "hide": "dontHide", + "includeAll": true, + "label": "test-label", + "multi": true, + "name": "test", + "options": [], + "query": { + "kind": "fake-std", "spec": { - "allValue": "test-all", - "allowCustomValue": true, - "current": { - "text": [ - "selected-value-text", - ], - "value": [ - "selected-value", - ], - }, - "definition": undefined, - "description": "test-desc", - "hide": "dontHide", - "includeAll": true, - "label": "test-label", - "multi": true, - "name": "test", - "options": [], - "query": { - "datasource": { - "name": "fake-uid", - }, - "group": "fake-type", - "kind": "DataQuery", - "spec": { - "__legacyStringValue": "query", - }, - "version": "v0", - }, - "refresh": "onDashboardLoad", - "regex": "", - "skipUrlSync": false, - "sort": "disabled", + "__legacyStringValue": "query", }, - } - `); + }, + "refresh": "onDashboardLoad", + "regex": "", + "skipUrlSync": false, + "sort": "disabled", + }, + } + `); }); it('should handle CustomVariable', () => { @@ -1153,7 +1152,7 @@ describe('sceneVariablesSetToVariables', () => { name: 'test', label: 'test-label', description: 'test-desc', - datasource: { uid: 'fake-uid', type: 'fake-type' }, + datasource: { uid: 'fake-std', type: 'fake-std' }, filters: [ { key: 'filterTest', @@ -1189,8 +1188,8 @@ describe('sceneVariablesSetToVariables', () => { }, ], "datasource": { - "type": "fake-type", - "uid": "fake-uid", + "type": "fake-std", + "uid": "fake-std", }, "defaultKeys": [], "description": "test-desc", @@ -1215,7 +1214,7 @@ describe('sceneVariablesSetToVariables', () => { name: 'test', label: 'test-label', description: 'test-desc', - datasource: { uid: 'fake-uid', type: 'fake-type' }, + datasource: { uid: 'fake-std', type: 'fake-std' }, defaultKeys: [ { text: 'some', @@ -1265,8 +1264,8 @@ describe('sceneVariablesSetToVariables', () => { }, ], "datasource": { - "type": "fake-type", - "uid": "fake-uid", + "type": "fake-std", + "uid": "fake-std", }, "defaultKeys": [ { @@ -1313,7 +1312,7 @@ describe('sceneVariablesSetToVariables', () => { name: 'test', label: 'test-label', description: 'test-desc', - datasource: { uid: 'fake-uid', type: 'fake-type' }, + datasource: { uid: 'fake-std', type: 'fake-std' }, defaultOptions: [ { text: 'Foo', @@ -1341,8 +1340,8 @@ describe('sceneVariablesSetToVariables', () => { "value": [], }, "datasource": { - "type": "fake-type", - "uid": "fake-uid", + "type": "fake-std", + "uid": "fake-std", }, "defaultValue": undefined, "description": "test-desc", @@ -1373,7 +1372,7 @@ describe('sceneVariablesSetToVariables', () => { name: 'test', label: 'test-label', description: 'test-desc', - datasource: { uid: 'fake-uid', type: 'fake-type' }, + datasource: { uid: 'fake-std', type: 'fake-std' }, defaultOptions: [ { text: 'Foo', diff --git a/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.ts b/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.ts index c2d602d6c8f..74304a2a9a6 100644 --- a/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.ts +++ b/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.ts @@ -24,7 +24,6 @@ import { GroupByVariableKind, defaultVariableHide, VariableOption, - defaultDataQueryKind, AdHocFilterWithLabels, } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen'; @@ -295,30 +294,14 @@ export function sceneVariablesSetToSchemaV2Variables( } const query = variable.state.query; let dataQuery: DataQueryKind | string; - const datasource = getElementDatasource(set, variable, 'variable', undefined, dsReferencesMapping); - if (typeof query !== 'string') { dataQuery = { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: datasource?.type ?? getDataQueryKind(query), - ...(datasource?.uid && { - datasource: { - name: datasource.uid, - }, - }), + kind: variable.state.datasource?.type ?? getDataQueryKind(query), spec: getDataQuerySpec(query), }; } else { dataQuery = { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: datasource?.type ?? getDataQueryKind(query), - ...(datasource?.uid && { - datasource: { - name: datasource.uid, - }, - }), + kind: variable.state.datasource?.type ?? getDataQueryKind(query), spec: { [LEGACY_STRING_VALUE_KEY]: query, }, @@ -332,6 +315,7 @@ export function sceneVariablesSetToSchemaV2Variables( options, query: dataQuery, definition: variable.state.definition, + datasource: getElementDatasource(set, variable, 'variable', undefined, dsReferencesMapping), sort: transformSortVariableToEnum(variable.state.sort), refresh: transformVariableRefreshToEnum(variable.state.refresh), regex: variable.state.regex, diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.test.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.test.ts index c78cbd4c480..ce31ae57d0e 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.test.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.test.ts @@ -22,7 +22,6 @@ import { CustomVariableKind, Spec as DashboardV2Spec, DatasourceVariableKind, - defaultDataQueryKind, GridLayoutItemSpec, GridLayoutSpec, GroupByVariableKind, @@ -139,7 +138,6 @@ describe('transformSaveModelSchemaV2ToScene', () => { // Variables const variables = scene.state?.$variables; expect(variables?.state.variables).toHaveLength(dash.variables.length); - validateVariable({ sceneVariable: variables?.state.variables[0], variableKind: dash.variables[0] as QueryVariableKind, @@ -208,26 +206,36 @@ describe('transformSaveModelSchemaV2ToScene', () => { // Annotations expect(scene.state.$data).toBeInstanceOf(DashboardDataLayerSet); const dataLayers = scene.state.$data as DashboardDataLayerSet; + // we should get two annotations, Grafana built-in and the custom ones expect(dataLayers.state.annotationLayers).toHaveLength(dash.annotations.length); - expect(dataLayers.state.annotationLayers[0].state.name).toBe(dash.annotations[0].spec.name); - expect(dataLayers.state.annotationLayers[0].state.isEnabled).toBe(dash.annotations[0].spec.enable); - expect(dataLayers.state.annotationLayers[0].state.isHidden).toBe(dash.annotations[0].spec.hide); + expect(dataLayers.state.annotationLayers).toHaveLength(5); + + // Built-in + const builtInAnnotation = dataLayers.state.annotationLayers[0] as unknown as DashboardAnnotationsDataLayer; + expect(builtInAnnotation.state.name).toBe('Annotations & Alerts'); + expect(builtInAnnotation.state.isEnabled).toBe(true); + expect(builtInAnnotation.state.isHidden).toBe(true); + expect(builtInAnnotation.state?.query.builtIn).toBe(1); // Enabled expect(dataLayers.state.annotationLayers[1].state.name).toBe(dash.annotations[1].spec.name); expect(dataLayers.state.annotationLayers[1].state.isEnabled).toBe(dash.annotations[1].spec.enable); expect(dataLayers.state.annotationLayers[1].state.isHidden).toBe(dash.annotations[1].spec.hide); - // Disabled expect(dataLayers.state.annotationLayers[2].state.name).toBe(dash.annotations[2].spec.name); expect(dataLayers.state.annotationLayers[2].state.isEnabled).toBe(dash.annotations[2].spec.enable); expect(dataLayers.state.annotationLayers[2].state.isHidden).toBe(dash.annotations[2].spec.hide); - // Hidden + // Disabled expect(dataLayers.state.annotationLayers[3].state.name).toBe(dash.annotations[3].spec.name); expect(dataLayers.state.annotationLayers[3].state.isEnabled).toBe(dash.annotations[3].spec.enable); expect(dataLayers.state.annotationLayers[3].state.isHidden).toBe(dash.annotations[3].spec.hide); + // Hidden + expect(dataLayers.state.annotationLayers[4].state.name).toBe(dash.annotations[4].spec.name); + expect(dataLayers.state.annotationLayers[4].state.isEnabled).toBe(dash.annotations[4].spec.enable); + expect(dataLayers.state.annotationLayers[4].state.isHidden).toBe(dash.annotations[4].spec.hide); + // VizPanel const vizPanels = (scene.state.body as DashboardLayoutManager).getVizPanels(); expect(vizPanels).toHaveLength(2); @@ -271,14 +279,13 @@ describe('transformSaveModelSchemaV2ToScene', () => { kind: 'PanelQuery', spec: { refId: 'A', + datasource: { + type: 'graphite', + uid: 'datasource1', + }, hidden: false, query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'graphite', - datasource: { - name: 'datasource1', - }, + kind: 'prometheus', spec: { expr: 'test-query', }, @@ -300,14 +307,13 @@ describe('transformSaveModelSchemaV2ToScene', () => { kind: 'PanelQuery', spec: { refId: 'A', + datasource: { + type: 'prometheus', + uid: 'datasource1', + }, hidden: false, query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'prometheus', - datasource: { - name: 'datasource1', - }, + kind: 'prometheus', spec: { expr: 'test-query', }, @@ -334,12 +340,7 @@ describe('transformSaveModelSchemaV2ToScene', () => { refId: 'A', hidden: false, query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'prometheus', - datasource: { - name: 'abc123', - }, + kind: 'prometheus', spec: { expr: 'test-query', }, @@ -721,6 +722,10 @@ describe('transformSaveModelSchemaV2ToScene', () => { enable: true, hide: false, iconColor: 'purple', + datasource: { + type: 'prometheus', + uid: 'abc123', + }, legacyOptions: { expr: 'rate(http_requests_total[5m])', queryType: 'range', @@ -728,15 +733,6 @@ describe('transformSaveModelSchemaV2ToScene', () => { useValueAsTime: true, step: '1m', }, - query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'prometheus', - datasource: { - name: 'abc123', - }, - spec: {}, - }, }, }, ], @@ -768,36 +764,14 @@ describe('transformSaveModelSchemaV2ToScene', () => { // Get the annotation layers const dataLayerSet = scene.state.$data as DashboardDataLayerSet; expect(dataLayerSet).toBeDefined(); + // it should have two annotation layers, built-in and custom expect(dataLayerSet.state.annotationLayers.length).toBe(2); - const defaultAnnotationLayer = dataLayerSet.state.annotationLayers[0] as DashboardAnnotationsDataLayer; - - // Verify that the default annotation layer has been correctly initialized - expect(defaultAnnotationLayer.state.query).toEqual({ - datasource: { - uid: '-- Grafana --', - type: 'grafana', - }, - builtIn: 1, - enable: true, - iconColor: 'rgba(0, 211, 255, 1)', - name: 'Annotations & Alerts', - filter: undefined, - hide: true, - }); const annotationLayer = dataLayerSet.state.annotationLayers[1] as DashboardAnnotationsDataLayer; // Verify that the legacyOptions have been merged into the query object expect(annotationLayer.state.query).toMatchObject({ - datasource: { - uid: 'abc123', - type: 'prometheus', - }, name: 'Annotation with legacy options', - builtIn: 0, - enable: true, - hide: false, - iconColor: 'purple', expr: 'rate(http_requests_total[5m])', queryType: 'range', legendFormat: '{{method}} {{endpoint}}', diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts index f0ed00957f2..ae132430e0c 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts @@ -1,6 +1,5 @@ import { uniqueId } from 'lodash'; -import { AnnotationQuery } from '@grafana/data'; import { config, getDataSourceSrv } from '@grafana/runtime'; import { AdHocFiltersVariable, @@ -29,7 +28,6 @@ import { defaultAdhocVariableKind, defaultConstantVariableKind, defaultCustomVariableKind, - defaultDataQueryKind, defaultDatasourceVariableKind, defaultGroupByVariableKind, defaultIntervalVariableKind, @@ -66,7 +64,7 @@ import { getIntervalsFromQueryString } from '../utils/utils'; import { SnapshotVariable } from './custom-variables/SnapshotVariable'; import { layoutDeserializerRegistry } from './layoutSerializers/layoutSerializerRegistry'; -import { getRuntimePanelDataSource, getRuntimeVariableDataSource } from './layoutSerializers/utils'; +import { getRuntimeVariableDataSource } from './layoutSerializers/utils'; import { registerPanelInteractionsReporter } from './transformSaveModelToScene'; import { transformCursorSyncV2ToV1, @@ -99,46 +97,25 @@ export function transformSaveModelSchemaV2ToScene(dto: DashboardWithAccessInfo { - let { query: dataQuery, ...annotationQuery } = annotation.spec; - - // Mapping from AnnotationQueryKind to AnnotationQuery used by scenes. - let annoQuerySpec: AnnotationQuery = { - builtIn: annotation.spec.builtIn ? 1 : 0, - enable: annotation.spec.enable, - iconColor: annotation.spec.iconColor, - name: annotation.spec.name, - filter: annotation.spec.filter, - hide: annotation.spec.hide, - ...dataQuery?.spec, - }; - + let annoQuerySpec = annotation.spec; // some annotations will contain in the legacyOptions properties that need to be // added to the root level annotation spec - if (annotationQuery.legacyOptions) { + if (annoQuerySpec?.legacyOptions) { annoQuerySpec = { ...annoQuerySpec, - ...annotationQuery.legacyOptions, - legacyOptions: { - ...annotationQuery.legacyOptions, - }, + ...annoQuerySpec.legacyOptions, }; } - - // get data source from annotation query - const datasource = getRuntimePanelDataSource(dataQuery); - - const layerState = { + return new DashboardAnnotationsDataLayer({ key: uniqueId('annotations-'), query: { ...annoQuerySpec, - datasource, + builtIn: annotation.spec.builtIn ? 1 : 0, }, name: annotation.spec.name, isEnabled: Boolean(annotation.spec.enable), isHidden: Boolean(annotation.spec.hide), - }; - - return new DashboardAnnotationsDataLayer(layerState); + }); }); const isDashboardEditable = Boolean(dashboard.editable); @@ -537,15 +514,7 @@ function getGrafanaBuiltInAnnotationDataLayer(dashboard: DashboardV2Spec) { const grafanaBuiltAnnotation: AnnotationQueryKind = { kind: 'AnnotationQuery', spec: { - query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'grafana', - datasource: { - name: '-- Grafana --', - }, - spec: {}, - }, + datasource: { uid: '-- Grafana --', type: 'grafana' }, name: 'Annotations & Alerts', iconColor: DEFAULT_ANNOTATION_COLOR, enable: true, diff --git a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.test.ts b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.test.ts index ad6137da1e5..0bc40f8d9d6 100644 --- a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.test.ts +++ b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.test.ts @@ -57,7 +57,6 @@ import { validateDashboardSchemaV2, getDataQueryKind, getAutoAssignedDSRef, - getVizPanelQueries, } from './transformSceneToSaveModelSchemaV2'; // Mock dependencies @@ -411,7 +410,9 @@ describe('transformSceneToSaveModelSchemaV2', () => { expect(result).toMatchSnapshot(); // Check that the annotation layers are correctly transformed - expect(result.annotations).toHaveLength(2); + expect(result.annotations).toHaveLength(3); + // Check annotation layer 3 without initial data source isn't updated with runtime default + expect(result.annotations?.[2].spec.datasource?.type).toBe(undefined); }); it('should transform the minimum scene to save model schema v2', () => { @@ -833,50 +834,6 @@ describe('getElementDatasource', () => { }); }); -describe('getVizPanelQueries', () => { - it('should handle panel query datasources correctly', () => { - const queryWithDS: SceneDataQuery = { - refId: 'B', - datasource: { uid: 'prometheus-uid', type: 'prometheus' }, - }; - - const queryWithoutDS: SceneDataQuery = { - refId: 'A', - }; - - // Mock query runner - const queryRunner = new SceneQueryRunner({ - queries: [queryWithoutDS, queryWithDS], - datasource: { uid: 'default-ds', type: 'default' }, - }); - // Create test elements - const vizPanel = new VizPanel({ - key: 'panel-1', - pluginId: 'timeseries', - $data: queryRunner, - }); - - // Mock dsReferencesMapping - const dsReferencesMapping = { - panels: new Map(new Set([['panel-1', new Set(['A'])]])), - variables: new Set(), - annotations: new Set(), - }; - - const result = getVizPanelQueries(vizPanel, dsReferencesMapping); - expect(result.length).toBe(2); - expect(result[0].spec.query.kind).toBe('DataQuery'); - expect(result[0].spec.query.datasource).toBeUndefined(); // ignore datasource if it wasn't provided - expect(result[0].spec.query.group).toBe('default'); - expect(result[0].spec.query.version).toBe('v0'); - - expect(result[1].spec.query.kind).toBe('DataQuery'); - expect(result[1].spec.query.datasource?.name).toBe('prometheus-uid'); - expect(result[1].spec.query.group).toBe('prometheus'); - expect(result[1].spec.query.version).toBe('v0'); - }); -}); - function getMinimalSceneState(body: DashboardLayoutManager): Partial { return { id: 1, @@ -1108,6 +1065,18 @@ function createAnnotationLayers() { isEnabled: true, isHidden: true, }), + // this could happen if a dahboard was created from code and the datasource was not defined + new DashboardAnnotationsDataLayer({ + key: 'layer3', + query: { + name: 'query3', + enable: true, + iconColor: 'green', + }, + name: 'layer3', + isEnabled: true, + isHidden: true, + }), ]; } diff --git a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts index a7682c4e559..b8a0bfd3b6e 100644 --- a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts +++ b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts @@ -43,7 +43,6 @@ import { DashboardCursorSync, FieldConfig, FieldColor, - defaultDataQueryKind, } from '../../../../../packages/grafana-schema/src/schema/dashboard/v2alpha1/types.spec.gen'; import { DashboardDataLayerSet } from '../scene/DashboardDataLayerSet'; import { DashboardScene, DashboardSceneState } from '../scene/DashboardScene'; @@ -251,7 +250,7 @@ function getPanelLinks(panel: VizPanel): DataLink[] { return []; } -export function getVizPanelQueries(vizPanel: VizPanel, dsReferencesMapping?: DSReferencesMapping): PanelQueryKind[] { +function getVizPanelQueries(vizPanel: VizPanel, dsReferencesMapping?: DSReferencesMapping): PanelQueryKind[] { const queries: PanelQueryKind[] = []; const queryRunner = getQueryRunnerFor(vizPanel); const vizPanelQueries = queryRunner?.state.queries; @@ -259,22 +258,12 @@ export function getVizPanelQueries(vizPanel: VizPanel, dsReferencesMapping?: DSR if (vizPanelQueries) { vizPanelQueries.forEach((query) => { const queryDatasource = getElementDatasource(vizPanel, query, 'panel', queryRunner, dsReferencesMapping); - const dataQuery: DataQueryKind = { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: getDataQueryKind(query, queryRunner), - datasource: { - name: queryDatasource?.uid, - }, + kind: getDataQueryKind(query, queryRunner), spec: omit(query, 'datasource', 'refId', 'hide'), }; - - if (!dataQuery.datasource?.name) { - delete dataQuery.datasource; - } - const querySpec: PanelQuerySpec = { + datasource: queryDatasource, query: dataQuery, refId: query.refId, hidden: Boolean(query.hide), @@ -418,36 +407,18 @@ function getAnnotations(state: DashboardSceneState, dsReferencesMapping?: DSRefe if (!(layer instanceof dataLayers.AnnotationsDataLayer)) { continue; } - const datasource = getElementDatasource(layer, layer.state.query, 'annotation', undefined, dsReferencesMapping); - - const layerDs = layer.state.query.datasource; - if (!layerDs) { - throw new Error('Misconfigured AnnotationsDataLayer: Datasource is required for annotations'); - } - const result: AnnotationQueryKind = { kind: 'AnnotationQuery', spec: { builtIn: Boolean(layer.state.query.builtIn), name: layer.state.query.name, + datasource: getElementDatasource(layer, layer.state.query, 'annotation', undefined, dsReferencesMapping), enable: Boolean(layer.state.isEnabled), hide: Boolean(layer.state.isHidden), iconColor: layer.state.query.iconColor, - query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: layerDs.type!, // Annotation layer has a datasource type provided in runtime. - spec: {}, - }, }, }; - if (datasource) { - result.spec.query!.datasource = { - name: datasource.uid, - }; - } - // Transform v1 dashboard (using target) to v2 structure // adds extra condition to prioritize query over target // if query is defined, use it @@ -455,37 +426,24 @@ function getAnnotations(state: DashboardSceneState, dsReferencesMapping?: DSRefe // Handle built-in annotations if (layer.state.query.builtIn) { result.spec.query = { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'grafana', // built-in annotations are always of type grafana + kind: 'grafana', // built-in annotations are always of type grafana spec: { ...layer.state.query.target, }, }; } else { result.spec.query = { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: datasource?.type!, + kind: getAnnotationQueryKind(layer.state.query), spec: { ...layer.state.query.target, }, }; - - if (layer.state.query.datasource?.uid) { - result.spec.query.datasource = { - name: layer.state.query.datasource?.uid, - }; - } } } // For annotations without query.query defined (e.g., grafana annotations without tags) else if (layer.state.query.query?.kind) { result.spec.query = { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: layer.state.query.query.group || getAnnotationQueryKind(layer.state.query), - datasource: layer.state.query.query.datasource, + kind: layer.state.query.query.kind, spec: { ...layer.state.query.query.spec, }, @@ -508,15 +466,10 @@ function getAnnotations(state: DashboardSceneState, dsReferencesMapping?: DSRefe // Store extra properties in the legacyOptions field instead of directly in the spec if (Object.keys(otherProps).length > 0) { - // // Extract options property and get the rest of the properties + // Extract options property and get the rest of the properties const { legacyOptions, ...restProps } = otherProps; - if (legacyOptions) { - // Merge options with the rest of the properties - result.spec.legacyOptions = { ...legacyOptions, ...restProps }; - } - result.spec.query!.spec = { - ...otherProps, - }; + // Merge options with the rest of the properties + result.spec.legacyOptions = { ...legacyOptions, ...restProps }; } // If filter is an empty array, don't save it diff --git a/public/app/features/dashboard-scene/v2schema/ImportDashboardOverviewV2.tsx b/public/app/features/dashboard-scene/v2schema/ImportDashboardOverviewV2.tsx index aa4c06d3684..c5cd4e4d15f 100644 --- a/public/app/features/dashboard-scene/v2schema/ImportDashboardOverviewV2.tsx +++ b/public/app/features/dashboard-scene/v2schema/ImportDashboardOverviewV2.tsx @@ -5,7 +5,6 @@ import { locationService, reportInteraction } from '@grafana/runtime'; import { AnnotationQueryKind, Spec as DashboardV2Spec, - defaultDataQueryKind, } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen'; import { Form } from 'app/core/components/Form/Form'; import { getDashboardAPI } from 'app/features/dashboard/api/dashboard_api'; @@ -17,8 +16,6 @@ import { ImportDashboardFormV2 } from './ImportDashboardFormV2'; const IMPORT_FINISHED_EVENT_NAME = 'dashboard_import_imported'; -type FormData = SaveDashboardCommand & { [key: `datasource-${string}`]: string }; - export function ImportDashboardOverviewV2() { const [uidReset, setUidReset] = useState(false); const dispatch = useDispatch(); @@ -37,29 +34,24 @@ export function ImportDashboardOverviewV2() { dispatch(clearLoadedDashboard()); } - async function onSubmit(form: FormData) { + async function onSubmit(form: SaveDashboardCommand) { reportInteraction(IMPORT_FINISHED_EVENT_NAME); const dashboardWithDataSources: DashboardV2Spec = { ...dashboard, title: form.dashboard.title, annotations: dashboard.annotations?.map((annotation: AnnotationQueryKind) => { - const dsType = annotation.spec.query?.spec.group; - if (dsType) { + if (annotation.spec.query?.kind) { + const dsType = annotation.spec.query.kind; if (form[`datasource-${dsType}` as keyof typeof form]) { const ds = form[`datasource-${dsType}` as keyof typeof form] as { uid: string; type: string }; return { ...annotation, spec: { ...annotation.spec, - query: { - kind: 'DataQuery', - group: dsType, - version: defaultDataQueryKind().version, - datasource: { name: ds.uid }, - spec: { - ...annotation.spec.query?.spec, - }, + datasource: { + uid: ds.uid, + type: ds.type, }, }, }; @@ -69,23 +61,18 @@ export function ImportDashboardOverviewV2() { }), variables: dashboard.variables?.map((variable) => { if (variable.kind === 'QueryVariable') { - const dsType = variable.spec.query?.spec.group; - if (dsType) { + if (variable.spec.query?.kind) { + const dsType = variable.spec.query.kind; if (form[`datasource-${dsType}` as keyof typeof form]) { const ds = form[`datasource-${dsType}` as keyof typeof form] as { uid: string; type: string }; return { ...variable, spec: { ...variable.spec, - query: { - ...variable.spec.query, - spec: { - ...variable.spec.query.spec, - group: ds.type, - datasource: { - name: ds.uid, - }, - }, + datasource: { + ...variable.spec.datasource, + uid: ds.uid, + type: ds.type, }, options: [], current: { @@ -170,7 +157,7 @@ export function ImportDashboardOverviewV2() { return ( <> - + & { [key: `datasource-${string}`]: string }> onSubmit={onSubmit} defaultValues={{ dashboard, k8s: { annotations: { 'grafana.app/folder': folder.uid } } }} validateOnMount diff --git a/public/app/features/dashboard-scene/v2schema/test-helpers.ts b/public/app/features/dashboard-scene/v2schema/test-helpers.ts index c16b8bc0a6b..815762fdd31 100644 --- a/public/app/features/dashboard-scene/v2schema/test-helpers.ts +++ b/public/app/features/dashboard-scene/v2schema/test-helpers.ts @@ -52,8 +52,7 @@ export function validateVariable< expect(sceneVariable?.state.pluginId).toBe(variableKind.spec.pluginId); } if (sceneVariable instanceof QueryVariable && variableKind.kind === 'QueryVariable') { - expect(sceneVariable?.state.datasource?.type).toBe(variableKind.spec.query?.group); - expect(sceneVariable?.state.datasource?.uid).toBe(variableKind.spec.query?.datasource?.name); + expect(sceneVariable?.state.datasource).toBe(variableKind.spec.datasource); expect(sceneVariable?.state.query).toEqual(variableKind.spec.query.spec); } if (sceneVariable instanceof CustomVariable && variableKind.kind === 'CustomVariable') { diff --git a/public/app/features/dashboard/api/ResponseTransformers.test.ts b/public/app/features/dashboard/api/ResponseTransformers.test.ts index 5111fc74e5c..9187b6fc9c8 100644 --- a/public/app/features/dashboard/api/ResponseTransformers.test.ts +++ b/public/app/features/dashboard/api/ResponseTransformers.test.ts @@ -2,7 +2,6 @@ import { AnnotationQuery, DataQuery, VariableModel, VariableRefresh, Panel } fro import { handyTestingSchema } from '@grafana/schema/dist/esm/schema/dashboard/v2_examples'; import { Spec as DashboardV2Spec, - defaultDataQueryKind, GridLayoutItemKind, GridLayoutKind, PanelKind, @@ -467,14 +466,10 @@ describe('ResponseTransformers', () => { { kind: 'PanelQuery', spec: { + datasource: 'datasource1', hidden: false, query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'prometheus', - datasource: { - name: 'datasource1', - }, + kind: 'prometheus', spec: { expr: 'test-query', }, @@ -978,9 +973,11 @@ describe('ResponseTransformers', () => { result.forEach((query) => { expect(query.kind).toBe('PanelQuery'); - expect(query.spec.query.group).toEqual('theoretical-ds'); - expect(query.spec.query.datasource?.name).toEqual('theoretical-uid'); - expect(query.spec.query.kind).toBe('DataQuery'); + expect(query.spec.datasource).toEqual({ + type: 'theoretical-ds', + uid: 'theoretical-uid', + }); + expect(query.spec.query.kind).toBe('theoretical-ds'); }); }); @@ -1006,9 +1003,11 @@ describe('ResponseTransformers', () => { result.forEach((query) => { expect(query.kind).toBe('PanelQuery'); - expect(query.spec.query.group).toEqual('theoretical-ds'); - expect(query.spec.query.datasource?.name).toEqual('theoretical-uid'); - expect(query.spec.query.kind).toBe('DataQuery'); + expect(query.spec.datasource).toEqual({ + type: 'theoretical-ds', + uid: 'theoretical-uid', + }); + expect(query.spec.query.kind).toBe('theoretical-ds'); }); }); }); @@ -1018,8 +1017,7 @@ describe('ResponseTransformers', () => { const { spec: v2Spec } = v2; expect(v1.name).toBe(v2Spec.name); - expect(v1.datasource?.type).toBe(v2Spec.query?.spec.group); - expect(v1.datasource?.uid).toBe(v2Spec.query?.spec.datasource?.name); + expect(v1.datasource).toBe(v2Spec.datasource); expect(v1.enable).toBe(v2Spec.enable); expect(v1.hide).toBe(v2Spec.hide); expect(v1.iconColor).toBe(v2Spec.iconColor); @@ -1045,10 +1043,7 @@ describe('ResponseTransformers', () => { return { refId: q.spec.refId, hide: q.spec.hidden, - datasource: { - type: q.spec.query.spec.group, - uid: q.spec.query.spec.datasource?.uid, - }, + datasource: q.spec.datasource, ...q.spec.query.spec, }; }) @@ -1098,24 +1093,18 @@ describe('ResponseTransformers', () => { }; expect(v2Common).toEqual(v1Common); + if (v2.kind === 'QueryVariable') { - expect(v2.spec.query).toMatchObject({ - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: (v1.datasource?.type || getDefaultDataSourceRef()?.type) ?? 'grafana', - ...(v1.datasource?.uid && { - datasource: { - name: v1.datasource?.uid, - }, - }), - }); + expect(v2.spec.datasource).toEqual(v1.datasource); + if (typeof v1.query === 'string') { - expect(v2.spec.query.spec).toEqual({ - [LEGACY_STRING_VALUE_KEY]: v1.query, - }); + expect(v2.spec.query.spec[LEGACY_STRING_VALUE_KEY]).toEqual(v1.query); } else { - expect(v2.spec.query.spec).toEqual({ - ...(typeof v1.query === 'object' ? v1.query : {}), + expect(v2.spec.query).toEqual({ + kind: v1.datasource?.type, + spec: { + ...(typeof v1.query === 'object' ? v1.query : {}), + }, }); } } diff --git a/public/app/features/dashboard/api/ResponseTransformers.ts b/public/app/features/dashboard/api/ResponseTransformers.ts index 0fe72aaf365..509271f7e50 100644 --- a/public/app/features/dashboard/api/ResponseTransformers.ts +++ b/public/app/features/dashboard/api/ResponseTransformers.ts @@ -38,7 +38,6 @@ import { LibraryPanelKind, PanelKind, GridLayoutItemKind, - defaultDataQueryKind, RowsLayoutRowKind, GridLayoutKind, } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen'; @@ -503,13 +502,9 @@ export function getPanelQueries(targets: DataQuery[], panelDatasource: DataSourc spec: { refId: t.refId, hidden: t.hide ?? false, + datasource: t.datasource ? t.datasource : panelDatasource, query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: t.datasource?.type || panelDatasource.type!, - datasource: { - name: t.datasource?.uid || panelDatasource.uid!, - }, + kind: t.datasource?.type || panelDatasource.type!, spec: { ...query, }, @@ -573,12 +568,7 @@ function getVariables(vars: TypedVariableModel[]): DashboardV2Spec['variables'] regex: v.regex || '', sort: transformSortVariableToEnum(v.sort), query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: v.datasource?.type ?? getDefaultDatasourceType(), - datasource: { - name: v.datasource?.uid, - }, + kind: v.datasource?.type || getDefaultDatasourceType(), spec: query, }, allowCustomValue: v.allowCustomValue ?? true, @@ -732,12 +722,7 @@ function getAnnotations(annotations: AnnotationQuery[]): DashboardV2Spec['annota iconColor: a.iconColor, builtIn: Boolean(a.builtIn), query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: a.datasource?.type || getDefaultDatasourceType(), - datasource: { - name: a.datasource?.uid, - }, + kind: a.datasource?.type || getDefaultDatasourceType(), spec: { ...a.target, }, @@ -772,10 +757,7 @@ function getVariablesV1(vars: DashboardV2Spec['variables']): VariableModel[] { LEGACY_STRING_VALUE_KEY in v.spec.query.spec ? v.spec.query.spec[LEGACY_STRING_VALUE_KEY] : v.spec.query.spec, - datasource: { - type: v.spec.query?.spec.group, - uid: v.spec.query?.spec.datasource?.name, - }, + datasource: v.spec.datasource, sort: transformSortVariableToEnumV1(v.spec.sort), refresh: transformVariableRefreshToEnumV1(v.spec.refresh), regex: v.spec.regex, @@ -897,10 +879,7 @@ function getAnnotationsV1(annotations: DashboardV2Spec['annotations']): Annotati return annotations.map((a) => { return { name: a.spec.name, - datasource: { - type: a.spec.query?.spec.group, - uid: a.spec.query?.spec.datasource?.name, - }, + datasource: a.spec.datasource, enable: a.spec.enable, hide: a.spec.hide, iconColor: a.spec.iconColor, @@ -971,10 +950,7 @@ function transformV2PanelToV1Panel( return { refId: q.spec.refId, hide: q.spec.hidden, - datasource: { - uid: q.spec.query.spec.datasource?.uid, - type: q.spec.query.spec.group, - }, + datasource: q.spec.datasource, ...q.spec.query.spec, }; }), diff --git a/public/app/features/manage-dashboards/state/actions.test.ts b/public/app/features/manage-dashboards/state/actions.test.ts index b6af47ee643..c4aebee06de 100644 --- a/public/app/features/manage-dashboards/state/actions.test.ts +++ b/public/app/features/manage-dashboards/state/actions.test.ts @@ -7,7 +7,6 @@ import { defaultSpec as defaultDashboardV2Spec, defaultPanelSpec, defaultQueryVariableSpec, - defaultDataQueryKind, } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen'; import { browseDashboardsAPI } from 'app/features/browse-dashboards/api/browseDashboardsAPI'; import { getLibraryPanel } from 'app/features/library-panels/state/api'; @@ -837,9 +836,7 @@ describe('processV2Datasources', () => { refId: 'A', hidden: false, query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'prometheus', + kind: 'prometheus', spec: { expr: 'access_evaluation_duration_count', range: true, @@ -865,9 +862,7 @@ describe('processV2Datasources', () => { ...defaultQueryVariableSpec(), name: 'var1', query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'loki', + kind: 'loki', spec: { expr: 'access_evaluation_duration_count', range: true, @@ -885,9 +880,7 @@ describe('processV2Datasources', () => { hide: false, iconColor: 'red', query: { - kind: 'DataQuery', - version: defaultDataQueryKind().version, - group: 'loki', + kind: 'loki', spec: { expr: 'access_evaluation_duration_count', range: true, @@ -989,17 +982,13 @@ describe('processV2DatasourceInput', () => { ...defaultQueryVariableSpec(), name: 'var2WithGrafanaDs', query: { - kind: 'DataQuery' as const, - version: defaultDataQueryKind().version, - group: 'grafana', + kind: 'grafana', spec: { - expr: 'access_evaluation_duration_count', - range: true, + panelId: 2, }, }, }, }; - const result = await processV2DatasourceInput(queryVariable.spec, {}); expect(result).toEqual({}); }); @@ -1012,9 +1001,7 @@ describe('processV2DatasourceInput', () => { refId: 'A', hidden: false, query: { - kind: 'DataQuery' as const, - version: defaultDataQueryKind().version, - group: 'datasource', + kind: 'datasource', spec: { panelId: 2, }, diff --git a/public/app/features/manage-dashboards/state/actions.ts b/public/app/features/manage-dashboards/state/actions.ts index 191ec9c2657..5d07c1d66e6 100644 --- a/public/app/features/manage-dashboards/state/actions.ts +++ b/public/app/features/manage-dashboards/state/actions.ts @@ -168,7 +168,6 @@ export function processV2Datasources(dashboard: DashboardV2Spec): ThunkResult 0) { for (const query of element.spec.data.spec.queries) { inputs = await processV2DatasourceInput(query.spec, inputs); @@ -333,43 +332,43 @@ export function getFolderByUid(uid: string): Promise<{ uid: string; title: strin } export async function processV2DatasourceInput( - spec: PanelQueryKind['spec'] | QueryVariableKind['spec'] | AnnotationQueryKind['spec'], + obj: PanelQueryKind['spec'] | QueryVariableKind['spec'] | AnnotationQueryKind['spec'], inputs: Record = {} ) { - const datasourceRef = spec.query.datasource; - let dataSourceInput: DataSourceInput | undefined; - const dsType = spec.query.group; - - if (!datasourceRef) { + const datasourceRef = obj?.datasource; + if (!datasourceRef && obj?.query) { + const dsType = obj.query.kind; // if dsType is grafana, it means we are using a built-in annotation or default grafana datasource, in those // cases we don't need to map it // "datasource" type is what we call "--Dashboard--" datasource <.-.> if (dsType === 'grafana' || dsType === 'datasource') { return inputs; } - } - - const datasource = await getDatasourceSrv().get({ type: dsType }); - if (datasource) { - dataSourceInput = { - name: datasource.name, - label: datasource.name, - info: `Select a ${datasource.name} data source`, - value: datasource.uid, - type: InputType.DataSource, - pluginId: datasource.meta?.id, - }; - inputs[datasource.meta?.id] = dataSourceInput; - } else { - dataSourceInput = { - name: dsType, - label: dsType, - info: `No data sources of type ${dsType} found`, - value: '', - type: InputType.DataSource, - pluginId: dsType, - }; - inputs[dsType] = dataSourceInput; + const datasource = await getDatasourceSrv().get({ type: dsType }); + let dataSourceInput: DataSourceInput | undefined; + if (datasource) { + dataSourceInput = { + name: datasource.name, + label: datasource.name, + info: `Select a ${datasource.name} data source`, + value: datasource.uid, + type: InputType.DataSource, + pluginId: datasource.meta?.id, + }; + + inputs[datasource.meta?.id] = dataSourceInput; + } else { + dataSourceInput = { + name: dsType, + label: dsType, + info: `No data sources of type ${dsType} found`, + value: '', + type: InputType.DataSource, + pluginId: dsType, + }; + + inputs[dsType] = dataSourceInput; + } } return inputs; }