Unified Storage/Large Object Support: Add test for dashboardv2 support (#107470)

* Add more unit tests to cover dashboardv2 and cross version unmarshalling

Signed-off-by: Bruno Abrantes <bruno@brunoabrantes.com>

* Change import name of meta v1

* Rename TestLargeDashboardSupport since there are tests for multiple versions

* Simplify TestLargeDashboardSupportV2

* Use v1 in TestLargeDashboardSupportCrossVersion, simplify original dash

* Marshal spec in TestLargeDashboardSupportCrossVersion

* Remove TestLargeDashboardSupportCrossVersion

---------

Signed-off-by: Bruno Abrantes <bruno@brunoabrantes.com>
Co-authored-by: Bruno Abrantes <bruno@brunoabrantes.com>
This commit is contained in:
Arati R.
2025-07-03 07:13:56 +02:00
committed by GitHub
co-authored by Bruno Abrantes
parent acabe86153
commit a68f8107df
+114 -4
View File
@@ -6,14 +6,15 @@ import (
"testing"
"github.com/stretchr/testify/require"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
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"
dashv2 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2alpha1"
)
func TestLargeDashboardSupport(t *testing.T) {
func TestLargeDashboardSupportV1(t *testing.T) {
devdash := "../../../../devenv/dev-dashboards/all-panels.json"
// nolint:gosec
@@ -22,7 +23,7 @@ func TestLargeDashboardSupport(t *testing.T) {
require.NoError(t, err)
dash := &dashv1.Dashboard{
ObjectMeta: v1.ObjectMeta{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "test",
},
@@ -57,7 +58,7 @@ func TestLargeDashboardSupport(t *testing.T) {
// Now make it big again
rehydratedDash := &dashv1.Dashboard{
ObjectMeta: v1.ObjectMeta{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "test",
},
@@ -71,3 +72,112 @@ func TestLargeDashboardSupport(t *testing.T) {
require.True(t, found)
require.Len(t, panels, expectedPanelCount)
}
func TestLargeDashboardSupportV2(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 := &dashv2.Dashboard{
ObjectMeta: metav1.ObjectMeta{
Name: "test-v2",
Namespace: "test",
},
Spec: dashv2.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: []dashv2.DashboardAnnotationQueryKind{
{
Kind: "AnnotationQuery",
Spec: dashv2.DashboardAnnotationQuerySpec{
Name: "Test Annotation",
},
},
},
Elements: map[string]dashv2.DashboardElement{
"panel-1": {
PanelKind: &dashv2.DashboardPanelKind{},
},
},
Layout: dashv2.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind{},
TimeSettings: dashv2.DashboardTimeSettingsSpec{},
CursorSync: dashv2.DashboardDashboardCursorSyncOff,
Variables: []dashv2.DashboardVariableKind{},
Links: []dashv2.DashboardDashboardLink{},
},
}
scheme := runtime.NewScheme()
err := dashv2.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 := &dashv2.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
}