+4








20b08ccaab
* Revert "Revert: Future-proofing query and data source model in Dashboard Sche… (#107985)" This reverts commit13a89d4ae3. * Revert "Revert "Schema V2: Simplify annotations v1<->v2 conversions" (#107984)" This reverts commit2b8c5bea1a. * make gen apps * e2e update * Use v2alpha2 by default (#108177) * Use v2alpha2 by default * Apply only DS changes to alpha2 * Use v2alpha2 by default except to query * Create a v2 index in @grafana/schema * Update path and apply lint * Update tests * Update imports to v2 status * Fix failing openapi test * Schemav2 breaking changes: conversion implementation (#108224) * provision v2alpha1 dashboard * Run conversions for DS refactor * Run snapshot testing on conversions * Normalize output name * Update snapshots to include all panel and variable cases * fix lint * fix lint * fix test and go lint * more go lint --------- Co-authored-by: Ivan Ortega <ivanortegaalba@gmail.com> Co-authored-by: Haris Rozajac <haris.rozajac12@gmail.com> * Schema v2: Introduce group/datasource convention to GroupBy and AdHoc variable (#108237) * Schema v2: Introduce group/datasource convention to GroupBy and AdHoc variables * add conversion * App Installer: Authorizer support (#108419) * Chore: use `satisfies` and remove a load of `any`s (#108397) use satisfies and remove a load of anys * improve logging and fail unified-storage migration with more than 0 errors (#108471) improve logging and fail unified-storage migration with more than 0 errors * fix conversion test * Secrets: Create more granular fixed roles for SecureValues (#108382) * Provisioning: Fix bug in job progress recording (#108440) Fix bug in job progress recording * Provisioning: Fix ImportAllPanelsFromLocalRepository test (#108441) * Provisioning: Skip flaky test * Fix flaky provisioning test * Fix lint --------- Co-authored-by: Roberto Jimenez Sanchez <roberto.jimenez@grafana.com> * BulkDeleteProvisionedResource: Move progress bar into a second step (#108417) * Move progress bar into a second step --------- Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com> * [Dashboard Schema Codegen] Move dashboard CUE codegen block back up into kind body (#108476) [Dashboard Schema Codegen] Move dashboard CUE codegen block back up into kind body to make sure new versions have the same settings. --------- Co-authored-by: Haris Rozajac <haris.rozajac12@gmail.com> Co-authored-by: Todd Treece <360020+toddtreece@users.noreply.github.com> Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com> Co-authored-by: Will Assis <35489495+gassiss@users.noreply.github.com> Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com> Co-authored-by: Roberto Jiménez Sánchez <jszroberto@gmail.com> Co-authored-by: Roberto Jimenez Sanchez <roberto.jimenez@grafana.com> Co-authored-by: Yunwen Zheng <yunwen.zheng@grafana.com> Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com> Co-authored-by: Austin Pond <IfSentient@users.noreply.github.com> Co-authored-by: Ivan Ortega <ivanortegaalba@gmail.com> * Dashboard Schema V2: Refactor VizConfigKind to follow DataQueryKind convention (#108148) * Dashboards API: Register v2alpha2 API * Prepare conversion functions * Fix test * Refactor VizConfigKind to follow DataQueryKind convention * fix tests * use new dataquerykind convention alpha 2 * add conversion * fix tests * fix tests * fix another test * Fix merge --------- Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com> * fix k8s codegen * Update e2e-playwright/dashboards/TestV2Dashboard.json * Update e2e/dashboards/TestV2Dashboard.json * revert app generation for non-related apps * try again * another try * also revert folder and secret app generation * v2alpha1 provisioned dashboard * Fix kind * Fix conversion snapshots * Update API discovery registry * Rename to v2beta1 * Rename migrations * Update apps/dashboard/pkg/apis/dashboard/v2beta1/doc.go Co-authored-by: Stephanie Hingtgen <stephanie.hingtgen@grafana.com> * Ensure conditional rendering and other non changed properties --------- Co-authored-by: Ivan Ortega <ivanortegaalba@gmail.com> Co-authored-by: Haris Rozajac <haris.rozajac12@gmail.com> Co-authored-by: Todd Treece <360020+toddtreece@users.noreply.github.com> Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com> Co-authored-by: Will Assis <35489495+gassiss@users.noreply.github.com> Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com> Co-authored-by: Roberto Jiménez Sánchez <jszroberto@gmail.com> Co-authored-by: Roberto Jimenez Sanchez <roberto.jimenez@grafana.com> Co-authored-by: Yunwen Zheng <yunwen.zheng@grafana.com> Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com> Co-authored-by: Austin Pond <IfSentient@users.noreply.github.com> Co-authored-by: Haris Rozajac <58232930+harisrozajac@users.noreply.github.com> Co-authored-by: Stephanie Hingtgen <stephanie.hingtgen@grafana.com>
285 lines
9.6 KiB
Go
285 lines
9.6 KiB
Go
package dashboard
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
|
|
dashv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1"
|
|
dashv2alpha1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1"
|
|
dashv2beta1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1"
|
|
)
|
|
|
|
func TestLargeDashboardSupportV1(t *testing.T) {
|
|
devdash := "../../../../devenv/dev-dashboards/all-panels.json"
|
|
|
|
// nolint:gosec
|
|
// We can ignore the gosec G304 warning because this is a test with hardcoded input values
|
|
f, err := os.ReadFile(devdash)
|
|
require.NoError(t, err)
|
|
|
|
dash := &dashv1.Dashboard{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test",
|
|
Namespace: "test",
|
|
},
|
|
}
|
|
err = json.Unmarshal(f, &dash.Spec)
|
|
require.NoError(t, err)
|
|
|
|
expectedPanelCount := 19
|
|
panels, found, err := unstructured.NestedSlice(dash.Spec.Object, "panels")
|
|
require.NoError(t, err)
|
|
require.True(t, found)
|
|
require.Len(t, panels, expectedPanelCount)
|
|
|
|
scheme := runtime.NewScheme()
|
|
|
|
err = dashv1.AddToScheme(scheme)
|
|
require.NoError(t, err)
|
|
|
|
largeObject := NewDashboardLargeObjectSupport(scheme, 0)
|
|
|
|
// Convert the dashboard to a small value
|
|
err = largeObject.ReduceSpec(dash)
|
|
require.NoError(t, err)
|
|
|
|
small, err := json.MarshalIndent(&dash.Spec, "", " ")
|
|
require.NoError(t, err)
|
|
require.JSONEq(t, `{
|
|
"schemaVersion": 36,
|
|
"title": "Panel tests - All panels",
|
|
"tags": ["gdev","panel-tests","all-panels"]
|
|
}`, string(small))
|
|
|
|
// Now make it big again
|
|
rehydratedDash := &dashv1.Dashboard{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test",
|
|
Namespace: "test",
|
|
},
|
|
}
|
|
err = largeObject.RebuildSpec(rehydratedDash, f)
|
|
require.NoError(t, err)
|
|
|
|
// check that all panels exist again
|
|
panels, found, err = unstructured.NestedSlice(rehydratedDash.Spec.Object, "panels")
|
|
require.NoError(t, err)
|
|
require.True(t, found)
|
|
require.Len(t, panels, expectedPanelCount)
|
|
}
|
|
|
|
func TestLargeDashboardSupportV2alpha1(t *testing.T) {
|
|
// Test RebuildSpec functionality specifically for v2 dashboards
|
|
// This tests the json.Unmarshal(blob, &dash.Spec) path for structured specs
|
|
// unlike v0/v1 which use the UnmarshalJSON path for unstructured specs
|
|
|
|
// Create a v2 dashboard with structured spec
|
|
originalV2Dash := &dashv2alpha1.Dashboard{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-v2",
|
|
Namespace: "test",
|
|
},
|
|
Spec: dashv2alpha1.DashboardSpec{
|
|
Title: "Test V2 Dashboard",
|
|
Description: stringPtr("A test dashboard for v2 large object support"),
|
|
Tags: []string{"test", "v2", "large-object"},
|
|
Editable: boolPtr(true),
|
|
LiveNow: boolPtr(false),
|
|
Preload: false,
|
|
Annotations: []dashv2alpha1.DashboardAnnotationQueryKind{
|
|
{
|
|
Kind: "AnnotationQuery",
|
|
Spec: dashv2alpha1.DashboardAnnotationQuerySpec{
|
|
Name: "Test Annotation",
|
|
},
|
|
},
|
|
},
|
|
Elements: map[string]dashv2alpha1.DashboardElement{
|
|
"panel-1": {
|
|
PanelKind: &dashv2alpha1.DashboardPanelKind{},
|
|
},
|
|
},
|
|
Layout: dashv2alpha1.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind{},
|
|
TimeSettings: dashv2alpha1.DashboardTimeSettingsSpec{},
|
|
CursorSync: dashv2alpha1.DashboardDashboardCursorSyncOff,
|
|
Variables: []dashv2alpha1.DashboardVariableKind{},
|
|
Links: []dashv2alpha1.DashboardDashboardLink{},
|
|
},
|
|
}
|
|
|
|
scheme := runtime.NewScheme()
|
|
err := dashv2alpha1.AddToScheme(scheme)
|
|
require.NoError(t, err)
|
|
|
|
largeObject := NewDashboardLargeObjectSupport(scheme, 0)
|
|
|
|
// Marshal the original spec to use as our "blob" data
|
|
originalSpecBlob, err := json.Marshal(originalV2Dash.Spec)
|
|
require.NoError(t, err)
|
|
|
|
// Create a copy to test reduction
|
|
dashToReduce := originalV2Dash.DeepCopy()
|
|
|
|
// Convert the dashboard to a small value (ReduceSpec)
|
|
err = largeObject.ReduceSpec(dashToReduce)
|
|
require.NoError(t, err)
|
|
|
|
// Verify only essential fields remain after reduction
|
|
require.Equal(t, "Test V2 Dashboard", dashToReduce.Spec.Title)
|
|
require.Equal(t, stringPtr("A test dashboard for v2 large object support"), dashToReduce.Spec.Description)
|
|
require.Equal(t, []string{"test", "v2", "large-object"}, dashToReduce.Spec.Tags)
|
|
|
|
// Everything else should be empty/default
|
|
require.Empty(t, dashToReduce.Spec.Annotations)
|
|
require.Empty(t, dashToReduce.Spec.Elements)
|
|
require.Nil(t, dashToReduce.Spec.Layout.GridLayoutKind)
|
|
require.Empty(t, dashToReduce.Spec.Variables)
|
|
require.Empty(t, dashToReduce.Spec.Links)
|
|
|
|
// Now test RebuildSpec - this is the key test for v2!
|
|
rehydratedDash := &dashv2alpha1.Dashboard{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-v2-rehydrated",
|
|
Namespace: "test",
|
|
},
|
|
}
|
|
|
|
// This tests the json.Unmarshal(blob, &dash.Spec) path for v2 dashboards
|
|
err = largeObject.RebuildSpec(rehydratedDash, originalSpecBlob)
|
|
require.NoError(t, err)
|
|
|
|
// Verify the full dashboard spec is restored correctly
|
|
require.Equal(t, originalV2Dash.Spec.Title, rehydratedDash.Spec.Title)
|
|
require.Equal(t, originalV2Dash.Spec.Description, rehydratedDash.Spec.Description)
|
|
require.Equal(t, originalV2Dash.Spec.Tags, rehydratedDash.Spec.Tags)
|
|
require.Equal(t, originalV2Dash.Spec.Editable, rehydratedDash.Spec.Editable)
|
|
require.Equal(t, originalV2Dash.Spec.LiveNow, rehydratedDash.Spec.LiveNow)
|
|
require.Equal(t, originalV2Dash.Spec.Preload, rehydratedDash.Spec.Preload)
|
|
|
|
// Verify annotations are restored
|
|
require.Len(t, rehydratedDash.Spec.Annotations, 1)
|
|
annotation := rehydratedDash.Spec.Annotations[0]
|
|
require.Equal(t, "AnnotationQuery", annotation.Kind)
|
|
require.Equal(t, "Test Annotation", annotation.Spec.Name)
|
|
|
|
// Verify elements are restored
|
|
require.Len(t, rehydratedDash.Spec.Elements, 1)
|
|
_, exists := rehydratedDash.Spec.Elements["panel-1"]
|
|
require.True(t, exists)
|
|
}
|
|
|
|
func TestLargeDashboardSupportV2beta1(t *testing.T) {
|
|
// Test RebuildSpec functionality specifically for v2 dashboards
|
|
// This tests the json.Unmarshal(blob, &dash.Spec) path for structured specs
|
|
// unlike v0/v1 which use the UnmarshalJSON path for unstructured specs
|
|
|
|
// Create a v2 dashboard with structured spec
|
|
originalV2Dash := &dashv2beta1.Dashboard{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-v2",
|
|
Namespace: "test",
|
|
},
|
|
Spec: dashv2beta1.DashboardSpec{
|
|
Title: "Test V2 Dashboard",
|
|
Description: stringPtr("A test dashboard for v2 large object support"),
|
|
Tags: []string{"test", "v2", "large-object"},
|
|
Editable: boolPtr(true),
|
|
LiveNow: boolPtr(false),
|
|
Preload: false,
|
|
Annotations: []dashv2beta1.DashboardAnnotationQueryKind{
|
|
{
|
|
Kind: "AnnotationQuery",
|
|
Spec: dashv2beta1.DashboardAnnotationQuerySpec{
|
|
Name: "Test Annotation",
|
|
},
|
|
},
|
|
},
|
|
Elements: map[string]dashv2beta1.DashboardElement{
|
|
"panel-1": {
|
|
PanelKind: &dashv2beta1.DashboardPanelKind{},
|
|
},
|
|
},
|
|
Layout: dashv2beta1.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind{},
|
|
TimeSettings: dashv2beta1.DashboardTimeSettingsSpec{},
|
|
CursorSync: dashv2beta1.DashboardDashboardCursorSyncOff,
|
|
Variables: []dashv2beta1.DashboardVariableKind{},
|
|
Links: []dashv2beta1.DashboardDashboardLink{},
|
|
},
|
|
}
|
|
|
|
scheme := runtime.NewScheme()
|
|
err := dashv2beta1.AddToScheme(scheme)
|
|
require.NoError(t, err)
|
|
|
|
largeObject := NewDashboardLargeObjectSupport(scheme, 0)
|
|
|
|
// Marshal the original spec to use as our "blob" data
|
|
originalSpecBlob, err := json.Marshal(originalV2Dash.Spec)
|
|
require.NoError(t, err)
|
|
|
|
// Create a copy to test reduction
|
|
dashToReduce := originalV2Dash.DeepCopy()
|
|
|
|
// Convert the dashboard to a small value (ReduceSpec)
|
|
err = largeObject.ReduceSpec(dashToReduce)
|
|
require.NoError(t, err)
|
|
|
|
// Verify only essential fields remain after reduction
|
|
require.Equal(t, "Test V2 Dashboard", dashToReduce.Spec.Title)
|
|
require.Equal(t, stringPtr("A test dashboard for v2 large object support"), dashToReduce.Spec.Description)
|
|
require.Equal(t, []string{"test", "v2", "large-object"}, dashToReduce.Spec.Tags)
|
|
|
|
// Everything else should be empty/default
|
|
require.Empty(t, dashToReduce.Spec.Annotations)
|
|
require.Empty(t, dashToReduce.Spec.Elements)
|
|
require.Nil(t, dashToReduce.Spec.Layout.GridLayoutKind)
|
|
require.Empty(t, dashToReduce.Spec.Variables)
|
|
require.Empty(t, dashToReduce.Spec.Links)
|
|
|
|
// Now test RebuildSpec - this is the key test for v2!
|
|
rehydratedDash := &dashv2beta1.Dashboard{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-v2-rehydrated",
|
|
Namespace: "test",
|
|
},
|
|
}
|
|
|
|
// This tests the json.Unmarshal(blob, &dash.Spec) path for v2 dashboards
|
|
err = largeObject.RebuildSpec(rehydratedDash, originalSpecBlob)
|
|
require.NoError(t, err)
|
|
|
|
// Verify the full dashboard spec is restored correctly
|
|
require.Equal(t, originalV2Dash.Spec.Title, rehydratedDash.Spec.Title)
|
|
require.Equal(t, originalV2Dash.Spec.Description, rehydratedDash.Spec.Description)
|
|
require.Equal(t, originalV2Dash.Spec.Tags, rehydratedDash.Spec.Tags)
|
|
require.Equal(t, originalV2Dash.Spec.Editable, rehydratedDash.Spec.Editable)
|
|
require.Equal(t, originalV2Dash.Spec.LiveNow, rehydratedDash.Spec.LiveNow)
|
|
require.Equal(t, originalV2Dash.Spec.Preload, rehydratedDash.Spec.Preload)
|
|
|
|
// Verify annotations are restored
|
|
require.Len(t, rehydratedDash.Spec.Annotations, 1)
|
|
annotation := rehydratedDash.Spec.Annotations[0]
|
|
require.Equal(t, "AnnotationQuery", annotation.Kind)
|
|
require.Equal(t, "Test Annotation", annotation.Spec.Name)
|
|
|
|
// Verify elements are restored
|
|
require.Len(t, rehydratedDash.Spec.Elements, 1)
|
|
_, exists := rehydratedDash.Spec.Elements["panel-1"]
|
|
require.True(t, exists)
|
|
}
|
|
|
|
// Helper functions for pointer types
|
|
func stringPtr(s string) *string {
|
|
return &s
|
|
}
|
|
|
|
func boolPtr(b bool) *bool {
|
|
return &b
|
|
}
|