From 8b60729052f41d64c4b4a10841028d94d750d0e6 Mon Sep 17 00:00:00 2001 From: Rafael Paulovic Date: Thu, 4 Dec 2025 17:02:04 +0100 Subject: [PATCH 1/2] chore: uncomment unified migration --- pkg/infra/metrics/metrics.go | 2 +- pkg/setting/setting_unified_storage.go | 5 ++--- pkg/storage/unified/migrations/service.go | 11 +++-------- pkg/tests/testinfra/testinfra.go | 2 +- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/pkg/infra/metrics/metrics.go b/pkg/infra/metrics/metrics.go index c1995545df8..19113ed3b1f 100644 --- a/pkg/infra/metrics/metrics.go +++ b/pkg/infra/metrics/metrics.go @@ -224,7 +224,7 @@ var ( MStatTotalRepositories prometheus.Gauge // MUnifiedStorageMigrationStatus indicates the migration status for unified storage in this instance. - // Possible values: 0 (default/undefined), 1 (migration disabled), 2 (migration would run). + // Possible values: 0 (default/undefined), 1 (migration disabled), 2 (migration would run), 3 (migration will run). MUnifiedStorageMigrationStatus prometheus.Gauge ) diff --git a/pkg/setting/setting_unified_storage.go b/pkg/setting/setting_unified_storage.go index 4f69daa64fd..589e5f66254 100644 --- a/pkg/setting/setting_unified_storage.go +++ b/pkg/setting/setting_unified_storage.go @@ -61,8 +61,8 @@ func (cfg *Cfg) setUnifiedStorageConfig() { cfg.DisableDataMigrations = section.Key("disable_data_migrations").MustBool(false) if !cfg.DisableDataMigrations && cfg.getUnifiedStorageType() == "unified" { // Helper log to find instances running migrations in the future - cfg.Logger.Info("Unified migration configs not yet enforced") - // cfg.enforceMigrationToUnifiedConfigs() // TODO: uncomment when ready for release + cfg.Logger.Info("Unified migration configs enforced") + cfg.enforceMigrationToUnifiedConfigs() } else { // Helper log to find instances disabling migration cfg.Logger.Info("Unified migration configs enforcement disabled", "storage_type", cfg.getUnifiedStorageType(), "disable_data_migrations", cfg.DisableDataMigrations) @@ -104,7 +104,6 @@ func (cfg *Cfg) setUnifiedStorageConfig() { cfg.MinFileIndexBuildVersion = section.Key("min_file_index_build_version").MustString("") } -// nolint:unused // enforceMigrationToUnifiedConfigs enforces configurations required to run migrated resources in mode 5 // All migrated resources in MigratedUnifiedResources are set to mode 5 and unified search is enabled func (cfg *Cfg) enforceMigrationToUnifiedConfigs() { diff --git a/pkg/storage/unified/migrations/service.go b/pkg/storage/unified/migrations/service.go index 1fda9b42593..d08aba36022 100644 --- a/pkg/storage/unified/migrations/service.go +++ b/pkg/storage/unified/migrations/service.go @@ -59,15 +59,10 @@ func (p *UnifiedStorageMigrationServiceImpl) Run(ctx context.Context) error { metrics.MUnifiedStorageMigrationStatus.Set(1) logger.Info("Data migrations are disabled, skipping") return nil - } else { - metrics.MUnifiedStorageMigrationStatus.Set(2) - logger.Info("Data migrations not yet enforced, skipping") } - - // TODO: Re-enable once migrations are ready - // TODO: add guarantee that this only runs once - // return RegisterMigrations(p.migrator, p.cfg, p.sqlStore, p.client) - return nil + logger.Info("Running migrations for unified storage") + metrics.MUnifiedStorageMigrationStatus.Set(3) + return RegisterMigrations(p.migrator, p.cfg, p.sqlStore, p.client) } func RegisterMigrations( diff --git a/pkg/tests/testinfra/testinfra.go b/pkg/tests/testinfra/testinfra.go index e9795f945ab..b372036760c 100644 --- a/pkg/tests/testinfra/testinfra.go +++ b/pkg/tests/testinfra/testinfra.go @@ -609,7 +609,7 @@ func CreateGrafDir(t *testing.T, opts GrafanaOpts) (string, string) { require.NoError(t, err) _, err = dbSection.NewKey("query_retries", fmt.Sprintf("%d", queryRetries)) require.NoError(t, err) - _, err = dbSection.NewKey("max_open_conn", "2") + _, err = dbSection.NewKey("max_open_conn", "3") require.NoError(t, err) _, err = dbSection.NewKey("max_idle_conn", "2") require.NoError(t, err) From 0b3f03e99a2be86e216e51935b998a2822d71d1a Mon Sep 17 00:00:00 2001 From: Rafael Paulovic Date: Fri, 5 Dec 2025 20:34:02 +0100 Subject: [PATCH 2/2] chore: adapt and fix tests --- pkg/setting/setting_unified_storage_test.go | 22 +- pkg/storage/unified/migrations/service.go | 8 +- .../alerting/api_convert_prometheus_test.go | 11 +- .../api/alerting/api_provisioning_test.go | 9 +- pkg/tests/api/alerting/api_ruler_test.go | 27 +-- pkg/tests/api/annotations/annotations_test.go | 5 +- .../api/dashboards/api_dashboards_test.go | 84 +++++--- pkg/tests/apis/collections/stars_test.go | 7 +- pkg/tests/apis/dashboard/dashboards_test.go | 14 +- .../integration/api_validation_test.go | 12 +- .../library_panels_api_validation_test.go | 9 +- pkg/tests/apis/dashboard/search_test.go | 7 +- pkg/tests/apis/folder/folder_tree_test.go | 7 +- pkg/tests/apis/folder/folders_test.go | 121 ++++++----- .../playlist.grafana.app-v0alpha1.json | 28 ++- pkg/tests/apis/playlist/playlist_test.go | 190 ++++++++++-------- pkg/tests/testinfra/testinfra.go | 8 + 17 files changed, 347 insertions(+), 222 deletions(-) diff --git a/pkg/setting/setting_unified_storage_test.go b/pkg/setting/setting_unified_storage_test.go index 094033a4244..f42535711f4 100644 --- a/pkg/setting/setting_unified_storage_test.go +++ b/pkg/setting/setting_unified_storage_test.go @@ -13,7 +13,16 @@ func TestCfg_setUnifiedStorageConfig(t *testing.T) { err := cfg.Load(CommandLineArgs{HomePath: "../../", Config: "../../conf/defaults.ini"}) assert.NoError(t, err) - s, err := cfg.Raw.NewSection("unified_storage.playlists.playlist.grafana.app") + // Validate that migrated resources are enforced to mode 5 + for _, migratedResource := range MigratedUnifiedResources { + sectionName := "unified_storage." + migratedResource + section, err := cfg.Raw.NewSection(sectionName) + assert.NoError(t, err) + _, err = section.NewKey("dualWriterMode", "0") // will be changed to 5 in setUnifiedStorageConfig + assert.NoError(t, err) + } + + s, err := cfg.Raw.NewSection("unified_storage.resource.not_migrated.grafana.app") assert.NoError(t, err) _, err = s.NewKey("dualWriterMode", "2") @@ -37,7 +46,7 @@ func TestCfg_setUnifiedStorageConfig(t *testing.T) { cfg.setUnifiedStorageConfig() - value, exists := cfg.UnifiedStorage["playlists.playlist.grafana.app"] + value, exists := cfg.UnifiedStorage["resource.not_migrated.grafana.app"] assert.Equal(t, exists, true) assert.Equal(t, value, UnifiedStorageConfig{ @@ -47,6 +56,15 @@ func TestCfg_setUnifiedStorageConfig(t *testing.T) { DataSyncerInterval: time.Minute * 10, }) + for _, migratedResource := range MigratedUnifiedResources { + value, exists := cfg.UnifiedStorage[migratedResource] + assert.Equal(t, exists, true) + assert.Equal(t, value, UnifiedStorageConfig{ + DualWriterMode: 5, + DualWriterMigrationDataSyncDisabled: true, + }) + } + // Test that index settings are correctly parsed assert.Equal(t, 5, cfg.IndexMinCount) }) diff --git a/pkg/storage/unified/migrations/service.go b/pkg/storage/unified/migrations/service.go index d08aba36022..404c71a6d14 100644 --- a/pkg/storage/unified/migrations/service.go +++ b/pkg/storage/unified/migrations/service.go @@ -3,7 +3,6 @@ package migrations import ( "context" "fmt" - "os" "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/kvstore" @@ -48,12 +47,7 @@ func ProvideUnifiedStorageMigrationService( } } -func (p *UnifiedStorageMigrationServiceImpl) Run(ctx context.Context) error { - // TODO: temporary skip migrations in test environments to prevent integration test timeouts. - if os.Getenv("GRAFANA_TEST_DB") != "" { - return nil - } - +func (p *UnifiedStorageMigrationServiceImpl) Run(_ context.Context) error { // skip migrations if disabled in config if p.cfg.DisableDataMigrations { metrics.MUnifiedStorageMigrationStatus.Set(1) diff --git a/pkg/tests/api/alerting/api_convert_prometheus_test.go b/pkg/tests/api/alerting/api_convert_prometheus_test.go index 4fc9151602f..f33ce55d851 100644 --- a/pkg/tests/api/alerting/api_convert_prometheus_test.go +++ b/pkg/tests/api/alerting/api_convert_prometheus_test.go @@ -1166,11 +1166,12 @@ func TestIntegrationConvertPrometheusEndpoints_Editor(t *testing.T) { testinfra.SQLiteIntegrationTest(t) dir, gpath := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ - DisableLegacyAlerting: true, - EnableUnifiedAlerting: true, - DisableAnonymous: true, - AppModeProduction: true, - EnableRecordingRules: true, + DisableAuthZClientCache: true, + DisableLegacyAlerting: true, + EnableUnifiedAlerting: true, + DisableAnonymous: true, + AppModeProduction: true, + EnableRecordingRules: true, }) grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, gpath) diff --git a/pkg/tests/api/alerting/api_provisioning_test.go b/pkg/tests/api/alerting/api_provisioning_test.go index 20484a38bf4..e952740f2e6 100644 --- a/pkg/tests/api/alerting/api_provisioning_test.go +++ b/pkg/tests/api/alerting/api_provisioning_test.go @@ -1192,10 +1192,11 @@ func TestIntegrationExportFileProvisionContactPoints(t *testing.T) { func TestIntegrationFullpath(t *testing.T) { dir, p := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ - DisableLegacyAlerting: true, - EnableUnifiedAlerting: true, - DisableAnonymous: true, - AppModeProduction: true, + DisableAuthZClientCache: true, + DisableLegacyAlerting: true, + EnableUnifiedAlerting: true, + DisableAnonymous: true, + AppModeProduction: true, }) grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, p) diff --git a/pkg/tests/api/alerting/api_ruler_test.go b/pkg/tests/api/alerting/api_ruler_test.go index 9e8855d8f19..a05829976f4 100644 --- a/pkg/tests/api/alerting/api_ruler_test.go +++ b/pkg/tests/api/alerting/api_ruler_test.go @@ -53,10 +53,11 @@ func TestIntegrationAlertRulePermissions(t *testing.T) { testinfra.SQLiteIntegrationTest(t) dir, p := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ - DisableLegacyAlerting: true, - EnableUnifiedAlerting: true, - DisableAnonymous: true, - AppModeProduction: true, + DisableAuthZClientCache: true, + DisableLegacyAlerting: true, + EnableUnifiedAlerting: true, + DisableAnonymous: true, + AppModeProduction: true, }) grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, p) @@ -360,10 +361,11 @@ func TestIntegrationAlertRuleNestedPermissions(t *testing.T) { testinfra.SQLiteIntegrationTest(t) dir, p := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ - DisableLegacyAlerting: true, - EnableUnifiedAlerting: true, - DisableAnonymous: true, - AppModeProduction: true, + DisableAuthZClientCache: true, + DisableLegacyAlerting: true, + EnableUnifiedAlerting: true, + DisableAnonymous: true, + AppModeProduction: true, }) grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, p) @@ -1429,10 +1431,11 @@ func TestIntegrationRuleGroupSequence(t *testing.T) { testinfra.SQLiteIntegrationTest(t) dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ - DisableLegacyAlerting: true, - EnableUnifiedAlerting: true, - DisableAnonymous: true, - AppModeProduction: true, + DisableAuthZClientCache: true, + DisableLegacyAlerting: true, + EnableUnifiedAlerting: true, + DisableAnonymous: true, + AppModeProduction: true, }) grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path) diff --git a/pkg/tests/api/annotations/annotations_test.go b/pkg/tests/api/annotations/annotations_test.go index 89e7131d4b5..6391d37d762 100644 --- a/pkg/tests/api/annotations/annotations_test.go +++ b/pkg/tests/api/annotations/annotations_test.go @@ -32,8 +32,9 @@ func TestIntegrationAnnotations(t *testing.T) { testutil.SkipIntegrationTestInShortMode(t) dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ - DisableAnonymous: true, - EnableFeatureToggles: []string{featuremgmt.FlagAnnotationPermissionUpdate}, + DisableAuthZClientCache: true, + DisableAnonymous: true, + EnableFeatureToggles: []string{featuremgmt.FlagAnnotationPermissionUpdate}, }) grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path) noneUserID := tests.CreateUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{ diff --git a/pkg/tests/api/dashboards/api_dashboards_test.go b/pkg/tests/api/dashboards/api_dashboards_test.go index fcfb09cb5ba..f4e30f8a142 100644 --- a/pkg/tests/api/dashboards/api_dashboards_test.go +++ b/pkg/tests/api/dashboards/api_dashboards_test.go @@ -218,11 +218,12 @@ func TestIntegrationDashboardServiceValidation(t *testing.T) { require.NoError(t, err) }) - t.Run("When updating uid with id", func(t *testing.T) { + dashboardWithDuplicatedLegacyAnnotation := "new-uid" + t.Run("When saving a dashboard with an already used legacy ID", func(t *testing.T) { resp, err := postDashboard(t, grafanaListedAddr, "admin", "admin", map[string]interface{}{ "dashboard": map[string]interface{}{ "id": savedDashInFolder.ID, // nolint:staticcheck - "uid": "new-uid", + "uid": dashboardWithDuplicatedLegacyAnnotation, "title": "Updated title", }, "folderUid": savedDashInFolder.FolderUID, @@ -234,7 +235,7 @@ func TestIntegrationDashboardServiceValidation(t *testing.T) { require.NoError(t, err) }) - t.Run("When updating uid with a dashboard already using that uid", func(t *testing.T) { + t.Run("When updating a dashboard with legacy ID in multiple dashboards", func(t *testing.T) { resp, err := postDashboard(t, grafanaListedAddr, "admin", "admin", map[string]interface{}{ "dashboard": map[string]interface{}{ "id": savedDashInFolder.ID, // nolint:staticcheck @@ -245,6 +246,46 @@ func TestIntegrationDashboardServiceValidation(t *testing.T) { "overwrite": true, }) require.NoError(t, err) + assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) + err = resp.Body.Close() + require.NoError(t, err) + // Delete the dashboard with duplicated legacy ID annotation + u := fmt.Sprintf("http://admin:admin@%s/api/dashboards/uid/%s", grafanaListedAddr, dashboardWithDuplicatedLegacyAnnotation) + req, err := http.NewRequest("DELETE", u, nil) + require.NoError(t, err) + resp, err = http.DefaultClient.Do(req) + require.NoError(t, err) + err = resp.Body.Close() + require.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + }) + + t.Run("When updating a dashboard already using that uid", func(t *testing.T) { + resp, err := postDashboard(t, grafanaListedAddr, "admin", "admin", map[string]interface{}{ + "dashboard": map[string]interface{}{ + "id": savedDashInFolder.ID, + "uid": savedDashInFolder.UID, + "title": "Dashboard with ", + }, + "folderUid": savedDashInFolder.FolderUID, + "overwrite": true, + }) + require.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + err = resp.Body.Close() + require.NoError(t, err) + + t.Run("When updating id with a dashboard already using that uid", func(t *testing.T) {}) + resp, err = postDashboard(t, grafanaListedAddr, "admin", "admin", map[string]interface{}{ + "dashboard": map[string]interface{}{ + "id": savedDashInFolder.ID, // nolint:staticcheck + "uid": savedDashInGeneralFolder.UID, + "title": "Updated title", + }, + "folderUid": savedDashInFolder.FolderUID, + "overwrite": true, + }) + require.NoError(t, err) assert.Equal(t, http.StatusBadRequest, resp.StatusCode) err = resp.Body.Close() require.NoError(t, err) @@ -268,8 +309,9 @@ func TestIntegrationDashboardServiceValidation(t *testing.T) { require.NoError(t, err) }) + // Obs: in legacy, the dashboard request would fail + // After the dashboard is created, the user can see that there is an error with the library panel and can remove them manually t.Run("When creating a dashboard that references a non-existent library panel", func(t *testing.T) { - originalCount := getDashboardCount(t, grafanaListedAddr, "admin", "admin") resp, err := postDashboard(t, grafanaListedAddr, "admin", "admin", map[string]interface{}{ "dashboard": map[string]interface{}{ "title": "Bad dashboard", @@ -285,15 +327,11 @@ func TestIntegrationDashboardServiceValidation(t *testing.T) { }, }) require.NoError(t, err) - assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) - body, err := io.ReadAll(resp.Body) + assert.Equal(t, http.StatusOK, resp.StatusCode) + _, err = io.ReadAll(resp.Body) require.NoError(t, err) - require.Contains(t, string(body), "library element could not be found") err = resp.Body.Close() require.NoError(t, err) - - // A new dashboard is not created in this situation. - require.Equal(t, originalCount, getDashboardCount(t, grafanaListedAddr, "admin", "admin")) }) } @@ -332,7 +370,7 @@ func TestIntegrationDashboardQuota(t *testing.T) { dashboardDTO := &plugindashboards.PluginDashboard{} err = json.Unmarshal(b, dashboardDTO) require.NoError(t, err) - require.EqualValues(t, 1, dashboardDTO.DashboardId) + require.EqualValues(t, "just testing", dashboardDTO.Title) }) t.Run("when quota limit exceeds importing a dashboard should fail", func(t *testing.T) { @@ -421,7 +459,7 @@ providers: dashboardUID = d.UID dashboardID = d.ID // nolint:staticcheck } - assert.Equal(t, int64(1), dashboardID) + assert.Len(t, *dashboardList, 1) testCases := []struct { desc string @@ -781,7 +819,7 @@ func TestIntegrationImportDashboardWithLibraryPanels(t *testing.T) { }, { "id": 2, - "title": "Library Panel 2", + "title": "Library Panel 2", "type": "stat", "gridPos": {"h": 8, "w": 12, "x": 12, "y": 0}, "libraryPanel": { @@ -805,7 +843,7 @@ func TestIntegrationImportDashboardWithLibraryPanels(t *testing.T) { } }, "test-lib-panel-2": { - "uid": "test-lib-panel-2", + "uid": "test-lib-panel-2", "name": "Test Library Panel 2", "kind": 1, "type": "stat", @@ -1011,26 +1049,12 @@ func postDashboard(t *testing.T, grafanaListedAddr, user, password string, paylo return http.Post(u, "application/json", bytes.NewBuffer(payloadBytes)) // nolint:gosec } -func getDashboardCount(t *testing.T, grafanaListenAddr, user, password string) int { - endpoint := fmt.Sprintf("http://%s:%s@%s/apis/dashboard.grafana.app/v0alpha1/namespaces/default/search", user, password, grafanaListenAddr) - resp, err := http.Get(endpoint) //nolint:gosec - require.NoError(t, err) - - body, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.NoError(t, resp.Body.Close()) - - var payload map[string]any - require.NoError(t, json.Unmarshal(body, &payload)) - - return int(payload["totalHits"].(float64)) -} - func TestIntegrationDashboardServicePermissions(t *testing.T) { testutil.SkipIntegrationTestInShortMode(t) dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ - DisableAnonymous: true, + DisableAnonymous: true, + DisableAuthZClientCache: true, }) grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path) tests.CreateUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{ diff --git a/pkg/tests/apis/collections/stars_test.go b/pkg/tests/apis/collections/stars_test.go index fe841fb4851..0def7dbce01 100644 --- a/pkg/tests/apis/collections/stars_test.go +++ b/pkg/tests/apis/collections/stars_test.go @@ -41,9 +41,10 @@ func TestIntegrationStars(t *testing.T) { } helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: false, // required for experimental APIs - DisableAnonymous: true, - EnableFeatureToggles: flags, + DisableDataMigrations: true, + AppModeProduction: false, // required for experimental APIs + DisableAnonymous: true, + EnableFeatureToggles: flags, UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ "dashboards.dashboard.grafana.app": { DualWriterMode: mode, diff --git a/pkg/tests/apis/dashboard/dashboards_test.go b/pkg/tests/apis/dashboard/dashboards_test.go index 85f369c2ac6..cbc8d280134 100644 --- a/pkg/tests/apis/dashboard/dashboards_test.go +++ b/pkg/tests/apis/dashboard/dashboards_test.go @@ -37,7 +37,8 @@ func TestMain(m *testing.M) { func runDashboardTest(t *testing.T, mode rest.DualWriterMode, gvr schema.GroupVersionResource) { t.Run("simple crud+list", func(t *testing.T) { helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - DisableAnonymous: true, + DisableAnonymous: true, + DisableDataMigrations: true, UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ "dashboards.dashboard.grafana.app": { DualWriterMode: mode, @@ -194,7 +195,9 @@ func TestIntegrationLegacySupport(t *testing.T) { testutil.SkipIntegrationTestInShortMode(t) ctx := context.Background() - helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{}) + helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ + DisableDataMigrations: true, + }) clientV0 := helper.GetResourceClient(apis.ResourceClientArgs{ User: helper.Org1.Admin, @@ -307,9 +310,10 @@ func runDashboardSearchTest(t *testing.T, mode rest.DualWriterMode) { ctx := context.Background() helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + AppModeProduction: true, + DisableDataMigrations: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ "dashboards.dashboard.grafana.app": {DualWriterMode: mode}, "folders.folder.grafana.app": {DualWriterMode: mode}, diff --git a/pkg/tests/apis/dashboard/integration/api_validation_test.go b/pkg/tests/apis/dashboard/integration/api_validation_test.go index 9e087cb76a6..36461ea910e 100644 --- a/pkg/tests/apis/dashboard/integration/api_validation_test.go +++ b/pkg/tests/apis/dashboard/integration/api_validation_test.go @@ -68,7 +68,8 @@ func TestIntegrationDashboardAPIValidation(t *testing.T) { t.Run(fmt.Sprintf("DualWriterMode %d", dualWriterMode), func(t *testing.T) { // Create a K8sTestHelper which will set up a real API server helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - DisableAnonymous: true, + DisableDataMigrations: true, + DisableAnonymous: true, EnableFeatureToggles: []string{ featuremgmt.FlagKubernetesDashboards, // Enable FE-only dashboard feature flag }, @@ -105,7 +106,8 @@ func TestIntegrationDashboardAPIValidation(t *testing.T) { t.Run(fmt.Sprintf("DualWriterMode %d - kubernetesDashboards disabled", dualWriterMode), func(t *testing.T) { // Create a K8sTestHelper which will set up a real API server helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - DisableAnonymous: true, + DisableDataMigrations: true, + DisableAnonymous: true, DisableFeatureToggles: []string{ featuremgmt.FlagKubernetesDashboards, }, @@ -138,7 +140,8 @@ func TestIntegrationDashboardAPIAuthorization(t *testing.T) { for _, dualWriterMode := range dualWriterModes { t.Run(fmt.Sprintf("DualWriterMode %d", dualWriterMode), func(t *testing.T) { helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - DisableAnonymous: true, + DisableDataMigrations: true, + DisableAnonymous: true, UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ "dashboards.dashboard.grafana.app": { DualWriterMode: dualWriterMode, @@ -185,7 +188,8 @@ func TestIntegrationDashboardAPI(t *testing.T) { t.Run(fmt.Sprintf("DualWriterMode %d", dualWriterMode), func(t *testing.T) { // Create a K8sTestHelper which will set up a real API server helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - DisableAnonymous: true, + DisableDataMigrations: true, + DisableAnonymous: true, EnableFeatureToggles: []string{ featuremgmt.FlagKubernetesDashboards, }, diff --git a/pkg/tests/apis/dashboard/integration/library_panels_api_validation_test.go b/pkg/tests/apis/dashboard/integration/library_panels_api_validation_test.go index dd85fdb2400..32548d593ea 100644 --- a/pkg/tests/apis/dashboard/integration/library_panels_api_validation_test.go +++ b/pkg/tests/apis/dashboard/integration/library_panels_api_validation_test.go @@ -29,7 +29,8 @@ func TestIntegrationLibraryPanelConnections(t *testing.T) { for _, dualWriterMode := range dualWriterModes { t.Run(fmt.Sprintf("DualWriterMode %d", dualWriterMode), func(t *testing.T) { helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - DisableAnonymous: true, + DisableDataMigrations: true, + DisableAnonymous: true, EnableFeatureToggles: []string{ "kubernetesLibraryPanels", }, @@ -93,7 +94,8 @@ func TestIntegrationLibraryElementPermissions(t *testing.T) { for _, dualWriterMode := range dualWriterModes { t.Run(fmt.Sprintf("DualWriterMode %d", dualWriterMode), func(t *testing.T) { helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - DisableAnonymous: true, + DisableDataMigrations: true, + DisableAnonymous: true, EnableFeatureToggles: []string{ "kubernetesLibraryPanels", "grafanaAPIServerWithExperimentalAPIs", // needed until we move it to v0beta1 at least (currently v0alpha1) @@ -296,7 +298,8 @@ func TestIntegrationLibraryPanelConnectionsWithFolderAccess(t *testing.T) { for _, dualWriterMode := range dualWriterModes { t.Run(fmt.Sprintf("DualWriterMode %d", dualWriterMode), func(t *testing.T) { helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - DisableAnonymous: true, + DisableDataMigrations: true, + DisableAnonymous: true, EnableFeatureToggles: []string{ "kubernetesLibraryPanels", }, diff --git a/pkg/tests/apis/dashboard/search_test.go b/pkg/tests/apis/dashboard/search_test.go index 09d23398c3f..3fe35c51b3a 100644 --- a/pkg/tests/apis/dashboard/search_test.go +++ b/pkg/tests/apis/dashboard/search_test.go @@ -37,9 +37,10 @@ func runSearchPermissionTest(t *testing.T, mode rest.DualWriterMode) { ctx := context.Background() helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ "dashboards.dashboard.grafana.app": {DualWriterMode: mode}, "folders.folder.grafana.app": {DualWriterMode: mode}, diff --git a/pkg/tests/apis/folder/folder_tree_test.go b/pkg/tests/apis/folder/folder_tree_test.go index b1d38ab3918..1b3d5df37f2 100644 --- a/pkg/tests/apis/folder/folder_tree_test.go +++ b/pkg/tests/apis/folder/folder_tree_test.go @@ -48,9 +48,10 @@ func TestIntegrationFolderTree(t *testing.T) { for _, mode := range modes { t.Run(fmt.Sprintf("mode %d", mode), func(t *testing.T) { helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ "dashboards.dashboard.grafana.app": { DualWriterMode: mode, diff --git a/pkg/tests/apis/folder/folders_test.go b/pkg/tests/apis/folder/folders_test.go index 43db6ff0932..c85c8729e9f 100644 --- a/pkg/tests/apis/folder/folders_test.go +++ b/pkg/tests/apis/folder/folders_test.go @@ -139,9 +139,10 @@ func TestIntegrationFoldersApp(t *testing.T) { t.Run(fmt.Sprintf("with dual write (unified storage, mode %v)", modeDw), func(t *testing.T) { doFolderTests(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: modeDw, @@ -153,9 +154,10 @@ func TestIntegrationFoldersApp(t *testing.T) { t.Run(fmt.Sprintf("with dual write (unified storage, mode %v, create nested folders)", modeDw), func(t *testing.T) { doNestedCreateTest(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: modeDw, @@ -166,9 +168,10 @@ func TestIntegrationFoldersApp(t *testing.T) { t.Run(fmt.Sprintf("with dual write (unified storage, mode %v, create existing folder)", modeDw), func(t *testing.T) { doCreateDuplicateFolderTest(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: modeDw, @@ -179,9 +182,10 @@ func TestIntegrationFoldersApp(t *testing.T) { t.Run(fmt.Sprintf("when creating a folder, mode %v, it should trim leading and trailing spaces", modeDw), func(t *testing.T) { doCreateEnsureTitleIsTrimmedTest(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: modeDw, @@ -192,9 +196,10 @@ func TestIntegrationFoldersApp(t *testing.T) { t.Run(fmt.Sprintf("with dual write (unified storage, mode %v, create circular reference folder)", modeDw), func(t *testing.T) { doCreateCircularReferenceFolderTest(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: modeDw, @@ -218,9 +223,10 @@ func TestIntegrationFoldersApp(t *testing.T) { for _, mode := range modes { t.Run(fmt.Sprintf("mode %d", mode), func(t *testing.T) { doListFoldersTest(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: mode, @@ -735,9 +741,10 @@ func TestIntegrationFolderCreatePermissions(t *testing.T) { t.Run(fmt.Sprintf("Mode_%d", mode), func(t *testing.T) { modeDw := grafanarest.DualWriterMode(mode) helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: modeDw, @@ -862,9 +869,10 @@ func TestIntegrationFolderGetPermissions(t *testing.T) { t.Run(fmt.Sprintf("Mode_%d", mode), func(t *testing.T) { modeDw := grafanarest.DualWriterMode(mode) helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: modeDw, @@ -1079,9 +1087,10 @@ func TestIntegrationFoldersCreateAPIEndpointK8S(t *testing.T) { for mode := 0; mode <= 4; mode++ { modeDw := grafanarest.DualWriterMode(mode) helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: modeDw, @@ -1254,9 +1263,10 @@ func TestIntegrationFoldersGetAPIEndpointK8S(t *testing.T) { modeDw := grafanarest.DualWriterMode(mode) helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: modeDw, @@ -1366,9 +1376,10 @@ func TestIntegrationFolderDeletionBlockedByLibraryElements(t *testing.T) { modeDw := grafanarest.DualWriterMode(mode) helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: modeDw, @@ -1446,9 +1457,10 @@ func TestIntegrationRootFolderDeletionBlockedByLibraryElementsInSubfolder(t *tes modeDw := grafanarest.DualWriterMode(mode) helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: modeDw, @@ -1542,9 +1554,10 @@ func TestIntegrationFolderDeletionBlockedByConnectedLibraryPanels(t *testing.T) modeDw := grafanarest.DualWriterMode(mode) helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: modeDw, @@ -1620,9 +1633,10 @@ func TestIntegrationFolderDeletionWithDanglingLibraryPanels(t *testing.T) { modeDw := grafanarest.DualWriterMode(mode) helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: modeDw, @@ -1893,9 +1907,10 @@ func TestIntegrationDeleteNestedFoldersPostorder(t *testing.T) { t.Run(fmt.Sprintf("Mode %d: Delete nested folder hierarchy in postorder", mode), func(t *testing.T) { modeDw := grafanarest.DualWriterMode(mode) helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: modeDw, @@ -2019,9 +2034,10 @@ func TestIntegrationDeleteFolderWithProvisionedDashboards(t *testing.T) { t.Run(fmt.Sprintf("Mode %d: Delete provisioned folders and dashboards", mode), func(t *testing.T) { modeDw := grafanarest.DualWriterMode(mode) ops := testinfra.GrafanaOpts{ - DisableAnonymous: true, - AppModeProduction: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + DisableAnonymous: true, + AppModeProduction: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: modeDw, @@ -2123,11 +2139,14 @@ func TestIntegrationDeleteFolderWithProvisionedDashboards(t *testing.T) { // Test that folders created during provisioning using the dual writer have the // appropriate labels and annotations in unified storage. func TestIntegrationProvisionedFolderPropagatesLabelsAndAnnotations(t *testing.T) { + testutil.SkipIntegrationTestInShortMode(t) + mode3 := grafanarest.DualWriterMode(3) ops := testinfra.GrafanaOpts{ - DisableAnonymous: true, - AppModeProduction: true, - APIServerStorageType: "unified", + DisableDataMigrations: true, + DisableAnonymous: true, + AppModeProduction: true, + APIServerStorageType: "unified", UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ folders.RESOURCEGROUP: { DualWriterMode: mode3, diff --git a/pkg/tests/apis/openapi_snapshots/playlist.grafana.app-v0alpha1.json b/pkg/tests/apis/openapi_snapshots/playlist.grafana.app-v0alpha1.json index dd1b486823e..dee1a56d6c0 100644 --- a/pkg/tests/apis/openapi_snapshots/playlist.grafana.app-v0alpha1.json +++ b/pkg/tests/apis/openapi_snapshots/playlist.grafana.app-v0alpha1.json @@ -40,7 +40,7 @@ "tags": [ "Playlist" ], - "description": "list objects of kind Playlist", + "description": "list or watch objects of kind Playlist", "operationId": "listPlaylist", "parameters": [ { @@ -1850,6 +1850,32 @@ "description": "Time is a wrapper around time.Time which supports correct marshaling to YAML and JSON. Wrappers are provided for many of the factory methods that the time package offers.", "type": "string", "format": "date-time" + }, + "io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent": { + "description": "Event represents a single event to a watched resource.", + "type": "object", + "required": [ + "type", + "object" + ], + "properties": { + "object": { + "description": "Object is:\n * If Type is Added or Modified: the new state of the object.\n * If Type is Deleted: the state of the object immediately before deletion.\n * If Type is Error: *Status is recommended; other types may make sense\n depending on context.", + "allOf": [ + { + "$ref": "#/components/schemas/io.k8s.apimachinery.pkg.runtime.RawExtension" + } + ] + }, + "type": { + "type": "string", + "default": "" + } + } + }, + "io.k8s.apimachinery.pkg.runtime.RawExtension": { + "description": "RawExtension is used to hold extensions in external versions.\n\nTo use this, make a field which has RawExtension as its type in your external, versioned struct, and Object in your internal struct. You also need to register your various plugin types.\n\n// Internal package:\n\n\ttype MyAPIObject struct {\n\t\truntime.TypeMeta `json:\",inline\"`\n\t\tMyPlugin runtime.Object `json:\"myPlugin\"`\n\t}\n\n\ttype PluginA struct {\n\t\tAOption string `json:\"aOption\"`\n\t}\n\n// External package:\n\n\ttype MyAPIObject struct {\n\t\truntime.TypeMeta `json:\",inline\"`\n\t\tMyPlugin runtime.RawExtension `json:\"myPlugin\"`\n\t}\n\n\ttype PluginA struct {\n\t\tAOption string `json:\"aOption\"`\n\t}\n\n// On the wire, the JSON will look something like this:\n\n\t{\n\t\t\"kind\":\"MyAPIObject\",\n\t\t\"apiVersion\":\"v1\",\n\t\t\"myPlugin\": {\n\t\t\t\"kind\":\"PluginA\",\n\t\t\t\"aOption\":\"foo\",\n\t\t},\n\t}\n\nSo what happens? Decode first uses json or yaml to unmarshal the serialized data into your external MyAPIObject. That causes the raw JSON to be stored, but not unpacked. The next step is to copy (using pkg/conversion) into the internal struct. The runtime package's DefaultScheme has conversion functions installed which will unpack the JSON stored in RawExtension, turning it into the correct object type, and storing it in the Object. (TODO: In the case where the object is of an unknown type, a runtime.Unknown object will be created and stored.)", + "type": "object" } } } diff --git a/pkg/tests/apis/playlist/playlist_test.go b/pkg/tests/apis/playlist/playlist_test.go index 057452eb7f9..cbfbf24a4b8 100644 --- a/pkg/tests/apis/playlist/playlist_test.go +++ b/pkg/tests/apis/playlist/playlist_test.go @@ -54,47 +54,48 @@ func TestIntegrationPlaylist(t *testing.T) { require.NoError(t, err) // t.Logf("%s", disco) require.JSONEq(t, `[ - { - "version": "v0alpha1", - "freshness": "Current", - "resources": [ - { - "resource": "playlists", - "responseKind": { - "group": "", - "kind": "Playlist", - "version": "" - }, - "scope": "Namespaced", - "singularResource": "playlist", - "subresources": [ - { - "responseKind": { - "group": "", - "kind": "Playlist", - "version": "" - }, - "subresource": "status", - "verbs": [ - "get", - "patch", - "update" - ] - } - ], - "verbs": [ - "create", - "delete", - "deletecollection", - "get", - "list", - "patch", - "update" - ] - } - ] - } - ]`, disco) + { + "freshness": "Current", + "resources": [ + { + "resource": "playlists", + "responseKind": { + "group": "", + "kind": "Playlist", + "version": "" + }, + "scope": "Namespaced", + "singularResource": "playlists", + "subresources": [ + { + "responseKind": { + "group": "", + "kind": "Playlist", + "version": "" + }, + "subresource": "status", + "verbs": [ + "get", + "patch", + "update" + ] + } + ], + "verbs": [ + "create", + "delete", + "deletecollection", + "get", + "list", + "patch", + "update", + "watch" + ] + } + ], + "version": "v0alpha1" + } + ]`, disco) }) t.Run("with k8s api flag", func(t *testing.T) { @@ -106,9 +107,10 @@ func TestIntegrationPlaylist(t *testing.T) { t.Run("with dual write (file, mode 0)", func(t *testing.T) { doPlaylistTests(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "file", // write the files to disk + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "file", // write the files to disk UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ RESOURCEGROUP: { DualWriterMode: grafanarest.Mode0, @@ -119,9 +121,10 @@ func TestIntegrationPlaylist(t *testing.T) { t.Run("with dual write (file, mode 1)", func(t *testing.T) { doPlaylistTests(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "file", // write the files to disk + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "file", // write the files to disk UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ RESOURCEGROUP: { DualWriterMode: grafanarest.Mode1, @@ -132,9 +135,10 @@ func TestIntegrationPlaylist(t *testing.T) { t.Run("with dual write (file, mode 2)", func(t *testing.T) { doPlaylistTests(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "file", // write the files to disk + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "file", // write the files to disk UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ RESOURCEGROUP: { DualWriterMode: grafanarest.Mode2, @@ -145,9 +149,10 @@ func TestIntegrationPlaylist(t *testing.T) { t.Run("with dual write (file, mode 3)", func(t *testing.T) { doPlaylistTests(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "file", // write the files to disk + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "file", // write the files to disk UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ RESOURCEGROUP: { DualWriterMode: grafanarest.Mode3, @@ -158,9 +163,10 @@ func TestIntegrationPlaylist(t *testing.T) { t.Run("with dual write (file, mode 5)", func(t *testing.T) { helper := doPlaylistTests(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: "file", // write the files to disk + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: "file", // write the files to disk UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ RESOURCEGROUP: { DualWriterMode: grafanarest.Mode5, @@ -198,9 +204,10 @@ func TestIntegrationPlaylist(t *testing.T) { t.Run("with dual write (unified storage, mode 0)", func(t *testing.T) { doPlaylistTests(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: false, // required for unified storage - DisableAnonymous: true, - APIServerStorageType: options.StorageTypeUnified, // use the entity api tables + DisableDataMigrations: true, + AppModeProduction: false, // required for unified storage + DisableAnonymous: true, + APIServerStorageType: options.StorageTypeUnified, // use the entity api tables UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ RESOURCEGROUP: { DualWriterMode: grafanarest.Mode0, @@ -211,18 +218,20 @@ func TestIntegrationPlaylist(t *testing.T) { t.Run("with dual write (unified storage, mode 1)", func(t *testing.T) { doPlaylistTests(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: false, - DisableAnonymous: true, - APIServerStorageType: options.StorageTypeUnified, - EnableFeatureToggles: []string{}, + DisableDataMigrations: true, + AppModeProduction: false, + DisableAnonymous: true, + APIServerStorageType: options.StorageTypeUnified, + EnableFeatureToggles: []string{}, })) }) t.Run("with dual write (unified storage, mode 2)", func(t *testing.T) { doPlaylistTests(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: false, // required for unified storage - DisableAnonymous: true, - APIServerStorageType: options.StorageTypeUnified, // use the entity api tables + DisableDataMigrations: true, + AppModeProduction: false, // required for unified storage + DisableAnonymous: true, + APIServerStorageType: options.StorageTypeUnified, // use the entity api tables UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ RESOURCEGROUP: { DualWriterMode: grafanarest.Mode2, @@ -233,9 +242,10 @@ func TestIntegrationPlaylist(t *testing.T) { t.Run("with dual write (unified storage, mode 3)", func(t *testing.T) { doPlaylistTests(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: false, // required for unified storage - DisableAnonymous: true, - APIServerStorageType: options.StorageTypeUnified, // use the entity api tables + DisableDataMigrations: true, + AppModeProduction: false, // required for unified storage + DisableAnonymous: true, + APIServerStorageType: options.StorageTypeUnified, // use the entity api tables UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ RESOURCEGROUP: { DualWriterMode: grafanarest.Mode3, @@ -246,9 +256,10 @@ func TestIntegrationPlaylist(t *testing.T) { t.Run("with dual write (unified storage, mode 5)", func(t *testing.T) { doPlaylistTests(t, apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: false, // required for unified storage - DisableAnonymous: true, - APIServerStorageType: options.StorageTypeUnified, // use the entity api tables + DisableDataMigrations: true, + AppModeProduction: false, // required for unified storage + DisableAnonymous: true, + APIServerStorageType: options.StorageTypeUnified, // use the entity api tables UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ RESOURCEGROUP: { DualWriterMode: grafanarest.Mode5, @@ -262,9 +273,10 @@ func TestIntegrationPlaylist(t *testing.T) { t.Skip("local etcd testing") helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: options.StorageTypeEtcd, // requires etcd running on localhost:2379 + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: options.StorageTypeEtcd, // requires etcd running on localhost:2379 UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ RESOURCEGROUP: { DualWriterMode: grafanarest.Mode0, @@ -288,9 +300,10 @@ func TestIntegrationPlaylist(t *testing.T) { t.Skip("local etcd testing") helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: options.StorageTypeEtcd, // requires etcd running on localhost:2379 + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: options.StorageTypeEtcd, // requires etcd running on localhost:2379 UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ RESOURCEGROUP: { DualWriterMode: grafanarest.Mode1, @@ -314,9 +327,10 @@ func TestIntegrationPlaylist(t *testing.T) { t.Skip("local etcd testing") helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: options.StorageTypeEtcd, // requires etcd running on localhost:2379 + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: options.StorageTypeEtcd, // requires etcd running on localhost:2379 UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ RESOURCEGROUP: { DualWriterMode: grafanarest.Mode2, @@ -340,9 +354,10 @@ func TestIntegrationPlaylist(t *testing.T) { t.Skip("local etcd testing") helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: options.StorageTypeEtcd, // requires etcd running on localhost:2379 + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: options.StorageTypeEtcd, // requires etcd running on localhost:2379 UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ RESOURCEGROUP: { DualWriterMode: grafanarest.Mode3, @@ -366,9 +381,10 @@ func TestIntegrationPlaylist(t *testing.T) { t.Skip("local etcd testing") helper := apis.NewK8sTestHelper(t, testinfra.GrafanaOpts{ - AppModeProduction: true, - DisableAnonymous: true, - APIServerStorageType: options.StorageTypeEtcd, // requires etcd running on localhost:2379 + DisableDataMigrations: true, + AppModeProduction: true, + DisableAnonymous: true, + APIServerStorageType: options.StorageTypeEtcd, // requires etcd running on localhost:2379 UnifiedStorageConfig: map[string]setting.UnifiedStorageConfig{ RESOURCEGROUP: { DualWriterMode: grafanarest.Mode5, diff --git a/pkg/tests/testinfra/testinfra.go b/pkg/tests/testinfra/testinfra.go index b372036760c..37769c09610 100644 --- a/pkg/tests/testinfra/testinfra.go +++ b/pkg/tests/testinfra/testinfra.go @@ -362,6 +362,13 @@ func CreateGrafDir(t *testing.T, opts GrafanaOpts) (string, string) { _, err = rbacSect.NewKey("permission_cache", "false") require.NoError(t, err) + if opts.DisableAuthZClientCache { + authzSect, err := cfg.NewSection("authorization") + require.NoError(t, err) + _, err = authzSect.NewKey("cache_ttl", "0") + require.NoError(t, err) + } + analyticsSect, err := cfg.NewSection("analytics") require.NoError(t, err) _, err = analyticsSect.NewKey("intercom_secret", "intercom_secret_at_config") @@ -670,6 +677,7 @@ type GrafanaOpts struct { DisableDataMigrations bool SecretsManagerEnableDBMigrations bool OpenFeatureAPIEnabled bool + DisableAuthZClientCache bool // Allow creating grafana dir beforehand Dir string