Dashboard: Schema V2 - Remove Dashboard id from spec (#99590)

* Dashboard: Schema V2 - Remove Dashboard id from spec

* Fix issue with dashboard id used in examples and serializers for schema v2

* Fix snapshot test
This commit is contained in:
Alexa V 2025-01-29 10:13:56 +01:00 committed by GitHub
parent 8e5a4560e8
commit 30c8ac7108
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 22 additions and 26 deletions

View File

@ -5,10 +5,6 @@ import (
) )
DashboardV2Spec: { DashboardV2Spec: {
// Unique numeric identifier for the dashboard.
// `id` is internal to a specific Grafana instance. `uid` should be used to identify a dashboard across Grafana instances.
id?: int64
// Title of dashboard. // Title of dashboard.
title: string title: string

View File

@ -1,7 +1,6 @@
import { DashboardV2Spec } from './types.gen'; import { DashboardV2Spec } from './types.gen';
export const handyTestingSchema: DashboardV2Spec = { export const handyTestingSchema: DashboardV2Spec = {
id: 1,
title: 'Default Dashboard', title: 'Default Dashboard',
description: 'This is a default dashboard', description: 'This is a default dashboard',
cursorSync: 'Off', cursorSync: 'Off',

View File

@ -4,9 +4,6 @@ import * as common from '@grafana/schema';
export interface DashboardV2Spec { export interface DashboardV2Spec {
// Unique numeric identifier for the dashboard.
// `id` is internal to a specific Grafana instance. `uid` should be used to identify a dashboard across Grafana instances.
id?: number;
// Title of dashboard. // Title of dashboard.
title: string; title: string;
// Description of dashboard. // Description of dashboard.

View File

@ -42,7 +42,6 @@ export const AnnoKeyFolderId = 'grafana.app/folderId';
export const AnnoKeyFolderUrl = 'grafana.app/folderUrl'; export const AnnoKeyFolderUrl = 'grafana.app/folderUrl';
export const AnnoKeyMessage = 'grafana.app/message'; export const AnnoKeyMessage = 'grafana.app/message';
export const AnnoKeySlug = 'grafana.app/slug'; export const AnnoKeySlug = 'grafana.app/slug';
export const AnnoKeyDashboardId = 'grafana.app/dashboardId';
// Identify where values came from // Identify where values came from
export const AnnoKeyRepoName = 'grafana.app/repoName'; export const AnnoKeyRepoName = 'grafana.app/repoName';
@ -66,7 +65,6 @@ type GrafanaAnnotations = {
[AnnoKeyUpdatedBy]?: string; [AnnoKeyUpdatedBy]?: string;
[AnnoKeyFolder]?: string; [AnnoKeyFolder]?: string;
[AnnoKeySlug]?: string; [AnnoKeySlug]?: string;
[AnnoKeyDashboardId]?: number;
[AnnoKeyRepoName]?: string; [AnnoKeyRepoName]?: string;
[AnnoKeyRepoPath]?: string; [AnnoKeyRepoPath]?: string;

View File

@ -138,7 +138,7 @@ export function SaveDashboardAsForm({ dashboard, changeInfo }: Props) {
// Old folder picker fields // Old folder picker fields
value={formValues.folder?.uid} value={formValues.folder?.uid}
initialTitle={defaultValues!.folder!.title} initialTitle={defaultValues!.folder!.title}
dashboardId={changedSaveModel.id ?? undefined} dashboardId={dashboard.state.id ?? undefined}
enableCreateNew enableCreateNew
/> />
</Field> </Field>

View File

@ -627,7 +627,6 @@ describe('DashboardSceneSerializer', () => {
expect(saveAsModel).toMatchObject({ expect(saveAsModel).toMatchObject({
title: baseOptions.title, title: baseOptions.title,
description: baseOptions.description, description: baseOptions.description,
id: undefined,
editable: true, editable: true,
annotations: [], annotations: [],
cursorSync: 'Off', cursorSync: 'Off',
@ -801,7 +800,6 @@ describe('DashboardSceneSerializer', () => {
expect(serializer.initialSaveModel).toEqual({ expect(serializer.initialSaveModel).toEqual({
...saveModel, ...saveModel,
id: response.id,
}); });
}); });

View File

@ -172,7 +172,6 @@ export class V2DashboardSerializer
onSaveComplete(saveModel: DashboardV2Spec, result: SaveDashboardResponseDTO): void { onSaveComplete(saveModel: DashboardV2Spec, result: SaveDashboardResponseDTO): void {
this.initialSaveModel = { this.initialSaveModel = {
...saveModel, ...saveModel,
id: result.id,
}; };
} }

View File

@ -89,7 +89,6 @@ exports[`transformSceneToSaveModelSchemaV2 should transform scene to save model
}, },
}, },
}, },
"id": 1,
"layout": { "layout": {
"kind": "GridLayout", "kind": "GridLayout",
"spec": { "spec": {

View File

@ -59,6 +59,7 @@ import {
AnnoKeyUpdatedBy, AnnoKeyUpdatedBy,
AnnoKeyUpdatedTimestamp, AnnoKeyUpdatedTimestamp,
AnnoKeyDashboardIsSnapshot, AnnoKeyDashboardIsSnapshot,
DeprecatedInternalId,
} from 'app/features/apiserver/types'; } from 'app/features/apiserver/types';
import { DashboardWithAccessInfo } from 'app/features/dashboard/api/types'; import { DashboardWithAccessInfo } from 'app/features/dashboard/api/types';
import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource';
@ -125,6 +126,7 @@ export function transformSaveModelSchemaV2ToScene(dto: DashboardWithAccessInfo<D
const isDashboardEditable = Boolean(dashboard.editable); const isDashboardEditable = Boolean(dashboard.editable);
const canSave = dto.access.canSave !== false; const canSave = dto.access.canSave !== false;
const dashboardId = metadata.labels?.[DeprecatedInternalId];
const meta: DashboardMeta = { const meta: DashboardMeta = {
canShare: dto.access.canShare !== false, canShare: dto.access.canShare !== false,
@ -162,7 +164,7 @@ export function transformSaveModelSchemaV2ToScene(dto: DashboardWithAccessInfo<D
description: dashboard.description, description: dashboard.description,
editable: dashboard.editable, editable: dashboard.editable,
preload: dashboard.preload, preload: dashboard.preload,
id: dashboard.id, id: dashboardId,
isDirty: false, isDirty: false,
links: dashboard.links, links: dashboard.links,
meta, meta,
@ -198,11 +200,11 @@ export function transformSaveModelSchemaV2ToScene(dto: DashboardWithAccessInfo<D
addPanelsOnLoadBehavior, addPanelsOnLoadBehavior,
new DashboardScopesFacade({ new DashboardScopesFacade({
reloadOnParamsChange: config.featureToggles.reloadDashboardsOnParamsChange, reloadOnParamsChange: config.featureToggles.reloadDashboardsOnParamsChange,
uid: dashboard.id?.toString(), uid: dashboardId?.toString(),
}), }),
new DashboardReloadBehavior({ new DashboardReloadBehavior({
reloadOnParamsChange: config.featureToggles.reloadDashboardsOnParamsChange, reloadOnParamsChange: config.featureToggles.reloadDashboardsOnParamsChange,
uid: dashboard.id?.toString(), uid: dashboardId?.toString(),
version: 1, version: 1,
}), }),
], ],

View File

@ -76,7 +76,6 @@ export function transformSceneToSaveModelSchemaV2(scene: DashboardScene, isSnaps
const dashboardSchemaV2: DeepPartial<DashboardV2Spec> = { const dashboardSchemaV2: DeepPartial<DashboardV2Spec> = {
//dashboard settings //dashboard settings
id: oldDash.id ? oldDash.id : undefined,
title: oldDash.title, title: oldDash.title,
description: oldDash.description ?? '', description: oldDash.description ?? '',
cursorSync: getCursorSync(oldDash), cursorSync: getCursorSync(oldDash),

View File

@ -4,11 +4,11 @@ import { handyTestingSchema } from '@grafana/schema/dist/esm/schema/dashboard/v2
import { import {
AnnoKeyCreatedBy, AnnoKeyCreatedBy,
AnnoKeyDashboardGnetId, AnnoKeyDashboardGnetId,
AnnoKeyDashboardId,
AnnoKeyFolder, AnnoKeyFolder,
AnnoKeySlug, AnnoKeySlug,
AnnoKeyUpdatedBy, AnnoKeyUpdatedBy,
AnnoKeyUpdatedTimestamp, AnnoKeyUpdatedTimestamp,
DeprecatedInternalId,
} from 'app/features/apiserver/types'; } from 'app/features/apiserver/types';
import { getDefaultDataSourceRef } from 'app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2'; import { getDefaultDataSourceRef } from 'app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2';
import { import {
@ -353,6 +353,9 @@ describe('ResponseTransformers', () => {
[AnnoKeyFolder]: 'folder1', [AnnoKeyFolder]: 'folder1',
[AnnoKeySlug]: 'dashboard-slug', [AnnoKeySlug]: 'dashboard-slug',
}, },
labels: {
[DeprecatedInternalId]: 123,
},
}, },
}; };
@ -366,8 +369,8 @@ describe('ResponseTransformers', () => {
expect(transformed.metadata.annotations?.[AnnoKeyUpdatedTimestamp]).toEqual('2023-01-02T00:00:00Z'); expect(transformed.metadata.annotations?.[AnnoKeyUpdatedTimestamp]).toEqual('2023-01-02T00:00:00Z');
expect(transformed.metadata.annotations?.[AnnoKeyFolder]).toEqual('folder1'); expect(transformed.metadata.annotations?.[AnnoKeyFolder]).toEqual('folder1');
expect(transformed.metadata.annotations?.[AnnoKeySlug]).toEqual('dashboard-slug'); expect(transformed.metadata.annotations?.[AnnoKeySlug]).toEqual('dashboard-slug');
expect(transformed.metadata.annotations?.[AnnoKeyDashboardId]).toBe(123);
expect(transformed.metadata.annotations?.[AnnoKeyDashboardGnetId]).toBe('something-like-a-uid'); expect(transformed.metadata.annotations?.[AnnoKeyDashboardGnetId]).toBe('something-like-a-uid');
expect(transformed.metadata.labels?.[DeprecatedInternalId]).toBe(123);
// Spec // Spec
const spec = transformed.spec; const spec = transformed.spec;

View File

@ -39,13 +39,13 @@ import { DashboardLink, DataTransformerConfig } from '@grafana/schema/src/raw/da
import { import {
AnnoKeyCreatedBy, AnnoKeyCreatedBy,
AnnoKeyDashboardGnetId, AnnoKeyDashboardGnetId,
AnnoKeyDashboardId,
AnnoKeyDashboardIsSnapshot, AnnoKeyDashboardIsSnapshot,
AnnoKeyDashboardSnapshotOriginalUrl, AnnoKeyDashboardSnapshotOriginalUrl,
AnnoKeyFolder, AnnoKeyFolder,
AnnoKeySlug, AnnoKeySlug,
AnnoKeyUpdatedBy, AnnoKeyUpdatedBy,
AnnoKeyUpdatedTimestamp, AnnoKeyUpdatedTimestamp,
DeprecatedInternalId,
} from 'app/features/apiserver/types'; } from 'app/features/apiserver/types';
import { TypedVariableModelV2 } from 'app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene'; import { TypedVariableModelV2 } from 'app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene';
import { getDefaultDataSourceRef } from 'app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2'; import { getDefaultDataSourceRef } from 'app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2';
@ -91,6 +91,7 @@ export function ensureV2Response(
let accessMeta: DashboardWithAccessInfo<DashboardV2Spec>['access']; let accessMeta: DashboardWithAccessInfo<DashboardV2Spec>['access'];
let annotationsMeta: DashboardWithAccessInfo<DashboardV2Spec>['metadata']['annotations']; let annotationsMeta: DashboardWithAccessInfo<DashboardV2Spec>['metadata']['annotations'];
let labelsMeta: DashboardWithAccessInfo<DashboardV2Spec>['metadata']['labels'];
let creationTimestamp; let creationTimestamp;
if (isDashboardResource(dto)) { if (isDashboardResource(dto)) {
@ -101,11 +102,13 @@ export function ensureV2Response(
[AnnoKeyUpdatedTimestamp]: dto.metadata.annotations?.[AnnoKeyUpdatedTimestamp], [AnnoKeyUpdatedTimestamp]: dto.metadata.annotations?.[AnnoKeyUpdatedTimestamp],
[AnnoKeyFolder]: dto.metadata.annotations?.[AnnoKeyFolder], [AnnoKeyFolder]: dto.metadata.annotations?.[AnnoKeyFolder],
[AnnoKeySlug]: dto.metadata.annotations?.[AnnoKeySlug], [AnnoKeySlug]: dto.metadata.annotations?.[AnnoKeySlug],
[AnnoKeyDashboardId]: dashboard.id ?? undefined,
[AnnoKeyDashboardGnetId]: dashboard.gnetId ?? undefined, [AnnoKeyDashboardGnetId]: dashboard.gnetId ?? undefined,
[AnnoKeyDashboardIsSnapshot]: dto.metadata.annotations?.[AnnoKeyDashboardIsSnapshot], [AnnoKeyDashboardIsSnapshot]: dto.metadata.annotations?.[AnnoKeyDashboardIsSnapshot],
}; };
creationTimestamp = dto.metadata.creationTimestamp; creationTimestamp = dto.metadata.creationTimestamp;
labelsMeta = {
[DeprecatedInternalId]: dto.metadata.labels?.[DeprecatedInternalId],
};
} else { } else {
accessMeta = { accessMeta = {
url: dto.meta.url, url: dto.meta.url,
@ -124,11 +127,13 @@ export function ensureV2Response(
[AnnoKeyUpdatedTimestamp]: dto.meta.updated, [AnnoKeyUpdatedTimestamp]: dto.meta.updated,
[AnnoKeyFolder]: dto.meta.folderUid, [AnnoKeyFolder]: dto.meta.folderUid,
[AnnoKeySlug]: dto.meta.slug, [AnnoKeySlug]: dto.meta.slug,
[AnnoKeyDashboardId]: dashboard.id ?? undefined,
[AnnoKeyDashboardGnetId]: dashboard.gnetId ?? undefined, [AnnoKeyDashboardGnetId]: dashboard.gnetId ?? undefined,
[AnnoKeyDashboardIsSnapshot]: dto.meta.isSnapshot, [AnnoKeyDashboardIsSnapshot]: dto.meta.isSnapshot,
}; };
creationTimestamp = dto.meta.created; creationTimestamp = dto.meta.created;
labelsMeta = {
[DeprecatedInternalId]: dashboard.id ?? undefined,
};
} }
if (annotationsMeta?.[AnnoKeyDashboardIsSnapshot]) { if (annotationsMeta?.[AnnoKeyDashboardIsSnapshot]) {
@ -171,6 +176,7 @@ export function ensureV2Response(
name: dashboard.uid, name: dashboard.uid,
resourceVersion: dashboard.version?.toString() || '0', resourceVersion: dashboard.version?.toString() || '0',
annotations: annotationsMeta, annotations: annotationsMeta,
labels: labelsMeta,
}, },
spec, spec,
access: accessMeta, access: accessMeta,