CloudMigrations: Add support for migration of plugin resources (#95612)

* start plugins migration

* more plugin work

* add warning

* fakepluginsettings test

* tests get plugins

* lint

* load logos

* go lint

* get all plugins once

* locales

* josh suggestion to inject query in rtk

* more plugin filters

* remove datasource warning

* access control for plugins

* remove unused method

* lint

* use gcom list
This commit is contained in:
Dana Axinte
2025-01-06 10:37:15 +00:00
committed by GitHub
parent 6ca6ad4df7
commit 1699dfa307
23 changed files with 431 additions and 264 deletions
@@ -19,6 +19,7 @@ import (
"github.com/grafana/grafana/pkg/infra/kvstore"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/authapi"
"github.com/grafana/grafana/pkg/services/authapi/fake"
"github.com/grafana/grafana/pkg/services/cloudmigration"
@@ -32,6 +33,7 @@ import (
"github.com/grafana/grafana/pkg/services/gcom"
"github.com/grafana/grafana/pkg/services/libraryelements"
"github.com/grafana/grafana/pkg/services/ngalert"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
"github.com/grafana/grafana/pkg/services/secrets"
secretskv "github.com/grafana/grafana/pkg/services/secrets/kvstore"
@@ -68,6 +70,8 @@ type Service struct {
dashboardService dashboards.DashboardService
folderService folder.Service
pluginStore pluginstore.Store
accessControl accesscontrol.AccessControl
pluginSettingsService pluginsettings.Service
secretsService secrets.Service
kvStore *kvstore.NamespacedKVStore
libraryElementsService libraryelements.Service
@@ -105,6 +109,8 @@ func ProvideService(
dashboardService dashboards.DashboardService,
folderService folder.Service,
pluginStore pluginstore.Store,
pluginSettingsService pluginsettings.Service,
accessControl accesscontrol.AccessControl,
kvStore kvstore.KVStore,
libraryElementsService libraryelements.Service,
ngAlert *ngalert.AlertNG,
@@ -125,6 +131,8 @@ func ProvideService(
dashboardService: dashboardService,
folderService: folderService,
pluginStore: pluginStore,
pluginSettingsService: pluginSettingsService,
accessControl: accessControl,
kvStore: kvstore.WithNamespace(kvStore, 0, "cloudmigration"),
libraryElementsService: libraryElementsService,
ngAlert: ngAlert,
@@ -588,13 +596,7 @@ func (s *Service) GetSnapshot(ctx context.Context, query cloudmigration.GetSnaps
s.log.Error("unexpected GMS snapshot state: %s", snapshotMeta.State)
return snapshot, nil
}
// For 11.2 we only support core data sources. Apply a warning for any non-core ones before storing.
resources, err := s.getResourcesWithPluginWarnings(ctx, snapshotMeta.Results)
if err != nil {
// treat this as non-fatal since the migration still succeeded
s.log.Error("error applying plugin warnings, please open a bug report: %w", err)
}
resources := snapshotMeta.Results
// Log the errors for resources with errors at migration
for _, resource := range resources {
@@ -901,40 +903,3 @@ func (s *Service) deleteLocalFiles(snapshots []cloudmigration.CloudMigrationSnap
}
return err
}
// getResourcesWithPluginWarnings iterates through each resource and, if a non-core datasource, applies a warning that we only support core
func (s *Service) getResourcesWithPluginWarnings(ctx context.Context, results []cloudmigration.CloudMigrationResource) ([]cloudmigration.CloudMigrationResource, error) {
dsList, err := s.dsService.GetAllDataSources(ctx, &datasources.GetAllDataSourcesQuery{})
if err != nil {
return nil, fmt.Errorf("getting all data sources: %w", err)
}
dsMap := make(map[string]*datasources.DataSource, len(dsList))
for i := 0; i < len(dsList); i++ {
dsMap[dsList[i].UID] = dsList[i]
}
for i := 0; i < len(results); i++ {
r := results[i]
if r.Type == cloudmigration.DatasourceDataType &&
r.Error == "" { // any error returned by GMS takes priority
ds, ok := dsMap[r.RefID]
if !ok {
s.log.Error("data source with id %s was not found in data sources list", r.RefID)
continue
}
p, found := s.pluginStore.Plugin(ctx, ds.Type)
// if the plugin is not found, it means it was uninstalled, meaning it wasn't core
if !p.IsCorePlugin() || !found {
r.Status = cloudmigration.ItemStatusWarning
r.ErrorCode = cloudmigration.ErrOnlyCoreDataSources
r.Error = "Only core data sources are supported. Please ensure the plugin is installed on the cloud stack."
}
results[i] = r
}
}
return results, nil
}