diff --git a/packages/grafana-schema/src/schema/dashboard/v2alpha0/dashboard.schema.cue b/packages/grafana-schema/src/schema/dashboard/v2alpha0/dashboard.schema.cue index 170094040c1..e49511ddddd 100644 --- a/packages/grafana-schema/src/schema/dashboard/v2alpha0/dashboard.schema.cue +++ b/packages/grafana-schema/src/schema/dashboard/v2alpha0/dashboard.schema.cue @@ -651,7 +651,7 @@ QueryVariableSpec: { skipUrlSync: bool | *false description?: string datasource?: DataSourceRef - query: string | DataQueryKind | *"" + query: DataQueryKind regex: string | *"" sort: VariableSort definition?: string diff --git a/packages/grafana-schema/src/schema/dashboard/v2alpha0/examples.ts b/packages/grafana-schema/src/schema/dashboard/v2alpha0/examples.ts index 340ffeeef12..40b091f29dd 100644 --- a/packages/grafana-schema/src/schema/dashboard/v2alpha0/examples.ts +++ b/packages/grafana-schema/src/schema/dashboard/v2alpha0/examples.ts @@ -344,7 +344,13 @@ export const handyTestingSchema: DashboardV2Spec = { multi: true, name: 'queryVar', options: [], - query: 'query1', + query: { + kind: 'prometheus', + spec: { + expr: 'test-query', + refId: 'A', + }, + }, refresh: 'onDashboardLoad', regex: 'regex1', skipUrlSync: false, diff --git a/packages/grafana-schema/src/schema/dashboard/v2alpha0/types.gen.ts b/packages/grafana-schema/src/schema/dashboard/v2alpha0/types.gen.ts index 0e41bb7fedc..641cb9173cb 100644 --- a/packages/grafana-schema/src/schema/dashboard/v2alpha0/types.gen.ts +++ b/packages/grafana-schema/src/schema/dashboard/v2alpha0/types.gen.ts @@ -960,7 +960,7 @@ export interface QueryVariableSpec { skipUrlSync: boolean; description?: string; datasource?: DataSourceRef; - query: string | DataQueryKind; + query: DataQueryKind; regex: string; sort: VariableSort; definition?: string; @@ -977,7 +977,7 @@ export const defaultQueryVariableSpec = (): QueryVariableSpec => ({ hide: "dontHide", refresh: "never", skipUrlSync: false, - query: "", + query: defaultDataQueryKind(), regex: "", sort: "disabled", options: [], 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 a62ba3c1daf..7695bba0ab6 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 @@ -222,7 +222,13 @@ exports[`transformSceneToSaveModelSchemaV2 should transform scene to save model "multi": true, "name": "queryVar", "options": [], - "query": "query1", + "query": { + "kind": "prometheus", + "spec": { + "expr": "label_values(node_boot_time_seconds)", + "refId": "A", + }, + }, "refresh": "onDashboardLoad", "regex": "regex1", "skipUrlSync": false, diff --git a/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.test.ts b/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.test.ts index 2cbb9a03550..d7514139230 100644 --- a/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.test.ts +++ b/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.test.ts @@ -775,7 +775,12 @@ describe('sceneVariablesSetToVariables', () => { "multi": true, "name": "test", "options": [], - "query": "query", + "query": { + "kind": "fake-std", + "spec": { + "__legacyStringValue": "query", + }, + }, "refresh": "onDashboardLoad", "regex": "", "skipUrlSync": false, diff --git a/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.ts b/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.ts index bb9c410c7ec..c7d86f4c910 100644 --- a/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.ts +++ b/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.ts @@ -27,6 +27,7 @@ import { transformVariableRefreshToEnum, transformVariableHideToEnum, transformSortVariableToEnum, + LEGACY_STRING_VALUE_KEY, } from './transformToV2TypesUtils'; /** * Converts a SceneVariables object into an array of VariableModel objects. @@ -269,16 +270,20 @@ export function sceneVariablesSetToSchemaV2Variables( if (transformVariableRefreshToEnum(variable.state.refresh) === 'never' || keepQueryOptions) { options = variableValueOptionsToVariableOptions(variable.state); } - //query: DataQueryKind | string; const query = variable.state.query; let dataQuery: DataQueryKind | string; if (typeof query !== 'string') { dataQuery = { - kind: getDataQueryKind(query), + kind: variable.state.datasource?.type ?? getDataQueryKind(query), spec: getDataQuerySpec(query), }; } else { - dataQuery = query; + dataQuery = { + kind: variable.state.datasource?.type ?? getDataQueryKind(query), + spec: { + [LEGACY_STRING_VALUE_KEY]: query, + }, + }; } const queryVariable: QueryVariableKind = { kind: 'QueryVariable', diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts index fd82cc7c161..61ed7495a8c 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts @@ -100,6 +100,7 @@ import { transformVariableHideToEnumV1, transformVariableRefreshToEnumV1, } from './transformToV1TypesUtils'; +import { LEGACY_STRING_VALUE_KEY } from './transformToV2TypesUtils'; const DEFAULT_DATASOURCE = 'default'; @@ -635,12 +636,12 @@ function createSceneVariableFromVariableModel(variable: TypedVariableModelV2): S } function getDataQueryForVariable(variable: QueryVariableKind) { - return typeof variable.spec.query !== 'string' - ? { + return LEGACY_STRING_VALUE_KEY in variable.spec.query.spec + ? (variable.spec.query.spec[LEGACY_STRING_VALUE_KEY] ?? '') + : { ...variable.spec.query.spec, refId: variable.spec.query.spec.refId ?? 'A', - } - : (variable.spec.query ?? ''); + }; } export function getCurrentValueForOldIntervalModel(variable: IntervalVariableKind, intervals: string[]): string { diff --git a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.test.ts b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.test.ts index 43121f54d8b..c87a4a0a687 100644 --- a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.test.ts +++ b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.test.ts @@ -225,7 +225,10 @@ describe('transformSceneToSaveModelSchemaV2', () => { hide: VariableHideV1.hideLabel, value: 'value1', text: 'text1', - query: 'query1', + query: { + expr: 'label_values(node_boot_time_seconds)', + refId: 'A', + }, definition: 'definition1', datasource: { uid: 'datasource1', type: 'prometheus' }, sort: VariableSortV1.alphabeticalDesc, diff --git a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts index 67cae374214..928ce92733f 100644 --- a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts +++ b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts @@ -403,8 +403,11 @@ function getVizPanelQueries(vizPanel: VizPanel): PanelQueryKind[] { return queries; } -export function getDataQueryKind(query: SceneDataQuery): string { - // If the query has a datasource, use the datasource type, otherwise return empty kind +export function getDataQueryKind(query: SceneDataQuery | string): string { + if (typeof query === 'string') { + return getDefaultDataSourceRef()?.type ?? ''; + } + return query.datasource?.type ?? getDefaultDataSourceRef()?.type ?? ''; } @@ -616,19 +619,15 @@ export function getAnnotationQueryKind(annotationQuery: AnnotationQuery): string } } -export function getDefaultDataSourceRef(): DataSourceRef | undefined { +export function getDefaultDataSourceRef(): DataSourceRef { // we need to return the default datasource configured in the BootConfig const defaultDatasource = config.bootData.settings.defaultDatasource; // get default datasource type - const dsList = config.bootData.settings.datasources ?? {}; + const dsList = config.bootData.settings.datasources; const ds = dsList[defaultDatasource]; - if (ds) { - return { type: ds.meta.id, uid: ds.name }; // in the datasource list from bootData "id" is the type - } - - return undefined; + return { type: ds.meta.id, uid: ds.name }; // in the datasource list from bootData "id" is the type } // Function to know if the dashboard transformed is a valid DashboardV2Spec diff --git a/public/app/features/dashboard-scene/serialization/transformToV2TypesUtils.ts b/public/app/features/dashboard-scene/serialization/transformToV2TypesUtils.ts index ca7c056d752..582b6b4cfcf 100644 --- a/public/app/features/dashboard-scene/serialization/transformToV2TypesUtils.ts +++ b/public/app/features/dashboard-scene/serialization/transformToV2TypesUtils.ts @@ -19,6 +19,9 @@ import { FieldColorModeId as FieldColorModeIdV2, } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0'; +// used for QueryVariableKind's query prop - in schema V2 we've deprecated string type and support only DataQuery +export const LEGACY_STRING_VALUE_KEY = '__legacyStringValue'; + export function transformCursorSynctoEnum(cursorSync?: DashboardCursorSyncV1): DashboardCursorSync { switch (cursorSync) { case 0: diff --git a/public/app/features/dashboard-scene/v2schema/test-helpers.ts b/public/app/features/dashboard-scene/v2schema/test-helpers.ts index 9c37f1df5d5..9f901bf67e4 100644 --- a/public/app/features/dashboard-scene/v2schema/test-helpers.ts +++ b/public/app/features/dashboard-scene/v2schema/test-helpers.ts @@ -53,7 +53,7 @@ export function validateVariable< } if (sceneVariable instanceof QueryVariable && variableKind.kind === 'QueryVariable') { expect(sceneVariable?.state.datasource).toBe(variableKind.spec.datasource); - expect(sceneVariable?.state.query).toBe(variableKind.spec.query); + expect(sceneVariable?.state.query).toEqual(variableKind.spec.query.spec); } if (sceneVariable instanceof CustomVariable && variableKind.kind === 'CustomVariable') { expect(sceneVariable?.state.query).toBe(variableKind.spec.query); diff --git a/public/app/features/dashboard/api/ResponseTransformers.test.ts b/public/app/features/dashboard/api/ResponseTransformers.test.ts index 3a677bf658e..1dfbd14eb04 100644 --- a/public/app/features/dashboard/api/ResponseTransformers.test.ts +++ b/public/app/features/dashboard/api/ResponseTransformers.test.ts @@ -19,6 +19,7 @@ import { } from 'app/features/apiserver/types'; import { getDefaultDataSourceRef } from 'app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2'; import { + LEGACY_STRING_VALUE_KEY, transformVariableHideToEnum, transformVariableRefreshToEnum, } from 'app/features/dashboard-scene/serialization/transformToV2TypesUtils'; @@ -915,7 +916,7 @@ describe('ResponseTransformers', () => { expect(v2.spec.datasource).toEqual(v1.datasource); if (typeof v1.query === 'string') { - expect(v2.spec.query).toEqual(v1.query); + expect(v2.spec.query.spec[LEGACY_STRING_VALUE_KEY]).toEqual(v1.query); } else { expect(v2.spec.query).toEqual({ kind: v1.datasource?.type, diff --git a/public/app/features/dashboard/api/ResponseTransformers.ts b/public/app/features/dashboard/api/ResponseTransformers.ts index 535265f606d..1b72d6b3c08 100644 --- a/public/app/features/dashboard/api/ResponseTransformers.ts +++ b/public/app/features/dashboard/api/ResponseTransformers.ts @@ -62,6 +62,7 @@ import { transformVariableRefreshToEnumV1, } from 'app/features/dashboard-scene/serialization/transformToV1TypesUtils'; import { + LEGACY_STRING_VALUE_KEY, transformCursorSynctoEnum, transformDataTopic, transformSortVariableToEnum, @@ -504,8 +505,12 @@ function getVariables(vars: TypedVariableModel[]): DashboardV2Spec['variables'] let query = v.query || {}; if (typeof query === 'string') { - console.error('Query variable query is a string. It needs to extend DataQuery.'); - query = {}; + console.warn( + 'Query variable query is a string which is deprecated in the schema v2. It should extend DataQuery' + ); + query = { + [LEGACY_STRING_VALUE_KEY]: query, + }; } const qv: QueryVariableKind = { @@ -527,7 +532,7 @@ function getVariables(vars: TypedVariableModel[]): DashboardV2Spec['variables'] query: { kind: v.datasource?.type || getDefaultDatasourceType(), spec: { - ...query, + ...v.query, }, }, }, @@ -708,7 +713,10 @@ function getVariablesV1(vars: DashboardV2Spec['variables']): VariableModel[] { ...commonProperties, current: v.spec.current, options: v.spec.options, - query: typeof v.spec.query === 'string' ? v.spec.query : v.spec.query.spec, + query: + LEGACY_STRING_VALUE_KEY in v.spec.query.spec + ? v.spec.query.spec[LEGACY_STRING_VALUE_KEY] + : v.spec.query.spec, datasource: v.spec.datasource, sort: transformSortVariableToEnumV1(v.spec.sort), refresh: transformVariableRefreshToEnumV1(v.spec.refresh),