Git sync / Schema v2: Make preview work with v2 dashboards (#103709)
* Git sync / Schema v2: Make preview work with v2 dashboards * Refactor * Add tests * Clean! * Clean more! * Update public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.ts Co-authored-by: Ivan Ortega Alba <ivanortegaalba@gmail.com> * Add basic v2 dashboard sample * Refactor to be instance independent * Remove commented out code --------- Co-authored-by: Ivan Ortega Alba <ivanortegaalba@gmail.com>
This commit is contained in:
@@ -1530,6 +1530,9 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
|
||||
],
|
||||
"public/app/features/dashboard-scene/pages/DashboardScenePageStateManager.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/features/dashboard-scene/panel-edit/LibraryVizPanelInfo.tsx:5381": [
|
||||
[0, 0, 0, "No untranslated strings. Wrap text with <Trans />", "0"]
|
||||
],
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
{
|
||||
"apiVersion": "dashboard.grafana.app/v2alpha1",
|
||||
"kind": "Dashboard",
|
||||
"metadata": {
|
||||
"name": "sample-dash-v2"
|
||||
},
|
||||
"spec": {
|
||||
"annotations": [
|
||||
{
|
||||
"kind": "AnnotationQuery",
|
||||
"spec": {
|
||||
"builtIn": true,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations \u0026 Alerts"
|
||||
}
|
||||
}
|
||||
],
|
||||
"cursorSync": "Off",
|
||||
"description": "",
|
||||
"editable": true,
|
||||
"elements": {
|
||||
"panel-1": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"hidden": false,
|
||||
"query": {
|
||||
"kind": "grafana-testdata-datasource",
|
||||
"spec": {}
|
||||
},
|
||||
"refId": "A"
|
||||
}
|
||||
}
|
||||
],
|
||||
"queryOptions": {},
|
||||
"transformations": []
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"id": 1,
|
||||
"links": [],
|
||||
"title": "Simle timeseries",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": false,
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "12.0.0-pre"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"panel-2": {
|
||||
"kind": "Panel",
|
||||
"spec": {
|
||||
"data": {
|
||||
"kind": "QueryGroup",
|
||||
"spec": {
|
||||
"queries": [
|
||||
{
|
||||
"kind": "PanelQuery",
|
||||
"spec": {
|
||||
"hidden": false,
|
||||
"query": {
|
||||
"kind": "grafana-testdata-datasource",
|
||||
"spec": {}
|
||||
},
|
||||
"refId": "A"
|
||||
}
|
||||
}
|
||||
],
|
||||
"queryOptions": {},
|
||||
"transformations": []
|
||||
}
|
||||
},
|
||||
"description": "",
|
||||
"id": 2,
|
||||
"links": [],
|
||||
"title": "Simple stat",
|
||||
"vizConfig": {
|
||||
"kind": "stat",
|
||||
"spec": {
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "thresholds"
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"options": {
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"percentChangeColorMode": "standard",
|
||||
"reduceOptions": {
|
||||
"calcs": ["lastNotNull"],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"showPercentChange": false,
|
||||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "12.0.0-pre"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"layout": {
|
||||
"kind": "AutoGridLayout",
|
||||
"spec": {
|
||||
"columnWidthMode": "standard",
|
||||
"items": [
|
||||
{
|
||||
"kind": "AutoGridLayoutItem",
|
||||
"spec": {
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-2"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"kind": "AutoGridLayoutItem",
|
||||
"spec": {
|
||||
"element": {
|
||||
"kind": "ElementReference",
|
||||
"name": "panel-1"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"maxColumnCount": 3,
|
||||
"rowHeightMode": "standard"
|
||||
}
|
||||
},
|
||||
"links": [],
|
||||
"liveNow": false,
|
||||
"preload": false,
|
||||
"tags": [],
|
||||
"timeSettings": {
|
||||
"autoRefresh": "",
|
||||
"autoRefreshIntervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
|
||||
"fiscalYearStartMonth": 0,
|
||||
"from": "now-6h",
|
||||
"hideTimepicker": false,
|
||||
"timezone": "browser",
|
||||
"to": "now"
|
||||
},
|
||||
"title": "v2alpha1 dashboard",
|
||||
"variables": []
|
||||
}
|
||||
}
|
||||
@@ -1004,6 +1004,34 @@ describe('UnifiedDashboardScenePageStateManager', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Provisioned dashboard', () => {
|
||||
it('should load a provisioned v1 dashboard', async () => {
|
||||
const loader = new UnifiedDashboardScenePageStateManager({});
|
||||
setBackendSrv({
|
||||
get: () => Promise.resolve(v1ProvisionedDashboardResource),
|
||||
} as unknown as BackendSrv);
|
||||
await loader.loadDashboard({ uid: 'blah-blah', route: DashboardRoutes.Provisioning });
|
||||
|
||||
expect(loader.state.dashboard).toBeDefined();
|
||||
expect(loader.state.dashboard!.serializer.initialSaveModel).toEqual(
|
||||
v1ProvisionedDashboardResource.resource.dryRun.spec
|
||||
);
|
||||
});
|
||||
|
||||
it('should load a provisioned v2 dashboard', async () => {
|
||||
const loader = new UnifiedDashboardScenePageStateManager({});
|
||||
setBackendSrv({
|
||||
get: () => Promise.resolve(v2ProvisionedDashboardResource),
|
||||
} as unknown as BackendSrv);
|
||||
await loader.loadDashboard({ uid: 'blah-blah', route: DashboardRoutes.Provisioning });
|
||||
|
||||
expect(loader.state.dashboard).toBeDefined();
|
||||
expect(loader.state.dashboard!.serializer.initialSaveModel).toEqual(
|
||||
v2ProvisionedDashboardResource.resource.dryRun.spec
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('New dashboards', () => {
|
||||
it('should use v1 manager for new dashboards when dashboardNewLayouts feature toggle is disabled', async () => {
|
||||
config.featureToggles.dashboardNewLayouts = false;
|
||||
@@ -1184,3 +1212,446 @@ const customHomeDashboardV2Spec = {
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const v1ProvisionedDashboardResource = {
|
||||
kind: 'ResourceWrapper',
|
||||
apiVersion: 'provisioning.grafana.app/v0alpha1',
|
||||
path: 'new-dashboard.json',
|
||||
ref: 'dashboard/2025-04-11-nkXIe',
|
||||
hash: '28e6dd34e226ec27e19f9894270290fc105a77b0',
|
||||
repository: {
|
||||
type: 'github',
|
||||
title: 'https://github.com/dprokop/grafana-git-sync-test',
|
||||
namespace: 'default',
|
||||
name: 'repository-643e5fb',
|
||||
},
|
||||
urls: {
|
||||
sourceURL: 'https://github.com/dprokop/grafana-git-sync-test/blob/dashboard/2025-04-11-nkXIe/new-dashboard.json',
|
||||
repositoryURL: 'https://github.com/dprokop/grafana-git-sync-test',
|
||||
newPullRequestURL:
|
||||
'https://github.com/dprokop/grafana-git-sync-test/compare/main...dashboard/2025-04-11-nkXIe?quick_pull=1&labels=grafana',
|
||||
compareURL: 'https://github.com/dprokop/grafana-git-sync-test/compare/main...dashboard/2025-04-11-nkXIe',
|
||||
},
|
||||
resource: {
|
||||
type: {
|
||||
group: 'dashboard.grafana.app',
|
||||
version: 'v1alpha1',
|
||||
kind: 'Dashboard',
|
||||
resource: 'dashboards',
|
||||
},
|
||||
file: {},
|
||||
existing: {},
|
||||
action: 'update',
|
||||
dryRun: {
|
||||
apiVersion: 'dashboard.grafana.app/v1alpha1',
|
||||
kind: 'Dashboard',
|
||||
metadata: {
|
||||
annotations: {
|
||||
'grafana.app/managedBy': 'repo',
|
||||
'grafana.app/managerId': 'repository-643e5fb',
|
||||
'grafana.app/sourceChecksum': '28e6dd34e226ec27e19f9894270290fc105a77b0',
|
||||
'grafana.app/sourcePath': 'new-dashboard.json',
|
||||
},
|
||||
creationTimestamp: '2025-04-09T07:27:46Z',
|
||||
generation: 1,
|
||||
managedFields: [
|
||||
{
|
||||
apiVersion: 'dashboard.grafana.app/v1alpha1',
|
||||
fieldsType: 'FieldsV1',
|
||||
fieldsV1: {
|
||||
'f:metadata': {
|
||||
'f:annotations': {
|
||||
'.': {},
|
||||
'f:grafana.app/managedBy': {},
|
||||
'f:grafana.app/managerId': {},
|
||||
'f:grafana.app/sourceChecksum': {},
|
||||
'f:grafana.app/sourcePath': {},
|
||||
},
|
||||
},
|
||||
'f:spec': {
|
||||
'f:annotations': {
|
||||
'.': {},
|
||||
'f:list': {},
|
||||
},
|
||||
'f:editable': {},
|
||||
'f:fiscalYearStartMonth': {},
|
||||
'f:graphTooltip': {},
|
||||
'f:links': {},
|
||||
'f:panels': {},
|
||||
'f:preload': {},
|
||||
'f:schemaVersion': {},
|
||||
'f:tags': {},
|
||||
'f:templating': {
|
||||
'.': {},
|
||||
'f:list': {},
|
||||
},
|
||||
'f:time': {
|
||||
'.': {},
|
||||
'f:from': {},
|
||||
'f:to': {},
|
||||
},
|
||||
'f:timepicker': {},
|
||||
'f:timezone': {},
|
||||
'f:title': {},
|
||||
},
|
||||
},
|
||||
manager: 'grafana',
|
||||
operation: 'Update',
|
||||
time: '2025-04-11T10:35:05Z',
|
||||
},
|
||||
],
|
||||
name: 'adsm7zf',
|
||||
namespace: 'default',
|
||||
resourceVersion: '1744183666927980',
|
||||
uid: 'ef523e2b-1e66-4921-b3f9-e7a9b215c988',
|
||||
},
|
||||
spec: {
|
||||
annotations: {
|
||||
list: [
|
||||
{
|
||||
builtIn: 1,
|
||||
datasource: {
|
||||
type: 'grafana',
|
||||
uid: '-- Grafana --',
|
||||
},
|
||||
enable: true,
|
||||
hide: true,
|
||||
iconColor: 'rgba(0, 211, 255, 1)',
|
||||
name: 'Annotations & Alerts',
|
||||
type: 'dashboard',
|
||||
},
|
||||
],
|
||||
},
|
||||
editable: true,
|
||||
fiscalYearStartMonth: 0,
|
||||
graphTooltip: 0,
|
||||
links: [],
|
||||
panels: [
|
||||
{
|
||||
datasource: {
|
||||
type: 'grafana-testdata-datasource',
|
||||
uid: 'PD8C576611E62080A',
|
||||
},
|
||||
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',
|
||||
},
|
||||
},
|
||||
mappings: [],
|
||||
thresholds: {
|
||||
mode: 'absolute',
|
||||
steps: [
|
||||
{
|
||||
color: 'green',
|
||||
},
|
||||
{
|
||||
color: 'red',
|
||||
value: 80,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
overrides: [],
|
||||
},
|
||||
gridPos: {
|
||||
h: 8,
|
||||
w: 10,
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
id: 1,
|
||||
options: {
|
||||
legend: {
|
||||
calcs: [],
|
||||
displayMode: 'list',
|
||||
placement: 'bottom',
|
||||
showLegend: true,
|
||||
},
|
||||
tooltip: {
|
||||
hideZeros: false,
|
||||
mode: 'single',
|
||||
sort: 'none',
|
||||
},
|
||||
},
|
||||
pluginVersion: '12.0.0-pre',
|
||||
targets: [
|
||||
{
|
||||
refId: 'A',
|
||||
},
|
||||
],
|
||||
title: 'New panel',
|
||||
type: 'timeseries',
|
||||
},
|
||||
],
|
||||
preload: false,
|
||||
schemaVersion: 41,
|
||||
tags: [],
|
||||
templating: {
|
||||
list: [],
|
||||
},
|
||||
time: {
|
||||
from: 'now-6h',
|
||||
to: 'now',
|
||||
},
|
||||
timepicker: {},
|
||||
timezone: 'browser',
|
||||
title: 'New dashboard',
|
||||
},
|
||||
status: {},
|
||||
},
|
||||
upsert: null,
|
||||
},
|
||||
};
|
||||
|
||||
const v2ProvisionedDashboardResource = {
|
||||
kind: 'ResourceWrapper',
|
||||
apiVersion: 'provisioning.grafana.app/v0alpha1',
|
||||
path: 'v2dashboards/new-dashboard-2025-04-09-nTqgq.json',
|
||||
ref: 'dashboard/2025-04-11-FzFKZ',
|
||||
hash: '2d1c7981d4327f5c75afd920e910f1f82e9be706',
|
||||
repository: {
|
||||
type: 'github',
|
||||
title: 'https://github.com/dprokop/grafana-git-sync-test',
|
||||
namespace: 'default',
|
||||
name: 'repository-643e5fb',
|
||||
},
|
||||
urls: {
|
||||
sourceURL:
|
||||
'https://github.com/dprokop/grafana-git-sync-test/blob/dashboard/2025-04-11-FzFKZ/v2dashboards/new-dashboard-2025-04-09-nTqgq.json',
|
||||
repositoryURL: 'https://github.com/dprokop/grafana-git-sync-test',
|
||||
newPullRequestURL:
|
||||
'https://github.com/dprokop/grafana-git-sync-test/compare/main...dashboard/2025-04-11-FzFKZ?quick_pull=1&labels=grafana',
|
||||
compareURL: 'https://github.com/dprokop/grafana-git-sync-test/compare/main...dashboard/2025-04-11-FzFKZ',
|
||||
},
|
||||
resource: {
|
||||
type: {
|
||||
group: 'dashboard.grafana.app',
|
||||
version: 'v2alpha1',
|
||||
kind: 'Dashboard',
|
||||
resource: 'dashboards',
|
||||
},
|
||||
file: {},
|
||||
existing: {},
|
||||
action: 'update',
|
||||
dryRun: {
|
||||
apiVersion: 'dashboard.grafana.app/v2alpha1',
|
||||
kind: 'Dashboard',
|
||||
metadata: {
|
||||
annotations: {
|
||||
'grafana.app/folder': 'v2dashboards-8mdocprxtfyldpbpod3ayidiitt',
|
||||
'grafana.app/managedBy': 'repo',
|
||||
'grafana.app/managerId': 'repository-643e5fb',
|
||||
'grafana.app/sourceChecksum': '2d1c7981d4327f5c75afd920e910f1f82e9be706',
|
||||
'grafana.app/sourcePath': 'v2dashboards/new-dashboard-2025-04-09-nTqgq.json',
|
||||
},
|
||||
creationTimestamp: '2025-04-09T12:11:20Z',
|
||||
generation: 1,
|
||||
name: 'dfeidsuico01kwc',
|
||||
namespace: 'default',
|
||||
resourceVersion: '1744200680060000',
|
||||
uid: '47ed4201-a181-4d1c-b755-17548526d294',
|
||||
},
|
||||
spec: {
|
||||
annotations: [
|
||||
{
|
||||
kind: 'AnnotationQuery',
|
||||
spec: {
|
||||
builtIn: true,
|
||||
datasource: {
|
||||
type: 'grafana',
|
||||
uid: '-- Grafana --',
|
||||
},
|
||||
enable: true,
|
||||
hide: true,
|
||||
iconColor: 'rgba(0, 211, 255, 1)',
|
||||
name: 'Annotations & Alerts',
|
||||
},
|
||||
},
|
||||
],
|
||||
cursorSync: 'Off',
|
||||
description: '',
|
||||
editable: true,
|
||||
elements: {
|
||||
'panel-1': {
|
||||
kind: 'Panel',
|
||||
spec: {
|
||||
data: {
|
||||
kind: 'QueryGroup',
|
||||
spec: {
|
||||
queries: [
|
||||
{
|
||||
kind: 'PanelQuery',
|
||||
spec: {
|
||||
datasource: {
|
||||
type: 'grafana-testdata-datasource',
|
||||
uid: 'PD8C576611E62080A',
|
||||
},
|
||||
hidden: false,
|
||||
query: {
|
||||
kind: 'grafana-testdata-datasource',
|
||||
spec: {
|
||||
scenarioId: 'random_walk',
|
||||
seriesCount: 2,
|
||||
},
|
||||
},
|
||||
refId: 'A',
|
||||
},
|
||||
},
|
||||
],
|
||||
queryOptions: {},
|
||||
transformations: [],
|
||||
},
|
||||
},
|
||||
description: '',
|
||||
id: 1,
|
||||
links: [],
|
||||
title: 'New panel',
|
||||
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.0.0-pre',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
kind: 'AutoGridLayout',
|
||||
spec: {
|
||||
columnWidthMode: 'standard',
|
||||
items: [
|
||||
{
|
||||
kind: 'AutoGridLayoutItem',
|
||||
spec: {
|
||||
element: {
|
||||
kind: 'ElementReference',
|
||||
name: 'panel-1',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
maxColumnCount: 3,
|
||||
rowHeightMode: 'short',
|
||||
},
|
||||
},
|
||||
links: [],
|
||||
liveNow: false,
|
||||
preload: false,
|
||||
tags: [],
|
||||
timeSettings: {
|
||||
autoRefresh: '',
|
||||
autoRefreshIntervals: ['5s', '10s', '30s', '1m', '5m', '15m', '30m', '1h', '2h', '1d'],
|
||||
fiscalYearStartMonth: 0,
|
||||
from: 'now-6h',
|
||||
hideTimepicker: false,
|
||||
timezone: 'browser',
|
||||
to: 'now',
|
||||
},
|
||||
title: 'v2 test - auto grid',
|
||||
variables: [],
|
||||
},
|
||||
status: {},
|
||||
},
|
||||
upsert: null,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4,10 +4,16 @@ import { locationUtil, UrlQueryMap } from '@grafana/data';
|
||||
import { config, getBackendSrv, isFetchError, locationService } from '@grafana/runtime';
|
||||
import { sceneGraph } from '@grafana/scenes';
|
||||
import { Spec as DashboardV2Spec } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha1/types.spec.gen';
|
||||
import { BASE_URL } from 'app/api/clients/provisioning/baseAPI';
|
||||
import { StateManagerBase } from 'app/core/services/StateManagerBase';
|
||||
import { getMessageFromError, getMessageIdFromError, getStatusFromError } from 'app/core/utils/errors';
|
||||
import { startMeasure, stopMeasure } from 'app/core/utils/metrics';
|
||||
import { AnnoKeyFolder } from 'app/features/apiserver/types';
|
||||
import {
|
||||
AnnoKeyFolder,
|
||||
AnnoKeyManagerIdentity,
|
||||
AnnoKeyManagerKind,
|
||||
AnnoKeySourcePath,
|
||||
} from 'app/features/apiserver/types';
|
||||
import { transformDashboardV2SpecToV1 } from 'app/features/dashboard/api/ResponseTransformers';
|
||||
import { DashboardVersionError, DashboardWithAccessInfo } from 'app/features/dashboard/api/types';
|
||||
import { isDashboardV2Resource, isDashboardV2Spec } from 'app/features/dashboard/api/utils';
|
||||
@@ -15,6 +21,7 @@ import { dashboardLoaderSrv, DashboardLoaderSrvV2 } from 'app/features/dashboard
|
||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||
import { emitDashboardViewEvent } from 'app/features/dashboard/state/analyticsProcessor';
|
||||
import { trackDashboardSceneLoaded } from 'app/features/dashboard/utils/tracking';
|
||||
import { ProvisioningPreview } from 'app/features/provisioning/types';
|
||||
import {
|
||||
DashboardDataDTO,
|
||||
DashboardDTO,
|
||||
@@ -176,6 +183,84 @@ abstract class DashboardScenePageStateManagerBase<T>
|
||||
}
|
||||
}
|
||||
|
||||
protected async loadProvisioningDashboard(repo: string, path: string): Promise<T> {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const ref = params.get('ref') ?? undefined; // commit hash or branch
|
||||
|
||||
const url = `${BASE_URL}/repositories/${repo}/files/${path}`;
|
||||
return getBackendSrv()
|
||||
.get(url, ref ? { ref } : undefined)
|
||||
.then((v) => {
|
||||
// Load the results from dryRun
|
||||
const dryRun = v.resource.dryRun;
|
||||
if (!dryRun) {
|
||||
return Promise.reject('failed to read provisioned dashboard');
|
||||
}
|
||||
|
||||
if (!dryRun.apiVersion.startsWith('dashboard.grafana.app')) {
|
||||
return Promise.reject('unexpected resource type: ' + dryRun.apiVersion);
|
||||
}
|
||||
|
||||
return this.processDashboardFromProvisioning(repo, path, dryRun, {
|
||||
file: url,
|
||||
ref: ref,
|
||||
repo: repo,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private processDashboardFromProvisioning(
|
||||
repo: string,
|
||||
path: string,
|
||||
dryRun: any,
|
||||
provisioningPreview: ProvisioningPreview
|
||||
) {
|
||||
if (dryRun.apiVersion.split('/')[1] === 'v2alpha1') {
|
||||
return {
|
||||
...dryRun,
|
||||
kind: 'DashboardWithAccessInfo',
|
||||
access: {
|
||||
canStar: false,
|
||||
isSnapshot: false,
|
||||
canShare: false,
|
||||
|
||||
// Should come from the repo settings
|
||||
canDelete: true,
|
||||
canSave: true,
|
||||
canEdit: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
let anno = dryRun.metadata.annotations;
|
||||
if (!anno) {
|
||||
dryRun.metadata.annotations = {};
|
||||
}
|
||||
anno[AnnoKeyManagerKind] = 'repo';
|
||||
anno[AnnoKeyManagerIdentity] = repo;
|
||||
anno[AnnoKeySourcePath] = provisioningPreview.ref ? path + '#' + provisioningPreview.ref : path;
|
||||
|
||||
return {
|
||||
meta: {
|
||||
canStar: false,
|
||||
isSnapshot: false,
|
||||
canShare: false,
|
||||
|
||||
// Should come from the repo settings
|
||||
canDelete: true,
|
||||
canSave: true,
|
||||
canEdit: true,
|
||||
|
||||
// Includes additional k8s metadata
|
||||
k8s: dryRun.metadata,
|
||||
|
||||
// lookup info
|
||||
provisioning: provisioningPreview,
|
||||
},
|
||||
dashboard: dryRun.spec,
|
||||
};
|
||||
}
|
||||
|
||||
public async loadDashboard(options: LoadDashboardOptions) {
|
||||
try {
|
||||
startMeasure(LOAD_SCENE_MEASUREMENT);
|
||||
@@ -230,15 +315,15 @@ abstract class DashboardScenePageStateManagerBase<T>
|
||||
// Handling home dashboard flow separately from regular dashboard flow.
|
||||
if (options.route === DashboardRoutes.Home) {
|
||||
return await this.loadHomeDashboard();
|
||||
} else {
|
||||
const rsp = await this.fetchDashboard(options);
|
||||
|
||||
if (!rsp) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.transformResponseToScene(rsp, options);
|
||||
}
|
||||
|
||||
const rsp = await this.fetchDashboard(options);
|
||||
|
||||
if (!rsp) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.transformResponseToScene(rsp, options);
|
||||
}
|
||||
|
||||
public getDashboardFromCache(cacheKey: string): T | null {
|
||||
@@ -356,9 +441,8 @@ export class DashboardScenePageStateManager extends DashboardScenePageStateManag
|
||||
case DashboardRoutes.New:
|
||||
rsp = await buildNewDashboardSaveModel(urlFolderUid);
|
||||
break;
|
||||
case DashboardRoutes.Provisioning: {
|
||||
return await dashboardLoaderSrv.loadDashboard('provisioning', slug, uid);
|
||||
}
|
||||
case DashboardRoutes.Provisioning:
|
||||
return this.loadProvisioningDashboard(slug || '', uid);
|
||||
case DashboardRoutes.Public: {
|
||||
return await dashboardLoaderSrv.loadDashboard('public', '', uid);
|
||||
}
|
||||
@@ -537,6 +621,9 @@ export class DashboardScenePageStateManagerV2 extends DashboardScenePageStateMan
|
||||
case DashboardRoutes.New:
|
||||
rsp = await buildNewDashboardSaveModelV2(urlFolderUid);
|
||||
break;
|
||||
case DashboardRoutes.Provisioning: {
|
||||
return await this.loadProvisioningDashboard(slug || '', uid);
|
||||
}
|
||||
case DashboardRoutes.Public: {
|
||||
return await this.dashboardLoader.loadDashboard('public', '', uid);
|
||||
}
|
||||
@@ -703,7 +790,6 @@ export class UnifiedDashboardScenePageStateManager extends DashboardScenePageSta
|
||||
if (!rsp) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isDashboardV2Resource(rsp)) {
|
||||
this.activeManager = this.v2Manager;
|
||||
return this.v2Manager.transformResponseToScene(rsp, options);
|
||||
|
||||
@@ -39,7 +39,11 @@ import { PanelEditor } from '../panel-edit/PanelEditor';
|
||||
import { DashboardSceneChangeTracker } from '../saving/DashboardSceneChangeTracker';
|
||||
import { SaveDashboardDrawer } from '../saving/SaveDashboardDrawer';
|
||||
import { DashboardChangeInfo } from '../saving/shared';
|
||||
import { DashboardSceneSerializerLike, getDashboardSceneSerializer } from '../serialization/DashboardSceneSerializer';
|
||||
import {
|
||||
DashboardSceneSerializerLike,
|
||||
getDashboardSceneSerializer,
|
||||
V2DashboardSerializer,
|
||||
} from '../serialization/DashboardSceneSerializer';
|
||||
import { serializeAutoGridItem } from '../serialization/layoutSerializers/AutoGridLayoutSerializer';
|
||||
import { gridItemToGridLayoutItemKind } from '../serialization/layoutSerializers/DefaultGridLayoutSerializer';
|
||||
import { getElement } from '../serialization/layoutSerializers/utils';
|
||||
@@ -767,8 +771,10 @@ export class DashboardScene extends SceneObjectBase<DashboardSceneState> impleme
|
||||
getSaveResource(options: SaveDashboardAsOptions): ResourceForCreate<unknown> {
|
||||
const { meta } = this.state;
|
||||
const spec = this.getSaveAsModel(options);
|
||||
|
||||
const apiVersion = this.serializer instanceof V2DashboardSerializer ? 'v2alpha1' : 'v1alpha1'; // get from the dashboard?
|
||||
return {
|
||||
apiVersion: 'dashboard.grafana.app/v1alpha1', // get from the dashboard?
|
||||
apiVersion: `dashboard.grafana.app/${apiVersion}`,
|
||||
kind: 'Dashboard',
|
||||
metadata: {
|
||||
...meta.k8s,
|
||||
|
||||
@@ -13,7 +13,6 @@ import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||
import { DashboardDTO } from 'app/types';
|
||||
|
||||
import { appEvents } from '../../../core/core';
|
||||
import { loadDashboardFromProvisioning } from '../../provisioning/dashboardLoader';
|
||||
import { ResponseTransformers } from '../api/ResponseTransformers';
|
||||
import { getDashboardAPI } from '../api/dashboard_api';
|
||||
import { DashboardVersionError, DashboardWithAccessInfo } from '../api/types';
|
||||
@@ -37,6 +36,7 @@ abstract class DashboardLoaderSrvBase<T> implements DashboardLoaderSrvLike<T> {
|
||||
uid: string | undefined,
|
||||
params?: UrlQueryMap
|
||||
): Promise<T>;
|
||||
|
||||
abstract loadSnapshot(slug: string): Promise<T>;
|
||||
|
||||
protected loadScriptedDashboard(file: string) {
|
||||
@@ -124,10 +124,6 @@ export class DashboardLoaderSrv extends DashboardLoaderSrvBase<DashboardDTO> {
|
||||
|
||||
if (type === 'script' && slug) {
|
||||
promise = this.loadScriptedDashboard(slug);
|
||||
} else if (type === 'provisioning' && uid && slug) {
|
||||
promise = loadDashboardFromProvisioning(slug, uid);
|
||||
// needed for the old architecture
|
||||
// in scenes this is handled through loadSnapshot method
|
||||
} else if (type === 'snapshot' && slug) {
|
||||
promise = getDashboardSnapshotSrv().getSnapshot(slug);
|
||||
} else if (type === 'public' && uid) {
|
||||
@@ -200,8 +196,6 @@ export class DashboardLoaderSrvV2 extends DashboardLoaderSrvBase<DashboardWithAc
|
||||
promise = backendSrv.getPublicDashboardByUid(uid).then((result) => {
|
||||
return ResponseTransformers.ensureV2Response(result);
|
||||
});
|
||||
} else if (type === 'provisioning' && uid && slug) {
|
||||
promise = loadDashboardFromProvisioning(slug, uid).then((r) => ResponseTransformers.ensureV2Response(r));
|
||||
} else if (uid) {
|
||||
if (!params) {
|
||||
const cachedDashboard = stateManager.getDashboardFromCache(uid);
|
||||
@@ -263,5 +257,6 @@ export const setDashboardLoaderSrv = (srv: DashboardLoaderSrv) => {
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
throw new Error('dashboardLoaderSrv can be only overriden in test environment');
|
||||
}
|
||||
|
||||
dashboardLoaderSrv = srv;
|
||||
};
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
import { BASE_URL } from 'app/api/clients/provisioning/baseAPI';
|
||||
import { DashboardDTO } from 'app/types';
|
||||
|
||||
import { AnnoKeyManagerIdentity, AnnoKeyManagerKind, AnnoKeySourcePath } from '../apiserver/types';
|
||||
|
||||
/**
|
||||
*
|
||||
* Load a dashboard from repository
|
||||
*/
|
||||
export async function loadDashboardFromProvisioning(repo: string, path: string): Promise<DashboardDTO> {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const ref = params.get('ref') ?? undefined; // commit hash or branch
|
||||
|
||||
const url = `${BASE_URL}/repositories/${repo}/files/${path}`;
|
||||
return getBackendSrv()
|
||||
.get(url, ref ? { ref } : undefined)
|
||||
.then((v) => {
|
||||
// Load the results from dryRun
|
||||
const dryRun = v.resource.dryRun;
|
||||
if (!dryRun) {
|
||||
return Promise.reject('failed to read provisioned dashboard');
|
||||
}
|
||||
|
||||
if (!dryRun.apiVersion.startsWith('dashboard.grafana.app')) {
|
||||
return Promise.reject('unexpected resource type: ' + dryRun.apiVersion);
|
||||
}
|
||||
|
||||
// Make sure the annotation key exists
|
||||
let anno = dryRun.metadata.annotations;
|
||||
if (!anno) {
|
||||
dryRun.metadata.annotations = {};
|
||||
}
|
||||
anno[AnnoKeyManagerKind] = 'repo';
|
||||
anno[AnnoKeyManagerIdentity] = repo;
|
||||
anno[AnnoKeySourcePath] = ref ? path + '#' + ref : path;
|
||||
|
||||
return {
|
||||
meta: {
|
||||
canStar: false,
|
||||
isSnapshot: false,
|
||||
canShare: false,
|
||||
|
||||
// Should come from the repo settings
|
||||
canDelete: true,
|
||||
canSave: true,
|
||||
canEdit: true,
|
||||
|
||||
// Includes additional k8s metadata
|
||||
k8s: dryRun.metadata,
|
||||
|
||||
// lookup info
|
||||
provisioning: {
|
||||
file: url,
|
||||
ref: ref,
|
||||
repo: repo,
|
||||
},
|
||||
},
|
||||
dashboard: dryRun.spec,
|
||||
};
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user