diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v10.table_thresholds.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v10.table_thresholds.v0alpha1.json index 5a6cebb8a91..e181c66eaf1 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v10.table_thresholds.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v10.table_thresholds.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +79,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v10.table_thresholds.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v10.table_thresholds.v1beta1.json index 122c6772dfe..6c7da8a3864 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v10.table_thresholds.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v10.table_thresholds.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +79,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v11.no-op-migration.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v11.no-op-migration.v0alpha1.json index 0442d15c222..ed6e158988b 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v11.no-op-migration.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v11.no-op-migration.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v11.no-op-migration.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v11.no-op-migration.v1beta1.json index e1548f77853..dab8e4d166c 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v11.no-op-migration.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v11.no-op-migration.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.graph_thresholds.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.graph_thresholds.v0alpha1.json index 7aadfcf8535..0d943be33e1 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.graph_thresholds.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.graph_thresholds.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +79,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -93,6 +105,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -115,6 +131,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.graph_thresholds.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.graph_thresholds.v1beta1.json index 7f7f61699e5..7d51fccb5f4 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.graph_thresholds.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.graph_thresholds.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +79,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -93,6 +105,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -115,6 +131,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.minimal_graph_config.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.minimal_graph_config.v0alpha1.json index e768e617055..d26aeb546b0 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.minimal_graph_config.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.minimal_graph_config.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.minimal_graph_config.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.minimal_graph_config.v1beta1.json index 2c88ea03447..1dc3f1743cd 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.minimal_graph_config.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v13.minimal_graph_config.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v14.shared_crosshair_to_graph_tooltip.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v14.shared_crosshair_to_graph_tooltip.v0alpha1.json index 6f6b04077da..cefd07bd3b0 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v14.shared_crosshair_to_graph_tooltip.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v14.shared_crosshair_to_graph_tooltip.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -50,6 +54,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v14.shared_crosshair_to_graph_tooltip.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v14.shared_crosshair_to_graph_tooltip.v1beta1.json index d83cb315419..765bf5993d3 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v14.shared_crosshair_to_graph_tooltip.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v14.shared_crosshair_to_graph_tooltip.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -50,6 +54,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.mimir_rollout_debugging.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.mimir_rollout_debugging.v0alpha1.json index cc366a688e3..556e8ee5040 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.mimir_rollout_debugging.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.mimir_rollout_debugging.v0alpha1.json @@ -65,6 +65,9 @@ "type": "row" }, { + "datasource": { + "uid": "$datasource" + }, "description": "### Versions running\nShows the versions reported by each running pod.\n\nThe rollout will fail if any pod is not running the expected version.\n\nPods in green are running the expected version, while pods running other versions are shown in orange.\n\n", "fieldConfig": { "defaults": { @@ -185,6 +188,9 @@ "type": "barchart" }, { + "datasource": { + "uid": "$datasource" + }, "description": "### Deployment rollout progress\nShows the number of pods for each `Deployment` that match the desired configuration, as a proportion of the desired number of pods.\n\nThe rollout will fail if insufficient pods match the desired configuration for any `Deployment`.\n\nPods in green match the desired configuration, while pods that do not match the desired configuration are shown in orange.\n\n", "fieldConfig": { "defaults": { @@ -286,6 +292,9 @@ "type": "barchart" }, { + "datasource": { + "uid": "$datasource" + }, "description": "### StatefulSet rollout progress\nShows the number of pods for each `StatefulSet` that match the desired configuration, as a proportion of the desired number of pods.\n\nThe rollout will fail if insufficient pods match the desired configuration for any `StatefulSet`.\n\nPods in green match the desired configuration, while pods that do not match the desired configuration are shown in orange.\n\n", "fieldConfig": { "defaults": { @@ -399,6 +408,9 @@ "type": "row" }, { + "datasource": { + "uid": "$datasource" + }, "description": "### Aggregator lag\nShows the consumption lag of each aggregator pod.\n\nThis panel may show no data if aggregators are not deployed to this cell.\n\nThe rollout will fail if any pod's consumption lag is both:\n* greater than 30s (red area on graph), and\n* trending upwards compared to 1 minute earlier\n\n", "fieldConfig": { "defaults": { @@ -468,6 +480,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "$datasource" + }, "description": "### Unhealthy Deployment replicas\nShows the number of unavailable pods for each `Deployment`.\n\nThe rollout will fail if any `Deployment` has an unavailable pod.\n\nBoth this panel and the rollout check ignore any `Deployment`s that require spot nodes, as these are expected to be unavailable from time to time.\n\n`Deployment`s shown in green do not have any unavailable pods, while `Deployment`s shown in orange have one or more unavailable pods.\n\n", "fieldConfig": { "defaults": { @@ -569,6 +584,9 @@ "type": "barchart" }, { + "datasource": { + "uid": "$datasource" + }, "description": "### Unhealthy StatefulSet replicas\nShows the number of pods for each `StatefulSet` that are not ready.\n\nThe rollout will fail if any `StatefulSet` has fewer ready pods than requested.\n\nBoth this panel and the rollout check ignore any `StatefulSets`s that require spot nodes, as these are expected to be unavailable from time to time.\n\n`StatefulSets`s shown in green do not have any pods that are not ready, while `StatefulSet`s shown in orange have one or more pods that are not ready.\n\n", "fieldConfig": { "defaults": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.mimir_rollout_debugging.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.mimir_rollout_debugging.v1beta1.json index cbe61ee0ed7..0b50d42fbe7 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.mimir_rollout_debugging.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.mimir_rollout_debugging.v1beta1.json @@ -65,6 +65,9 @@ "type": "row" }, { + "datasource": { + "uid": "$datasource" + }, "description": "### Versions running\nShows the versions reported by each running pod.\n\nThe rollout will fail if any pod is not running the expected version.\n\nPods in green are running the expected version, while pods running other versions are shown in orange.\n\n", "fieldConfig": { "defaults": { @@ -185,6 +188,9 @@ "type": "barchart" }, { + "datasource": { + "uid": "$datasource" + }, "description": "### Deployment rollout progress\nShows the number of pods for each `Deployment` that match the desired configuration, as a proportion of the desired number of pods.\n\nThe rollout will fail if insufficient pods match the desired configuration for any `Deployment`.\n\nPods in green match the desired configuration, while pods that do not match the desired configuration are shown in orange.\n\n", "fieldConfig": { "defaults": { @@ -286,6 +292,9 @@ "type": "barchart" }, { + "datasource": { + "uid": "$datasource" + }, "description": "### StatefulSet rollout progress\nShows the number of pods for each `StatefulSet` that match the desired configuration, as a proportion of the desired number of pods.\n\nThe rollout will fail if insufficient pods match the desired configuration for any `StatefulSet`.\n\nPods in green match the desired configuration, while pods that do not match the desired configuration are shown in orange.\n\n", "fieldConfig": { "defaults": { @@ -399,6 +408,9 @@ "type": "row" }, { + "datasource": { + "uid": "$datasource" + }, "description": "### Aggregator lag\nShows the consumption lag of each aggregator pod.\n\nThis panel may show no data if aggregators are not deployed to this cell.\n\nThe rollout will fail if any pod's consumption lag is both:\n* greater than 30s (red area on graph), and\n* trending upwards compared to 1 minute earlier\n\n", "fieldConfig": { "defaults": { @@ -468,6 +480,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "$datasource" + }, "description": "### Unhealthy Deployment replicas\nShows the number of unavailable pods for each `Deployment`.\n\nThe rollout will fail if any `Deployment` has an unavailable pod.\n\nBoth this panel and the rollout check ignore any `Deployment`s that require spot nodes, as these are expected to be unavailable from time to time.\n\n`Deployment`s shown in green do not have any unavailable pods, while `Deployment`s shown in orange have one or more unavailable pods.\n\n", "fieldConfig": { "defaults": { @@ -569,6 +584,9 @@ "type": "barchart" }, { + "datasource": { + "uid": "$datasource" + }, "description": "### Unhealthy StatefulSet replicas\nShows the number of pods for each `StatefulSet` that are not ready.\n\nThe rollout will fail if any `StatefulSet` has fewer ready pods than requested.\n\nBoth this panel and the rollout check ignore any `StatefulSets`s that require spot nodes, as these are expected to be unavailable from time to time.\n\n`StatefulSets`s shown in green do not have any pods that are not ready, while `StatefulSet`s shown in orange have one or more pods that are not ready.\n\n", "fieldConfig": { "defaults": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.no-op-migration.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.no-op-migration.v0alpha1.json index dd68f978199..720fff258cc 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.no-op-migration.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.no-op-migration.v0alpha1.json @@ -37,6 +37,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -59,6 +63,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.no-op-migration.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.no-op-migration.v1beta1.json index 6efa2fd1853..370eafaad0c 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.no-op-migration.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v15.no-op-migration.v1beta1.json @@ -37,6 +37,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -59,6 +63,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.empty-rows-and-panels-array.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.empty-rows-and-panels-array.v0alpha1.json index 3d8d1b11ad3..99a2102204c 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.empty-rows-and-panels-array.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.empty-rows-and-panels-array.v0alpha1.json @@ -44,6 +44,9 @@ "liveNow": false, "panels": [ { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample metric showing connection count.", "fieldConfig": { "defaults": { @@ -134,6 +137,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample counter metric.", "fieldConfig": { "defaults": { @@ -224,6 +230,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample error metric.", "fieldConfig": { "defaults": { @@ -314,6 +323,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample event rate metric.", "fieldConfig": { "defaults": { @@ -404,6 +416,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample resource utilization metric.", "fieldConfig": { "defaults": { @@ -493,6 +508,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample memory allocation metrics.", "fieldConfig": { "defaults": { @@ -593,6 +611,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample utilization percentage.", "fieldConfig": { "defaults": { @@ -662,6 +683,9 @@ "type": "row" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample latency metric for primary operations.", "fieldConfig": { "defaults": { @@ -748,6 +772,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample latency metric for secondary operations.", "fieldConfig": { "defaults": { @@ -834,6 +861,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample expansion events metric.", "fieldConfig": { "defaults": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.empty-rows-and-panels-array.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.empty-rows-and-panels-array.v1beta1.json index e93a8eb3132..58f46289f57 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.empty-rows-and-panels-array.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.empty-rows-and-panels-array.v1beta1.json @@ -44,6 +44,9 @@ "liveNow": false, "panels": [ { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample metric showing connection count.", "fieldConfig": { "defaults": { @@ -134,6 +137,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample counter metric.", "fieldConfig": { "defaults": { @@ -224,6 +230,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample error metric.", "fieldConfig": { "defaults": { @@ -314,6 +323,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample event rate metric.", "fieldConfig": { "defaults": { @@ -404,6 +416,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample resource utilization metric.", "fieldConfig": { "defaults": { @@ -493,6 +508,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample memory allocation metrics.", "fieldConfig": { "defaults": { @@ -593,6 +611,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample utilization percentage.", "fieldConfig": { "defaults": { @@ -662,6 +683,9 @@ "type": "row" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample latency metric for primary operations.", "fieldConfig": { "defaults": { @@ -748,6 +772,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample latency metric for secondary operations.", "fieldConfig": { "defaults": { @@ -834,6 +861,9 @@ "type": "timeseries" }, { + "datasource": { + "uid": "${example_datasource}" + }, "description": "Sample expansion events metric.", "fieldConfig": { "defaults": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.grid_layout_upgrade.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.grid_layout_upgrade.v0alpha1.json index 286cc75e2c0..025ec384a0c 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.grid_layout_upgrade.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.grid_layout_upgrade.v0alpha1.json @@ -39,6 +39,10 @@ "type": "row" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 7, "w": 12, @@ -61,6 +65,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 7, "w": 12, @@ -151,6 +159,10 @@ "type": "row" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 6, "w": 8, @@ -173,6 +185,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 6, "w": 8, @@ -195,6 +211,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 6, "w": 8, @@ -229,6 +249,10 @@ "type": "row" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 4, "w": 16, @@ -251,6 +275,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 8, @@ -286,6 +314,10 @@ "type": "row" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 7, "w": 24, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.grid_layout_upgrade.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.grid_layout_upgrade.v1beta1.json index a4d76abe265..1334aad64b4 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.grid_layout_upgrade.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.grid_layout_upgrade.v1beta1.json @@ -39,6 +39,10 @@ "type": "row" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 7, "w": 12, @@ -61,6 +65,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 7, "w": 12, @@ -151,6 +159,10 @@ "type": "row" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 6, "w": 8, @@ -173,6 +185,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 6, "w": 8, @@ -195,6 +211,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 6, "w": 8, @@ -229,6 +249,10 @@ "type": "row" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 4, "w": 16, @@ -251,6 +275,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 8, @@ -286,6 +314,10 @@ "type": "row" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 7, "w": 24, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.span_zero_demo.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.span_zero_demo.v0alpha1.json index a57a713ba61..0279b19424c 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.span_zero_demo.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.span_zero_demo.v0alpha1.json @@ -41,6 +41,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 24, @@ -78,6 +82,10 @@ "type": "row" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 7, "w": 8, @@ -103,6 +111,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 7, "w": 8, @@ -128,6 +140,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "fieldConfig": { "defaults": { "thresholds": { @@ -174,6 +190,10 @@ "type": "stat" }, { + "datasource": { + "type": "loki", + "uid": "${loki}" + }, "gridPos": { "h": 7, "w": 8, @@ -202,6 +222,10 @@ "type": "logs" }, { + "datasource": { + "type": "loki", + "uid": "${loki}" + }, "gridPos": { "h": 7, "w": 8, @@ -230,6 +254,10 @@ "type": "logs" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 7, "w": 8, @@ -255,6 +283,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "description": "Number of concurrent processing threads available for handling operations", "gridPos": { "h": 7, @@ -280,6 +312,10 @@ "type": "stat" }, { + "datasource": { + "type": "tempo", + "uid": "${tempo}" + }, "gridPos": { "h": 7, "w": 8, @@ -324,6 +360,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "description": "Histogram showing p99, p95, p50, and p10 percentiles for job processing duration based on number of resources changed", "fieldConfig": { "defaults": { @@ -425,6 +465,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "description": "Histogram showing p99, p95, p50, and p10 percentiles for job processing duration based on number of resources changed", "gridPos": { "h": 7, @@ -477,6 +521,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "description": "Total number of jobs waiting to be processed", "gridPos": { "h": 7, @@ -502,6 +550,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "fieldConfig": { "defaults": { "unit": "s" @@ -532,6 +584,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "description": "How long a job is in the queue before being picked up", "gridPos": { "h": 7, @@ -584,6 +640,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 7, "w": 8, @@ -609,6 +669,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "gridPos": { "h": 7, "w": 8, @@ -633,6 +697,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "gridPos": { "h": 7, "w": 8, @@ -675,6 +743,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "gridPos": { "h": 7, "w": 8, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.span_zero_demo.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.span_zero_demo.v1beta1.json index 61094ee5dbd..5597a468c53 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.span_zero_demo.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v16.span_zero_demo.v1beta1.json @@ -41,6 +41,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 24, @@ -78,6 +82,10 @@ "type": "row" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 7, "w": 8, @@ -103,6 +111,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 7, "w": 8, @@ -128,6 +140,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "fieldConfig": { "defaults": { "thresholds": { @@ -174,6 +190,10 @@ "type": "stat" }, { + "datasource": { + "type": "loki", + "uid": "${loki}" + }, "gridPos": { "h": 7, "w": 8, @@ -202,6 +222,10 @@ "type": "logs" }, { + "datasource": { + "type": "loki", + "uid": "${loki}" + }, "gridPos": { "h": 7, "w": 8, @@ -230,6 +254,10 @@ "type": "logs" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 7, "w": 8, @@ -255,6 +283,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "description": "Number of concurrent processing threads available for handling operations", "gridPos": { "h": 7, @@ -280,6 +312,10 @@ "type": "stat" }, { + "datasource": { + "type": "tempo", + "uid": "${tempo}" + }, "gridPos": { "h": 7, "w": 8, @@ -324,6 +360,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "description": "Histogram showing p99, p95, p50, and p10 percentiles for job processing duration based on number of resources changed", "fieldConfig": { "defaults": { @@ -425,6 +465,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "description": "Histogram showing p99, p95, p50, and p10 percentiles for job processing duration based on number of resources changed", "gridPos": { "h": 7, @@ -477,6 +521,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "description": "Total number of jobs waiting to be processed", "gridPos": { "h": 7, @@ -502,6 +550,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "fieldConfig": { "defaults": { "unit": "s" @@ -532,6 +584,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "description": "How long a job is in the queue before being picked up", "gridPos": { "h": 7, @@ -584,6 +640,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 7, "w": 8, @@ -609,6 +669,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "gridPos": { "h": 7, "w": 8, @@ -633,6 +697,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "gridPos": { "h": 7, "w": 8, @@ -675,6 +743,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "${prom}" + }, "gridPos": { "h": 7, "w": 8, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v17.minspan_to_maxperrow.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v17.minspan_to_maxperrow.v0alpha1.json index e169d2bfa64..ae598c96c0e 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v17.minspan_to_maxperrow.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v17.minspan_to_maxperrow.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, @@ -49,6 +53,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, @@ -71,6 +79,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 4, "w": 6, @@ -93,6 +105,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 4, @@ -115,6 +131,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 6, "w": 8, @@ -137,6 +157,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 4, "w": 6, @@ -159,6 +183,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 6, "w": 24, @@ -181,6 +209,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 4, "w": 24, @@ -203,6 +235,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 4, "w": 6, @@ -225,6 +261,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 4, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v17.minspan_to_maxperrow.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v17.minspan_to_maxperrow.v1beta1.json index b5a64a7634f..6b5a09f65ab 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v17.minspan_to_maxperrow.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v17.minspan_to_maxperrow.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, @@ -49,6 +53,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, @@ -71,6 +79,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 4, "w": 6, @@ -93,6 +105,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 4, @@ -115,6 +131,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 6, "w": 8, @@ -137,6 +157,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 4, "w": 6, @@ -159,6 +183,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 6, "w": 24, @@ -181,6 +209,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 4, "w": 24, @@ -203,6 +235,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 4, "w": 6, @@ -225,6 +261,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 4, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v18.gauge_options.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v18.gauge_options.v0alpha1.json index cc57f1b1914..a34b41d8bb6 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v18.gauge_options.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v18.gauge_options.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +75,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -98,6 +106,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -126,6 +138,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -160,6 +176,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v18.gauge_options.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v18.gauge_options.v1beta1.json index 1fcfe058203..269085d6048 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v18.gauge_options.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v18.gauge_options.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +75,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -98,6 +106,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -126,6 +138,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -160,6 +176,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v19.panel_links.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v19.panel_links.v0alpha1.json index 44bdfd7c1a0..d71f8e881d2 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v19.panel_links.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v19.panel_links.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -55,6 +59,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -83,6 +91,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -111,6 +123,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -140,6 +156,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -168,6 +188,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v19.panel_links.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v19.panel_links.v1beta1.json index 432355ba671..288d4f1c8aa 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v19.panel_links.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v19.panel_links.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -55,6 +59,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -83,6 +91,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -111,6 +123,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -140,6 +156,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -168,6 +188,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v2.panels-and-services.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v2.panels-and-services.v0alpha1.json index ec7aab7bc7a..ea66d446c51 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v2.panels-and-services.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v2.panels-and-services.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -50,6 +54,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -73,6 +81,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -95,6 +107,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v2.panels-and-services.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v2.panels-and-services.v1beta1.json index 5aaa48878d6..bd99678a8ff 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v2.panels-and-services.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v2.panels-and-services.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -50,6 +54,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -73,6 +81,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -95,6 +107,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v20.variable_syntax_links.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v20.variable_syntax_links.v0alpha1.json index 40a06e400a4..7e234377108 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v20.variable_syntax_links.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v20.variable_syntax_links.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, @@ -62,6 +66,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, @@ -102,6 +110,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 24, @@ -144,6 +156,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, @@ -186,6 +202,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v20.variable_syntax_links.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v20.variable_syntax_links.v1beta1.json index a914c1f29b6..4f519fb3d9c 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v20.variable_syntax_links.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v20.variable_syntax_links.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, @@ -62,6 +66,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, @@ -102,6 +110,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 24, @@ -144,6 +156,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, @@ -186,6 +202,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v21.data_links_series_to_field.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v21.data_links_series_to_field.v0alpha1.json index 25823b0fd99..c4240b5dd20 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v21.data_links_series_to_field.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v21.data_links_series_to_field.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -60,6 +64,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -97,6 +105,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -136,6 +148,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -165,6 +181,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v21.data_links_series_to_field.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v21.data_links_series_to_field.v1beta1.json index 6f5594d57f0..90783f28c4d 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v21.data_links_series_to_field.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v21.data_links_series_to_field.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -60,6 +64,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -97,6 +105,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -136,6 +148,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -165,6 +181,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v22.table_panel_align.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v22.table_panel_align.v0alpha1.json index ab9f271d900..a6e6e123cdb 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v22.table_panel_align.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v22.table_panel_align.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v22.table_panel_align.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v22.table_panel_align.v1beta1.json index b17a18593b8..19143fd0ac0 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v22.table_panel_align.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v22.table_panel_align.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v23.multi_variable_alignment.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v23.multi_variable_alignment.v0alpha1.json index 6bf600c5014..f55f52af9cf 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v23.multi_variable_alignment.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v23.multi_variable_alignment.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v23.multi_variable_alignment.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v23.multi_variable_alignment.v1beta1.json index 4f174d6742a..dd7c60c0e90 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v23.multi_variable_alignment.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v23.multi_variable_alignment.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v24.table-angular.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v24.table-angular.v0alpha1.json index 876be802767..aeec2f8300d 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v24.table-angular.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v24.table-angular.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests basic migration with default style pattern (/.*/) containing thresholds and colors. Should convert styles to fieldConfig.defaults with threshold steps.", "gridPos": { "h": 3, @@ -57,6 +61,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests comprehensive migration including: default style with thresholds/colors/unit/decimals/align/colorMode, column overrides with exact name and regex patterns, date formatting, hidden columns, and links with tooltips.", "gridPos": { "h": 3, @@ -80,6 +88,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests migration of timeseries_aggregations transform to reduce transformation with column mappings (avg-\u003emean, max-\u003emax, min-\u003emin, total-\u003esum, current-\u003elastNotNull, count-\u003ecount).", "gridPos": { "h": 3, @@ -103,6 +115,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests migration of timeseries_to_rows transform to seriesToRows transformation.", "gridPos": { "h": 3, @@ -126,6 +142,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests migration of timeseries_to_columns transform to seriesToColumns transformation.", "gridPos": { "h": 3, @@ -149,6 +169,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests migration of table transform to merge transformation. Also tests auto alignment conversion to empty string.", "gridPos": { "h": 3, @@ -172,6 +196,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests that existing transformations are preserved and new transformation from old format is appended to the list.", "gridPos": { "h": 3, @@ -208,6 +236,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests handling of mixed numeric and string threshold values (int, string, float) with proper type conversion.", "gridPos": { "h": 3, @@ -231,6 +263,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests all color mode mappings: cell-\u003ecolor-background, row-\u003ecolor-background, value-\u003ecolor-text.", "gridPos": { "h": 3, @@ -254,6 +290,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests all alignment options: left, center, right, and auto (should convert to empty string).", "gridPos": { "h": 3, @@ -277,6 +317,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests both field matcher types: byName for exact matches and byRegexp for regex patterns.", "gridPos": { "h": 3, @@ -300,6 +344,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests various link configurations: with and without tooltip, with and without target blank.", "gridPos": { "h": 3, @@ -323,6 +371,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests various date format patterns and aliases.", "gridPos": { "h": 3, @@ -346,6 +398,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "React table (table2) should not be migrated. Properties should remain unchanged.", "gridPos": { "h": 3, @@ -369,6 +425,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Angular table without styles property should not be migrated.", "gridPos": { "h": 3, @@ -392,6 +452,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Non-table panels should remain completely unchanged.", "gridPos": { "h": 3, @@ -415,6 +479,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Other panel types should not be affected by table migration.", "gridPos": { "h": 3, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v24.table-angular.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v24.table-angular.v1beta1.json index d79faf07932..f9a126e5f34 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v24.table-angular.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v24.table-angular.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests basic migration with default style pattern (/.*/) containing thresholds and colors. Should convert styles to fieldConfig.defaults with threshold steps.", "gridPos": { "h": 3, @@ -57,6 +61,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests comprehensive migration including: default style with thresholds/colors/unit/decimals/align/colorMode, column overrides with exact name and regex patterns, date formatting, hidden columns, and links with tooltips.", "gridPos": { "h": 3, @@ -80,6 +88,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests migration of timeseries_aggregations transform to reduce transformation with column mappings (avg-\u003emean, max-\u003emax, min-\u003emin, total-\u003esum, current-\u003elastNotNull, count-\u003ecount).", "gridPos": { "h": 3, @@ -103,6 +115,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests migration of timeseries_to_rows transform to seriesToRows transformation.", "gridPos": { "h": 3, @@ -126,6 +142,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests migration of timeseries_to_columns transform to seriesToColumns transformation.", "gridPos": { "h": 3, @@ -149,6 +169,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests migration of table transform to merge transformation. Also tests auto alignment conversion to empty string.", "gridPos": { "h": 3, @@ -172,6 +196,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests that existing transformations are preserved and new transformation from old format is appended to the list.", "gridPos": { "h": 3, @@ -208,6 +236,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests handling of mixed numeric and string threshold values (int, string, float) with proper type conversion.", "gridPos": { "h": 3, @@ -231,6 +263,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests all color mode mappings: cell-\u003ecolor-background, row-\u003ecolor-background, value-\u003ecolor-text.", "gridPos": { "h": 3, @@ -254,6 +290,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests all alignment options: left, center, right, and auto (should convert to empty string).", "gridPos": { "h": 3, @@ -277,6 +317,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests both field matcher types: byName for exact matches and byRegexp for regex patterns.", "gridPos": { "h": 3, @@ -300,6 +344,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests various link configurations: with and without tooltip, with and without target blank.", "gridPos": { "h": 3, @@ -323,6 +371,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests various date format patterns and aliases.", "gridPos": { "h": 3, @@ -346,6 +398,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "React table (table2) should not be migrated. Properties should remain unchanged.", "gridPos": { "h": 3, @@ -369,6 +425,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Angular table without styles property should not be migrated.", "gridPos": { "h": 3, @@ -392,6 +452,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Non-table panels should remain completely unchanged.", "gridPos": { "h": 3, @@ -415,6 +479,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Other panel types should not be affected by table migration.", "gridPos": { "h": 3, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v25.no-op-migration.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v25.no-op-migration.v0alpha1.json index 704035dffdf..92c8eaf2b14 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v25.no-op-migration.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v25.no-op-migration.v0alpha1.json @@ -33,6 +33,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -55,6 +59,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v25.no-op-migration.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v25.no-op-migration.v1beta1.json index 7daaf9fa380..2e0d3dbe0ef 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v25.no-op-migration.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v25.no-op-migration.v1beta1.json @@ -33,6 +33,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -55,6 +59,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v26.text2_to_text.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v26.text2_to_text.v0alpha1.json index 4ddc375e3d0..c36b9aaa1b9 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v26.text2_to_text.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v26.text2_to_text.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +79,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v26.text2_to_text.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v26.text2_to_text.v1beta1.json index ed958f0fc45..028ecd9792b 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v26.text2_to_text.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v26.text2_to_text.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +79,10 @@ "type": "text" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v27.repeated_panels_and_constant_variable.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v27.repeated_panels_and_constant_variable.v0alpha1.json index 99bdb079082..883875f9227 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v27.repeated_panels_and_constant_variable.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v27.repeated_panels_and_constant_variable.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v27.repeated_panels_and_constant_variable.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v27.repeated_panels_and_constant_variable.v1beta1.json index e2a7c8d360f..2775106705e 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v27.repeated_panels_and_constant_variable.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v27.repeated_panels_and_constant_variable.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_and_variable_properties.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_and_variable_properties.v0alpha1.json index 549d23f389c..baaa4bd3d9f 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_and_variable_properties.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_and_variable_properties.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -56,6 +60,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -78,6 +86,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -107,6 +119,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_and_variable_properties.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_and_variable_properties.v1beta1.json index 8fdfe74a0ca..da477bdc06d 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_and_variable_properties.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_and_variable_properties.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -56,6 +60,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -78,6 +86,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -107,6 +119,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_migration.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_migration.v0alpha1.json index f47146292f4..103dc503a7c 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_migration.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_migration.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -56,6 +60,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -85,6 +93,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -107,6 +119,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -136,6 +152,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -159,6 +179,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "PD8C576611E62080A" + }, "gridPos": { "h": 8, "w": 8, @@ -182,6 +206,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "PD8C576611E62080A" + }, "fieldConfig": { "defaults": { "mappings": [ @@ -249,6 +277,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "PD8C576611E62080A" + }, "gridPos": { "h": 8, "w": 8, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_migration.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_migration.v1beta1.json index 9e27ce9b373..fc357d68563 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_migration.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v28.singlestat_migration.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -56,6 +60,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -85,6 +93,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -107,6 +119,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -136,6 +152,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -159,6 +179,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "PD8C576611E62080A" + }, "gridPos": { "h": 8, "w": 8, @@ -182,6 +206,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "PD8C576611E62080A" + }, "fieldConfig": { "defaults": { "mappings": [ @@ -249,6 +277,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "PD8C576611E62080A" + }, "gridPos": { "h": 8, "w": 8, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v29.query_variables_refresh_and_options.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v29.query_variables_refresh_and_options.v0alpha1.json index 46a5be539cf..846bb168d12 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v29.query_variables_refresh_and_options.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v29.query_variables_refresh_and_options.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v29.query_variables_refresh_and_options.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v29.query_variables_refresh_and_options.v1beta1.json index 797aa7aa93b..da06dcbea48 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v29.query_variables_refresh_and_options.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v29.query_variables_refresh_and_options.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v3.no-op.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v3.no-op.v0alpha1.json index 811f9a00d89..f1b00a18973 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v3.no-op.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v3.no-op.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +79,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -93,6 +105,10 @@ "type": "barchart" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v3.no-op.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v3.no-op.v1beta1.json index 63203ed95de..4703aad237e 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v3.no-op.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v3.no-op.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +79,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -93,6 +105,10 @@ "type": "barchart" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v30.value_mappings_and_tooltip_options.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v30.value_mappings_and_tooltip_options.v0alpha1.json index e6ec721a7f3..a7847652883 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v30.value_mappings_and_tooltip_options.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v30.value_mappings_and_tooltip_options.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "mappings": [ @@ -125,6 +129,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -151,6 +159,10 @@ "type": "xychart" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -178,6 +190,10 @@ "type": "xychart2" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -204,6 +220,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "mappings": [ @@ -305,6 +325,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "unit": "bytes" @@ -337,6 +361,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "overrides": [ { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v30.value_mappings_and_tooltip_options.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v30.value_mappings_and_tooltip_options.v1beta1.json index 240ee83acfe..21fb00e8845 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v30.value_mappings_and_tooltip_options.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v30.value_mappings_and_tooltip_options.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "mappings": [ @@ -125,6 +129,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -151,6 +159,10 @@ "type": "xychart" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -178,6 +190,10 @@ "type": "xychart2" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -204,6 +220,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "mappings": [ @@ -305,6 +325,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "unit": "bytes" @@ -337,6 +361,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "overrides": [ { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v31.labels_to_fields_merge.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v31.labels_to_fields_merge.v0alpha1.json index b3261291c34..00817bd05b6 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v31.labels_to_fields_merge.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v31.labels_to_fields_merge.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -59,6 +63,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -99,6 +107,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -149,6 +161,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -171,6 +187,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -259,6 +279,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v31.labels_to_fields_merge.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v31.labels_to_fields_merge.v1beta1.json index 74ddec4f78c..6f3fb009a55 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v31.labels_to_fields_merge.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v31.labels_to_fields_merge.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -59,6 +63,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -99,6 +107,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -149,6 +161,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -171,6 +187,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -259,6 +279,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v32.no_op_migration.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v32.no_op_migration.v0alpha1.json index bde81f8e5b9..3389666f1ef 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v32.no_op_migration.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v32.no_op_migration.v0alpha1.json @@ -33,6 +33,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +75,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v32.no_op_migration.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v32.no_op_migration.v1beta1.json index 18aee40e8eb..ecf3f1bbd52 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v32.no_op_migration.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v32.no_op_migration.v1beta1.json @@ -33,6 +33,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +75,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v33.panel_ds_name_to_ref.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v33.panel_ds_name_to_ref.v0alpha1.json index a860cf2dd06..142d01d9ffb 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v33.panel_ds_name_to_ref.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v33.panel_ds_name_to_ref.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "loki", + "uid": "non-default-test-ds-uid" + }, "description": "Tests v33 migration behavior when panel datasource is explicitly null. Should remain null after migration (returnDefaultAsNull: true).", "gridPos": { "h": 3, @@ -51,6 +55,10 @@ "type": "stat" }, { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, "description": "Tests v33 migration behavior when panel datasource is already a proper object reference. Should remain unchanged.", "gridPos": { "h": 3, @@ -75,6 +83,10 @@ "type": "stat" }, { + "datasource": { + "type": "loki", + "uid": "non-default-test-ds-uid" + }, "description": "Tests v33 migration when panel datasource is a string name. Should convert to proper object with uid, type, apiVersion.", "gridPos": { "h": 3, @@ -98,6 +110,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests v33 migration when panel has datasource string but empty targets array. Panel datasource should still migrate.", "gridPos": { "h": 3, @@ -283,6 +299,10 @@ "id": -1, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Nested panel with string datasource should migrate to proper object reference, proving row panel recursion works.", "gridPos": { "h": 3, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v33.panel_ds_name_to_ref.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v33.panel_ds_name_to_ref.v1beta1.json index 36b1c55fb41..d9af9bca3d7 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v33.panel_ds_name_to_ref.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v33.panel_ds_name_to_ref.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "loki", + "uid": "non-default-test-ds-uid" + }, "description": "Tests v33 migration behavior when panel datasource is explicitly null. Should remain null after migration (returnDefaultAsNull: true).", "gridPos": { "h": 3, @@ -51,6 +55,10 @@ "type": "stat" }, { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, "description": "Tests v33 migration behavior when panel datasource is already a proper object reference. Should remain unchanged.", "gridPos": { "h": 3, @@ -75,6 +83,10 @@ "type": "stat" }, { + "datasource": { + "type": "loki", + "uid": "non-default-test-ds-uid" + }, "description": "Tests v33 migration when panel datasource is a string name. Should convert to proper object with uid, type, apiVersion.", "gridPos": { "h": 3, @@ -98,6 +110,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests v33 migration when panel has datasource string but empty targets array. Panel datasource should still migrate.", "gridPos": { "h": 3, @@ -283,6 +299,10 @@ "id": -1, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Nested panel with string datasource should migrate to proper object reference, proving row panel recursion works.", "gridPos": { "h": 3, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v34.multiple_stats_cloudwatch.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v34.multiple_stats_cloudwatch.v0alpha1.json index af5a9eb4fb2..7755aa29cf7 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v34.multiple_stats_cloudwatch.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v34.multiple_stats_cloudwatch.v0alpha1.json @@ -289,6 +289,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -355,6 +359,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -386,6 +394,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -492,6 +504,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -522,6 +538,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -626,6 +646,10 @@ "id": -1, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -689,6 +713,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -738,6 +766,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -769,6 +801,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -818,6 +854,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -849,6 +889,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -927,6 +971,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -1006,6 +1054,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v34.multiple_stats_cloudwatch.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v34.multiple_stats_cloudwatch.v1beta1.json index 8a6009228aa..1568231f000 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v34.multiple_stats_cloudwatch.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v34.multiple_stats_cloudwatch.v1beta1.json @@ -289,6 +289,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -355,6 +359,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -386,6 +394,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -492,6 +504,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -522,6 +538,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -626,6 +646,10 @@ "id": -1, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -689,6 +713,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -738,6 +766,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -769,6 +801,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -818,6 +854,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -849,6 +889,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -927,6 +971,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -1006,6 +1054,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v35.ensure_x_axis_visibility.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v35.ensure_x_axis_visibility.v0alpha1.json index 83e0d94fd78..9aef1000c89 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v35.ensure_x_axis_visibility.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v35.ensure_x_axis_visibility.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "custom": { @@ -70,6 +74,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "custom": { @@ -125,6 +133,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "custom": { @@ -154,6 +166,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "custom": { @@ -183,6 +199,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -205,6 +225,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -227,6 +251,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "unit": "bytes" @@ -254,6 +282,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "custom": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v35.ensure_x_axis_visibility.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v35.ensure_x_axis_visibility.v1beta1.json index 59a03171c59..5b383957bd3 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v35.ensure_x_axis_visibility.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v35.ensure_x_axis_visibility.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "custom": { @@ -70,6 +74,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "custom": { @@ -125,6 +133,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "custom": { @@ -154,6 +166,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "custom": { @@ -183,6 +199,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -205,6 +225,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -227,6 +251,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "unit": "bytes" @@ -254,6 +282,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "fieldConfig": { "defaults": { "custom": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v36.ds_name_to_ref.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v36.ds_name_to_ref.v0alpha1.json index 6cfba3afdaf..4678a84253d 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v36.ds_name_to_ref.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v36.ds_name_to_ref.v0alpha1.json @@ -77,6 +77,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests null panel datasource migration with targets - should fallback to default", "gridPos": { "h": 3, @@ -100,6 +104,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests null panel datasource with empty targets array - should create default target", "gridPos": { "h": 3, @@ -123,6 +131,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests null panel datasource with missing targets - should create default target array", "gridPos": { "h": 3, @@ -180,6 +192,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, "description": "Tests panel with already migrated datasource object - should preserve existing refs", "gridPos": { "h": 3, @@ -203,6 +219,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "unknown-target-datasource" + }, "description": "Tests panel with unknown datasource - should preserve as UID-only reference", "gridPos": { "h": 3, @@ -260,6 +280,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, "description": "Tests panel inheriting datasource from target when panel datasource was default", "gridPos": { "h": 3, @@ -283,6 +307,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, "description": "Tests panel with datasource referenced by name - should migrate to full object", "gridPos": { "h": 3, @@ -306,6 +334,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, "description": "Tests panel with datasource referenced by UID - should migrate to full object", "gridPos": { "h": 3, @@ -345,6 +377,10 @@ "id": -1, "panels": [ { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, "description": "Nested panel in collapsed row with default datasource", "gridPos": { "h": 3, @@ -368,6 +404,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, "description": "Nested panel in collapsed row with unknown datasource", "gridPos": { "h": 3, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v36.ds_name_to_ref.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v36.ds_name_to_ref.v1beta1.json index 535ea1447f0..a1b5270382b 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v36.ds_name_to_ref.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v36.ds_name_to_ref.v1beta1.json @@ -77,6 +77,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests null panel datasource migration with targets - should fallback to default", "gridPos": { "h": 3, @@ -100,6 +104,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests null panel datasource with empty targets array - should create default target", "gridPos": { "h": 3, @@ -123,6 +131,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "description": "Tests null panel datasource with missing targets - should create default target array", "gridPos": { "h": 3, @@ -180,6 +192,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, "description": "Tests panel with already migrated datasource object - should preserve existing refs", "gridPos": { "h": 3, @@ -203,6 +219,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "unknown-target-datasource" + }, "description": "Tests panel with unknown datasource - should preserve as UID-only reference", "gridPos": { "h": 3, @@ -260,6 +280,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, "description": "Tests panel inheriting datasource from target when panel datasource was default", "gridPos": { "h": 3, @@ -283,6 +307,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, "description": "Tests panel with datasource referenced by name - should migrate to full object", "gridPos": { "h": 3, @@ -306,6 +334,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, "description": "Tests panel with datasource referenced by UID - should migrate to full object", "gridPos": { "h": 3, @@ -345,6 +377,10 @@ "id": -1, "panels": [ { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, "description": "Nested panel in collapsed row with default datasource", "gridPos": { "h": 3, @@ -368,6 +404,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "elasticsearch", + "uid": "existing-target-uid" + }, "description": "Nested panel in collapsed row with unknown datasource", "gridPos": { "h": 3, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v4.no-op.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v4.no-op.v0alpha1.json index 5daafe44636..5be318447ec 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v4.no-op.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v4.no-op.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +79,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v4.no-op.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v4.no-op.v1beta1.json index e5b057639fb..8e1436e850a 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v4.no-op.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v4.no-op.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +79,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v5.no-op.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v5.no-op.v0alpha1.json index 4872dd21894..07538e41a8f 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v5.no-op.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v5.no-op.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +79,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v5.no-op.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v5.no-op.v1beta1.json index aeb12a936e1..88148baa546 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v5.no-op.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v5.no-op.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +79,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v6.pulldowns_and_templating.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v6.pulldowns_and_templating.v0alpha1.json index 7f61b3e7b90..5cdc2d5e424 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v6.pulldowns_and_templating.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v6.pulldowns_and_templating.v0alpha1.json @@ -49,6 +49,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, @@ -72,6 +76,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v6.pulldowns_and_templating.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v6.pulldowns_and_templating.v1beta1.json index cb826c382bd..558e765f719 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v6.pulldowns_and_templating.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v6.pulldowns_and_templating.v1beta1.json @@ -49,6 +49,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, @@ -72,6 +76,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 8, "w": 12, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v7.timepicker.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v7.timepicker.v0alpha1.json index 100c239dc08..db8c34264b4 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v7.timepicker.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v7.timepicker.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v7.timepicker.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v7.timepicker.v1beta1.json index 2a2541d7861..18283a762cb 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v7.timepicker.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v7.timepicker.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v9.no-op.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v9.no-op.v0alpha1.json index 3f575f7f5fc..8ffe55cd0d9 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v9.no-op.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v9.no-op.v0alpha1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +79,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v9.no-op.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v9.no-op.v1beta1.json index fd2231c5509..d2ea95d4a03 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v9.no-op.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/migrated_dashboards_from_v0_to_v2/v2beta1.v9.no-op.v1beta1.json @@ -27,6 +27,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -49,6 +53,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, @@ -71,6 +79,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "default-ds-uid" + }, "gridPos": { "h": 3, "w": 6, diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v0alpha1.json index e3e0747bfc4..ecb9021b96c 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v0alpha1.json @@ -66,6 +66,10 @@ "type": "row" }, { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, "description": "This panel demonstrates conditional rendering features", "fieldConfig": { "defaults": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v1beta1.json index 7c37ba8f8ab..35fc204793d 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.complete.v1beta1.json @@ -66,6 +66,10 @@ "type": "row" }, { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, "description": "This panel demonstrates conditional rendering features", "fieldConfig": { "defaults": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v0alpha1.json index e648923e684..20f70a0a647 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v0alpha1.json @@ -150,6 +150,9 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus" + }, "fieldConfig": { "defaults": { "color": { @@ -245,6 +248,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, "fieldConfig": { "defaults": { "color": { @@ -341,6 +348,9 @@ "type": "timeseries" }, { + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -400,6 +410,10 @@ "type": "stat" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v1beta1.json index d2a4e93982e..9956ad6962f 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.ds-data-query.v1beta1.json @@ -150,6 +150,9 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus" + }, "fieldConfig": { "defaults": { "color": { @@ -245,6 +248,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, "fieldConfig": { "defaults": { "color": { @@ -341,6 +348,9 @@ "type": "timeseries" }, { + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -400,6 +410,10 @@ "type": "stat" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v0alpha1.json index 37bbba541cd..d57c8d086a9 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v0alpha1.json @@ -14,6 +14,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v1beta1.json index 464c1d4c240..b2e7bd78dba 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2alpha1.viz-config.v1beta1.json @@ -14,6 +14,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.complete.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.complete.v0alpha1.json index b942305c98d..f3b6ab864fb 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.complete.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.complete.v0alpha1.json @@ -66,6 +66,10 @@ "type": "row" }, { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, "description": "This panel demonstrates conditional rendering features", "fieldConfig": { "defaults": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.complete.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.complete.v1beta1.json index 06f8c45bdad..e3236448c9d 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.complete.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.complete.v1beta1.json @@ -66,6 +66,10 @@ "type": "row" }, { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, "description": "This panel demonstrates conditional rendering features", "fieldConfig": { "defaults": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.datasource-resolution.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.datasource-resolution.v0alpha1.json index c1066edc211..33fd022e0db 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.datasource-resolution.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.datasource-resolution.v0alpha1.json @@ -80,6 +80,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, "description": "This should resolve to the grafana-testdata-datasource datasource", "fieldConfig": { "defaults": { @@ -170,6 +174,9 @@ "type": "timeseries" }, { + "datasource": { + "type": "elasticsearch" + }, "description": "This should resolve to the first elasticsearch datasource", "fieldConfig": { "defaults": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.datasource-resolution.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.datasource-resolution.v1beta1.json index 9bbd2f8f555..05d6df3537a 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.datasource-resolution.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.datasource-resolution.v1beta1.json @@ -80,6 +80,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, "description": "This should resolve to the grafana-testdata-datasource datasource", "fieldConfig": { "defaults": { @@ -170,6 +174,9 @@ "type": "timeseries" }, { + "datasource": { + "type": "elasticsearch" + }, "description": "This should resolve to the first elasticsearch datasource", "fieldConfig": { "defaults": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.ds-data-query.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.ds-data-query.v0alpha1.json index 6a418f1e21d..4494023eb13 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.ds-data-query.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.ds-data-query.v0alpha1.json @@ -150,6 +150,9 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus" + }, "fieldConfig": { "defaults": { "color": { @@ -245,6 +248,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, "fieldConfig": { "defaults": { "color": { @@ -341,6 +348,9 @@ "type": "timeseries" }, { + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -400,6 +410,10 @@ "type": "stat" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.ds-data-query.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.ds-data-query.v1beta1.json index 212dbdfd0f3..bc8d90d796a 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.ds-data-query.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.ds-data-query.v1beta1.json @@ -150,6 +150,9 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus" + }, "fieldConfig": { "defaults": { "color": { @@ -245,6 +248,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "prometheus", + "uid": "gdev-prometheus" + }, "fieldConfig": { "defaults": { "color": { @@ -341,6 +348,9 @@ "type": "timeseries" }, { + "datasource": { + "type": "grafana-testdata-datasource" + }, "fieldConfig": { "defaults": { "color": { @@ -400,6 +410,10 @@ "type": "stat" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.rows-with-nested-tabs.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.rows-with-nested-tabs.v0alpha1.json index f81abd723dc..bd7c8c392ee 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.rows-with-nested-tabs.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.rows-with-nested-tabs.v0alpha1.json @@ -67,6 +67,10 @@ "type": "row" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -219,6 +223,10 @@ "type": "row" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -309,6 +317,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.rows-with-nested-tabs.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.rows-with-nested-tabs.v1beta1.json index 2ade48c620d..a81de0ed319 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.rows-with-nested-tabs.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.rows-with-nested-tabs.v1beta1.json @@ -67,6 +67,10 @@ "type": "row" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -219,6 +223,10 @@ "type": "row" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -309,6 +317,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tab-with-multiple-panels.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tab-with-multiple-panels.v0alpha1.json index 0357c22536a..98791135a12 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tab-with-multiple-panels.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tab-with-multiple-panels.v0alpha1.json @@ -54,6 +54,10 @@ "type": "row" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tab-with-multiple-panels.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tab-with-multiple-panels.v1beta1.json index 7a9ea77ba65..38c93eb1cc8 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tab-with-multiple-panels.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tab-with-multiple-panels.v1beta1.json @@ -54,6 +54,10 @@ "type": "row" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-and-rows-repeated.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-and-rows-repeated.v0alpha1.json index ef513d48d97..716b476f825 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-and-rows-repeated.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-and-rows-repeated.v0alpha1.json @@ -54,6 +54,10 @@ "type": "row" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -167,6 +171,10 @@ "id": -1, "panels": [ { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -271,6 +279,10 @@ "id": -1, "panels": [ { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -361,6 +373,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -467,6 +483,10 @@ "type": "row" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-and-rows-repeated.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-and-rows-repeated.v1beta1.json index f94a49fc420..f915142fd14 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-and-rows-repeated.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-and-rows-repeated.v1beta1.json @@ -54,6 +54,10 @@ "type": "row" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -167,6 +171,10 @@ "id": -1, "panels": [ { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -271,6 +279,10 @@ "id": -1, "panels": [ { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -361,6 +373,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -467,6 +483,10 @@ "type": "row" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-with-nested-rows.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-with-nested-rows.v0alpha1.json index 6ed7076e121..ebc40675495 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-with-nested-rows.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-with-nested-rows.v0alpha1.json @@ -54,6 +54,10 @@ "type": "row" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -167,6 +171,10 @@ "id": -1, "panels": [ { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -271,6 +279,10 @@ "id": -1, "panels": [ { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -361,6 +373,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-with-nested-rows.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-with-nested-rows.v1beta1.json index 9444d6b8eef..b5c74ce6a26 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-with-nested-rows.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.tabs-with-nested-rows.v1beta1.json @@ -54,6 +54,10 @@ "type": "row" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -167,6 +171,10 @@ "id": -1, "panels": [ { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -271,6 +279,10 @@ "id": -1, "panels": [ { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { @@ -361,6 +373,10 @@ "type": "timeseries" }, { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "defin43am9o1sd" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.value-mapping-and-overrides.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.value-mapping-and-overrides.v0alpha1.json index bd8e440efb2..916f2442b71 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.value-mapping-and-overrides.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.value-mapping-and-overrides.v0alpha1.json @@ -36,6 +36,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "prometheus-uid" + }, "description": "Panel with ValueMap mapping type - maps specific text values to colors and display text", "fieldConfig": { "defaults": { @@ -104,6 +108,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "prometheus-uid" + }, "description": "Panel with RangeMap mapping type - maps numerical ranges to colors and display text", "fieldConfig": { "defaults": { @@ -188,6 +196,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "prometheus-uid" + }, "description": "Panel with RegexMap mapping type - maps values matching regex patterns to colors", "fieldConfig": { "defaults": { @@ -267,6 +279,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "prometheus-uid" + }, "description": "Panel with SpecialValueMap mapping type - maps special values like null, NaN, true, false to display text", "fieldConfig": { "defaults": { @@ -380,6 +396,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "prometheus-uid" + }, "description": "Panel with all mapping types combined - demonstrates mixing different mapping types and multiple override matchers", "fieldConfig": { "defaults": { @@ -567,6 +587,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "prometheus-uid" + }, "description": "Panel with override that has empty properties array - tests conversion of overrides without any property modifications", "fieldConfig": { "overrides": [ diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.value-mapping-and-overrides.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.value-mapping-and-overrides.v1beta1.json index 07d899db46c..9c96e15fbc3 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.value-mapping-and-overrides.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.value-mapping-and-overrides.v1beta1.json @@ -36,6 +36,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "prometheus", + "uid": "prometheus-uid" + }, "description": "Panel with ValueMap mapping type - maps specific text values to colors and display text", "fieldConfig": { "defaults": { @@ -104,6 +108,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "prometheus-uid" + }, "description": "Panel with RangeMap mapping type - maps numerical ranges to colors and display text", "fieldConfig": { "defaults": { @@ -188,6 +196,10 @@ "type": "gauge" }, { + "datasource": { + "type": "prometheus", + "uid": "prometheus-uid" + }, "description": "Panel with RegexMap mapping type - maps values matching regex patterns to colors", "fieldConfig": { "defaults": { @@ -267,6 +279,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "prometheus-uid" + }, "description": "Panel with SpecialValueMap mapping type - maps special values like null, NaN, true, false to display text", "fieldConfig": { "defaults": { @@ -380,6 +396,10 @@ "type": "stat" }, { + "datasource": { + "type": "prometheus", + "uid": "prometheus-uid" + }, "description": "Panel with all mapping types combined - demonstrates mixing different mapping types and multiple override matchers", "fieldConfig": { "defaults": { @@ -567,6 +587,10 @@ "type": "table" }, { + "datasource": { + "type": "prometheus", + "uid": "prometheus-uid" + }, "description": "Panel with override that has empty properties array - tests conversion of overrides without any property modifications", "fieldConfig": { "overrides": [ diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.viz-config.v0alpha1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.viz-config.v0alpha1.json index 0502ebf6b4c..083dfb5347c 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.viz-config.v0alpha1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.viz-config.v0alpha1.json @@ -14,6 +14,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.viz-config.v1beta1.json b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.viz-config.v1beta1.json index 2187a3406e7..69cec2d4e7b 100644 --- a/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.viz-config.v1beta1.json +++ b/apps/dashboard/pkg/migration/conversion/testdata/output/v2beta1.viz-config.v1beta1.json @@ -14,6 +14,10 @@ "liveNow": false, "panels": [ { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "gdev-testdata" + }, "fieldConfig": { "defaults": { "color": { diff --git a/apps/dashboard/pkg/migration/conversion/v2alpha1_to_v1beta1.go b/apps/dashboard/pkg/migration/conversion/v2alpha1_to_v1beta1.go index e2a3e17843c..46a2a533d41 100644 --- a/apps/dashboard/pkg/migration/conversion/v2alpha1_to_v1beta1.go +++ b/apps/dashboard/pkg/migration/conversion/v2alpha1_to_v1beta1.go @@ -1072,10 +1072,14 @@ func convertPanelKindToV1(panelKind *dashv2alpha1.DashboardPanelKind, panel map[ } panel["targets"] = targets - // Detect mixed datasource - set panel.datasource to "mixed" if queries use different datasources - // This matches the frontend behavior in getPanelDataSource (layoutSerializers/utils.ts) - if mixedDS := detectMixedDatasource(spec.Data.Spec.Queries); mixedDS != nil { - panel["datasource"] = mixedDS + // Set panel-level datasource from queries. + // - If queries use different datasources, set to "mixed" + // - If all queries use the same datasource, set to that datasource + // This is required because the frontend's legacy PanelModel.PanelQueryRunner.run uses panel.datasource + // and some components like CSVExportPage rely on it to resolve the datasource. If undefined, it falls back to the default datasource + // which would overwrite the query's datasource. + if panelDS := getPanelDatasource(spec.Data.Spec.Queries); panelDS != nil { + panel["datasource"] = panelDS } // Convert transformations @@ -1188,12 +1192,15 @@ func getDataSourceForQuery(explicitDS *dashv2alpha1.DashboardDataSourceRef, quer return nil } -// detectMixedDatasource checks if panel queries use different datasources. -// Returns a mixed datasource reference if queries use different datasources, nil otherwise. +// getPanelDatasource determines the panel-level datasource for V1. +// Returns: +// - Mixed datasource reference if queries use different datasources +// - First query's datasource if all queries use the same datasource +// - nil if no queries exist // Compares based on V2 input without runtime resolution: // - If query has explicit datasource.uid → use that UID and type // - Else → use query.Kind as type (empty UID) -func detectMixedDatasource(queries []dashv2alpha1.DashboardPanelQueryKind) map[string]interface{} { +func getPanelDatasource(queries []dashv2alpha1.DashboardPanelQueryKind) map[string]interface{} { if len(queries) == 0 { return nil } @@ -1232,8 +1239,21 @@ func detectMixedDatasource(queries []dashv2alpha1.DashboardPanelQueryKind) map[s } } - // Not mixed - don't set panel-level datasource - return nil + // Not mixed - return the first query's datasource so the panel has a datasource set. + // This is required because the frontend's legacy PanelModel.PanelQueryRunner.run uses panel.datasource + // to resolve the datasource, and if undefined, it falls back to the default datasource + // which then overwrites the query's datasource. + if firstType == "" && firstUID == "" { + return nil + } + result := make(map[string]interface{}) + if firstType != "" { + result["type"] = firstType + } + if firstUID != "" { + result["uid"] = firstUID + } + return result } func convertLibraryPanelKindToV1(libPanelKind *dashv2alpha1.DashboardLibraryPanelKind, panel map[string]interface{}) (map[string]interface{}, error) { diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-canvas/canvas_kitchen_sink.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-canvas/canvas_kitchen_sink.v42.json new file mode 100644 index 00000000000..cf4db2fb1b6 --- /dev/null +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-canvas/canvas_kitchen_sink.v42.json @@ -0,0 +1,598 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations \u0026 Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Mixed --" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "1": { + "color": "green", + "icon": "img/icons/unicons/check-circle.svg", + "index": 0, + "text": "Success" + }, + "2": { + "color": "orange", + "icon": "img/icons/unicons/exclamation-triangle.svg", + "index": 1, + "text": "Warning" + }, + "3": { + "color": "red", + "icon": "img/icons/unicons/times-circle.svg", + "index": 2, + "text": "Error" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "text" + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "success" + }, + "properties": [ + { + "id": "mappings", + "value": [ + { + "options": { + "1": { + "color": "green", + "icon": "img/icons/unicons/check-circle.svg", + "index": 0, + "text": "Success" + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "warning" + }, + "properties": [ + { + "id": "mappings", + "value": [ + { + "options": { + "2": { + "color": "orange", + "icon": "img/icons/unicons/exclamation-triangle.svg", + "index": 1, + "text": "Warning" + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "error" + }, + "properties": [ + { + "id": "mappings", + "value": [ + { + "options": { + "3": { + "color": "red", + "icon": "img/icons/unicons/times-circle.svg", + "index": 2, + "text": "Error" + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "unmapped" + }, + "properties": [ + { + "id": "mappings", + "value": [ + { + "options": { + "1": { + "color": "green", + "icon": "img/icons/unicons/check-circle.svg", + "index": 0, + "text": "Success" + }, + "2": { + "color": "orange", + "icon": "img/icons/unicons/exclamation-triangle.svg", + "index": 1, + "text": "Warning" + }, + "3": { + "color": "red", + "icon": "img/icons/unicons/times-circle.svg", + "index": 2, + "text": "Error" + } + }, + "type": "value" + } + ] + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "inlineEditing": true, + "root": { + "background": { + "color": { + "fixed": "transparent" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "elements": [ + { + "config": { + "align": "center", + "color": { + "fixed": "text" + }, + "size": 16, + "text": { + "fixed": "Field-based Icons (from value mappings):", + "mode": "fixed" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Header", + "placement": { + "height": 40, + "left": 20, + "top": 10, + "width": 400 + }, + "type": "text" + }, + { + "config": { + "fill": { + "field": "success", + "fixed": "green" + }, + "path": { + "field": "success", + "mode": "field" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Success Icon", + "placement": { + "height": 50, + "left": 50, + "top": 60, + "width": 50 + }, + "type": "icon" + }, + { + "config": { + "align": "center", + "color": { + "field": "success", + "fixed": "text" + }, + "size": 12, + "text": { + "field": "success", + "mode": "field" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Success Text", + "placement": { + "height": 25, + "left": 30, + "top": 115, + "width": 90 + }, + "type": "text" + }, + { + "config": { + "fill": { + "field": "warning", + "fixed": "orange" + }, + "path": { + "field": "warning", + "mode": "field" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Warning Icon", + "placement": { + "height": 50, + "left": 180, + "top": 60, + "width": 50 + }, + "type": "icon" + }, + { + "config": { + "align": "center", + "color": { + "field": "warning", + "fixed": "text" + }, + "size": 12, + "text": { + "field": "warning", + "mode": "field" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Warning Text", + "placement": { + "height": 25, + "left": 160, + "top": 115, + "width": 90 + }, + "type": "text" + }, + { + "config": { + "fill": { + "field": "error", + "fixed": "red" + }, + "path": { + "field": "error", + "mode": "field" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Error Icon", + "placement": { + "height": 50, + "left": 310, + "top": 60, + "width": 50 + }, + "type": "icon" + }, + { + "config": { + "align": "center", + "color": { + "field": "error", + "fixed": "text" + }, + "size": 12, + "text": { + "field": "error", + "mode": "field" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Error Text", + "placement": { + "height": 25, + "left": 290, + "top": 115, + "width": 90 + }, + "type": "text" + }, + { + "config": { + "fill": { + "field": "unmapped", + "fixed": "#808080" + }, + "path": { + "field": "unmapped", + "fixed": "img/icons/unicons/question-circle.svg", + "mode": "field" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Unmapped Icon", + "placement": { + "height": 50, + "left": 440, + "top": 60, + "width": 50 + }, + "type": "icon" + }, + { + "config": { + "align": "center", + "color": { + "field": "unmapped", + "fixed": "text" + }, + "size": 12, + "text": { + "fixed": "No mapping (14)", + "mode": "fixed" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Unmapped Text", + "placement": { + "height": 25, + "left": 410, + "top": 115, + "width": 110 + }, + "type": "text" + }, + { + "config": { + "align": "center", + "color": { + "fixed": "text" + }, + "size": 14, + "text": { + "fixed": "Fixed Relative Path:", + "mode": "fixed" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Relative Label", + "placement": { + "height": 30, + "left": 50, + "top": 170, + "width": 200 + }, + "type": "text" + }, + { + "config": { + "fill": { + "fixed": "blue" + }, + "path": { + "fixed": "img/icons/unicons/cloud.svg", + "mode": "fixed" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Relative Icon", + "placement": { + "height": 50, + "left": 260, + "top": 165, + "width": 50 + }, + "type": "icon" + }, + { + "config": { + "align": "center", + "color": { + "fixed": "text" + }, + "size": 14, + "text": { + "fixed": "Fixed Absolute URL:", + "mode": "fixed" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Absolute Label", + "placement": { + "height": 30, + "left": 50, + "top": 240, + "width": 200 + }, + "type": "text" + }, + { + "config": { + "fill": { + "fixed": "purple" + }, + "path": { + "fixed": "https://grafana.com/static/assets/img/grafana_icon.svg", + "mode": "fixed" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Absolute Icon", + "placement": { + "height": 50, + "left": 260, + "top": 235, + "width": 50 + }, + "type": "icon" + } + ], + "name": "Canvas Root", + "placement": { + "height": 100, + "left": 0, + "top": 0, + "width": 100 + }, + "type": "frame" + } + }, + "pluginVersion": "12.1.0", + "targets": [ + { + "csvContent": "success\n1", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_content" + }, + { + "csvContent": "warning\n2", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "B", + "scenarioId": "csv_content" + }, + { + "csvContent": "error\n3", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "C", + "scenarioId": "csv_content" + }, + { + "csvContent": "unmapped\n14", + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "D", + "scenarioId": "csv_content" + } + ], + "title": "Various SVG icons", + "type": "canvas" + } + ], + "refresh": "", + "schemaVersion": 42, + "tags": [ + "canvas", + "icons", + "test", + "v2" + ], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Panel tests - Canvas - Kitchen sink", + "uid": "canvas-icon-fix-test-v2", + "weekStart": "" +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests.v42.json index a705218273e..635103053bf 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests.v42.json @@ -631,7 +631,7 @@ "transformations": [ { "id": "convertFieldType", - "options": { + "options": { "conversions": [ { "destinationType": "number", @@ -1193,4 +1193,4 @@ "title": "Panel Tests - Gauge", "uid": "_5rDmaQiz", "weekStart": "" -} +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_new.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_new.v42.json index f24ec9a61a0..61f092d491e 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_new.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_new.v42.json @@ -71,13 +71,13 @@ "id": 1, "maxDataPoints": 20, "options": { + "barShape": "rounded", "barWidthFactor": 0.4, "effects": { "barGlow": false, "centerGlow": false, "gradient": false }, - "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -149,13 +149,13 @@ "id": 4, "maxDataPoints": 20, "options": { + "barShape": "rounded", "barWidthFactor": 0.4, "effects": { "barGlow": false, "centerGlow": true, "gradient": false }, - "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -227,13 +227,13 @@ "id": 3, "maxDataPoints": 20, "options": { + "barShape": "rounded", "barWidthFactor": 0.4, "effects": { "barGlow": true, "centerGlow": true, "gradient": false }, - "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -305,13 +305,13 @@ "id": 8, "maxDataPoints": 20, "options": { + "barShape": "rounded", "barWidthFactor": 0.4, "effects": { "barGlow": true, "centerGlow": true, "gradient": false }, - "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -383,13 +383,13 @@ "id": 22, "maxDataPoints": 20, "options": { + "barShape": "flat", "barWidthFactor": 0.72, "effects": { "barGlow": true, "centerGlow": true, "gradient": false }, - "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -461,13 +461,13 @@ "id": 23, "maxDataPoints": 20, "options": { + "barShape": "flat", "barWidthFactor": 0.72, "effects": { "barGlow": true, "centerGlow": true, "gradient": false }, - "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -552,13 +552,13 @@ "id": 18, "maxDataPoints": 20, "options": { + "barShape": "rounded", "barWidthFactor": 0.1, "effects": { "barGlow": true, "centerGlow": true, "gradient": false }, - "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -630,13 +630,13 @@ "id": 19, "maxDataPoints": 20, "options": { + "barShape": "rounded", "barWidthFactor": 0.32, "effects": { "barGlow": true, "centerGlow": true, "gradient": false }, - "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -708,13 +708,13 @@ "id": 20, "maxDataPoints": 20, "options": { + "barShape": "rounded", "barWidthFactor": 0.57, "effects": { "barGlow": true, "centerGlow": true, "gradient": false }, - "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -786,13 +786,13 @@ "id": 21, "maxDataPoints": 20, "options": { + "barShape": "rounded", "barWidthFactor": 0.8, "effects": { "barGlow": true, "centerGlow": true, "gradient": false }, - "barShape": "rounded", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -881,13 +881,13 @@ "id": 25, "maxDataPoints": 20, "options": { + "barShape": "flat", "barWidthFactor": 0.9, "effects": { "barGlow": false, "centerGlow": false, "gradient": false }, - "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -959,13 +959,13 @@ "id": 26, "maxDataPoints": 20, "options": { + "barShape": "flat", "barWidthFactor": 0.72, "effects": { "barGlow": false, "centerGlow": false, "gradient": false }, - "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1037,13 +1037,13 @@ "id": 29, "maxDataPoints": 20, "options": { + "barShape": "flat", "barWidthFactor": 0.72, "effects": { "barGlow": false, "centerGlow": false, "gradient": true }, - "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1115,13 +1115,13 @@ "id": 30, "maxDataPoints": 20, "options": { + "barShape": "flat", "barWidthFactor": 0.9, "effects": { "barGlow": false, "centerGlow": false, "gradient": false }, - "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1193,13 +1193,13 @@ "id": 28, "maxDataPoints": 20, "options": { + "barShape": "flat", "barWidthFactor": 0.72, "effects": { "barGlow": false, "centerGlow": false, "gradient": false }, - "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1288,13 +1288,13 @@ "id": 32, "maxDataPoints": 20, "options": { + "barShape": "flat", "barWidthFactor": 0.9, "effects": { "barGlow": false, "centerGlow": false, "gradient": true }, - "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1370,13 +1370,13 @@ "id": 34, "maxDataPoints": 20, "options": { + "barShape": "flat", "barWidthFactor": 0.9, "effects": { "barGlow": false, "centerGlow": false, "gradient": true }, - "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1452,13 +1452,13 @@ "id": 33, "maxDataPoints": 20, "options": { + "barShape": "flat", "barWidthFactor": 0.9, "effects": { "barGlow": false, "centerGlow": false, "gradient": true }, - "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -1541,9 +1541,9 @@ "id": 9, "maxDataPoints": 20, "options": { + "barShape": "rounded", "barWidth": 12, "barWidthFactor": 0.4, - "barShape": "rounded", "effects": { "barGlow": true, "centerGlow": true, @@ -1624,6 +1624,7 @@ "id": 11, "maxDataPoints": 20, "options": { + "barShape": "rounded", "barWidth": 12, "barWidthFactor": 0.4, "effects": { @@ -1631,7 +1632,6 @@ "centerGlow": true, "gradient": true }, - "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1720,6 +1720,7 @@ "id": 13, "maxDataPoints": 20, "options": { + "barShape": "rounded", "barWidth": 12, "barWidthFactor": 0.49, "effects": { @@ -1727,7 +1728,6 @@ "centerGlow": true, "gradient": true }, - "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1760,6 +1760,7 @@ "startValue": 0 } ], + "title": "Active gateways", "transformations": [ { "id": "calculateField", @@ -1770,13 +1771,12 @@ }, "replaceFields": true, "unary": { - "operator": "round", - "fieldName": "A-series" + "fieldName": "A-series", + "operator": "round" } } } ], - "title": "Active gateways", "type": "radialbar" }, { @@ -1819,6 +1819,7 @@ "id": 14, "maxDataPoints": 20, "options": { + "barShape": "rounded", "barWidth": 12, "barWidthFactor": 0.49, "effects": { @@ -1826,7 +1827,6 @@ "centerGlow": true, "gradient": true }, - "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1859,6 +1859,7 @@ "startValue": 0 } ], + "title": "Active pods", "transformations": [ { "id": "calculateField", @@ -1869,13 +1870,12 @@ }, "replaceFields": true, "unary": { - "operator": "round", - "fieldName": "A-series" + "fieldName": "A-series", + "operator": "round" } } } ], - "title": "Active pods", "type": "radialbar" }, { @@ -1917,6 +1917,7 @@ "id": 15, "maxDataPoints": 20, "options": { + "barShape": "rounded", "barWidth": 12, "barWidthFactor": 0.84, "effects": { @@ -1924,7 +1925,6 @@ "centerGlow": true, "gradient": true }, - "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -1999,6 +1999,7 @@ "id": 16, "maxDataPoints": 20, "options": { + "barShape": "rounded", "barWidth": 12, "barWidthFactor": 0.66, "effects": { @@ -2006,7 +2007,6 @@ "centerGlow": true, "gradient": true }, - "barShape": "rounded", "glow": "both", "orientation": "auto", "reduceOptions": { @@ -2086,13 +2086,13 @@ }, "id": 36, "options": { + "barShape": "flat", "barWidthFactor": 0.5, "effects": { "barGlow": false, "centerGlow": false, "gradient": true }, - "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -2153,13 +2153,13 @@ }, "id": 37, "options": { + "barShape": "flat", "barWidthFactor": 0.5, "effects": { "barGlow": false, "centerGlow": false, "gradient": true }, - "barShape": "flat", "orientation": "auto", "reduceOptions": { "calcs": [ @@ -2201,4 +2201,4 @@ "title": "Panel tests - Gauge (new)", "uid": "panel-tests-gauge-new", "weekStart": "" -} +} \ No newline at end of file diff --git a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_old_to_new.v42.json b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_old_to_new.v42.json index a75a58b7530..449955a9cc8 100644 --- a/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_old_to_new.v42.json +++ b/apps/dashboard/pkg/migration/testdata/dev-dashboards-output/panel-gauge/gauge_tests_old_to_new.v42.json @@ -1161,4 +1161,4 @@ "title": "Panel tests - Old gauge to new", "uid": "panel-tests-old-gauge-to-new", "weekStart": "" -} +} \ No newline at end of file diff --git a/apps/plugins/go.mod b/apps/plugins/go.mod index 9a3e3776efb..0b9ba53e76a 100644 --- a/apps/plugins/go.mod +++ b/apps/plugins/go.mod @@ -13,6 +13,7 @@ require ( github.com/grafana/grafana v0.0.0-00010101000000-000000000000 github.com/grafana/grafana-app-sdk v0.48.7 github.com/grafana/grafana-app-sdk/logging v0.48.7 + github.com/grafana/grafana/pkg/apimachinery v0.0.0 github.com/stretchr/testify v1.11.1 k8s.io/apimachinery v0.34.3 k8s.io/apiserver v0.34.3 @@ -99,7 +100,6 @@ require ( github.com/grafana/grafana-aws-sdk v1.3.0 // indirect github.com/grafana/grafana-azure-sdk-go/v2 v2.3.1 // indirect github.com/grafana/grafana-plugin-sdk-go v0.284.0 // indirect - github.com/grafana/grafana/pkg/apimachinery v0.0.0 // indirect github.com/grafana/grafana/pkg/apiserver v0.0.0 // indirect github.com/grafana/grafana/pkg/semconv v0.0.0-20250804150913-990f1c69ecc2 // indirect github.com/grafana/otel-profiling-go v0.5.1 // indirect diff --git a/apps/plugins/kinds/meta.cue b/apps/plugins/kinds/meta.cue index d29308e2ca2..b3b506e6101 100644 --- a/apps/plugins/kinds/meta.cue +++ b/apps/plugins/kinds/meta.cue @@ -137,7 +137,7 @@ metaV0Alpha1: { type?: "dashboard" | "page" | "panel" | "datasource" name?: string component?: string - role?: "Admin" | "Editor" | "Viewer" + role?: "Admin" | "Editor" | "Viewer" | "None" action?: string path?: string addToNav?: bool diff --git a/apps/plugins/pkg/apis/plugins/v0alpha1/meta_spec_gen.go b/apps/plugins/pkg/apis/plugins/v0alpha1/meta_spec_gen.go index f3671a040db..c88d9b7ff8a 100644 --- a/apps/plugins/pkg/apis/plugins/v0alpha1/meta_spec_gen.go +++ b/apps/plugins/pkg/apis/plugins/v0alpha1/meta_spec_gen.go @@ -504,6 +504,7 @@ const ( MetaIncludeRoleAdmin MetaIncludeRole = "Admin" MetaIncludeRoleEditor MetaIncludeRole = "Editor" MetaIncludeRoleViewer MetaIncludeRole = "Viewer" + MetaIncludeRoleNone MetaIncludeRole = "None" ) // +k8s:openapi-gen=true diff --git a/apps/plugins/pkg/apis/plugins_manifest.go b/apps/plugins/pkg/apis/plugins_manifest.go index 7b87dcf0ea7..1cabb46a611 100644 --- a/apps/plugins/pkg/apis/plugins_manifest.go +++ b/apps/plugins/pkg/apis/plugins_manifest.go @@ -23,7 +23,7 @@ var ( rawSchemaPluginv0alpha1 = []byte(`{"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"Plugin":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"spec":{"additionalProperties":false,"properties":{"id":{"type":"string"},"url":{"type":"string"},"version":{"type":"string"}},"required":["id","version"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`) versionSchemaPluginv0alpha1 app.VersionSchema _ = json.Unmarshal(rawSchemaPluginv0alpha1, &versionSchemaPluginv0alpha1) - rawSchemaMetav0alpha1 = []byte(`{"Dependencies":{"additionalProperties":false,"properties":{"extensions":{"additionalProperties":false,"properties":{"exposedComponents":{"description":"+listType=set","items":{"type":"string"},"type":"array"}},"type":"object"},"grafanaDependency":{"description":"Required field","type":"string"},"grafanaVersion":{"description":"Optional fields","type":"string"},"plugins":{"description":"+listType=set\n+listMapKey=id","items":{"additionalProperties":false,"properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"enum":["app","datasource","panel"],"type":"string"}},"required":["id","type","name"],"type":"object"},"type":"array"}},"required":["grafanaDependency"],"type":"object"},"EnterpriseFeatures":{"additionalProperties":false,"properties":{"healthDiagnosticsErrors":{"default":false,"description":"Allow additional properties","type":"boolean"}},"type":"object"},"Extensions":{"additionalProperties":false,"properties":{"addedComponents":{"description":"+listType=atomic","items":{"additionalProperties":false,"properties":{"description":{"type":"string"},"targets":{"description":"+listType=set","items":{"type":"string"},"type":"array"},"title":{"type":"string"}},"required":["targets","title"],"type":"object"},"type":"array"},"addedLinks":{"description":"+listType=atomic","items":{"additionalProperties":false,"properties":{"description":{"type":"string"},"targets":{"description":"+listType=set","items":{"type":"string"},"type":"array"},"title":{"type":"string"}},"required":["targets","title"],"type":"object"},"type":"array"},"exposedComponents":{"description":"+listType=set\n+listMapKey=id","items":{"additionalProperties":false,"properties":{"description":{"type":"string"},"id":{"type":"string"},"title":{"type":"string"}},"required":["id"],"type":"object"},"type":"array"},"extensionPoints":{"description":"+listType=set\n+listMapKey=id","items":{"additionalProperties":false,"properties":{"description":{"type":"string"},"id":{"type":"string"},"title":{"type":"string"}},"required":["id"],"type":"object"},"type":"array"}},"type":"object"},"IAM":{"additionalProperties":false,"properties":{"permissions":{"description":"+listType=atomic","items":{"additionalProperties":false,"properties":{"action":{"type":"string"},"scope":{"type":"string"}},"type":"object"},"type":"array"}},"type":"object"},"Include":{"additionalProperties":false,"properties":{"action":{"type":"string"},"addToNav":{"type":"boolean"},"component":{"type":"string"},"defaultNav":{"type":"boolean"},"icon":{"type":"string"},"name":{"type":"string"},"path":{"type":"string"},"role":{"enum":["Admin","Editor","Viewer"],"type":"string"},"type":{"enum":["dashboard","page","panel","datasource"],"type":"string"},"uid":{"type":"string"}},"type":"object"},"Info":{"additionalProperties":false,"properties":{"author":{"additionalProperties":false,"description":"Optional fields","properties":{"email":{"type":"string"},"name":{"type":"string"},"url":{"type":"string"}},"type":"object"},"description":{"type":"string"},"keywords":{"description":"Required fields\n+listType=set","items":{"type":"string"},"type":"array"},"links":{"description":"+listType=atomic","items":{"additionalProperties":false,"properties":{"name":{"type":"string"},"url":{"type":"string"}},"type":"object"},"type":"array"},"logos":{"additionalProperties":false,"properties":{"large":{"type":"string"},"small":{"type":"string"}},"required":["small","large"],"type":"object"},"screenshots":{"description":"+listType=atomic","items":{"additionalProperties":false,"properties":{"name":{"type":"string"},"path":{"type":"string"}},"type":"object"},"type":"array"},"updated":{"type":"string"},"version":{"type":"string"}},"required":["keywords","logos","updated","version"],"type":"object"},"JSONData":{"additionalProperties":false,"description":"JSON configuration schema for Grafana plugins\nConverted from: https://github.com/grafana/grafana/blob/main/docs/sources/developers/plugins/plugin.schema.json","properties":{"alerting":{"description":"Optional fields","type":"boolean"},"annotations":{"type":"boolean"},"autoEnabled":{"type":"boolean"},"backend":{"type":"boolean"},"buildMode":{"type":"string"},"builtIn":{"type":"boolean"},"category":{"enum":["tsdb","logging","cloud","tracing","profiling","sql","enterprise","iot","other"],"type":"string"},"dependencies":{"$ref":"#/components/schemas/Dependencies","description":"Dependency information"},"enterpriseFeatures":{"$ref":"#/components/schemas/EnterpriseFeatures"},"executable":{"type":"string"},"extensions":{"$ref":"#/components/schemas/Extensions"},"hideFromList":{"type":"boolean"},"iam":{"$ref":"#/components/schemas/IAM"},"id":{"description":"Unique name of the plugin","type":"string"},"includes":{"description":"+listType=atomic","items":{"$ref":"#/components/schemas/Include"},"type":"array"},"info":{"$ref":"#/components/schemas/Info","description":"Metadata for the plugin"},"logs":{"type":"boolean"},"metrics":{"type":"boolean"},"multiValueFilterOperators":{"type":"boolean"},"name":{"description":"Human-readable name of the plugin","type":"string"},"pascalName":{"type":"string"},"preload":{"type":"boolean"},"queryOptions":{"$ref":"#/components/schemas/QueryOptions"},"roles":{"description":"+listType=atomic","items":{"$ref":"#/components/schemas/Role"},"type":"array"},"routes":{"description":"+listType=atomic","items":{"$ref":"#/components/schemas/Route"},"type":"array"},"skipDataQuery":{"type":"boolean"},"state":{"enum":["alpha","beta"],"type":"string"},"streaming":{"type":"boolean"},"suggestions":{"type":"boolean"},"tracing":{"type":"boolean"},"type":{"description":"Plugin type","enum":["app","datasource","panel","renderer"],"type":"string"}},"required":["id","type","name","info","dependencies"],"type":"object"},"Meta":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"QueryOptions":{"additionalProperties":false,"properties":{"cacheTimeout":{"type":"boolean"},"maxDataPoints":{"type":"boolean"},"minInterval":{"type":"boolean"}},"type":"object"},"Role":{"additionalProperties":false,"properties":{"grants":{"description":"+listType=set","items":{"type":"string"},"type":"array"},"role":{"additionalProperties":false,"properties":{"description":{"type":"string"},"name":{"type":"string"},"permissions":{"description":"+listType=atomic","items":{"additionalProperties":false,"properties":{"action":{"type":"string"},"scope":{"type":"string"}},"type":"object"},"type":"array"}},"type":"object"}},"type":"object"},"Route":{"additionalProperties":false,"properties":{"body":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"},"headers":{"description":"+listType=atomic","items":{"type":"string"},"type":"array"},"jwtTokenAuth":{"additionalProperties":false,"properties":{"params":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"},"scopes":{"description":"+listType=set","items":{"type":"string"},"type":"array"},"url":{"type":"string"}},"type":"object"},"method":{"type":"string"},"path":{"type":"string"},"reqAction":{"type":"string"},"reqRole":{"type":"string"},"reqSignedIn":{"type":"boolean"},"tokenAuth":{"additionalProperties":false,"properties":{"params":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"},"scopes":{"description":"+listType=set","items":{"type":"string"},"type":"array"},"url":{"type":"string"}},"type":"object"},"url":{"type":"string"},"urlParams":{"description":"+listType=atomic","items":{"additionalProperties":false,"properties":{"content":{"type":"string"},"name":{"type":"string"}},"type":"object"},"type":"array"}},"type":"object"},"spec":{"additionalProperties":false,"properties":{"angular":{"additionalProperties":false,"properties":{"detected":{"type":"boolean"}},"required":["detected"],"type":"object"},"baseURL":{"type":"string"},"children":{"description":"+listType=atomic","items":{"type":"string"},"type":"array"},"class":{"enum":["core","external"],"type":"string"},"module":{"additionalProperties":false,"properties":{"hash":{"type":"string"},"loadingStrategy":{"enum":["fetch","script"],"type":"string"},"path":{"type":"string"}},"required":["path"],"type":"object"},"pluginJson":{"$ref":"#/components/schemas/JSONData"},"signature":{"additionalProperties":false,"properties":{"org":{"type":"string"},"status":{"enum":["internal","valid","invalid","modified","unsigned"],"type":"string"},"type":{"enum":["grafana","commercial","community","private","private-glob"],"type":"string"}},"required":["status"],"type":"object"},"translations":{"additionalProperties":{"type":"string"},"type":"object"}},"required":["pluginJson","class"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`) + rawSchemaMetav0alpha1 = []byte(`{"Dependencies":{"additionalProperties":false,"properties":{"extensions":{"additionalProperties":false,"properties":{"exposedComponents":{"description":"+listType=set","items":{"type":"string"},"type":"array"}},"type":"object"},"grafanaDependency":{"description":"Required field","type":"string"},"grafanaVersion":{"description":"Optional fields","type":"string"},"plugins":{"description":"+listType=set\n+listMapKey=id","items":{"additionalProperties":false,"properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"enum":["app","datasource","panel"],"type":"string"}},"required":["id","type","name"],"type":"object"},"type":"array"}},"required":["grafanaDependency"],"type":"object"},"EnterpriseFeatures":{"additionalProperties":false,"properties":{"healthDiagnosticsErrors":{"default":false,"description":"Allow additional properties","type":"boolean"}},"type":"object"},"Extensions":{"additionalProperties":false,"properties":{"addedComponents":{"description":"+listType=atomic","items":{"additionalProperties":false,"properties":{"description":{"type":"string"},"targets":{"description":"+listType=set","items":{"type":"string"},"type":"array"},"title":{"type":"string"}},"required":["targets","title"],"type":"object"},"type":"array"},"addedLinks":{"description":"+listType=atomic","items":{"additionalProperties":false,"properties":{"description":{"type":"string"},"targets":{"description":"+listType=set","items":{"type":"string"},"type":"array"},"title":{"type":"string"}},"required":["targets","title"],"type":"object"},"type":"array"},"exposedComponents":{"description":"+listType=set\n+listMapKey=id","items":{"additionalProperties":false,"properties":{"description":{"type":"string"},"id":{"type":"string"},"title":{"type":"string"}},"required":["id"],"type":"object"},"type":"array"},"extensionPoints":{"description":"+listType=set\n+listMapKey=id","items":{"additionalProperties":false,"properties":{"description":{"type":"string"},"id":{"type":"string"},"title":{"type":"string"}},"required":["id"],"type":"object"},"type":"array"}},"type":"object"},"IAM":{"additionalProperties":false,"properties":{"permissions":{"description":"+listType=atomic","items":{"additionalProperties":false,"properties":{"action":{"type":"string"},"scope":{"type":"string"}},"type":"object"},"type":"array"}},"type":"object"},"Include":{"additionalProperties":false,"properties":{"action":{"type":"string"},"addToNav":{"type":"boolean"},"component":{"type":"string"},"defaultNav":{"type":"boolean"},"icon":{"type":"string"},"name":{"type":"string"},"path":{"type":"string"},"role":{"enum":["Admin","Editor","Viewer","None"],"type":"string"},"type":{"enum":["dashboard","page","panel","datasource"],"type":"string"},"uid":{"type":"string"}},"type":"object"},"Info":{"additionalProperties":false,"properties":{"author":{"additionalProperties":false,"description":"Optional fields","properties":{"email":{"type":"string"},"name":{"type":"string"},"url":{"type":"string"}},"type":"object"},"description":{"type":"string"},"keywords":{"description":"Required fields\n+listType=set","items":{"type":"string"},"type":"array"},"links":{"description":"+listType=atomic","items":{"additionalProperties":false,"properties":{"name":{"type":"string"},"url":{"type":"string"}},"type":"object"},"type":"array"},"logos":{"additionalProperties":false,"properties":{"large":{"type":"string"},"small":{"type":"string"}},"required":["small","large"],"type":"object"},"screenshots":{"description":"+listType=atomic","items":{"additionalProperties":false,"properties":{"name":{"type":"string"},"path":{"type":"string"}},"type":"object"},"type":"array"},"updated":{"type":"string"},"version":{"type":"string"}},"required":["keywords","logos","updated","version"],"type":"object"},"JSONData":{"additionalProperties":false,"description":"JSON configuration schema for Grafana plugins\nConverted from: https://github.com/grafana/grafana/blob/main/docs/sources/developers/plugins/plugin.schema.json","properties":{"alerting":{"description":"Optional fields","type":"boolean"},"annotations":{"type":"boolean"},"autoEnabled":{"type":"boolean"},"backend":{"type":"boolean"},"buildMode":{"type":"string"},"builtIn":{"type":"boolean"},"category":{"enum":["tsdb","logging","cloud","tracing","profiling","sql","enterprise","iot","other"],"type":"string"},"dependencies":{"$ref":"#/components/schemas/Dependencies","description":"Dependency information"},"enterpriseFeatures":{"$ref":"#/components/schemas/EnterpriseFeatures"},"executable":{"type":"string"},"extensions":{"$ref":"#/components/schemas/Extensions"},"hideFromList":{"type":"boolean"},"iam":{"$ref":"#/components/schemas/IAM"},"id":{"description":"Unique name of the plugin","type":"string"},"includes":{"description":"+listType=atomic","items":{"$ref":"#/components/schemas/Include"},"type":"array"},"info":{"$ref":"#/components/schemas/Info","description":"Metadata for the plugin"},"logs":{"type":"boolean"},"metrics":{"type":"boolean"},"multiValueFilterOperators":{"type":"boolean"},"name":{"description":"Human-readable name of the plugin","type":"string"},"pascalName":{"type":"string"},"preload":{"type":"boolean"},"queryOptions":{"$ref":"#/components/schemas/QueryOptions"},"roles":{"description":"+listType=atomic","items":{"$ref":"#/components/schemas/Role"},"type":"array"},"routes":{"description":"+listType=atomic","items":{"$ref":"#/components/schemas/Route"},"type":"array"},"skipDataQuery":{"type":"boolean"},"state":{"enum":["alpha","beta"],"type":"string"},"streaming":{"type":"boolean"},"suggestions":{"type":"boolean"},"tracing":{"type":"boolean"},"type":{"description":"Plugin type","enum":["app","datasource","panel","renderer"],"type":"string"}},"required":["id","type","name","info","dependencies"],"type":"object"},"Meta":{"properties":{"spec":{"$ref":"#/components/schemas/spec"},"status":{"$ref":"#/components/schemas/status"}},"required":["spec"]},"OperatorState":{"additionalProperties":false,"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"details contains any extra information that is operator-specific","type":"object"},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"QueryOptions":{"additionalProperties":false,"properties":{"cacheTimeout":{"type":"boolean"},"maxDataPoints":{"type":"boolean"},"minInterval":{"type":"boolean"}},"type":"object"},"Role":{"additionalProperties":false,"properties":{"grants":{"description":"+listType=set","items":{"type":"string"},"type":"array"},"role":{"additionalProperties":false,"properties":{"description":{"type":"string"},"name":{"type":"string"},"permissions":{"description":"+listType=atomic","items":{"additionalProperties":false,"properties":{"action":{"type":"string"},"scope":{"type":"string"}},"type":"object"},"type":"array"}},"type":"object"}},"type":"object"},"Route":{"additionalProperties":false,"properties":{"body":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"},"headers":{"description":"+listType=atomic","items":{"type":"string"},"type":"array"},"jwtTokenAuth":{"additionalProperties":false,"properties":{"params":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"},"scopes":{"description":"+listType=set","items":{"type":"string"},"type":"array"},"url":{"type":"string"}},"type":"object"},"method":{"type":"string"},"path":{"type":"string"},"reqAction":{"type":"string"},"reqRole":{"type":"string"},"reqSignedIn":{"type":"boolean"},"tokenAuth":{"additionalProperties":false,"properties":{"params":{"additionalProperties":{"additionalProperties":{},"type":"object"},"type":"object"},"scopes":{"description":"+listType=set","items":{"type":"string"},"type":"array"},"url":{"type":"string"}},"type":"object"},"url":{"type":"string"},"urlParams":{"description":"+listType=atomic","items":{"additionalProperties":false,"properties":{"content":{"type":"string"},"name":{"type":"string"}},"type":"object"},"type":"array"}},"type":"object"},"spec":{"additionalProperties":false,"properties":{"angular":{"additionalProperties":false,"properties":{"detected":{"type":"boolean"}},"required":["detected"],"type":"object"},"baseURL":{"type":"string"},"children":{"description":"+listType=atomic","items":{"type":"string"},"type":"array"},"class":{"enum":["core","external"],"type":"string"},"module":{"additionalProperties":false,"properties":{"hash":{"type":"string"},"loadingStrategy":{"enum":["fetch","script"],"type":"string"},"path":{"type":"string"}},"required":["path"],"type":"object"},"pluginJson":{"$ref":"#/components/schemas/JSONData"},"signature":{"additionalProperties":false,"properties":{"org":{"type":"string"},"status":{"enum":["internal","valid","invalid","modified","unsigned"],"type":"string"},"type":{"enum":["grafana","commercial","community","private","private-glob"],"type":"string"}},"required":["status"],"type":"object"},"translations":{"additionalProperties":{"type":"string"},"type":"object"}},"required":["pluginJson","class"],"type":"object"},"status":{"additionalProperties":false,"properties":{"additionalFields":{"additionalProperties":{"additionalProperties":{},"type":"object"},"description":"additionalFields is reserved for future use","type":"object"},"operatorStates":{"additionalProperties":{"$ref":"#/components/schemas/OperatorState"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object"}}`) versionSchemaMetav0alpha1 app.VersionSchema _ = json.Unmarshal(rawSchemaMetav0alpha1, &versionSchemaMetav0alpha1) ) diff --git a/apps/plugins/pkg/app/meta/converter.go b/apps/plugins/pkg/app/meta/converter.go index 28180a263bd..2af699f6f9e 100644 --- a/apps/plugins/pkg/app/meta/converter.go +++ b/apps/plugins/pkg/app/meta/converter.go @@ -5,6 +5,7 @@ import ( "time" pluginsv0alpha1 "github.com/grafana/grafana/apps/plugins/pkg/apis/plugins/v0alpha1" + "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore" ) @@ -253,12 +254,14 @@ func jsonDataToMetaJSONData(jsonData plugins.JSONData) pluginsv0alpha1.MetaJSOND if include.Role != "" { var role pluginsv0alpha1.MetaIncludeRole switch include.Role { - case "Admin": + case identity.RoleAdmin: role = pluginsv0alpha1.MetaIncludeRoleAdmin - case "Editor": + case identity.RoleEditor: role = pluginsv0alpha1.MetaIncludeRoleEditor - case "Viewer": + case identity.RoleViewer: role = pluginsv0alpha1.MetaIncludeRoleViewer + case identity.RoleNone: + role = pluginsv0alpha1.MetaIncludeRoleNone } v0Include.Role = &role } diff --git a/apps/plugins/pkg/app/meta/core.go b/apps/plugins/pkg/app/meta/core.go index 9fb167d5578..1837386f7a3 100644 --- a/apps/plugins/pkg/app/meta/core.go +++ b/apps/plugins/pkg/app/meta/core.go @@ -20,7 +20,7 @@ import ( "github.com/grafana/grafana/pkg/plugins/manager/pipeline/termination" "github.com/grafana/grafana/pkg/plugins/manager/pipeline/validation" "github.com/grafana/grafana/pkg/plugins/manager/sources" - "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs" + "github.com/grafana/grafana/pkg/plugins/pluginerrs" ) const ( diff --git a/devenv/dev-dashboards/panel-canvas/canvas_kitchen_sink.json b/devenv/dev-dashboards/panel-canvas/canvas_kitchen_sink.json new file mode 100644 index 00000000000..069a43c0888 --- /dev/null +++ b/devenv/dev-dashboards/panel-canvas/canvas_kitchen_sink.json @@ -0,0 +1,582 @@ +{ + "annotations": { + "list": [] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "panels": [ + { + "datasource": { + "type": "datasource", + "uid": "-- Mixed --" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "1": { + "color": "green", + "icon": "img/icons/unicons/check-circle.svg", + "index": 0, + "text": "Success" + }, + "2": { + "color": "orange", + "icon": "img/icons/unicons/exclamation-triangle.svg", + "index": 1, + "text": "Warning" + }, + "3": { + "color": "red", + "icon": "img/icons/unicons/times-circle.svg", + "index": 2, + "text": "Error" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "text", + "value": null + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "success" + }, + "properties": [ + { + "id": "mappings", + "value": [ + { + "options": { + "1": { + "color": "green", + "icon": "img/icons/unicons/check-circle.svg", + "index": 0, + "text": "Success" + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "warning" + }, + "properties": [ + { + "id": "mappings", + "value": [ + { + "options": { + "2": { + "color": "orange", + "icon": "img/icons/unicons/exclamation-triangle.svg", + "index": 1, + "text": "Warning" + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "error" + }, + "properties": [ + { + "id": "mappings", + "value": [ + { + "options": { + "3": { + "color": "red", + "icon": "img/icons/unicons/times-circle.svg", + "index": 2, + "text": "Error" + } + }, + "type": "value" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "unmapped" + }, + "properties": [ + { + "id": "mappings", + "value": [ + { + "options": { + "1": { + "color": "green", + "icon": "img/icons/unicons/check-circle.svg", + "index": 0, + "text": "Success" + }, + "2": { + "color": "orange", + "icon": "img/icons/unicons/exclamation-triangle.svg", + "index": 1, + "text": "Warning" + }, + "3": { + "color": "red", + "icon": "img/icons/unicons/times-circle.svg", + "index": 2, + "text": "Error" + } + }, + "type": "value" + } + ] + } + ] + } + ] + }, + "gridPos": { + "h": 12, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "inlineEditing": true, + "root": { + "background": { + "color": { + "fixed": "transparent" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "elements": [ + { + "config": { + "align": "center", + "color": { + "fixed": "text" + }, + "size": 16, + "text": { + "fixed": "Field-based Icons (from value mappings):", + "mode": "fixed" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Header", + "placement": { + "height": 40, + "left": 20, + "top": 10, + "width": 400 + }, + "type": "text" + }, + { + "config": { + "fill": { + "field": "success", + "fixed": "green" + }, + "path": { + "field": "success", + "mode": "field" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Success Icon", + "placement": { + "height": 50, + "left": 50, + "top": 60, + "width": 50 + }, + "type": "icon" + }, + { + "config": { + "align": "center", + "color": { + "field": "success", + "fixed": "text" + }, + "size": 12, + "text": { + "field": "success", + "mode": "field" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Success Text", + "placement": { + "height": 25, + "left": 30, + "top": 115, + "width": 90 + }, + "type": "text" + }, + { + "config": { + "fill": { + "field": "warning", + "fixed": "orange" + }, + "path": { + "field": "warning", + "mode": "field" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Warning Icon", + "placement": { + "height": 50, + "left": 180, + "top": 60, + "width": 50 + }, + "type": "icon" + }, + { + "config": { + "align": "center", + "color": { + "field": "warning", + "fixed": "text" + }, + "size": 12, + "text": { + "field": "warning", + "mode": "field" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Warning Text", + "placement": { + "height": 25, + "left": 160, + "top": 115, + "width": 90 + }, + "type": "text" + }, + { + "config": { + "fill": { + "field": "error", + "fixed": "red" + }, + "path": { + "field": "error", + "mode": "field" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Error Icon", + "placement": { + "height": 50, + "left": 310, + "top": 60, + "width": 50 + }, + "type": "icon" + }, + { + "config": { + "align": "center", + "color": { + "field": "error", + "fixed": "text" + }, + "size": 12, + "text": { + "field": "error", + "mode": "field" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Error Text", + "placement": { + "height": 25, + "left": 290, + "top": 115, + "width": 90 + }, + "type": "text" + }, + { + "config": { + "fill": { + "field": "unmapped", + "fixed": "#808080" + }, + "path": { + "field": "unmapped", + "fixed": "img/icons/unicons/question-circle.svg", + "mode": "field" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Unmapped Icon", + "placement": { + "height": 50, + "left": 440, + "top": 60, + "width": 50 + }, + "type": "icon" + }, + { + "config": { + "align": "center", + "color": { + "field": "unmapped", + "fixed": "text" + }, + "size": 12, + "text": { + "fixed": "No mapping (14)", + "mode": "fixed" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Unmapped Text", + "placement": { + "height": 25, + "left": 410, + "top": 115, + "width": 110 + }, + "type": "text" + }, + { + "config": { + "align": "center", + "color": { + "fixed": "text" + }, + "size": 14, + "text": { + "fixed": "Fixed Relative Path:", + "mode": "fixed" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Relative Label", + "placement": { + "height": 30, + "left": 50, + "top": 170, + "width": 200 + }, + "type": "text" + }, + { + "config": { + "fill": { + "fixed": "blue" + }, + "path": { + "fixed": "img/icons/unicons/cloud.svg", + "mode": "fixed" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Relative Icon", + "placement": { + "height": 50, + "left": 260, + "top": 165, + "width": 50 + }, + "type": "icon" + }, + { + "config": { + "align": "center", + "color": { + "fixed": "text" + }, + "size": 14, + "text": { + "fixed": "Fixed Absolute URL:", + "mode": "fixed" + }, + "valign": "middle" + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Absolute Label", + "placement": { + "height": 30, + "left": 50, + "top": 240, + "width": 200 + }, + "type": "text" + }, + { + "config": { + "fill": { + "fixed": "purple" + }, + "path": { + "fixed": "https://grafana.com/static/assets/img/grafana_icon.svg", + "mode": "fixed" + } + }, + "constraint": { + "horizontal": "left", + "vertical": "top" + }, + "name": "Absolute Icon", + "placement": { + "height": 50, + "left": 260, + "top": 235, + "width": 50 + }, + "type": "icon" + } + ], + "name": "Canvas Root", + "placement": { + "height": 100, + "left": 0, + "top": 0, + "width": 100 + }, + "type": "frame" + } + }, + "pluginVersion": "12.1.0", + "targets": [ + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "A", + "scenarioId": "csv_content", + "csvContent": "success\n1" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "B", + "scenarioId": "csv_content", + "csvContent": "warning\n2" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "C", + "scenarioId": "csv_content", + "csvContent": "error\n3" + }, + { + "datasource": { + "type": "grafana-testdata-datasource", + "uid": "PD8C576611E62080A" + }, + "refId": "D", + "scenarioId": "csv_content", + "csvContent": "unmapped\n14" + } + ], + "title": "Various SVG icons", + "type": "canvas" + } + ], + "schemaVersion": 39, + "tags": ["canvas", "icons", "test", "v2"], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Panel tests - Canvas - Kitchen sink", + "uid": "canvas-icon-fix-test-v2", + "version": 1, + "weekStart": "" +} diff --git a/devenv/jsonnet/dev-dashboards.libsonnet b/devenv/jsonnet/dev-dashboards.libsonnet index cac117cd4e7..98eb14e9217 100644 --- a/devenv/jsonnet/dev-dashboards.libsonnet +++ b/devenv/jsonnet/dev-dashboards.libsonnet @@ -24,6 +24,7 @@ "canvas-connection-examples": (import '../dev-dashboards/panel-canvas/canvas-connection-examples.json'), "canvas-datalinks": (import '../dev-dashboards/panel-canvas/canvas-datalinks.json'), "canvas-examples": (import '../dev-dashboards/panel-canvas/canvas-examples.json'), + "canvas_kitchen_sink": (import '../dev-dashboards/panel-canvas/canvas_kitchen_sink.json'), "color_modes": (import '../dev-dashboards/panel-common/color_modes.json'), "config-from-query": (import '../dev-dashboards/transforms/config-from-query.json'), "dashlist": (import '../dev-dashboards/panel-dashlist/dashlist.json'), diff --git a/e2e-playwright/panels-suite/canvas-icon-mappings.spec.ts b/e2e-playwright/panels-suite/canvas-icon-mappings.spec.ts new file mode 100644 index 00000000000..72de7a6c62c --- /dev/null +++ b/e2e-playwright/panels-suite/canvas-icon-mappings.spec.ts @@ -0,0 +1,99 @@ +import { test, expect } from '@grafana/plugin-e2e'; + +const DASHBOARD_UID = 'canvas-icon-fix-test-v2'; +const PANEL_TITLE = 'Various SVG icons'; + +test.describe('Canvas Panel - Icon Mappings', () => { + test('should render field-based icons from value mappings correctly', async ({ gotoDashboardPage, page }) => { + await test.step('Navigate to dashboard and wait for panel to load', async () => { + await gotoDashboardPage({ uid: DASHBOARD_UID }); + await page.waitForSelector('svg', { timeout: 10000 }); + }); + + await test.step('Verify value mapping text values are displayed', async () => { + await expect(page.getByText('Success')).toBeVisible(); + await expect(page.getByText('Warning')).toBeVisible(); + await expect(page.getByText('Error')).toBeVisible(); + }); + + await test.step('Verify SVG icons rendered for mapped values', async () => { + const svgCount = await page.locator('svg').count(); + expect(svgCount).toBeGreaterThanOrEqual(3); + }); + }); + + test('should render fixed path icons correctly', async ({ gotoDashboardPage, page }) => { + await test.step('Set up network interception for absolute URL icon', async () => { + await page.route('https://grafana.com/static/assets/img/grafana_icon.svg', async (route) => { + const dummySvg = ` + + TEST + `; + await route.fulfill({ + status: 200, + contentType: 'image/svg+xml', + body: dummySvg, + }); + }); + }); + + await test.step('Navigate to dashboard and wait for SVGs to load', async () => { + await gotoDashboardPage({ uid: DASHBOARD_UID }); + await page.waitForSelector('svg:not([aria-hidden="true"])', { timeout: 10000 }); + await page.waitForLoadState('networkidle', { timeout: 10000 }); + }); + + await test.step('Verify at least 5 visible SVG icons are rendered (3 mapped + 2 fixed)', async () => { + const visibleSvgs = page.locator('svg:not([aria-hidden="true"])'); + const svgCount = await visibleSvgs.count(); + expect(svgCount).toBeGreaterThanOrEqual(5); + }); + + await test.step('Verify visible SVG icons have content', async () => { + const visibleSvgs = page.locator('svg:not([aria-hidden="true"])'); + const count = await visibleSvgs.count(); + + for (let i = 0; i < Math.min(count, 5); i++) { + const svg = visibleSvgs.nth(i); + await expect(svg).toBeAttached(); + const svgContent = await svg.innerHTML(); + expect(svgContent.length).toBeGreaterThan(0); + } + }); + }); + + test('should not make invalid requests for unmapped numeric values', async ({ gotoDashboardPage, page }) => { + const failedRequests: string[] = []; + + await test.step('Set up network request monitoring', async () => { + page.on('requestfailed', (request) => { + const url = request.url(); + if (url.match(/\/build\/\d+$/)) { + failedRequests.push(url); + } + }); + }); + + await test.step('Navigate to dashboard and wait for loading', async () => { + await gotoDashboardPage({ uid: DASHBOARD_UID }); + await page.waitForTimeout(2000); + }); + + await test.step('Verify no invalid numeric path requests were made', async () => { + expect(failedRequests).toHaveLength(0); + }); + }); + + test('should display text values from value mappings correctly', async ({ gotoDashboardPage, page }) => { + await test.step('Navigate to dashboard', async () => { + await gotoDashboardPage({ uid: DASHBOARD_UID }); + }); + + await test.step('Verify mapped text values are displayed', async () => { + await expect(page.getByText('Success')).toBeVisible(); + await expect(page.getByText('Warning')).toBeVisible(); + await expect(page.getByText('Error')).toBeVisible(); + await expect(page.getByText('No mapping (14)')).toBeVisible(); + }); + }); +}); diff --git a/e2e-playwright/panels-suite/state-timeline.spec.ts b/e2e-playwright/panels-suite/state-timeline.spec.ts index ebdeb8d5398..d851a25f8af 100644 --- a/e2e-playwright/panels-suite/state-timeline.spec.ts +++ b/e2e-playwright/panels-suite/state-timeline.spec.ts @@ -78,6 +78,16 @@ test.describe('Panels test: StateTimeine', { tag: ['@panels', '@state-timeline'] await dashboardPage.getByGrafanaSelector(selectors.components.Portal.container).getByLabel('Close').click(); await expect(tooltip, 'tooltip closed on "x" click').toBeHidden(); + // test that CMD/CTRL+C doesn't dismiss the tooltip + await stateTimelineUplot.click({ position: { x: 100, y: 50 } }); + await expect(tooltip, 'tooltip appears on click').toBeVisible(); + await page.keyboard.press('Meta+C'); + await expect(tooltip, 'tooltip persists after CMD/CTRL+C').toBeVisible(); + + // test that Escape key dismisses the tooltip + await page.keyboard.press('Escape'); + await expect(tooltip, 'tooltip closed on Escape key').toBeHidden(); + // disable tooltips await dashboardPage .getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldLabel('Tooltip Tooltip mode')) diff --git a/e2e-playwright/panels-suite/status-history.spec.ts b/e2e-playwright/panels-suite/status-history.spec.ts index bece3aa47c7..b2e628c0795 100644 --- a/e2e-playwright/panels-suite/status-history.spec.ts +++ b/e2e-playwright/panels-suite/status-history.spec.ts @@ -76,6 +76,16 @@ test.describe('Panels test: StatusHistory', { tag: ['@panels', '@status-history' await dashboardPage.getByGrafanaSelector(selectors.components.Portal.container).getByLabel('Close').click(); await expect(tooltip, 'tooltip closed on "x" click').toBeHidden(); + // test that CMD/CTRL+C doesn't dismiss the tooltip + await statusHistoryUplot.click({ position: { x: 100, y: 50 } }); + await expect(tooltip, 'tooltip appears on click').toBeVisible(); + await page.keyboard.press('Meta+C'); + await expect(tooltip, 'tooltip persists after CMD/CTRL+C').toBeVisible(); + + // test that Escape key dismisses the tooltip + await page.keyboard.press('Escape'); + await expect(tooltip, 'tooltip closed on Escape key').toBeHidden(); + // disable tooltips await dashboardPage .getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldLabel('Tooltip Tooltip mode')) diff --git a/packages/grafana-prometheus/src/dashboards/prometheus_2_stats.json b/packages/grafana-prometheus/src/dashboards/prometheus_2_stats.json index 5a6fbdf8518..063e4af2c8c 100644 --- a/packages/grafana-prometheus/src/dashboards/prometheus_2_stats.json +++ b/packages/grafana-prometheus/src/dashboards/prometheus_2_stats.json @@ -180,15 +180,12 @@ "pluginVersion": "8.1.0-pre", "targets": [ { - "expr": "sum(irate(prometheus_tsdb_head_samples_appended_total{job=\"prometheus\"}[5m]))", + "expr": "sum(irate(prometheus_tsdb_head_samples_appended_total{job=\"prometheus\"}[$__rate_interval]))", "format": "time_series", "hide": false, - "interval": "", - "intervalFactor": 2, "legendFormat": "samples", "metric": "", - "refId": "A", - "step": 20 + "refId": "A" } ], "timeFrom": null, @@ -273,12 +270,9 @@ { "expr": "topk(5, max(scrape_duration_seconds) by (job))", "format": "time_series", - "interval": "", - "intervalFactor": 2, "legendFormat": "{{job}}", "metric": "", - "refId": "A", - "step": 20 + "refId": "A" } ], "timeFrom": null, @@ -366,20 +360,15 @@ "expr": "sum(process_resident_memory_bytes{job=\"prometheus\"})", "format": "time_series", "hide": false, - "interval": "", - "intervalFactor": 2, "legendFormat": "p8s process resident memory", - "refId": "D", - "step": 20 + "refId": "D" }, { "expr": "process_virtual_memory_bytes{job=\"prometheus\"}", "format": "time_series", "hide": false, - "intervalFactor": 2, "legendFormat": "virtual memory", - "refId": "C", - "step": 20 + "refId": "C" } ], "timeFrom": null, @@ -454,10 +443,8 @@ { "expr": "prometheus_tsdb_wal_corruptions_total{job=\"prometheus\"}", "format": "time_series", - "intervalFactor": 2, "legendFormat": "", - "refId": "A", - "step": 60 + "refId": "A" } ], "title": "WAL Corruptions", @@ -540,21 +527,15 @@ { "expr": "sum(prometheus_tsdb_head_active_appenders{job=\"prometheus\"})", "format": "time_series", - "interval": "", - "intervalFactor": 2, "legendFormat": "active_appenders", "metric": "", - "refId": "A", - "step": 20 + "refId": "A" }, { "expr": "sum(process_open_fds{job=\"prometheus\"})", "format": "time_series", - "interval": "", - "intervalFactor": 2, "legendFormat": "open_fds", - "refId": "B", - "step": 20 + "refId": "B" } ], "timeFrom": null, @@ -670,10 +651,8 @@ { "expr": "prometheus_tsdb_blocks_loaded{job=\"prometheus\"}", "format": "time_series", - "intervalFactor": 2, "legendFormat": "blocks", - "refId": "A", - "step": 20 + "refId": "A" } ], "timeFrom": null, @@ -759,11 +738,8 @@ { "expr": "prometheus_tsdb_head_chunks{job=\"prometheus\"}", "format": "time_series", - "interval": "", - "intervalFactor": 2, "legendFormat": "chunks", - "refId": "A", - "step": 20 + "refId": "A" } ], "timeFrom": null, @@ -862,18 +838,14 @@ { "expr": "prometheus_tsdb_head_gc_duration_seconds{job=\"prometheus\",quantile=\"0.99\"}", "format": "time_series", - "intervalFactor": 2, "legendFormat": "duration-p99", - "refId": "A", - "step": 20 + "refId": "A" }, { - "expr": "irate(prometheus_tsdb_head_gc_duration_seconds_count{job=\"prometheus\"}[5m])", + "expr": "irate(prometheus_tsdb_head_gc_duration_seconds_count{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", - "intervalFactor": 2, "legendFormat": "collections", - "refId": "B", - "step": 20 + "refId": "B" } ], "timeFrom": null, @@ -971,38 +943,29 @@ "pluginVersion": "8.1.0-pre", "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(prometheus_tsdb_compaction_duration_bucket{job=\"prometheus\"}[5m])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(prometheus_tsdb_compaction_duration_bucket{job=\"prometheus\"}[$__rate_interval])) by (le))", "format": "time_series", "hide": false, - "interval": "", - "intervalFactor": 2, "legendFormat": "duration-{{p99}}", - "refId": "A", - "step": 20 + "refId": "A" }, { - "expr": "irate(prometheus_tsdb_compactions_total{job=\"prometheus\"}[5m])", + "expr": "irate(prometheus_tsdb_compactions_total{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", - "intervalFactor": 2, "legendFormat": "compactions", - "refId": "B", - "step": 20 + "refId": "B" }, { - "expr": "irate(prometheus_tsdb_compactions_failed_total{job=\"prometheus\"}[5m])", + "expr": "irate(prometheus_tsdb_compactions_failed_total{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", - "intervalFactor": 2, "legendFormat": "failed", - "refId": "C", - "step": 20 + "refId": "C" }, { - "expr": "irate(prometheus_tsdb_compactions_triggered_total{job=\"prometheus\"}[5m])", + "expr": "irate(prometheus_tsdb_compactions_triggered_total{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", - "intervalFactor": 2, "legendFormat": "triggered", - "refId": "D", - "step": 20 + "refId": "D" } ], "timeFrom": null, @@ -1085,21 +1048,17 @@ "pluginVersion": "8.1.0-pre", "targets": [ { - "expr": "rate(prometheus_tsdb_reloads_total{job=\"prometheus\"}[5m])", + "expr": "rate(prometheus_tsdb_reloads_total{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", - "intervalFactor": 2, "legendFormat": "reloads", - "refId": "A", - "step": 20 + "refId": "A" }, { - "expr": "rate(prometheus_tsdb_reloads_failures_total{job=\"prometheus\"}[5m])", + "expr": "rate(prometheus_tsdb_reloads_failures_total{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", "hide": false, - "intervalFactor": 2, "legendFormat": "failures", - "refId": "B", - "step": 20 + "refId": "B" } ], "timeFrom": null, @@ -1184,10 +1143,8 @@ { "expr": "prometheus_engine_query_duration_seconds{job=\"prometheus\", quantile=\"0.99\"}", "format": "time_series", - "intervalFactor": 2, "legendFormat": "{{slice}}_p99", - "refId": "A", - "step": 20 + "refId": "A" } ], "timeFrom": null, @@ -1272,11 +1229,8 @@ { "expr": "max(prometheus_rule_group_duration_seconds{job=\"prometheus\"}) by (quantile)", "format": "time_series", - "interval": "", - "intervalFactor": 2, "legendFormat": "{{quantile}}", - "refId": "A", - "step": 10 + "refId": "A" } ], "timeFrom": null, @@ -1359,20 +1313,16 @@ "pluginVersion": "8.1.0-pre", "targets": [ { - "expr": "rate(prometheus_rule_group_iterations_missed_total{job=\"prometheus\"}[5m])", + "expr": "rate(prometheus_rule_group_iterations_missed_total{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", - "intervalFactor": 2, "legendFormat": "missed", - "refId": "B", - "step": 10 + "refId": "B" }, { - "expr": "rate(prometheus_rule_group_iterations_total{job=\"prometheus\"}[5m])", + "expr": "rate(prometheus_rule_group_iterations_total{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", - "intervalFactor": 2, "legendFormat": "iterations", - "refId": "A", - "step": 10 + "refId": "A" } ], "timeFrom": null, diff --git a/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx b/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx index 606839aacad..138ec2bea42 100644 --- a/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx +++ b/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx @@ -240,6 +240,15 @@ export const TooltipPlugin2 = ({ // in some ways this is similar to ClickOutsideWrapper.tsx const downEventOutside = (e: Event) => { + if (e instanceof KeyboardEvent) { + if (e.key === 'Escape') { + e.preventDefault(); + e.stopPropagation(); + dismiss(); + } + return; + } + // this tooltip is Portaled, but actions inside it create forms in Modals const isModalOrPortaled = '[role="dialog"], #grafana-portal-container'; diff --git a/pkg/api/plugins_test.go b/pkg/api/plugins_test.go index bda739c5020..342c6293d7e 100644 --- a/pkg/api/plugins_test.go +++ b/pkg/api/plugins_test.go @@ -30,6 +30,7 @@ import ( "github.com/grafana/grafana/pkg/plugins/manager/registry" "github.com/grafana/grafana/pkg/plugins/manager/signature" "github.com/grafana/grafana/pkg/plugins/manager/signature/statickey" + "github.com/grafana/grafana/pkg/plugins/pluginerrs" "github.com/grafana/grafana/pkg/plugins/pluginscdn" ac "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/acimpl" @@ -44,7 +45,6 @@ import ( "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginassets" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginchecker" - "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore" "github.com/grafana/grafana/pkg/services/pluginsintegration/provisionedplugins" diff --git a/pkg/plugins/manager/loader/loader.go b/pkg/plugins/manager/loader/loader.go index d4943cee865..0bbaa0db015 100644 --- a/pkg/plugins/manager/loader/loader.go +++ b/pkg/plugins/manager/loader/loader.go @@ -15,7 +15,7 @@ import ( "github.com/grafana/grafana/pkg/plugins/manager/pipeline/initialization" "github.com/grafana/grafana/pkg/plugins/manager/pipeline/termination" "github.com/grafana/grafana/pkg/plugins/manager/pipeline/validation" - "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs" + "github.com/grafana/grafana/pkg/plugins/pluginerrs" ) type Loader struct { diff --git a/pkg/plugins/manager/loader/loader_test.go b/pkg/plugins/manager/loader/loader_test.go index 6e6021bc021..7613392f497 100644 --- a/pkg/plugins/manager/loader/loader_test.go +++ b/pkg/plugins/manager/loader/loader_test.go @@ -11,6 +11,7 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/plugins/config" "github.com/grafana/grafana/pkg/plugins/manager/pipeline/bootstrap" @@ -20,8 +21,7 @@ import ( "github.com/grafana/grafana/pkg/plugins/manager/pipeline/validation" "github.com/grafana/grafana/pkg/plugins/manager/pluginfakes" "github.com/grafana/grafana/pkg/plugins/manager/sources" - "github.com/grafana/grafana/pkg/services/org" - "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs" + "github.com/grafana/grafana/pkg/plugins/pluginerrs" ) var compareOpts = []cmp.Option{cmpopts.IgnoreFields(plugins.Plugin{}, "client", "log", "mu"), fsComparer} @@ -180,7 +180,7 @@ func TestLoader_Load(t *testing.T) { Name: "Nginx Connections", Path: "dashboards/connections.json", Type: "dashboard", - Role: org.RoleViewer, + Role: identity.RoleViewer, Action: plugins.ActionAppAccess, Slug: "nginx-connections", }, @@ -188,21 +188,21 @@ func TestLoader_Load(t *testing.T) { Name: "Nginx Memory", Path: "dashboards/memory.json", Type: "dashboard", - Role: org.RoleViewer, + Role: identity.RoleViewer, Action: plugins.ActionAppAccess, Slug: "nginx-memory", }, { Name: "Nginx Panel", Type: string(plugins.TypePanel), - Role: org.RoleViewer, + Role: identity.RoleViewer, Action: plugins.ActionAppAccess, Slug: "nginx-panel", }, { Name: "Nginx Datasource", Type: string(plugins.TypeDataSource), - Role: org.RoleViewer, + Role: identity.RoleViewer, Action: plugins.ActionAppAccess, Slug: "nginx-datasource", }, @@ -413,8 +413,8 @@ func TestLoader_Load(t *testing.T) { }, }, Includes: []*plugins.Includes{ - {Name: "Nginx Memory", Path: "dashboards/memory.json", Type: "dashboard", Role: org.RoleViewer, Action: plugins.ActionAppAccess, Slug: "nginx-memory"}, - {Name: "Root Page (react)", Type: "page", Role: org.RoleViewer, Action: plugins.ActionAppAccess, Path: "/a/my-simple-app", DefaultNav: true, AddToNav: true, Slug: "root-page-react"}, + {Name: "Nginx Memory", Path: "dashboards/memory.json", Type: "dashboard", Role: identity.RoleViewer, Action: plugins.ActionAppAccess, Slug: "nginx-memory"}, + {Name: "Root Page (react)", Type: "page", Role: identity.RoleViewer, Action: plugins.ActionAppAccess, Path: "/a/my-simple-app", DefaultNav: true, AddToNav: true, Slug: "root-page-react"}, }, Extensions: plugins.Extensions{ AddedLinks: []plugins.AddedLink{}, diff --git a/pkg/plugins/models.go b/pkg/plugins/models.go index 8356a652793..dfad38bcaa1 100644 --- a/pkg/plugins/models.go +++ b/pkg/plugins/models.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" - "github.com/grafana/grafana/pkg/services/org" + "github.com/grafana/grafana/pkg/apimachinery/identity" ) const ( @@ -148,17 +148,17 @@ type ExtensionsDependencies struct { } type Includes struct { - Name string `json:"name"` - Path string `json:"path"` - Type string `json:"type"` - Component string `json:"component"` - Role org.RoleType `json:"role"` - Action string `json:"action,omitempty"` - AddToNav bool `json:"addToNav"` - DefaultNav bool `json:"defaultNav"` - Slug string `json:"slug"` - Icon string `json:"icon"` - UID string `json:"uid"` + Name string `json:"name"` + Path string `json:"path"` + Type string `json:"type"` + Component string `json:"component"` + Role identity.RoleType `json:"role"` + Action string `json:"action,omitempty"` + AddToNav bool `json:"addToNav"` + DefaultNav bool `json:"defaultNav"` + Slug string `json:"slug"` + Icon string `json:"icon"` + UID string `json:"uid"` ID string `json:"-"` } diff --git a/pkg/services/pluginsintegration/pluginerrs/errors.go b/pkg/plugins/pluginerrs/errors.go similarity index 100% rename from pkg/services/pluginsintegration/pluginerrs/errors.go rename to pkg/plugins/pluginerrs/errors.go diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go index 7f010565c9c..bf1b23a35b0 100644 --- a/pkg/plugins/plugins.go +++ b/pkg/plugins/plugins.go @@ -14,11 +14,11 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" + "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/plugins/auth" "github.com/grafana/grafana/pkg/plugins/backendplugin" "github.com/grafana/grafana/pkg/plugins/backendplugin/pluginextensionv2" "github.com/grafana/grafana/pkg/plugins/log" - "github.com/grafana/grafana/pkg/services/org" ) var ( @@ -26,7 +26,6 @@ var ( ErrPluginFileRead = errors.New("file could not be read") ErrUninstallInvalidPluginDir = errors.New("cannot recognize as plugin folder") ErrInvalidPluginJSON = errors.New("did not find valid type or id properties in plugin.json") - ErrUnsupportedAlias = errors.New("can not set alias in plugin.json") ) type Plugin struct { @@ -186,11 +185,11 @@ func ReadPluginJSON(reader io.Reader) (JSONData, error) { for _, include := range plugin.Includes { if include.Role == "" { - include.Role = org.RoleViewer + include.Role = identity.RoleViewer } // Default to app access for app plugins - if plugin.Type == TypeApp && include.Role == org.RoleViewer && include.Action == "" { + if plugin.Type == TypeApp && include.Role == identity.RoleViewer && include.Action == "" { include.Action = ActionAppAccess } } @@ -219,17 +218,17 @@ func (d JSONData) DashboardIncludes() []*Includes { // Route describes a plugin route that is defined in // the plugin.json file for a plugin. type Route struct { - Path string `json:"path"` - Method string `json:"method"` - ReqRole org.RoleType `json:"reqRole"` - ReqAction string `json:"reqAction"` - URL string `json:"url"` - URLParams []URLParam `json:"urlParams"` - Headers []Header `json:"headers"` - AuthType string `json:"authType"` - TokenAuth *JWTTokenAuth `json:"tokenAuth"` - JwtTokenAuth *JWTTokenAuth `json:"jwtTokenAuth"` - Body json.RawMessage `json:"body"` + Path string `json:"path"` + Method string `json:"method"` + ReqRole identity.RoleType `json:"reqRole"` + ReqAction string `json:"reqAction"` + URL string `json:"url"` + URLParams []URLParam `json:"urlParams"` + Headers []Header `json:"headers"` + AuthType string `json:"authType"` + TokenAuth *JWTTokenAuth `json:"tokenAuth"` + JwtTokenAuth *JWTTokenAuth `json:"jwtTokenAuth"` + Body json.RawMessage `json:"body"` } // Header describes an HTTP header that is forwarded with diff --git a/pkg/plugins/plugins_test.go b/pkg/plugins/plugins_test.go index 3ee1f1a2dab..ef77045dcc4 100644 --- a/pkg/plugins/plugins_test.go +++ b/pkg/plugins/plugins_test.go @@ -8,8 +8,9 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/grafana/grafana/pkg/services/org" "github.com/stretchr/testify/require" + + "github.com/grafana/grafana/pkg/apimachinery/identity" ) func Test_ReadPluginJSON(t *testing.T) { @@ -73,10 +74,10 @@ func Test_ReadPluginJSON(t *testing.T) { }, Includes: []*Includes{ - {Name: "Nginx Connections", Path: "dashboards/connections.json", Type: "dashboard", Role: org.RoleViewer, Action: ActionAppAccess}, - {Name: "Nginx Memory", Path: "dashboards/memory.json", Type: "dashboard", Role: org.RoleViewer, Action: ActionAppAccess}, - {Name: "Nginx Panel", Type: "panel", Role: org.RoleViewer, Action: ActionAppAccess}, - {Name: "Nginx Datasource", Type: "datasource", Role: org.RoleViewer, Action: ActionAppAccess}, + {Name: "Nginx Connections", Path: "dashboards/connections.json", Type: "dashboard", Role: identity.RoleViewer, Action: ActionAppAccess}, + {Name: "Nginx Memory", Path: "dashboards/memory.json", Type: "dashboard", Role: identity.RoleViewer, Action: ActionAppAccess}, + {Name: "Nginx Panel", Type: "panel", Role: identity.RoleViewer, Action: ActionAppAccess}, + {Name: "Nginx Datasource", Type: "datasource", Role: identity.RoleViewer, Action: ActionAppAccess}, }, Backend: false, }, @@ -126,7 +127,7 @@ func Test_ReadPluginJSON(t *testing.T) { }, Includes: []*Includes{ - {Name: "Pie Charts", Path: "dashboards/demo.json", Type: "dashboard", Role: org.RoleViewer}, + {Name: "Pie Charts", Path: "dashboards/demo.json", Type: "dashboard", Role: identity.RoleViewer}, }, }, }, diff --git a/pkg/server/wire_gen.go b/pkg/server/wire_gen.go index a235e71ec10..d396dcfdd02 100644 --- a/pkg/server/wire_gen.go +++ b/pkg/server/wire_gen.go @@ -45,6 +45,7 @@ import ( "github.com/grafana/grafana/pkg/plugins/manager/registry" "github.com/grafana/grafana/pkg/plugins/manager/signature" "github.com/grafana/grafana/pkg/plugins/pluginassets" + "github.com/grafana/grafana/pkg/plugins/pluginerrs" "github.com/grafana/grafana/pkg/plugins/pluginscdn" "github.com/grafana/grafana/pkg/plugins/repo" "github.com/grafana/grafana/pkg/registry/apis" @@ -191,7 +192,6 @@ import ( "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginchecker" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginconfig" "github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext" - "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginexternal" "github.com/grafana/grafana/pkg/services/pluginsintegration/plugininstaller" service6 "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings/service" diff --git a/pkg/services/ngalert/api/api_prometheus_test.go b/pkg/services/ngalert/api/api_prometheus_test.go index dc0f6d1f13d..4fdd8e08b92 100644 --- a/pkg/services/ngalert/api/api_prometheus_test.go +++ b/pkg/services/ngalert/api/api_prometheus_test.go @@ -805,9 +805,20 @@ func TestRouteGetRuleStatuses(t *testing.T) { OrgID: orgID, })).GenerateManyRef(3) + // Plugin rule with __grafana_origin label for plugins filter test + pluginRule := gen.With( + gen.WithGroupKey(ngmodels.AlertRuleGroupKey{ + RuleGroup: "plugins-test-plugin", + NamespaceUID: "folder-2", + OrgID: orgID, + }), + gen.WithLabels(map[string]string{"__grafana_origin": "plugin/grafana-slo-app"}), + ).GenerateRef() + ruleStore.PutRule(context.Background(), rulesInGroup1...) ruleStore.PutRule(context.Background(), rulesInGroup2...) ruleStore.PutRule(context.Background(), rulesInGroup3...) + ruleStore.PutRule(context.Background(), pluginRule) api := NewPrometheusSrv( log.NewNopLogger(), @@ -818,7 +829,7 @@ func TestRouteGetRuleStatuses(t *testing.T) { fakes.NewFakeProvisioningStore(), ) - permissions := createPermissionsForRules(slices.Concat(rulesInGroup1, rulesInGroup2, rulesInGroup3), orgID) + permissions := createPermissionsForRules(slices.Concat(rulesInGroup1, rulesInGroup2, rulesInGroup3, []*ngmodels.AlertRule{pluginRule}), orgID) user := &user.SignedInUser{ OrgID: orgID, Permissions: permissions, @@ -948,6 +959,68 @@ func TestRouteGetRuleStatuses(t *testing.T) { require.Equal(t, expectedRuleInGroup3.UID, result.Data.RuleGroups[0].Rules[0].UID) } }) + + t.Run("should filter rules by plugins parameter", func(t *testing.T) { + t.Run("returns all groups when plugins filter not specified", func(t *testing.T) { + r, err := http.NewRequest("GET", "/api/v1/rules?folder_uid=folder-2", nil) + require.NoError(t, err) + c.Context = &web.Context{Req: r} + + resp := api.RouteGetRuleStatuses(c) + require.Equal(t, http.StatusOK, resp.Status()) + + result := &apimodels.RuleResponse{} + require.NoError(t, json.Unmarshal(resp.Body(), result)) + + require.Len(t, result.Data.RuleGroups, 2, "should return all groups including plugin group") + }) + + t.Run("excludes plugin rules when plugins=hide", func(t *testing.T) { + r, err := http.NewRequest("GET", "/api/v1/rules?folder_uid=folder-2&plugins=hide", nil) + require.NoError(t, err) + c.Context = &web.Context{Req: r} + + resp := api.RouteGetRuleStatuses(c) + require.Equal(t, http.StatusOK, resp.Status()) + + result := &apimodels.RuleResponse{} + require.NoError(t, json.Unmarshal(resp.Body(), result)) + + require.Len(t, result.Data.RuleGroups, 1, "should only return non-plugin groups") + for _, group := range result.Data.RuleGroups { + require.NotEqual(t, "plugins-test-plugin", group.Name, "should not include plugin group") + } + }) + + t.Run("returns only plugin rules when plugins=only", func(t *testing.T) { + r, err := http.NewRequest("GET", "/api/v1/rules?folder_uid=folder-2&plugins=only", nil) + require.NoError(t, err) + c.Context = &web.Context{Req: r} + + resp := api.RouteGetRuleStatuses(c) + require.Equal(t, http.StatusOK, resp.Status()) + + result := &apimodels.RuleResponse{} + require.NoError(t, json.Unmarshal(resp.Body(), result)) + + require.Len(t, result.Data.RuleGroups, 1, "should only return plugin group") + require.Equal(t, "plugins-test-plugin", result.Data.RuleGroups[0].Name) + }) + + t.Run("returns all groups when plugins filter has invalid value", func(t *testing.T) { + r, err := http.NewRequest("GET", "/api/v1/rules?folder_uid=folder-2&plugins=invalid", nil) + require.NoError(t, err) + c.Context = &web.Context{Req: r} + + resp := api.RouteGetRuleStatuses(c) + require.Equal(t, http.StatusOK, resp.Status()) + + result := &apimodels.RuleResponse{} + require.NoError(t, json.Unmarshal(resp.Body(), result)) + + require.Len(t, result.Data.RuleGroups, 2, "invalid value should return all groups") + }) + }) }) t.Run("when requesting rules with pagination", func(t *testing.T) { diff --git a/pkg/services/ngalert/api/prometheus/api_prometheus.go b/pkg/services/ngalert/api/prometheus/api_prometheus.go index 077761d0caf..16efa84fe26 100644 --- a/pkg/services/ngalert/api/prometheus/api_prometheus.go +++ b/pkg/services/ngalert/api/prometheus/api_prometheus.go @@ -452,17 +452,18 @@ type paginationContext struct { alertStateMutator RuleAlertStateMutator // Query parameters - namespaceUIDs []string - ruleUIDs []string - dashboardUID string - panelID int64 - ruleGroups []string - receiverName string - dataSourceUIDs []string - title string - searchRuleGroup string - ruleType ngmodels.RuleTypeFilter - ruleNamesSet map[string]struct{} + namespaceUIDs []string + ruleUIDs []string + dashboardUID string + panelID int64 + ruleGroups []string + receiverName string + dataSourceUIDs []string + title string + searchRuleGroup string + ruleType ngmodels.RuleTypeFilter + pluginOriginFilter ngmodels.PluginOriginFilter + ruleNamesSet map[string]struct{} // Filters stateFilterSet map[eval.State]struct{} @@ -508,11 +509,12 @@ func (ctx *paginationContext) fetchAndFilterPage(log log.Logger, store ListAlert SearchRuleGroup: ctx.searchRuleGroup, LabelMatchers: storeMatchers, }, - RuleType: ctx.ruleType, - Limit: remainingGroups, - RuleLimit: remainingRules, - ContinueToken: token, - Compact: ctx.compact, + RuleType: ctx.ruleType, + PluginOriginFilter: ctx.pluginOriginFilter, + Limit: remainingGroups, + RuleLimit: remainingRules, + ContinueToken: token, + Compact: ctx.compact, } ruleList, newToken, err := store.ListAlertRulesByGroup(ctx.opts.Ctx, &byGroupQuery) @@ -668,6 +670,7 @@ func paginateRuleGroups(log log.Logger, store ListAlertRulesStoreV2, ctx *pagina return allGroups, rulesTotals, continueToken, nil } +// nolint:gocyclo func PrepareRuleGroupStatusesV2(log log.Logger, store ListAlertRulesStoreV2, opts RuleGroupStatusesOptions, ruleStatusMutator RuleStatusMutator, alertStateMutator RuleAlertStateMutator, provenanceStore ProvenanceStore) apimodels.RuleResponse { ctx, span := tracer.Start(opts.Ctx, "api.prometheus.PrepareRuleGroupStatusesV2") defer span.End() @@ -825,6 +828,15 @@ func PrepareRuleGroupStatusesV2(log log.Logger, store ListAlertRulesStoreV2, opt ruleType = ngmodels.RuleTypeFilterAll } + pluginOriginFilter := ngmodels.PluginOriginFilterNone + switch opts.Query.Get("plugins") { + case "hide": + pluginOriginFilter = ngmodels.PluginOriginFilterHide + case "only": + pluginOriginFilter = ngmodels.PluginOriginFilterOnly + } + span.SetAttributes(attribute.String("plugins_filter", string(pluginOriginFilter))) + // Pagination limits // // group_limit: Maximum number of rule groups to return @@ -874,6 +886,7 @@ func PrepareRuleGroupStatusesV2(log log.Logger, store ListAlertRulesStoreV2, opt dataSourceUIDs: dataSourceUIDs, searchRuleGroup: searchRuleGroup, ruleType: ruleType, + pluginOriginFilter: pluginOriginFilter, ruleNamesSet: ruleNamesSet, stateFilterSet: stateFilterSet, healthFilterSet: healthFilterSet, diff --git a/pkg/services/ngalert/models/alert_rule.go b/pkg/services/ngalert/models/alert_rule.go index 7d6e8a1fab5..4b59fcfa164 100644 --- a/pkg/services/ngalert/models/alert_rule.go +++ b/pkg/services/ngalert/models/alert_rule.go @@ -171,6 +171,9 @@ const ( // AutogeneratedRouteSettingsHashLabel a label name that contains the hash of the notification settings that will be used to send notifications for the alert. // This should uniquely identify the notification settings (group_by, group_wait, group_interval, repeat_interval, mute_time_intervals) for the alert. AutogeneratedRouteSettingsHashLabel = "__grafana_route_settings_hash__" + + // PluginGrafanaOriginLabel is a label that indicates that the alert rule originated from a plugin. + PluginGrafanaOriginLabel = "__grafana_origin" ) const ( @@ -966,6 +969,14 @@ const ( RuleTypeFilterRecording ) +type PluginOriginFilter string + +const ( + PluginOriginFilterNone PluginOriginFilter = "" // Show all (default) + PluginOriginFilterHide PluginOriginFilter = "hide" // Exclude plugin rules + PluginOriginFilterOnly PluginOriginFilter = "only" // Only plugin rules +) + type GroupCursor struct { NamespaceUID string `json:"n"` RuleGroup string `json:"g"` @@ -1026,7 +1037,8 @@ type ListAlertRulesQuery struct { type ListAlertRulesExtendedQuery struct { ListAlertRulesQuery - RuleType RuleTypeFilter + RuleType RuleTypeFilter + PluginOriginFilter PluginOriginFilter Limit int64 RuleLimit int64 diff --git a/pkg/services/ngalert/store/alert_rule.go b/pkg/services/ngalert/store/alert_rule.go index 30856587794..225499dc1d3 100644 --- a/pkg/services/ngalert/store/alert_rule.go +++ b/pkg/services/ngalert/store/alert_rule.go @@ -30,11 +30,13 @@ import ( "github.com/grafana/grafana/pkg/util" ) -// AlertRuleMaxTitleLength is the maximum length of the alert rule title -const AlertRuleMaxTitleLength = 190 +const ( + // AlertRuleMaxTitleLength is the maximum length of the alert rule title + AlertRuleMaxTitleLength = 190 -// AlertRuleMaxRuleGroupNameLength is the maximum length of the alert rule group name -const AlertRuleMaxRuleGroupNameLength = 190 + // AlertRuleMaxRuleGroupNameLength is the maximum length of the alert rule group name + AlertRuleMaxRuleGroupNameLength = 190 +) var ( ErrOptimisticLock = errors.New("version conflict while updating a record in the database with optimistic locking") @@ -970,6 +972,13 @@ func (st DBstore) buildListAlertRulesQuery(sess *db.Session, query *ngmodels.Lis } } + if query.PluginOriginFilter != ngmodels.PluginOriginFilterNone { + q, err = st.filterByPluginOrigin(query.PluginOriginFilter, q) + if err != nil { + return nil, groupsSet, err + } + } + // FIXME: record is nullable but we don't save it as null when it's nil switch query.RuleType { case ngmodels.RuleTypeFilterAlerting: @@ -1427,6 +1436,32 @@ func (st DBstore) filterByLabelMatchers(matchers labels.Matchers, sess *xorm.Ses return sess, nil } +// filterByPluginOrigin adds filtering for plugin-originated rules based on the __grafana_origin label. +func (st DBstore) filterByPluginOrigin(filter ngmodels.PluginOriginFilter, sess *xorm.Session) (*xorm.Session, error) { + if filter == ngmodels.PluginOriginFilterNone { + return sess, nil + } + + var sql string + var args []any + var err error + + switch filter { + case ngmodels.PluginOriginFilterHide: + sql, args, err = buildLabelKeyMissingCondition(st.SQLStore.GetDialect(), "labels", ngmodels.PluginGrafanaOriginLabel) + case ngmodels.PluginOriginFilterOnly: + sql, args, err = buildLabelKeyExistsCondition(st.SQLStore.GetDialect(), "labels", ngmodels.PluginGrafanaOriginLabel) + default: + return nil, fmt.Errorf("unknown plugin origin filter %q", filter) + } + + if err != nil { + return nil, err + } + + return sess.And(sql, args...), nil +} + func (st DBstore) RenameReceiverInNotificationSettings(ctx context.Context, orgID int64, oldReceiver, newReceiver string, validateProvenance func(ngmodels.Provenance) bool, dryRun bool) ([]ngmodels.AlertRuleKey, []ngmodels.AlertRuleKey, error) { // fetch entire rules because Update method requires it because it copies rules to version table rules, err := st.ListAlertRules(ctx, &ngmodels.ListAlertRulesQuery{ diff --git a/pkg/services/ngalert/store/alert_rule_labels.go b/pkg/services/ngalert/store/alert_rule_labels.go index 721071d5219..9c35d194d37 100644 --- a/pkg/services/ngalert/store/alert_rule_labels.go +++ b/pkg/services/ngalert/store/alert_rule_labels.go @@ -18,6 +18,20 @@ func buildLabelMatcherCondition(dialect migrator.Dialect, column string, m *labe return buildLabelMatcherJSON(dialect, column, m) } +func buildLabelKeyExistsCondition(dialect migrator.Dialect, column string, key string) (string, []any, error) { + if dialect.DriverName() == migrator.SQLite { + return globKeyExists(column, key) + } + return jsonKeyExists(dialect, column, key) +} + +func buildLabelKeyMissingCondition(dialect migrator.Dialect, column string, key string) (string, []any, error) { + if dialect.DriverName() == migrator.SQLite { + return globKeyMissing(column, key) + } + return jsonKeyMissing(dialect, column, key) +} + func buildLabelMatcherGlob(column string, m *labels.Matcher) (string, []any, error) { switch { case m.Type == labels.MatchEqual && m.Value == "": @@ -37,7 +51,10 @@ func buildLabelMatcherJSON(dialect migrator.Dialect, column string, m *labels.Ma switch { case m.Type == labels.MatchEqual && m.Value == "": eqSQL, eqArgs := jsonEquals(dialect, column, m.Name, "") - missingSQL, missingArgs := jsonKeyMissing(dialect, column, m.Name) + missingSQL, missingArgs, err := jsonKeyMissing(dialect, column, m.Name) + if err != nil { + return "", nil, err + } return "(" + eqSQL + " OR " + missingSQL + ")", append(eqArgs, missingArgs...), nil case m.Type == labels.MatchEqual: sql, args := jsonEquals(dialect, column, m.Name, m.Value) diff --git a/pkg/services/ngalert/store/alert_rule_labels_test.go b/pkg/services/ngalert/store/alert_rule_labels_test.go index 2006c49fd7a..1e6eb2b04e6 100644 --- a/pkg/services/ngalert/store/alert_rule_labels_test.go +++ b/pkg/services/ngalert/store/alert_rule_labels_test.go @@ -134,3 +134,93 @@ func TestBuildLabelMatcherJSON(t *testing.T) { }) } } + +func TestBuildLabelKeyExistsCondition(t *testing.T) { + tests := []struct { + name string + dialect migrator.Dialect + column string + key string + wantSQL string + wantArgs []any + }{ + { + name: "MySQL", + dialect: migrator.NewMysqlDialect(), + column: "labels", + key: "__grafana_origin", + wantSQL: "JSON_EXTRACT(NULLIF(labels, ''), CONCAT('$.', ?)) IS NOT NULL", + wantArgs: []any{"__grafana_origin"}, + }, + { + name: "PostgreSQL", + dialect: migrator.NewPostgresDialect(), + column: "labels", + key: "__grafana_origin", + wantSQL: "jsonb_extract_path_text(NULLIF(labels, '')::jsonb, ?) IS NOT NULL", + wantArgs: []any{"__grafana_origin"}, + }, + { + name: "SQLite", + dialect: migrator.NewSQLite3Dialect(), + column: "labels", + key: "__grafana_origin", + wantSQL: "labels GLOB ?", + wantArgs: []any{`*"__grafana_origin":*`}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + sql, args, err := buildLabelKeyExistsCondition(tt.dialect, tt.column, tt.key) + require.NoError(t, err) + require.Equal(t, tt.wantSQL, sql) + require.Equal(t, tt.wantArgs, args) + }) + } +} + +func TestBuildLabelKeyMissingCondition(t *testing.T) { + tests := []struct { + name string + dialect migrator.Dialect + column string + key string + wantSQL string + wantArgs []any + }{ + { + name: "MySQL", + dialect: migrator.NewMysqlDialect(), + column: "labels", + key: "__grafana_origin", + wantSQL: "JSON_EXTRACT(NULLIF(labels, ''), CONCAT('$.', ?)) IS NULL", + wantArgs: []any{"__grafana_origin"}, + }, + { + name: "PostgreSQL", + dialect: migrator.NewPostgresDialect(), + column: "labels", + key: "__grafana_origin", + wantSQL: "jsonb_extract_path_text(NULLIF(labels, '')::jsonb, ?) IS NULL", + wantArgs: []any{"__grafana_origin"}, + }, + { + name: "SQLite", + dialect: migrator.NewSQLite3Dialect(), + column: "labels", + key: "__grafana_origin", + wantSQL: "labels NOT GLOB ?", + wantArgs: []any{`*"__grafana_origin":*`}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + sql, args, err := buildLabelKeyMissingCondition(tt.dialect, tt.column, tt.key) + require.NoError(t, err) + require.Equal(t, tt.wantSQL, sql) + require.Equal(t, tt.wantArgs, args) + }) + } +} diff --git a/pkg/services/ngalert/store/alert_rule_test.go b/pkg/services/ngalert/store/alert_rule_test.go index f7497c7b05a..e38a7052dff 100644 --- a/pkg/services/ngalert/store/alert_rule_test.go +++ b/pkg/services/ngalert/store/alert_rule_test.go @@ -2592,6 +2592,54 @@ func TestIntegration_ListAlertRules(t *testing.T) { require.ErrorContains(t, err, "is not supported") }) }) + + t.Run("filter by PluginOriginFilter", func(t *testing.T) { + sqlStore := db.InitTestDB(t) + folderService := setupFolderService(t, sqlStore, cfg, featuremgmt.WithFeatures()) + store := createTestStore(sqlStore, folderService, &logtest.Fake{}, cfg.UnifiedAlerting, b) + testOrgID := int64(12345) + testRuleGen := ruleGen.With(models.RuleMuts.WithOrgID(testOrgID)) + + regularRule := createRule(t, store, testRuleGen) + pluginRule := createRule(t, store, testRuleGen.With( + models.RuleMuts.WithLabel(models.PluginGrafanaOriginLabel, "plugin/grafana-slo-app"), + )) + + tc := []struct { + name string + filter models.PluginOriginFilter + expectedRules []*models.AlertRule + }{ + { + name: "should return all rules when PluginOriginFilterNone", + filter: models.PluginOriginFilterNone, + expectedRules: []*models.AlertRule{regularRule, pluginRule}, + }, + { + name: "should filter out plugin rules when PluginOriginFilterHide", + filter: models.PluginOriginFilterHide, + expectedRules: []*models.AlertRule{regularRule}, + }, + { + name: "should return only plugin rules when PluginOriginFilterOnly", + filter: models.PluginOriginFilterOnly, + expectedRules: []*models.AlertRule{pluginRule}, + }, + } + for _, tt := range tc { + t.Run(tt.name, func(t *testing.T) { + query := &models.ListAlertRulesExtendedQuery{ + ListAlertRulesQuery: models.ListAlertRulesQuery{ + OrgID: testOrgID, + }, + PluginOriginFilter: tt.filter, + } + result, _, err := store.ListAlertRulesByGroup(context.Background(), query) + require.NoError(t, err) + require.ElementsMatch(t, tt.expectedRules, result) + }) + } + }) } func TestIntegration_ListAlertRulesPaginated(t *testing.T) { diff --git a/pkg/services/ngalert/store/json.go b/pkg/services/ngalert/store/json.go index e0c71975a76..ac38d2f4ca5 100644 --- a/pkg/services/ngalert/store/json.go +++ b/pkg/services/ngalert/store/json.go @@ -34,14 +34,26 @@ func jsonNotEquals(dialect migrator.Dialect, column, key, value string) (string, return fmt.Sprintf("(%s IS NULL OR %s != ?)", jx, jx), []any{key, key, value} } -func jsonKeyMissing(dialect migrator.Dialect, column, key string) (string, []any) { +func jsonKeyMissing(dialect migrator.Dialect, column, key string) (string, []any, error) { + return jsonKeyCondition(dialect, column, key, false) +} + +func jsonKeyExists(dialect migrator.Dialect, column, key string) (string, []any, error) { + return jsonKeyCondition(dialect, column, key, true) +} + +func jsonKeyCondition(dialect migrator.Dialect, column, key string, exists bool) (string, []any, error) { + nullCheck := "IS NULL" + if exists { + nullCheck = "IS NOT NULL" + } switch dialect.DriverName() { case migrator.MySQL: - return fmt.Sprintf("JSON_EXTRACT(NULLIF(%s, ''), CONCAT('$.', ?)) IS NULL", column), []any{key} + return fmt.Sprintf("JSON_EXTRACT(NULLIF(%s, ''), CONCAT('$.', ?)) %s", column, nullCheck), []any{key}, nil case migrator.Postgres: - return fmt.Sprintf("jsonb_extract_path_text(NULLIF(%s, '')::jsonb, ?) IS NULL", column), []any{key} + return fmt.Sprintf("jsonb_extract_path_text(NULLIF(%s, '')::jsonb, ?) %s", column, nullCheck), []any{key}, nil default: - return "", nil + return "", nil, fmt.Errorf("unsupported dialect for JSON key condition: %s", dialect.DriverName()) } } @@ -71,6 +83,14 @@ func globKeyMissing(column, key string) (string, []any, error) { return column + " NOT GLOB ?", []any{"*" + pattern + "*"}, nil } +func globKeyExists(column, key string) (string, []any, error) { + pattern, err := buildGlobKeyPattern(key) + if err != nil { + return "", nil, err + } + return column + " GLOB ?", []any{"*" + pattern + "*"}, nil +} + // Search for `"key":"value"` func buildGlobPattern(key, value string) (string, error) { keyJSON, err := json.Marshal(key) diff --git a/pkg/services/ngalert/store/json_test.go b/pkg/services/ngalert/store/json_test.go index d09d3741c4b..93ca1531f61 100644 --- a/pkg/services/ngalert/store/json_test.go +++ b/pkg/services/ngalert/store/json_test.go @@ -114,7 +114,45 @@ func TestJsonKeyMissing(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - sql, args := jsonKeyMissing(tt.dialect, tt.column, tt.key) + sql, args, err := jsonKeyMissing(tt.dialect, tt.column, tt.key) + require.NoError(t, err) + require.Equal(t, tt.wantSQL, sql) + require.Equal(t, tt.wantArgs, args) + }) + } +} + +func TestJsonKeyExists(t *testing.T) { + tests := []struct { + name string + dialect migrator.Dialect + column string + key string + wantSQL string + wantArgs []any + }{ + { + name: "MySQL", + dialect: migrator.NewMysqlDialect(), + column: "labels", + key: "__grafana_origin", + wantSQL: "JSON_EXTRACT(NULLIF(labels, ''), CONCAT('$.', ?)) IS NOT NULL", + wantArgs: []any{"__grafana_origin"}, + }, + { + name: "PostgreSQL", + dialect: migrator.NewPostgresDialect(), + column: "labels", + key: "__grafana_origin", + wantSQL: "jsonb_extract_path_text(NULLIF(labels, '')::jsonb, ?) IS NOT NULL", + wantArgs: []any{"__grafana_origin"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + sql, args, err := jsonKeyExists(tt.dialect, tt.column, tt.key) + require.NoError(t, err) require.Equal(t, tt.wantSQL, sql) require.Equal(t, tt.wantArgs, args) }) diff --git a/pkg/services/ngalert/tests/fakes/rules.go b/pkg/services/ngalert/tests/fakes/rules.go index f4b5afb282d..654eaac471d 100644 --- a/pkg/services/ngalert/tests/fakes/rules.go +++ b/pkg/services/ngalert/tests/fakes/rules.go @@ -228,6 +228,9 @@ func (f *RuleStore) ListAlertRulesByGroup(_ context.Context, q *models.ListAlert return nil, "", err } + // Filter by PluginOriginFilter if specified + ruleList = applyPluginOriginFilter(ruleList, q.PluginOriginFilter) + // < group limit logic > // sort rules to ensure order is consistent, pagination depends on this @@ -304,6 +307,10 @@ func (f *RuleStore) ListAlertRulesPaginated(_ context.Context, q *models.ListAle if err != nil { return nil, "", err } + + // Filter by PluginOriginFilter if specified + rules = applyPluginOriginFilter(rules, q.PluginOriginFilter) + return rules, "", nil } @@ -648,3 +655,28 @@ func (f *RuleStore) ListDeletedRules(_ context.Context, orgID int64) ([]*models. } return f.Deleted[orgID], nil } + +// applyPluginOriginFilter filters rules based on the presence of the __grafana_origin label. +func applyPluginOriginFilter(rules []*models.AlertRule, filter models.PluginOriginFilter) []*models.AlertRule { + if filter == models.PluginOriginFilterNone { + return rules + } + + filteredList := make([]*models.AlertRule, 0, len(rules)) + for _, r := range rules { + _, hasOriginLabel := r.Labels[models.PluginGrafanaOriginLabel] + switch filter { + case models.PluginOriginFilterHide: + if !hasOriginLabel { + filteredList = append(filteredList, r) + } + case models.PluginOriginFilterOnly: + if hasOriginLabel { + filteredList = append(filteredList, r) + } + default: + filteredList = append(filteredList, r) + } + } + return filteredList +} diff --git a/pkg/services/pluginsintegration/loader/loader.go b/pkg/services/pluginsintegration/loader/loader.go index b3a03885752..986151041ff 100644 --- a/pkg/services/pluginsintegration/loader/loader.go +++ b/pkg/services/pluginsintegration/loader/loader.go @@ -11,7 +11,7 @@ import ( "github.com/grafana/grafana/pkg/plugins/manager/pipeline/initialization" "github.com/grafana/grafana/pkg/plugins/manager/pipeline/termination" "github.com/grafana/grafana/pkg/plugins/manager/pipeline/validation" - "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs" + "github.com/grafana/grafana/pkg/plugins/pluginerrs" ) var _ pluginsLoader.Service = (*Loader)(nil) diff --git a/pkg/services/pluginsintegration/loader/loader_test.go b/pkg/services/pluginsintegration/loader/loader_test.go index 60f5ac757a1..a5a7a7fd8db 100644 --- a/pkg/services/pluginsintegration/loader/loader_test.go +++ b/pkg/services/pluginsintegration/loader/loader_test.go @@ -25,9 +25,9 @@ import ( "github.com/grafana/grafana/pkg/plugins/manager/signature" "github.com/grafana/grafana/pkg/plugins/manager/sources" "github.com/grafana/grafana/pkg/plugins/pluginassets" + "github.com/grafana/grafana/pkg/plugins/pluginerrs" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/pluginsintegration/pipeline" - "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs" "github.com/grafana/grafana/pkg/services/pluginsintegration/provisionedplugins" ) diff --git a/pkg/services/pluginsintegration/pluginsintegration.go b/pkg/services/pluginsintegration/pluginsintegration.go index 387d9884f9a..fbfa3379afd 100644 --- a/pkg/services/pluginsintegration/pluginsintegration.go +++ b/pkg/services/pluginsintegration/pluginsintegration.go @@ -28,6 +28,7 @@ import ( "github.com/grafana/grafana/pkg/plugins/manager/signature" "github.com/grafana/grafana/pkg/plugins/manager/sources" pluginassets2 "github.com/grafana/grafana/pkg/plugins/pluginassets" + "github.com/grafana/grafana/pkg/plugins/pluginerrs" "github.com/grafana/grafana/pkg/plugins/pluginscdn" "github.com/grafana/grafana/pkg/plugins/repo" "github.com/grafana/grafana/pkg/services/caching" @@ -50,7 +51,6 @@ import ( "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginchecker" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginconfig" "github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext" - "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginexternal" "github.com/grafana/grafana/pkg/services/pluginsintegration/plugininstaller" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings" diff --git a/pkg/services/pluginsintegration/renderer/renderer.go b/pkg/services/pluginsintegration/renderer/renderer.go index c061693879b..6d02768f79e 100644 --- a/pkg/services/pluginsintegration/renderer/renderer.go +++ b/pkg/services/pluginsintegration/renderer/renderer.go @@ -22,8 +22,8 @@ import ( "github.com/grafana/grafana/pkg/plugins/manager/registry" "github.com/grafana/grafana/pkg/plugins/manager/signature" "github.com/grafana/grafana/pkg/plugins/manager/sources" + "github.com/grafana/grafana/pkg/plugins/pluginerrs" "github.com/grafana/grafana/pkg/services/pluginsintegration/pipeline" - "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs" "github.com/grafana/grafana/pkg/services/rendering" ) diff --git a/pkg/services/pluginsintegration/test_helper.go b/pkg/services/pluginsintegration/test_helper.go index 018305a71ad..d6cff58d313 100644 --- a/pkg/services/pluginsintegration/test_helper.go +++ b/pkg/services/pluginsintegration/test_helper.go @@ -25,10 +25,10 @@ import ( "github.com/grafana/grafana/pkg/plugins/manager/signature" "github.com/grafana/grafana/pkg/plugins/manager/signature/statickey" "github.com/grafana/grafana/pkg/plugins/pluginassets" + "github.com/grafana/grafana/pkg/plugins/pluginerrs" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/pluginsintegration/pipeline" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginconfig" - "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsources" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore" "github.com/grafana/grafana/pkg/services/pluginsintegration/provisionedplugins" diff --git a/pkg/tests/api/alerting/api_prometheus_test.go b/pkg/tests/api/alerting/api_prometheus_test.go index 067372a3470..1695e267903 100644 --- a/pkg/tests/api/alerting/api_prometheus_test.go +++ b/pkg/tests/api/alerting/api_prometheus_test.go @@ -910,6 +910,87 @@ func TestIntegrationPrometheusRulesFilterByDashboard(t *testing.T) { } } +func TestIntegrationPrometheusPluginsFilter(t *testing.T) { + testutil.SkipIntegrationTestInShortMode(t) + + dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ + DisableLegacyAlerting: true, + EnableUnifiedAlerting: true, + DisableAnonymous: true, + AppModeProduction: true, + }) + + grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path) + + createUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{ + DefaultOrgRole: string(org.RoleEditor), + Password: "password", + Login: "grafana", + }) + + apiClient := newAlertingApiClient(grafanaListedAddr, "grafana", "password") + + apiClient.CreateFolder(t, "folder1", "folder1") + + // Create a regular alert rule + createRule(t, apiClient, "folder1", withRuleGroup("group1")) + // Create a rule from plugin + createRule(t, apiClient, "folder1", withRuleGroup("group2"), withLabels(map[string]string{"__grafana_origin": "plugin/grafana-slo-app"})) + + verifyRulesResponse := func(t *testing.T, b []byte, expectedGroupName string, shouldHaveOriginLabel bool) { + t.Helper() + + var result apimodels.RuleResponse + require.NoError(t, json.Unmarshal(b, &result)) + require.Equal(t, "success", result.Status) + + require.Len(t, result.Data.RuleGroups, 1) + group := result.Data.RuleGroups[0] + require.Equal(t, expectedGroupName, group.Name) + + require.Len(t, group.Rules, 1) + rule := group.Rules[0] + _, hasOriginLabel := rule.Labels.Map()["__grafana_origin"] + require.Equal(t, shouldHaveOriginLabel, hasOriginLabel) + } + + t.Run("plugins=hide returns only non-plugin rules", func(t *testing.T) { + promRulesURL := fmt.Sprintf("http://grafana:password@%s/api/prometheus/grafana/api/v1/rules?plugins=hide", grafanaListedAddr) + // nolint:gosec + resp, err := http.Get(promRulesURL) + require.NoError(t, err) + + t.Cleanup(func() { + err := resp.Body.Close() + require.NoError(t, err) + }) + + require.Equal(t, http.StatusOK, resp.StatusCode) + b, err := io.ReadAll(resp.Body) + require.NoError(t, err) + + verifyRulesResponse(t, b, "group1", false) + }) + + t.Run("plugins=only returns only plugin rules", func(t *testing.T) { + promRulesURL := fmt.Sprintf("http://grafana:password@%s/api/prometheus/grafana/api/v1/rules?plugins=only", grafanaListedAddr) + // nolint:gosec + resp, err := http.Get(promRulesURL) + require.NoError(t, err) + + t.Cleanup(func() { + err := resp.Body.Close() + require.NoError(t, err) + }) + + require.Equal(t, http.StatusOK, resp.StatusCode) + b, err := io.ReadAll(resp.Body) + require.NoError(t, err) + + verifyRulesResponse(t, b, "group2", true) + }) +} + func TestIntegrationPrometheusRulesPermissions(t *testing.T) { testutil.SkipIntegrationTestInShortMode(t) diff --git a/pkg/tests/api/alerting/api_ruler_test.go b/pkg/tests/api/alerting/api_ruler_test.go index a05829976f4..f25fb859299 100644 --- a/pkg/tests/api/alerting/api_ruler_test.go +++ b/pkg/tests/api/alerting/api_ruler_test.go @@ -5105,43 +5105,71 @@ func rulesNamespaceWithoutVariableValues(t *testing.T, b []byte) (string, map[st return string(json), m } -func createRule(t *testing.T, client apiClient, folder string) (apimodels.PostableRuleGroupConfig, string) { +type ruleOption func(*ruleConfig) + +type ruleConfig struct { + rule *apimodels.PostableExtendedRuleNode + groupName string +} + +func withLabels(labels map[string]string) ruleOption { + return func(cfg *ruleConfig) { + cfg.rule.Labels = labels + } +} + +func withRuleGroup(groupName string) ruleOption { + return func(cfg *ruleConfig) { + cfg.groupName = groupName + } +} + +func createRule(t *testing.T, client apiClient, folder string, opts ...ruleOption) (apimodels.PostableRuleGroupConfig, string) { t.Helper() interval, err := model.ParseDuration("1m") require.NoError(t, err) doubleInterval := 2 * interval - rules := apimodels.PostableRuleGroupConfig{ - Name: "arulegroup", - Interval: interval, - Rules: []apimodels.PostableExtendedRuleNode{ - { - ApiRuleNode: &apimodels.ApiRuleNode{ - For: &doubleInterval, - Labels: map[string]string{"label1": "val1"}, - Annotations: map[string]string{"annotation1": "val1"}, - }, - GrafanaManagedAlert: &apimodels.PostableGrafanaRule{ - Title: fmt.Sprintf("rule under folder %s", folder), - Condition: "A", - Data: []apimodels.AlertQuery{ - { - RefID: "A", - RelativeTimeRange: apimodels.RelativeTimeRange{ - From: apimodels.Duration(time.Duration(5) * time.Hour), - To: apimodels.Duration(time.Duration(3) * time.Hour), - }, - DatasourceUID: expr.DatasourceUID, - Model: json.RawMessage(`{ - "type": "math", - "expression": "2 + 3 > 1" - }`), - }, + + rule := apimodels.PostableExtendedRuleNode{ + ApiRuleNode: &apimodels.ApiRuleNode{ + For: &doubleInterval, + Labels: map[string]string{"label1": "val1"}, + Annotations: map[string]string{"annotation1": "val1"}, + }, + GrafanaManagedAlert: &apimodels.PostableGrafanaRule{ + Title: fmt.Sprintf("rule under folder %s", folder), + Condition: "A", + Data: []apimodels.AlertQuery{ + { + RefID: "A", + RelativeTimeRange: apimodels.RelativeTimeRange{ + From: apimodels.Duration(time.Duration(5) * time.Hour), + To: apimodels.Duration(time.Duration(3) * time.Hour), }, + DatasourceUID: expr.DatasourceUID, + Model: json.RawMessage(`{ + "type": "math", + "expression": "2 + 3 > 1" + }`), }, }, }, } + + cfg := &ruleConfig{ + rule: &rule, + groupName: "arulegroup", + } + for _, opt := range opts { + opt(cfg) + } + + rules := apimodels.PostableRuleGroupConfig{ + Name: cfg.groupName, + Interval: interval, + Rules: []apimodels.PostableExtendedRuleNode{*cfg.rule}, + } resp, status, _ := client.PostRulesGroupWithStatus(t, folder, &rules, false) require.Equal(t, http.StatusAccepted, status) require.Len(t, resp.Created, 1) diff --git a/public/app/features/alerting/unified/api/prometheusApi.ts b/public/app/features/alerting/unified/api/prometheusApi.ts index 12fa3aae223..9432da368b6 100644 --- a/public/app/features/alerting/unified/api/prometheusApi.ts +++ b/public/app/features/alerting/unified/api/prometheusApi.ts @@ -48,6 +48,7 @@ export type GrafanaPromRulesOptions = Omit ({ url: `api/prometheus/grafana/api/v1/rules`, params: { @@ -123,6 +125,7 @@ export const prometheusApi = alertingApi.injectEndpoints({ 'search.rule_group': searchGroupName, dashboard_uid: dashboardUid, rule_matcher: ruleMatchers, + plugins: plugins, }, }), providesTags: (_result, _error, { folderUid, groupName, ruleName }) => { diff --git a/public/app/features/alerting/unified/home/GettingStarted.tsx b/public/app/features/alerting/unified/home/GettingStarted.tsx index e25e3da07e8..9440902374d 100644 --- a/public/app/features/alerting/unified/home/GettingStarted.tsx +++ b/public/app/features/alerting/unified/home/GettingStarted.tsx @@ -4,6 +4,7 @@ import SVG from 'react-inlinesvg'; import { GrafanaTheme2 } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; +import { config } from '@grafana/runtime'; import { Stack, Text, TextLink, useStyles2, useTheme2 } from '@grafana/ui'; import atAGlanceDarkSvg from 'img/alerting/at_a_glance_dark.svg'; import atAGlanceLightSvg from 'img/alerting/at_a_glance_light.svg'; @@ -123,6 +124,20 @@ export function WelcomeHeader({ className }: { className?: string }) { return ( + {config.featureToggles.alertingTriage && ( + <> + +
+ + )} ({ container: css({ color: theme.colors.text.primary, flex: 1, - minWidth: '240px', + minWidth: '160px', display: 'grid', rowGap: theme.spacing(1), gridTemplateColumns: 'min-content 1fr 1fr 1fr', diff --git a/public/app/features/alerting/unified/rule-list/hooks/grafanaFilter.test.ts b/public/app/features/alerting/unified/rule-list/hooks/grafanaFilter.test.ts index ab9404d4e52..f97b1195a61 100644 --- a/public/app/features/alerting/unified/rule-list/hooks/grafanaFilter.test.ts +++ b/public/app/features/alerting/unified/rule-list/hooks/grafanaFilter.test.ts @@ -429,7 +429,7 @@ describe('grafana-managed rules', () => { ]); }); - it('should still apply other frontend filters', () => { + it('should include plugins in backend filter and skip frontend filtering', () => { // Set up test plugin as installed config.apps[SupportedPlugin.Slo] = pluginMetaToPluginConfig(pluginMeta[SupportedPlugin.Slo]); @@ -445,14 +445,15 @@ describe('grafana-managed rules', () => { alerts: [], }); - // Plugins filter should still work on frontend - const { frontendFilter } = getGrafanaFilter(getFilter({ plugins: 'hide' })); + // Plugins filter should be handled by backend + const { backendFilter, frontendFilter } = getGrafanaFilter(getFilter({ plugins: 'hide' })); - // Non-plugin rules should pass through + // Backend filter should include plugins parameter + expect(backendFilter.plugins).toBe('hide'); + + // Frontend filter should pass through all rules (no filtering) expect(frontendFilter.ruleMatches(regularRule)).toBe(true); - - // Plugin-provided rules should be filtered out - expect(frontendFilter.ruleMatches(pluginRule)).toBe(false); + expect(frontendFilter.ruleMatches(pluginRule)).toBe(true); }); }); @@ -808,7 +809,10 @@ describe('grafana-managed rules', () => { it('should return true for client-side only filters', () => { expect(hasGrafanaClientSideFilters(getFilter({ namespace: 'production' }))).toBe(true); - expect(hasGrafanaClientSideFilters(getFilter({ plugins: 'hide' }))).toBe(true); + }); + + it('should return false for plugins filter (handled by backend when feature toggle is enabled)', () => { + expect(hasGrafanaClientSideFilters(getFilter({ plugins: 'hide' }))).toBe(false); }); it('should return false for backend-only filters (state, health, contactPoint)', () => { @@ -831,13 +835,15 @@ describe('grafana-managed rules', () => { expect(hasGrafanaClientSideFilters(getFilter({ ruleHealth: RuleHealth.Ok }))).toBe(false); expect(hasGrafanaClientSideFilters(getFilter({ contactPoint: 'my-contact-point' }))).toBe(false); - // Should return true for: frontend-handled filters (labels, namespace, plugins) + // Should return true for: frontend-handled filters (labels, namespace) expect(hasGrafanaClientSideFilters(getFilter({ freeFormWords: ['cpu'] }))).toBe(true); expect(hasGrafanaClientSideFilters(getFilter({ ruleName: 'alert' }))).toBe(true); expect(hasGrafanaClientSideFilters(getFilter({ groupName: 'test-group' }))).toBe(true); expect(hasGrafanaClientSideFilters(getFilter({ namespace: 'production' }))).toBe(true); expect(hasGrafanaClientSideFilters(getFilter({ labels: ['severity=critical'] }))).toBe(true); - expect(hasGrafanaClientSideFilters(getFilter({ plugins: 'hide' }))).toBe(true); + + // plugins is backend-handled when alertingUIUseFullyCompatBackendFilters is enabled + expect(hasGrafanaClientSideFilters(getFilter({ plugins: 'hide' }))).toBe(false); }); }); @@ -856,9 +862,11 @@ describe('grafana-managed rules', () => { expect(hasGrafanaClientSideFilters(getFilter({ ruleHealth: RuleHealth.Ok }))).toBe(false); expect(hasGrafanaClientSideFilters(getFilter({ contactPoint: 'my-contact-point' }))).toBe(false); - // Should return true for: always-frontend filters only (namespace, plugins) + // Should return true for: always-frontend filters only (namespace) expect(hasGrafanaClientSideFilters(getFilter({ namespace: 'production' }))).toBe(true); - expect(hasGrafanaClientSideFilters(getFilter({ plugins: 'hide' }))).toBe(true); + + // plugins is backend-handled when both feature toggles are enabled + expect(hasGrafanaClientSideFilters(getFilter({ plugins: 'hide' }))).toBe(false); // Should return false for: backend-handled filters when both feature toggles are enabled expect(hasGrafanaClientSideFilters(getFilter({ dataSourceNames: ['prometheus'] }))).toBe(false); diff --git a/public/app/features/alerting/unified/rule-list/hooks/grafanaFilter.ts b/public/app/features/alerting/unified/rule-list/hooks/grafanaFilter.ts index 96ee951ee37..e8c4cf3c44a 100644 --- a/public/app/features/alerting/unified/rule-list/hooks/grafanaFilter.ts +++ b/public/app/features/alerting/unified/rule-list/hooks/grafanaFilter.ts @@ -95,6 +95,7 @@ export function getGrafanaFilter(filterState: Partial) { searchGroupName: groupFilterConfig.groupName ? undefined : normalizedFilterState.groupName, datasources: ruleFilterConfig.dataSourceNames ? undefined : datasourceUids, ruleMatchers: ruleMatchersBackendFilter, + plugins: ruleFilterConfig.plugins ? undefined : normalizedFilterState.plugins, }; return { @@ -128,7 +129,7 @@ function buildGrafanaFilterConfigs() { labels: useBackendFilters ? null : labelsFilter, ruleHealth: null, dashboardUid: useBackendFilters || useFullyCompatibleBackendFilters ? null : dashboardUidFilter, - plugins: pluginsFilter, + plugins: useBackendFilters || useFullyCompatibleBackendFilters ? null : pluginsFilter, contactPoint: null, }; diff --git a/public/app/features/dashboard-scene/utils/createPanelDataProvider.ts b/public/app/features/dashboard-scene/utils/createPanelDataProvider.ts index 94bfc7912fa..340d512fc8f 100644 --- a/public/app/features/dashboard-scene/utils/createPanelDataProvider.ts +++ b/public/app/features/dashboard-scene/utils/createPanelDataProvider.ts @@ -1,5 +1,6 @@ import { config } from '@grafana/runtime'; import { SceneDataProvider, SceneDataTransformer, SceneQueryRunner } from '@grafana/scenes'; +import { DataQuery, DataSourceRef } from '@grafana/schema/dist/esm/index'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; import { DashboardDatasourceBehaviour } from '../scene/DashboardDatasourceBehaviour'; @@ -18,7 +19,8 @@ export function createPanelDataProvider(panel: PanelModel): SceneDataProvider | let dataProvider: SceneDataProvider | undefined = undefined; dataProvider = new SceneQueryRunner({ - datasource: panel.datasource ?? undefined, + // If panel.datasource is not defined, we use the first datasource from the targets (queries) + datasource: panel.datasource ?? findFirstDatasource(panel.targets), queries: panel.targets, maxDataPoints: panel.maxDataPoints ?? undefined, maxDataPointsFromWidth: true, @@ -37,3 +39,17 @@ export function createPanelDataProvider(panel: PanelModel): SceneDataProvider | transformations: panel.transformations || [], }); } + +function findFirstDatasource(targets: DataQuery[]): DataSourceRef | undefined { + const datasource = targets.find((t) => Boolean(t.datasource))?.datasource; + if (!datasource) { + return undefined; + } + + const dsRef: DataSourceRef = { + ...(datasource?.type && { type: datasource?.type }), + ...(datasource?.uid && { uid: datasource?.uid }), + }; + + return dsRef; +} diff --git a/public/app/features/dimensions/resource.test.ts b/public/app/features/dimensions/resource.test.ts index ad644b61b4f..ac4d1c349dc 100644 --- a/public/app/features/dimensions/resource.test.ts +++ b/public/app/features/dimensions/resource.test.ts @@ -103,6 +103,84 @@ describe('getResourceDimension', () => { expect(getResourceDimension(frame, config).value()).toEqual(''); }); + it('should handle numeric field values with icon from value mapping', () => { + const publicPath = 'https://grafana.fake/public/'; + const frame = createDataFrame({ + fields: [ + { + name: 'status_field', + values: [1, 2, 3], + display: (v) => ({ + text: v === 1 ? 'Success' : v === 2 ? 'Warning' : 'Error', + numeric: Number(v), + icon: + v === 1 + ? 'img/icons/unicons/check-circle.svg' + : v === 2 + ? 'img/icons/unicons/exclamation-triangle.svg' + : 'img/icons/unicons/times-circle.svg', + }), + }, + ], + }); + const config = { mode: ResourceDimensionMode.Field, field: 'status_field', fixed: '' }; + + expect(getResourceDimension(frame, config).get(0)).toEqual(`${publicPath}build/img/icons/unicons/check-circle.svg`); + expect(getResourceDimension(frame, config).get(1)).toEqual( + `${publicPath}build/img/icons/unicons/exclamation-triangle.svg` + ); + expect(getResourceDimension(frame, config).get(2)).toEqual(`${publicPath}build/img/icons/unicons/times-circle.svg`); + }); + + it('should return empty string for unmapped numeric values without icon', () => { + const frame = createDataFrame({ + fields: [ + { + name: 'status_field', + values: [14], + display: (v) => ({ + text: String(v), + numeric: Number(v), + icon: undefined, + }), + }, + ], + }); + const config = { mode: ResourceDimensionMode.Field, field: 'status_field', fixed: '' }; + + expect(getResourceDimension(frame, config).get(0)).toEqual(''); + expect(getResourceDimension(frame, config).value()).toEqual(''); + }); + + it('should handle mixed numeric values with partial mappings', () => { + const publicPath = 'https://grafana.fake/public/'; + const frame = createDataFrame({ + fields: [ + { + name: 'status_field', + values: [1, 99, 2], + display: (v) => ({ + text: v === 1 ? 'Success' : v === 2 ? 'Warning' : String(v), + numeric: Number(v), + icon: + v === 1 + ? 'img/icons/unicons/check-circle.svg' + : v === 2 + ? 'img/icons/unicons/exclamation-triangle.svg' + : undefined, + }), + }, + ], + }); + const config = { mode: ResourceDimensionMode.Field, field: 'status_field', fixed: '' }; + + expect(getResourceDimension(frame, config).get(0)).toEqual(`${publicPath}build/img/icons/unicons/check-circle.svg`); + expect(getResourceDimension(frame, config).get(1)).toEqual(''); + expect(getResourceDimension(frame, config).get(2)).toEqual( + `${publicPath}build/img/icons/unicons/exclamation-triangle.svg` + ); + }); + // TODO: write tests for mapping modes }); @@ -125,4 +203,25 @@ describe('getPublicOrAbsoluteUrl', () => { expect(getPublicOrAbsoluteUrl({ path: 'icon.png' })).toEqual(''); expect(getPublicOrAbsoluteUrl(['icon.png'])).toEqual(''); }); + + it('should handle undefined publicPath gracefully', () => { + const originalPath = window.__grafana_public_path__; + + // @ts-ignore - Intentionally testing runtime edge case + window.__grafana_public_path__ = undefined; + + expect(getPublicOrAbsoluteUrl('icon.png')).toEqual('/build/icon.png'); + + window.__grafana_public_path__ = originalPath; + }); + + it('should handle empty string publicPath gracefully', () => { + const originalPath = window.__grafana_public_path__; + + window.__grafana_public_path__ = ''; + + expect(getPublicOrAbsoluteUrl('icon.png')).toEqual('/build/icon.png'); + + window.__grafana_public_path__ = originalPath; + }); }); diff --git a/public/app/features/dimensions/resource.ts b/public/app/features/dimensions/resource.ts index 4eb28242550..822d808b016 100644 --- a/public/app/features/dimensions/resource.ts +++ b/public/app/features/dimensions/resource.ts @@ -15,8 +15,9 @@ export function getPublicOrAbsoluteUrl(path: unknown): string { // NOTE: The value of `path` could be either an URL string or a relative // path to a Grafana CDN asset served from the CDN. const isUrl = path.indexOf(':/') > 0; + const publicPath = window.__grafana_public_path__ || '/'; - return isUrl ? path : `${window.__grafana_public_path__}build/${path}`; + return isUrl ? path : `${publicPath}build/${path}`; } export function getResourceDimension( @@ -56,11 +57,11 @@ export function getResourceDimension( // mode === ResourceDimensionMode.Field case const getImageOrIcon = (value: unknown): string => { - if (typeof value !== 'string') { + if (typeof value !== 'string' && typeof value !== 'number') { return ''; } - let url = value; + let url = typeof value === 'string' ? value : ''; if (field && field.display) { const displayValue = field.display(value); if (displayValue.icon) { @@ -68,6 +69,11 @@ export function getResourceDimension( } } + const noIconFound = !url; + if (noIconFound) { + return ''; + } + return getPublicOrAbsoluteUrl(url); }; diff --git a/public/app/plugins/datasource/prometheus/dashboards/prometheus_2_stats.json b/public/app/plugins/datasource/prometheus/dashboards/prometheus_2_stats.json index 57e2bb5e47d..6c9831a5d2f 100644 --- a/public/app/plugins/datasource/prometheus/dashboards/prometheus_2_stats.json +++ b/public/app/plugins/datasource/prometheus/dashboards/prometheus_2_stats.json @@ -179,15 +179,12 @@ "pluginVersion": "8.1.0-pre", "targets": [ { - "expr": "sum(irate(prometheus_tsdb_head_samples_appended_total{job=\"prometheus\"}[5m]))", + "expr": "sum(irate(prometheus_tsdb_head_samples_appended_total{job=\"prometheus\"}[$__rate_interval]))", "format": "time_series", "hide": false, - "interval": "", - "intervalFactor": 2, "legendFormat": "samples", "metric": "", - "refId": "A", - "step": 20 + "refId": "A" } ], "timeFrom": null, @@ -272,12 +269,9 @@ { "expr": "topk(5, max(scrape_duration_seconds) by (job))", "format": "time_series", - "interval": "", - "intervalFactor": 2, "legendFormat": "{{job}}", "metric": "", - "refId": "A", - "step": 20 + "refId": "A" } ], "timeFrom": null, @@ -365,20 +359,15 @@ "expr": "sum(process_resident_memory_bytes{job=\"prometheus\"})", "format": "time_series", "hide": false, - "interval": "", - "intervalFactor": 2, "legendFormat": "p8s process resident memory", - "refId": "D", - "step": 20 + "refId": "D" }, { "expr": "process_virtual_memory_bytes{job=\"prometheus\"}", "format": "time_series", "hide": false, - "intervalFactor": 2, "legendFormat": "virtual memory", - "refId": "C", - "step": 20 + "refId": "C" } ], "timeFrom": null, @@ -453,10 +442,8 @@ { "expr": "prometheus_tsdb_wal_corruptions_total{job=\"prometheus\"}", "format": "time_series", - "intervalFactor": 2, "legendFormat": "", - "refId": "A", - "step": 60 + "refId": "A" } ], "title": "WAL Corruptions", @@ -539,21 +526,15 @@ { "expr": "sum(prometheus_tsdb_head_active_appenders{job=\"prometheus\"})", "format": "time_series", - "interval": "", - "intervalFactor": 2, "legendFormat": "active_appenders", "metric": "", - "refId": "A", - "step": 20 + "refId": "A" }, { "expr": "sum(process_open_fds{job=\"prometheus\"})", "format": "time_series", - "interval": "", - "intervalFactor": 2, "legendFormat": "open_fds", - "refId": "B", - "step": 20 + "refId": "B" } ], "timeFrom": null, @@ -669,10 +650,8 @@ { "expr": "prometheus_tsdb_blocks_loaded{job=\"prometheus\"}", "format": "time_series", - "intervalFactor": 2, "legendFormat": "blocks", - "refId": "A", - "step": 20 + "refId": "A" } ], "timeFrom": null, @@ -758,11 +737,8 @@ { "expr": "prometheus_tsdb_head_chunks{job=\"prometheus\"}", "format": "time_series", - "interval": "", - "intervalFactor": 2, "legendFormat": "chunks", - "refId": "A", - "step": 20 + "refId": "A" } ], "timeFrom": null, @@ -861,18 +837,14 @@ { "expr": "prometheus_tsdb_head_gc_duration_seconds{job=\"prometheus\",quantile=\"0.99\"}", "format": "time_series", - "intervalFactor": 2, "legendFormat": "duration-p99", - "refId": "A", - "step": 20 + "refId": "A" }, { - "expr": "irate(prometheus_tsdb_head_gc_duration_seconds_count{job=\"prometheus\"}[5m])", + "expr": "irate(prometheus_tsdb_head_gc_duration_seconds_count{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", - "intervalFactor": 2, "legendFormat": "collections", - "refId": "B", - "step": 20 + "refId": "B" } ], "timeFrom": null, @@ -970,38 +942,29 @@ "pluginVersion": "8.1.0-pre", "targets": [ { - "expr": "histogram_quantile(0.99, sum(rate(prometheus_tsdb_compaction_duration_bucket{job=\"prometheus\"}[5m])) by (le))", + "expr": "histogram_quantile(0.99, sum(rate(prometheus_tsdb_compaction_duration_bucket{job=\"prometheus\"}[$__rate_interval])) by (le))", "format": "time_series", "hide": false, - "interval": "", - "intervalFactor": 2, "legendFormat": "duration-{{p99}}", - "refId": "A", - "step": 20 + "refId": "A" }, { - "expr": "irate(prometheus_tsdb_compactions_total{job=\"prometheus\"}[5m])", + "expr": "irate(prometheus_tsdb_compactions_total{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", - "intervalFactor": 2, "legendFormat": "compactions", - "refId": "B", - "step": 20 + "refId": "B" }, { - "expr": "irate(prometheus_tsdb_compactions_failed_total{job=\"prometheus\"}[5m])", + "expr": "irate(prometheus_tsdb_compactions_failed_total{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", - "intervalFactor": 2, "legendFormat": "failed", - "refId": "C", - "step": 20 + "refId": "C" }, { - "expr": "irate(prometheus_tsdb_compactions_triggered_total{job=\"prometheus\"}[5m])", + "expr": "irate(prometheus_tsdb_compactions_triggered_total{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", - "intervalFactor": 2, "legendFormat": "triggered", - "refId": "D", - "step": 20 + "refId": "D" } ], "timeFrom": null, @@ -1084,21 +1047,17 @@ "pluginVersion": "8.1.0-pre", "targets": [ { - "expr": "rate(prometheus_tsdb_reloads_total{job=\"prometheus\"}[5m])", + "expr": "rate(prometheus_tsdb_reloads_total{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", - "intervalFactor": 2, "legendFormat": "reloads", - "refId": "A", - "step": 20 + "refId": "A" }, { - "expr": "rate(prometheus_tsdb_reloads_failures_total{job=\"prometheus\"}[5m])", + "expr": "rate(prometheus_tsdb_reloads_failures_total{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", "hide": false, - "intervalFactor": 2, "legendFormat": "failures", - "refId": "B", - "step": 20 + "refId": "B" } ], "timeFrom": null, @@ -1183,10 +1142,8 @@ { "expr": "prometheus_engine_query_duration_seconds{job=\"prometheus\", quantile=\"0.99\"}", "format": "time_series", - "intervalFactor": 2, "legendFormat": "{{slice}}_p99", - "refId": "A", - "step": 20 + "refId": "A" } ], "timeFrom": null, @@ -1271,11 +1228,8 @@ { "expr": "max(prometheus_rule_group_duration_seconds{job=\"prometheus\"}) by (quantile)", "format": "time_series", - "interval": "", - "intervalFactor": 2, "legendFormat": "{{quantile}}", - "refId": "A", - "step": 10 + "refId": "A" } ], "timeFrom": null, @@ -1358,20 +1312,16 @@ "pluginVersion": "8.1.0-pre", "targets": [ { - "expr": "rate(prometheus_rule_group_iterations_missed_total{job=\"prometheus\"}[5m])", + "expr": "rate(prometheus_rule_group_iterations_missed_total{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", - "intervalFactor": 2, "legendFormat": "missed", - "refId": "B", - "step": 10 + "refId": "B" }, { - "expr": "rate(prometheus_rule_group_iterations_total{job=\"prometheus\"}[5m])", + "expr": "rate(prometheus_rule_group_iterations_total{job=\"prometheus\"}[$__rate_interval])", "format": "time_series", - "intervalFactor": 2, "legendFormat": "iterations", - "refId": "A", - "step": 10 + "refId": "A" } ], "timeFrom": null, diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 10967a7331c..d4274aa98cd 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -3135,9 +3135,12 @@ "table": "Table" }, "welcome-header": { + "description-alert-activity": "See what is currently alerting and explore historical data to investigate current or past issues.", "description-alert-rules": "Define the condition that must be met before an alert rule fires", "description-configure-firing-alert-instances-routed-contact": "Configure how firing alert instances are routed to contact points", "description-configure-receives-notifications": "Configure who receives notifications and how they are sent", + "href-text-alert-activity": "View alert activity", + "title-alert-activity": "Alert activity", "title-alert-rules": "Alert rules", "title-contact-points": "Contact points", "title-notification-policies": "Notification policies"