feat(dashboard): Org-aware cache for schema migration (#115025)
* fix: use dsIndexProvider cache on migrations * chore: use same comment as before * feat: org-aware TTL cache for schemaversion migration and warmup for single tenant * chore: use LRU cache * chore: change DefaultCacheTTL to 1 minute * chore: address copilot reviews * chore: use expirable cache * chore: remove unused import
This commit is contained in:
@@ -0,0 +1,454 @@
|
||||
package conversion
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
dashv0 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v0alpha1"
|
||||
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"
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/migration"
|
||||
"github.com/grafana/grafana/apps/dashboard/pkg/migration/schemaversion"
|
||||
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// countingDataSourceProvider tracks how many times Index() is called
|
||||
type countingDataSourceProvider struct {
|
||||
datasources []schemaversion.DataSourceInfo
|
||||
callCount atomic.Int64
|
||||
}
|
||||
|
||||
func newCountingDataSourceProvider(datasources []schemaversion.DataSourceInfo) *countingDataSourceProvider {
|
||||
return &countingDataSourceProvider{
|
||||
datasources: datasources,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *countingDataSourceProvider) Index(_ context.Context) *schemaversion.DatasourceIndex {
|
||||
p.callCount.Add(1)
|
||||
return schemaversion.NewDatasourceIndex(p.datasources)
|
||||
}
|
||||
|
||||
func (p *countingDataSourceProvider) getCallCount() int64 {
|
||||
return p.callCount.Load()
|
||||
}
|
||||
|
||||
// countingLibraryElementProvider tracks how many times GetLibraryElementInfo() is called
|
||||
type countingLibraryElementProvider struct {
|
||||
elements []schemaversion.LibraryElementInfo
|
||||
callCount atomic.Int64
|
||||
}
|
||||
|
||||
func newCountingLibraryElementProvider(elements []schemaversion.LibraryElementInfo) *countingLibraryElementProvider {
|
||||
return &countingLibraryElementProvider{
|
||||
elements: elements,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *countingLibraryElementProvider) GetLibraryElementInfo(_ context.Context) []schemaversion.LibraryElementInfo {
|
||||
p.callCount.Add(1)
|
||||
return p.elements
|
||||
}
|
||||
|
||||
func (p *countingLibraryElementProvider) getCallCount() int64 {
|
||||
return p.callCount.Load()
|
||||
}
|
||||
|
||||
// createTestV0Dashboard creates a minimal v0 dashboard for testing
|
||||
// The dashboard has a datasource with UID only (no type) to force provider lookup
|
||||
// and includes library panels to test library element provider caching
|
||||
func createTestV0Dashboard(namespace, title string) *dashv0.Dashboard {
|
||||
return &dashv0.Dashboard{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-dashboard",
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: common.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"title": title,
|
||||
"schemaVersion": schemaversion.LATEST_VERSION,
|
||||
// Variables with datasource reference that requires lookup
|
||||
"templating": map[string]interface{}{
|
||||
"list": []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "query_var",
|
||||
"type": "query",
|
||||
"query": "label_values(up, job)",
|
||||
// Datasource with UID only - type needs to be looked up
|
||||
"datasource": map[string]interface{}{
|
||||
"uid": "ds1",
|
||||
// type is intentionally omitted to trigger provider lookup
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"panels": []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": 1,
|
||||
"title": "Test Panel",
|
||||
"type": "timeseries",
|
||||
"targets": []interface{}{
|
||||
map[string]interface{}{
|
||||
// Datasource with UID only - type needs to be looked up
|
||||
"datasource": map[string]interface{}{
|
||||
"uid": "ds1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// Library panel reference - triggers library element provider lookup
|
||||
map[string]interface{}{
|
||||
"id": 2,
|
||||
"title": "Library Panel with Horizontal Repeat",
|
||||
"type": "library-panel-ref",
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 8,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 8,
|
||||
},
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": "lib-panel-repeat-h",
|
||||
"name": "Library Panel with Horizontal Repeat",
|
||||
},
|
||||
},
|
||||
// Another library panel reference
|
||||
map[string]interface{}{
|
||||
"id": 3,
|
||||
"title": "Library Panel without Repeat",
|
||||
"type": "library-panel-ref",
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 3,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 16,
|
||||
},
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": "lib-panel-no-repeat",
|
||||
"name": "Library Panel without Repeat",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// createTestV1Dashboard creates a minimal v1beta1 dashboard for testing
|
||||
// The dashboard has a datasource with UID only (no type) to force provider lookup
|
||||
// and includes library panels to test library element provider caching
|
||||
func createTestV1Dashboard(namespace, title string) *dashv1.Dashboard {
|
||||
return &dashv1.Dashboard{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-dashboard",
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: common.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"title": title,
|
||||
"schemaVersion": schemaversion.LATEST_VERSION,
|
||||
// Variables with datasource reference that requires lookup
|
||||
"templating": map[string]interface{}{
|
||||
"list": []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "query_var",
|
||||
"type": "query",
|
||||
"query": "label_values(up, job)",
|
||||
// Datasource with UID only - type needs to be looked up
|
||||
"datasource": map[string]interface{}{
|
||||
"uid": "ds1",
|
||||
// type is intentionally omitted to trigger provider lookup
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"panels": []interface{}{
|
||||
map[string]interface{}{
|
||||
"id": 1,
|
||||
"title": "Test Panel",
|
||||
"type": "timeseries",
|
||||
"targets": []interface{}{
|
||||
map[string]interface{}{
|
||||
// Datasource with UID only - type needs to be looked up
|
||||
"datasource": map[string]interface{}{
|
||||
"uid": "ds1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// Library panel reference - triggers library element provider lookup
|
||||
map[string]interface{}{
|
||||
"id": 2,
|
||||
"title": "Library Panel with Vertical Repeat",
|
||||
"type": "library-panel-ref",
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 4,
|
||||
"w": 6,
|
||||
"x": 0,
|
||||
"y": 8,
|
||||
},
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": "lib-panel-repeat-v",
|
||||
"name": "Library Panel with Vertical Repeat",
|
||||
},
|
||||
},
|
||||
// Another library panel reference
|
||||
map[string]interface{}{
|
||||
"id": 3,
|
||||
"title": "Library Panel without Repeat",
|
||||
"type": "library-panel-ref",
|
||||
"gridPos": map[string]interface{}{
|
||||
"h": 3,
|
||||
"w": 6,
|
||||
"x": 6,
|
||||
"y": 8,
|
||||
},
|
||||
"libraryPanel": map[string]interface{}{
|
||||
"uid": "lib-panel-no-repeat",
|
||||
"name": "Library Panel without Repeat",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// TestConversionCaching_V0_to_V2alpha1 verifies caching works when converting V0 to V2alpha1
|
||||
func TestConversionCaching_V0_to_V2alpha1(t *testing.T) {
|
||||
datasources := []schemaversion.DataSourceInfo{
|
||||
{UID: "ds1", Type: "prometheus", Name: "Prometheus", Default: true},
|
||||
}
|
||||
elements := []schemaversion.LibraryElementInfo{
|
||||
{UID: "lib-panel-repeat-h", Name: "Library Panel with Horizontal Repeat", Type: "timeseries"},
|
||||
{UID: "lib-panel-no-repeat", Name: "Library Panel without Repeat", Type: "graph"},
|
||||
}
|
||||
|
||||
underlyingDS := newCountingDataSourceProvider(datasources)
|
||||
underlyingLE := newCountingLibraryElementProvider(elements)
|
||||
|
||||
cachedDS := schemaversion.WrapIndexProviderWithCache(underlyingDS, time.Minute)
|
||||
cachedLE := schemaversion.WrapLibraryElementProviderWithCache(underlyingLE, time.Minute)
|
||||
|
||||
migration.ResetForTesting()
|
||||
migration.Initialize(cachedDS, cachedLE, migration.DefaultCacheTTL)
|
||||
|
||||
// Convert multiple dashboards in the same namespace
|
||||
numDashboards := 5
|
||||
namespace := "default"
|
||||
|
||||
for i := 0; i < numDashboards; i++ {
|
||||
source := createTestV0Dashboard(namespace, "Dashboard "+string(rune('A'+i)))
|
||||
target := &dashv2alpha1.Dashboard{}
|
||||
|
||||
err := Convert_V0_to_V2alpha1(source, target, nil, cachedDS, cachedLE)
|
||||
require.NoError(t, err, "conversion %d should succeed", i)
|
||||
require.NotNil(t, target.Spec)
|
||||
}
|
||||
|
||||
// With caching, the underlying datasource provider should only be called once per namespace
|
||||
// The test dashboard has datasources without type that require lookup
|
||||
assert.Equal(t, int64(1), underlyingDS.getCallCount(),
|
||||
"datasource provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
// Library element provider should also be called only once per namespace due to caching
|
||||
assert.Equal(t, int64(1), underlyingLE.getCallCount(),
|
||||
"library element provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
}
|
||||
|
||||
// TestConversionCaching_V0_to_V2beta1 verifies caching works when converting V0 to V2beta1
|
||||
func TestConversionCaching_V0_to_V2beta1(t *testing.T) {
|
||||
datasources := []schemaversion.DataSourceInfo{
|
||||
{UID: "ds1", Type: "prometheus", Name: "Prometheus", Default: true},
|
||||
}
|
||||
elements := []schemaversion.LibraryElementInfo{
|
||||
{UID: "lib-panel-repeat-h", Name: "Library Panel with Horizontal Repeat", Type: "timeseries"},
|
||||
{UID: "lib-panel-no-repeat", Name: "Library Panel without Repeat", Type: "graph"},
|
||||
}
|
||||
|
||||
underlyingDS := newCountingDataSourceProvider(datasources)
|
||||
underlyingLE := newCountingLibraryElementProvider(elements)
|
||||
|
||||
cachedDS := schemaversion.WrapIndexProviderWithCache(underlyingDS, time.Minute)
|
||||
cachedLE := schemaversion.WrapLibraryElementProviderWithCache(underlyingLE, time.Minute)
|
||||
|
||||
migration.ResetForTesting()
|
||||
migration.Initialize(cachedDS, cachedLE, migration.DefaultCacheTTL)
|
||||
|
||||
numDashboards := 5
|
||||
namespace := "default"
|
||||
|
||||
for i := 0; i < numDashboards; i++ {
|
||||
source := createTestV0Dashboard(namespace, "Dashboard "+string(rune('A'+i)))
|
||||
target := &dashv2beta1.Dashboard{}
|
||||
|
||||
err := Convert_V0_to_V2beta1(source, target, nil, cachedDS, cachedLE)
|
||||
require.NoError(t, err, "conversion %d should succeed", i)
|
||||
require.NotNil(t, target.Spec)
|
||||
}
|
||||
|
||||
assert.Equal(t, int64(1), underlyingDS.getCallCount(),
|
||||
"datasource provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
assert.Equal(t, int64(1), underlyingLE.getCallCount(),
|
||||
"library element provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
}
|
||||
|
||||
// TestConversionCaching_V1beta1_to_V2alpha1 verifies caching works when converting V1beta1 to V2alpha1
|
||||
func TestConversionCaching_V1beta1_to_V2alpha1(t *testing.T) {
|
||||
datasources := []schemaversion.DataSourceInfo{
|
||||
{UID: "ds1", Type: "prometheus", Name: "Prometheus", Default: true},
|
||||
}
|
||||
elements := []schemaversion.LibraryElementInfo{
|
||||
{UID: "lib-panel-repeat-v", Name: "Library Panel with Vertical Repeat", Type: "timeseries"},
|
||||
{UID: "lib-panel-no-repeat", Name: "Library Panel without Repeat", Type: "graph"},
|
||||
}
|
||||
|
||||
underlyingDS := newCountingDataSourceProvider(datasources)
|
||||
underlyingLE := newCountingLibraryElementProvider(elements)
|
||||
|
||||
cachedDS := schemaversion.WrapIndexProviderWithCache(underlyingDS, time.Minute)
|
||||
cachedLE := schemaversion.WrapLibraryElementProviderWithCache(underlyingLE, time.Minute)
|
||||
|
||||
migration.ResetForTesting()
|
||||
migration.Initialize(cachedDS, cachedLE, migration.DefaultCacheTTL)
|
||||
|
||||
numDashboards := 5
|
||||
namespace := "default"
|
||||
|
||||
for i := 0; i < numDashboards; i++ {
|
||||
source := createTestV1Dashboard(namespace, "Dashboard "+string(rune('A'+i)))
|
||||
target := &dashv2alpha1.Dashboard{}
|
||||
|
||||
err := Convert_V1beta1_to_V2alpha1(source, target, nil, cachedDS, cachedLE)
|
||||
require.NoError(t, err, "conversion %d should succeed", i)
|
||||
require.NotNil(t, target.Spec)
|
||||
}
|
||||
|
||||
assert.Equal(t, int64(1), underlyingDS.getCallCount(),
|
||||
"datasource provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
assert.Equal(t, int64(1), underlyingLE.getCallCount(),
|
||||
"library element provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
}
|
||||
|
||||
// TestConversionCaching_V1beta1_to_V2beta1 verifies caching works when converting V1beta1 to V2beta1
|
||||
func TestConversionCaching_V1beta1_to_V2beta1(t *testing.T) {
|
||||
datasources := []schemaversion.DataSourceInfo{
|
||||
{UID: "ds1", Type: "prometheus", Name: "Prometheus", Default: true},
|
||||
}
|
||||
elements := []schemaversion.LibraryElementInfo{
|
||||
{UID: "lib-panel-repeat-v", Name: "Library Panel with Vertical Repeat", Type: "timeseries"},
|
||||
{UID: "lib-panel-no-repeat", Name: "Library Panel without Repeat", Type: "graph"},
|
||||
}
|
||||
|
||||
underlyingDS := newCountingDataSourceProvider(datasources)
|
||||
underlyingLE := newCountingLibraryElementProvider(elements)
|
||||
|
||||
cachedDS := schemaversion.WrapIndexProviderWithCache(underlyingDS, time.Minute)
|
||||
cachedLE := schemaversion.WrapLibraryElementProviderWithCache(underlyingLE, time.Minute)
|
||||
|
||||
migration.ResetForTesting()
|
||||
migration.Initialize(cachedDS, cachedLE, migration.DefaultCacheTTL)
|
||||
|
||||
numDashboards := 5
|
||||
namespace := "default"
|
||||
|
||||
for i := 0; i < numDashboards; i++ {
|
||||
source := createTestV1Dashboard(namespace, "Dashboard "+string(rune('A'+i)))
|
||||
target := &dashv2beta1.Dashboard{}
|
||||
|
||||
err := Convert_V1beta1_to_V2beta1(source, target, nil, cachedDS, cachedLE)
|
||||
require.NoError(t, err, "conversion %d should succeed", i)
|
||||
require.NotNil(t, target.Spec)
|
||||
}
|
||||
|
||||
assert.Equal(t, int64(1), underlyingDS.getCallCount(),
|
||||
"datasource provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
assert.Equal(t, int64(1), underlyingLE.getCallCount(),
|
||||
"library element provider should be called only once for %d conversions in same namespace", numDashboards)
|
||||
}
|
||||
|
||||
// TestConversionCaching_MultipleNamespaces verifies that different namespaces get separate cache entries
|
||||
func TestConversionCaching_MultipleNamespaces(t *testing.T) {
|
||||
datasources := []schemaversion.DataSourceInfo{
|
||||
{UID: "ds1", Type: "prometheus", Name: "Prometheus", Default: true},
|
||||
}
|
||||
elements := []schemaversion.LibraryElementInfo{
|
||||
{UID: "lib-panel-repeat-h", Name: "Library Panel with Horizontal Repeat", Type: "timeseries"},
|
||||
{UID: "lib-panel-no-repeat", Name: "Library Panel without Repeat", Type: "graph"},
|
||||
}
|
||||
|
||||
underlyingDS := newCountingDataSourceProvider(datasources)
|
||||
underlyingLE := newCountingLibraryElementProvider(elements)
|
||||
|
||||
cachedDS := schemaversion.WrapIndexProviderWithCache(underlyingDS, time.Minute)
|
||||
cachedLE := schemaversion.WrapLibraryElementProviderWithCache(underlyingLE, time.Minute)
|
||||
|
||||
migration.ResetForTesting()
|
||||
migration.Initialize(cachedDS, cachedLE, migration.DefaultCacheTTL)
|
||||
|
||||
namespaces := []string{"default", "org-2", "org-3"}
|
||||
numDashboardsPerNs := 3
|
||||
|
||||
for _, ns := range namespaces {
|
||||
for i := 0; i < numDashboardsPerNs; i++ {
|
||||
source := createTestV0Dashboard(ns, "Dashboard "+string(rune('A'+i)))
|
||||
target := &dashv2alpha1.Dashboard{}
|
||||
|
||||
err := Convert_V0_to_V2alpha1(source, target, nil, cachedDS, cachedLE)
|
||||
require.NoError(t, err, "conversion for namespace %s should succeed", ns)
|
||||
}
|
||||
}
|
||||
|
||||
// With caching, each namespace should result in one call to the underlying provider
|
||||
expectedCalls := int64(len(namespaces))
|
||||
assert.Equal(t, expectedCalls, underlyingDS.getCallCount(),
|
||||
"datasource provider should be called once per namespace (%d namespaces)", len(namespaces))
|
||||
assert.Equal(t, expectedCalls, underlyingLE.getCallCount(),
|
||||
"library element provider should be called once per namespace (%d namespaces)", len(namespaces))
|
||||
}
|
||||
|
||||
// TestConversionCaching_CacheDisabled verifies that TTL=0 disables caching
|
||||
func TestConversionCaching_CacheDisabled(t *testing.T) {
|
||||
datasources := []schemaversion.DataSourceInfo{
|
||||
{UID: "ds1", Type: "prometheus", Name: "Prometheus", Default: true},
|
||||
}
|
||||
elements := []schemaversion.LibraryElementInfo{
|
||||
{UID: "lib-panel-repeat-h", Name: "Library Panel with Horizontal Repeat", Type: "timeseries"},
|
||||
{UID: "lib-panel-no-repeat", Name: "Library Panel without Repeat", Type: "graph"},
|
||||
}
|
||||
|
||||
underlyingDS := newCountingDataSourceProvider(datasources)
|
||||
underlyingLE := newCountingLibraryElementProvider(elements)
|
||||
|
||||
// TTL of 0 should disable caching - the wrapper returns the underlying provider directly
|
||||
cachedDS := schemaversion.WrapIndexProviderWithCache(underlyingDS, 0)
|
||||
cachedLE := schemaversion.WrapLibraryElementProviderWithCache(underlyingLE, 0)
|
||||
|
||||
migration.ResetForTesting()
|
||||
migration.Initialize(cachedDS, cachedLE, migration.DefaultCacheTTL)
|
||||
|
||||
numDashboards := 3
|
||||
namespace := "default"
|
||||
|
||||
for i := 0; i < numDashboards; i++ {
|
||||
source := createTestV0Dashboard(namespace, "Dashboard "+string(rune('A'+i)))
|
||||
target := &dashv2alpha1.Dashboard{}
|
||||
|
||||
err := Convert_V0_to_V2alpha1(source, target, nil, cachedDS, cachedLE)
|
||||
require.NoError(t, err, "conversion %d should succeed", i)
|
||||
}
|
||||
|
||||
// Without caching, each conversion calls the underlying provider multiple times
|
||||
// (once for each datasource lookup needed - variables and panels)
|
||||
// The key check is that the count is GREATER than 1 per conversion (no caching benefit)
|
||||
assert.Greater(t, underlyingDS.getCallCount(), int64(numDashboards),
|
||||
"with cache disabled, conversions should call datasource provider multiple times")
|
||||
// Library element provider is also called for each conversion without caching
|
||||
assert.GreaterOrEqual(t, underlyingLE.getCallCount(), int64(numDashboards),
|
||||
"with cache disabled, conversions should call library element provider multiple times")
|
||||
}
|
||||
@@ -829,7 +829,7 @@ func TestDataLossDetectionOnAllInputFiles(t *testing.T) {
|
||||
// Initialize the migrator with a test data source provider
|
||||
dsProvider := testutil.NewDataSourceProvider(testutil.StandardTestConfig)
|
||||
leProvider := testutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
|
||||
@@ -35,7 +35,7 @@ func TestConversionMatrixExist(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
versions := []metav1.Object{
|
||||
&dashv0.Dashboard{Spec: common.Unstructured{Object: map[string]any{"title": "dashboardV0"}}},
|
||||
@@ -89,7 +89,7 @@ func TestDashboardConversionToAllVersions(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
@@ -309,7 +309,7 @@ func TestMigratedDashboardsConversion(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
@@ -428,7 +428,7 @@ func setupTestConversionScheme(t *testing.T) *runtime.Scheme {
|
||||
t.Helper()
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := RegisterConversions(scheme, dsProvider, leProvider)
|
||||
@@ -527,7 +527,7 @@ func TestConversionMetrics(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
// Create a test registry for metrics
|
||||
registry := prometheus.NewRegistry()
|
||||
@@ -694,7 +694,7 @@ func TestConversionMetricsWrapper(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
// Create a test registry for metrics
|
||||
registry := prometheus.NewRegistry()
|
||||
@@ -864,7 +864,7 @@ func TestSchemaVersionExtraction(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
// Create a test registry for metrics
|
||||
registry := prometheus.NewRegistry()
|
||||
@@ -910,7 +910,7 @@ func TestConversionLogging(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
// Create a test registry for metrics
|
||||
registry := prometheus.NewRegistry()
|
||||
@@ -1003,7 +1003,7 @@ func TestConversionLogLevels(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
t.Run("log levels and structured fields verification", func(t *testing.T) {
|
||||
// Create test wrapper to verify logging behavior
|
||||
@@ -1076,7 +1076,7 @@ func TestConversionLoggingFields(t *testing.T) {
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
// Use TestLibraryElementProvider for tests that need library panel models with repeat options
|
||||
leProvider := migrationtestutil.NewTestLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
t.Run("verify all log fields are present", func(t *testing.T) {
|
||||
// Test that the conversion wrapper includes all expected structured fields
|
||||
|
||||
@@ -20,7 +20,7 @@ func TestV0ConversionErrorHandling(t *testing.T) {
|
||||
// Initialize the migrator with a test data source provider
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -132,7 +132,7 @@ func TestV0ConversionErrorPropagation(t *testing.T) {
|
||||
// Initialize the migrator with a test data source provider
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
t.Run("ConvertDashboard_V0_to_V1beta1 returns error on migration failure", func(t *testing.T) {
|
||||
source := &dashv0.Dashboard{
|
||||
@@ -206,7 +206,7 @@ func TestV0ConversionSuccessPaths(t *testing.T) {
|
||||
// Initialize the migrator with a test data source provider
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
t.Run("Convert_V0_to_V1beta1 success path returns nil", func(t *testing.T) {
|
||||
source := &dashv0.Dashboard{
|
||||
@@ -275,7 +275,7 @@ func TestV0ConversionSecondStepErrors(t *testing.T) {
|
||||
// Initialize the migrator with a test data source provider
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
t.Run("Convert_V0_to_V2alpha1 sets status on first step error", func(t *testing.T) {
|
||||
// Create a dashboard that will fail v0->v1beta1 conversion
|
||||
|
||||
@@ -19,7 +19,7 @@ func TestV1ConversionErrorHandling(t *testing.T) {
|
||||
// Initialize the migrator with a test data source provider
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
t.Run("Convert_V1beta1_to_V2alpha1 sets status on conversion error", func(t *testing.T) {
|
||||
// Create a dashboard that will cause conversion to fail
|
||||
|
||||
@@ -19,7 +19,7 @@ func TestV1beta1ToV2alpha1(t *testing.T) {
|
||||
// Initialize the migrator with test providers
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
|
||||
@@ -18,7 +18,7 @@ func TestV2alpha1ConversionErrorHandling(t *testing.T) {
|
||||
// Initialize the migrator with test data source and library element providers
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
t.Run("Convert_V2alpha1_to_V1beta1 sets status on conversion", func(t *testing.T) {
|
||||
// Create a dashboard for conversion
|
||||
@@ -90,7 +90,7 @@ func TestV2beta1ConversionErrorHandling(t *testing.T) {
|
||||
// Initialize the migrator with test data source and library element providers
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
t.Run("Convert_V2beta1_to_V1beta1 sets status on first step failure", func(t *testing.T) {
|
||||
// Create a dashboard that might cause conversion to fail on first step (v2beta1 -> v2alpha1)
|
||||
|
||||
@@ -282,7 +282,7 @@ func TestV2alpha1ToV1beta1LayoutErrors(t *testing.T) {
|
||||
// Initialize the migrator with test data source and library element providers
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
@@ -498,7 +498,7 @@ func TestV2alpha1ToV1beta1BasicFields(t *testing.T) {
|
||||
// Initialize the migrator with test data source and library element providers
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
|
||||
@@ -18,7 +18,7 @@ func TestV2alpha1ToV2beta1(t *testing.T) {
|
||||
// Initialize the migrator with test providers
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
|
||||
@@ -24,7 +24,7 @@ func TestV2beta1ToV2alpha1RoundTrip(t *testing.T) {
|
||||
// Initialize the migrator with test providers
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
@@ -107,7 +107,7 @@ func TestV2beta1ToV2alpha1FromOutputFiles(t *testing.T) {
|
||||
// Initialize the migrator with test providers
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
@@ -193,7 +193,7 @@ func TestV2beta1ToV2alpha1(t *testing.T) {
|
||||
// Initialize the migrator with test providers
|
||||
dsProvider := migrationtestutil.NewDataSourceProvider(migrationtestutil.StandardTestConfig)
|
||||
leProvider := migrationtestutil.NewLibraryElementProvider()
|
||||
migration.Initialize(dsProvider, leProvider)
|
||||
migration.Initialize(dsProvider, leProvider, migration.DefaultCacheTTL)
|
||||
|
||||
// Set up conversion scheme
|
||||
scheme := runtime.NewScheme()
|
||||
|
||||
Reference in New Issue
Block a user