Prometheus data source: Migration service (#107364)

* copying from secrets migration

* service runs and mig promds type

* creating data source check

* adding aws

* split into azure/aws service. feature flag. auto install

* add tests

* clean up

* lint

* add code owner

* imporvments from andres

* remove prom mig from http_server

* remove interface for testing

* add prom mig to provisining data sources so prov happens before mig

* fit into prov

* comment

* log debug instead of returning in update type

* Trigger Build

* feature flag being weird

* not public method

* copying from secrets migration

* service runs and mig promds type

* creating data source check

* adding aws

* add tests

* clean up

* imporvments from andres

* remove prom mig from http_server

* remove interface for testing

* add prom mig to provisining data sources so prov happens before mig

* fit into prov

* Trigger Build

* not public method

* remove logger import
This commit is contained in:
Andrew Hackmann
2025-09-05 15:07:06 -05:00
committed by GitHub
parent 7cbc55d615
commit 9445328a59
18 changed files with 631 additions and 5 deletions
+2
View File
@@ -1137,6 +1137,8 @@ eslint-suppressions.json @grafanabot
# Feature toggles
/pkg/services/featuremgmt/ @grafana/grafana-backend-services-squad
# Data source migrations
/pkg/services/promtypemigration/ @grafana/partner-datasources @grafana/aws-datasources
# Kind definitions
/kinds/dashboard @grafana/dashboards-squad
@@ -1132,4 +1132,9 @@ export interface FeatureToggles {
* @default false
*/
azureResourcePickerUpdates?: boolean;
/**
* Checks for deprecated Prometheus authentication methods (SigV4 and Azure), installs the relevant data source, and migrates the Prometheus data sources
* @default false
*/
prometheusTypeMigration?: boolean;
}
@@ -33,6 +33,7 @@ import (
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginexternal"
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugininstaller"
pluginStore "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
"github.com/grafana/grafana/pkg/services/promtypemigration"
"github.com/grafana/grafana/pkg/services/provisioning"
publicdashboardsmetric "github.com/grafana/grafana/pkg/services/publicdashboards/metric"
"github.com/grafana/grafana/pkg/services/rendering"
@@ -71,6 +72,7 @@ func ProvideBackgroundServiceRegistry(
pluginDashboardUpdater *plugindashboardsservice.DashboardUpdater,
dashboardServiceImpl *service.DashboardServiceImpl,
secretsGarbageCollectionWorker *secretsgarbagecollectionworker.Worker,
promTypeMigrationProvider promtypemigration.PromTypeMigrationProvider,
// Need to make sure these are initialized, is there a better place to put them?
_ dashboardsnapshots.Service,
_ serviceaccounts.Service,
@@ -118,6 +120,7 @@ func ProvideBackgroundServiceRegistry(
pluginDashboardUpdater,
dashboardServiceImpl,
secretsGarbageCollectionWorker,
promTypeMigrationProvider,
)
}
+5
View File
@@ -125,6 +125,7 @@ import (
pluginDashboards "github.com/grafana/grafana/pkg/services/pluginsintegration/dashboards"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol"
"github.com/grafana/grafana/pkg/services/preference/prefimpl"
promTypeMigration "github.com/grafana/grafana/pkg/services/promtypemigration"
"github.com/grafana/grafana/pkg/services/publicdashboards"
publicdashboardsApi "github.com/grafana/grafana/pkg/services/publicdashboards/api"
publicdashboardsStore "github.com/grafana/grafana/pkg/services/publicdashboards/database"
@@ -392,6 +393,10 @@ var wireBasicSet = wire.NewSet(
secretsMigrations.ProvideDataSourceMigrationService,
secretsMigrations.ProvideSecretMigrationProvider,
wire.Bind(new(secretsMigrations.SecretMigrationProvider), new(*secretsMigrations.SecretMigrationProviderImpl)),
promTypeMigration.ProvideAzurePromMigrationService,
promTypeMigration.ProvideAmazonPromMigrationService,
promTypeMigration.ProvidePromTypeMigrationProvider,
wire.Bind(new(promTypeMigration.PromTypeMigrationProvider), new(*promTypeMigration.PromTypeMigrationProviderImpl)),
resourcepermissions.NewActionSetService,
wire.Bind(new(accesscontrol.ActionResolver), new(resourcepermissions.ActionSetService)),
wire.Bind(new(pluginaccesscontrol.ActionSetRegistry), new(resourcepermissions.ActionSetService)),
+12 -5
View File
File diff suppressed because one or more lines are too long
+8
View File
@@ -1964,6 +1964,14 @@ var (
Owner: grafanaPartnerPluginsSquad,
Expression: "false",
},
{
Name: "prometheusTypeMigration",
Description: "Checks for deprecated Prometheus authentication methods (SigV4 and Azure), installs the relevant data source, and migrates the Prometheus data sources",
Stage: FeatureStageExperimental,
RequiresRestart: true,
Owner: grafanaPartnerPluginsSquad,
Expression: "false",
},
}
)
+1
View File
@@ -252,3 +252,4 @@ teamFolders,experimental,@grafana/grafana-search-navigate-organise,false,false,f
alertingTriage,experimental,@grafana/alerting-squad,false,false,true
graphiteBackendMode,privatePreview,@grafana/partner-datasources,false,false,false
azureResourcePickerUpdates,preview,@grafana/partner-datasources,false,false,true
prometheusTypeMigration,experimental,@grafana/partner-datasources,false,true,false
1 Name Stage Owner requiresDevMode RequiresRestart FrontendOnly
252 alertingTriage experimental @grafana/alerting-squad false false true
253 graphiteBackendMode privatePreview @grafana/partner-datasources false false false
254 azureResourcePickerUpdates preview @grafana/partner-datasources false false true
255 prometheusTypeMigration experimental @grafana/partner-datasources false true false
+4
View File
@@ -1018,4 +1018,8 @@ const (
// FlagAzureResourcePickerUpdates
// Enables the updated Azure Monitor resource picker
FlagAzureResourcePickerUpdates = "azureResourcePickerUpdates"
// FlagPrometheusTypeMigration
// Checks for deprecated Prometheus authentication methods (SigV4 and Azure), installs the relevant data source, and migrates the Prometheus data sources
FlagPrometheusTypeMigration = "prometheusTypeMigration"
)
+17
View File
@@ -2714,6 +2714,23 @@
"frontend": true
}
},
{
"metadata": {
"name": "prometheusTypeMigration",
"resourceVersion": "1757089774247",
"creationTimestamp": "2025-08-25T21:53:16Z",
"annotations": {
"grafana.app/updatedTimestamp": "2025-09-05 16:29:34.247055837 +0000 UTC"
}
},
"spec": {
"description": "Checks for deprecated Prometheus authentication methods (SigV4 and Azure), installs the relevant data source, and migrates the Prometheus data sources",
"stage": "experimental",
"codeowner": "@grafana/partner-datasources",
"requiresRestart": true,
"expression": "false"
}
},
{
"metadata": {
"name": "provisioning",
@@ -0,0 +1,62 @@
package promtypemigration
import (
"context"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/manager/registry"
"github.com/grafana/grafana/pkg/plugins/repo"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/setting"
)
type AmazonPromMigrationService struct {
promMigrationService
}
func ProvideAmazonPromMigrationService(
dataSourcesService datasources.DataSourceService,
pluginRegistry registry.Service,
pluginRepo repo.Service,
pluginInstaller plugins.Installer,
cfg *setting.Cfg,
) *AmazonPromMigrationService {
return &AmazonPromMigrationService{
promMigrationService: promMigrationService{
dataSourcesService: dataSourcesService,
pluginRegistry: pluginRegistry,
pluginRepo: pluginRepo,
pluginInstaller: pluginInstaller,
cfg: cfg,
},
}
}
func (s *AmazonPromMigrationService) getPrometheusDataSources(ctx context.Context) ([]*datasources.DataSource, error) {
amazonPromDs := []*datasources.DataSource{}
query := &datasources.GetDataSourcesByTypeQuery{
Type: datasources.DS_PROMETHEUS,
}
dsList, err := s.dataSourcesService.GetDataSourcesByType(ctx, query)
if err != nil {
return nil, err
}
for _, ds := range dsList {
if sigV4Auth, found := ds.JsonData.CheckGet("sigV4Auth"); found {
if enabled, err := sigV4Auth.Bool(); err != nil || !enabled {
continue
}
amazonPromDs = append(amazonPromDs, ds)
continue
}
}
return amazonPromDs, nil
}
func (s *AmazonPromMigrationService) Migrate(ctx context.Context) error {
pds, err := s.getPrometheusDataSources(ctx)
if err != nil {
return err
}
return s.applyMigration(ctx, datasources.DS_AMAZON_PROMETHEUS, pds)
}
@@ -0,0 +1,81 @@
package promtypemigration
import (
"context"
"errors"
"testing"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/stretchr/testify/assert"
)
func TestGetPrometheusDataSources_Amazon_ReturnsOnlyAmazonPrometheus(t *testing.T) {
ds1 := &datasources.DataSource{
JsonData: simplejson.NewFromAny(map[string]any{
"sigV4Auth": true,
}),
}
ds2 := &datasources.DataSource{
JsonData: simplejson.NewFromAny(map[string]any{
"sigV4Auth": false,
}),
}
ds3 := &datasources.DataSource{
JsonData: simplejson.NewFromAny(map[string]any{
"sigV4Auth": true,
}),
}
ds4 := &datasources.DataSource{
JsonData: simplejson.NewFromAny(map[string]any{
"sigV4Auth": nil,
}),
}
mock := &mockDataSourcesService{
dataSources: []*datasources.DataSource{ds1, ds2, ds3, ds4},
}
svc := &AmazonPromMigrationService{
promMigrationService: promMigrationService{
dataSourcesService: mock,
},
}
got, err := svc.getPrometheusDataSources(context.Background())
assert.NoError(t, err)
assert.Len(t, got, 2)
assert.Contains(t, got, ds1)
assert.Contains(t, got, ds3)
}
func TestGetPrometheusDataSources_Amazon_ErrorFromService(t *testing.T) {
mockSvc := &mockDataSourcesService{
err: errors.New("service error"),
}
svc := &AmazonPromMigrationService{
promMigrationService: promMigrationService{
dataSourcesService: mockSvc,
},
}
got, err := svc.getPrometheusDataSources(context.Background())
assert.Error(t, err)
assert.Nil(t, got)
}
func TestGetPrometheusDataSources_Amazon_NoSigV4Auth(t *testing.T) {
ds := &datasources.DataSource{
JsonData: simplejson.NewFromAny(map[string]any{}),
}
mockSvc := &mockDataSourcesService{
dataSources: []*datasources.DataSource{ds},
}
svc := &AmazonPromMigrationService{
promMigrationService: promMigrationService{
dataSourcesService: mockSvc,
},
}
got, err := svc.getPrometheusDataSources(context.Background())
assert.NoError(t, err)
assert.Empty(t, got)
}
@@ -0,0 +1,63 @@
package promtypemigration
import (
"context"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/manager/registry"
"github.com/grafana/grafana/pkg/plugins/repo"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/setting"
)
type AzurePromMigrationService struct {
promMigrationService
}
func ProvideAzurePromMigrationService(
dataSourcesService datasources.DataSourceService,
pluginRegistry registry.Service,
pluginRepo repo.Service,
pluginInstaller plugins.Installer,
cfg *setting.Cfg,
) *AzurePromMigrationService {
return &AzurePromMigrationService{
promMigrationService: promMigrationService{
dataSourcesService: dataSourcesService,
pluginRegistry: pluginRegistry,
pluginRepo: pluginRepo,
pluginInstaller: pluginInstaller,
cfg: cfg,
},
}
}
func (s *AzurePromMigrationService) getPrometheusDataSources(ctx context.Context) ([]*datasources.DataSource, error) {
azurePromDs := []*datasources.DataSource{}
query := &datasources.GetDataSourcesByTypeQuery{
Type: datasources.DS_PROMETHEUS,
}
dsList, err := s.dataSourcesService.GetDataSourcesByType(ctx, query)
if err != nil {
return nil, err
}
for _, ds := range dsList {
if azureAuth, found := ds.JsonData.CheckGet("azureCredentials"); found {
var val any
if val, err = azureAuth.Value(); err != nil || val == nil {
continue
}
azurePromDs = append(azurePromDs, ds)
continue
}
}
return azurePromDs, nil
}
func (s *AzurePromMigrationService) Migrate(ctx context.Context) error {
pds, err := s.getPrometheusDataSources(ctx)
if err != nil {
return err
}
return s.applyMigration(ctx, datasources.DS_AZURE_PROMETHEUS, pds)
}
@@ -0,0 +1,77 @@
package promtypemigration
import (
"context"
"errors"
"testing"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/stretchr/testify/assert"
)
func TestGetPrometheusDataSources_Azure_ReturnsOnlyAzurePrometheus(t *testing.T) {
ds1 := &datasources.DataSource{
JsonData: simplejson.NewFromAny(map[string]any{
"azureCredentials": []any{},
}),
}
ds2 := &datasources.DataSource{
JsonData: simplejson.NewFromAny(map[string]any{}),
}
ds3 := &datasources.DataSource{
JsonData: simplejson.NewFromAny(map[string]any{
"azureCredentials": []any{},
}),
}
ds4 := &datasources.DataSource{
JsonData: simplejson.NewFromAny(map[string]any{}),
}
mock := &mockDataSourcesService{
dataSources: []*datasources.DataSource{ds1, ds2, ds3, ds4},
}
svc := &AzurePromMigrationService{
promMigrationService: promMigrationService{
dataSourcesService: mock,
},
}
got, err := svc.getPrometheusDataSources(context.Background())
assert.NoError(t, err)
assert.Len(t, got, 2)
assert.Contains(t, got, ds1)
assert.Contains(t, got, ds3)
}
func TestGetPrometheusDataSources_Azure_ErrorFromService(t *testing.T) {
mockSvc := &mockDataSourcesService{
err: errors.New("service error"),
}
svc := &AzurePromMigrationService{
promMigrationService: promMigrationService{
dataSourcesService: mockSvc,
},
}
got, err := svc.getPrometheusDataSources(context.Background())
assert.Error(t, err)
assert.Nil(t, got)
}
func TestGetPrometheusDataSources_Azure_NoAzureAuth(t *testing.T) {
ds := &datasources.DataSource{
JsonData: simplejson.NewFromAny(map[string]any{}),
}
mockSvc := &mockDataSourcesService{
dataSources: []*datasources.DataSource{ds},
}
svc := &AzurePromMigrationService{
promMigrationService: promMigrationService{
dataSourcesService: mockSvc,
},
}
got, err := svc.getPrometheusDataSources(context.Background())
assert.NoError(t, err)
assert.Empty(t, got)
}
@@ -0,0 +1,70 @@
package promtypemigration
import (
"context"
"reflect"
"time"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/serverlock"
"github.com/grafana/grafana/pkg/registry"
"github.com/grafana/grafana/pkg/services/featuremgmt"
)
var logger = log.New("promds.migration")
const actionName = "prom type migration task"
type PromTypeMigrationService interface {
Migrate(ctx context.Context) error
}
type PromTypeMigrationProvider interface {
registry.BackgroundService
}
type PromTypeMigrationProviderImpl struct {
services []PromTypeMigrationService
features featuremgmt.FeatureToggles
ServerLockService *serverlock.ServerLockService
}
func ProvidePromTypeMigrationProvider(
serverLockService *serverlock.ServerLockService,
features featuremgmt.FeatureToggles,
promAzureAuthMigrationService *AzurePromMigrationService,
promAmazonAuthMigrationService *AmazonPromMigrationService,
) *PromTypeMigrationProviderImpl {
return &PromTypeMigrationProviderImpl{
ServerLockService: serverLockService,
features: features,
services: []PromTypeMigrationService{promAzureAuthMigrationService, promAmazonAuthMigrationService},
}
}
func (s *PromTypeMigrationProviderImpl) Run(ctx context.Context) error {
if !s.features.IsEnabled(ctx, featuremgmt.FlagPrometheusTypeMigration) {
return nil
}
return s.migrate(ctx)
}
// migrate Run migration services. This will block until all services have exited.
// This should only be called once at startup
func (s *PromTypeMigrationProviderImpl) migrate(ctx context.Context) error {
err := s.ServerLockService.LockExecuteAndRelease(ctx, actionName, time.Minute*10, func(context.Context) {
for _, service := range s.services {
serviceName := reflect.TypeOf(service).String()
logger.Debug("Starting prom data source type migration service", "service", serviceName)
err := service.Migrate(ctx)
if err != nil {
logger.Error("Stopped prom data source type migration service", "service", serviceName, "reason", err)
}
logger.Debug("Finished prom data source type migration service", "service", serviceName)
}
})
if err != nil {
logger.Error("Server lock for prom data source type migration already exists")
}
return nil
}
@@ -0,0 +1,83 @@
package promtypemigration
import (
"context"
"runtime"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/manager/registry"
"github.com/grafana/grafana/pkg/plugins/repo"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/setting"
)
type PromMigrationHandler interface {
Migrate(context.Context, *promMigrationService) error
}
type promMigrationService struct {
cfg *setting.Cfg
dataSourcesService datasources.DataSourceService
pluginRegistry registry.Service
pluginRepo repo.Service
pluginInstaller plugins.Installer
}
func (s *promMigrationService) applyMigration(ctx context.Context, pluginID string, promDataSources []*datasources.DataSource) error {
if len(promDataSources) == 0 {
return nil
}
// check to see if prom is installed, if not install it
if _, installed := s.pluginRegistry.Plugin(ctx, pluginID, ""); !installed {
compatOpts := plugins.NewAddOpts(s.cfg.BuildVersion, runtime.GOOS, runtime.GOARCH, "")
err := s.pluginInstaller.Add(ctx, pluginID, "", compatOpts)
if err != nil {
return err
}
}
logger.Debug("performing prometheus data source type migration", "plugin", pluginID)
for _, ds := range promDataSources {
err := s.updateDataSourceType(ctx, ds, pluginID)
if err != nil {
return err
}
}
logger.Debug("prometheus data source type migration complete", "plugin", pluginID)
return nil
}
func (s *promMigrationService) updateDataSourceType(ctx context.Context, ds *datasources.DataSource, newType string) error {
secureJsonData, err := s.dataSourcesService.DecryptedValues(ctx, ds)
if err != nil {
return err
}
if ds.JsonData == nil {
logger.Debug("no JsonData found", "data source ID", ds.ID)
ds.JsonData = &simplejson.Json{}
}
ds.JsonData.Set("prometheus-type-migration", true)
_, err = s.dataSourcesService.UpdateDataSource(ctx, &datasources.UpdateDataSourceCommand{
ID: ds.ID,
Type: newType,
OrgID: ds.OrgID,
UID: ds.UID,
Name: ds.Name,
JsonData: ds.JsonData,
SecureJsonData: secureJsonData,
// These are needed by the SQL function due to UseBool and MustCols
IsDefault: ds.IsDefault,
BasicAuth: ds.BasicAuth,
WithCredentials: ds.WithCredentials,
ReadOnly: ds.ReadOnly,
User: ds.User,
Database: ds.Database,
})
return err
}
@@ -0,0 +1,120 @@
package promtypemigration
import (
"context"
"errors"
"testing"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/assert"
)
// Mocks
type mockPluginRegistry struct {
installed bool
}
func (m *mockPluginRegistry) Plugin(ctx context.Context, id string, _ string) (*plugins.Plugin, bool) {
if m.installed {
return &plugins.Plugin{}, true
}
return &plugins.Plugin{}, false
}
func (m *mockPluginRegistry) Plugins(ctx context.Context) []*plugins.Plugin { return nil }
func (m *mockPluginRegistry) Add(ctx context.Context, plugin *plugins.Plugin) error { return nil }
func (m *mockPluginRegistry) Remove(ctx context.Context, id, version string) error { return nil }
type mockPluginInstaller struct {
addCalled bool
addErr error
}
func (m *mockPluginInstaller) Add(ctx context.Context, pluginID, version string, opts plugins.AddOpts) error {
m.addCalled = true
return m.addErr
}
func (m *mockPluginInstaller) Remove(ctx context.Context, pluginID, version string) error {
return nil
}
type mockDataSourcesService struct {
datasources.DataSourceService
dataSources []*datasources.DataSource
err error
}
func (m *mockDataSourcesService) DecryptedValues(ctx context.Context, ds *datasources.DataSource) (map[string]string, error) {
return map[string]string{}, nil
}
func (m *mockDataSourcesService) UpdateDataSource(ctx context.Context, cmd *datasources.UpdateDataSourceCommand) (*datasources.DataSource, error) {
return &datasources.DataSource{}, m.err
}
func (m *mockDataSourcesService) GetDataSourcesByType(ctx context.Context, query *datasources.GetDataSourcesByTypeQuery) ([]*datasources.DataSource, error) {
return m.dataSources, m.err
}
// Test cases
func TestApplyMigration_NoDataSources(t *testing.T) {
svc := &promMigrationService{}
err := svc.applyMigration(context.Background(), "prometheus", []*datasources.DataSource{})
assert.NoError(t, err)
}
func TestApplyMigration_PluginAlreadyInstalled(t *testing.T) {
ds := &datasources.DataSource{ID: 1, JsonData: simplejson.New()}
svc := &promMigrationService{
cfg: &setting.Cfg{BuildVersion: "1.0"},
dataSourcesService: &mockDataSourcesService{},
pluginRegistry: &mockPluginRegistry{installed: true},
pluginInstaller: &mockPluginInstaller{},
}
err := svc.applyMigration(context.Background(), "prometheus", []*datasources.DataSource{ds})
assert.NoError(t, err)
}
func TestApplyMigration_PluginNotInstalled_InstallSucceeds(t *testing.T) {
ds := &datasources.DataSource{ID: 1, JsonData: simplejson.New()}
installer := &mockPluginInstaller{}
svc := &promMigrationService{
cfg: &setting.Cfg{BuildVersion: "1.0"},
dataSourcesService: &mockDataSourcesService{},
pluginRegistry: &mockPluginRegistry{installed: false},
pluginInstaller: installer,
}
err := svc.applyMigration(context.Background(), "prometheus", []*datasources.DataSource{ds})
assert.NoError(t, err)
assert.True(t, installer.addCalled)
}
func TestApplyMigration_PluginNotInstalled_InstallFails(t *testing.T) {
ds := &datasources.DataSource{ID: 1}
installer := &mockPluginInstaller{addErr: errors.New("install failed")}
svc := &promMigrationService{
cfg: &setting.Cfg{BuildVersion: "1.0"},
dataSourcesService: &mockDataSourcesService{},
pluginRegistry: &mockPluginRegistry{installed: false},
pluginInstaller: installer,
}
err := svc.applyMigration(context.Background(), "prometheus", []*datasources.DataSource{ds})
assert.EqualError(t, err, "install failed")
}
func TestApplyMigration_UpdateDataSourceFails(t *testing.T) {
ds := &datasources.DataSource{ID: 1, JsonData: simplejson.New()}
dataSvc := &mockDataSourcesService{err: errors.New("update failed")}
svc := &promMigrationService{
cfg: &setting.Cfg{BuildVersion: "1.0"},
dataSourcesService: dataSvc,
pluginRegistry: &mockPluginRegistry{installed: true},
pluginInstaller: &mockPluginInstaller{},
}
err := svc.applyMigration(context.Background(), "prometheus", []*datasources.DataSource{ds})
assert.EqualError(t, err, "update failed")
}
+15
View File
@@ -27,6 +27,7 @@ import (
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
"github.com/grafana/grafana/pkg/services/promtypemigration"
prov_alerting "github.com/grafana/grafana/pkg/services/provisioning/alerting"
"github.com/grafana/grafana/pkg/services/provisioning/dashboards"
"github.com/grafana/grafana/pkg/services/provisioning/datasources"
@@ -59,6 +60,7 @@ func ProvideService(
resourcePermissions accesscontrol.ReceiverPermissionsService,
tracer tracing.Tracer,
dual dualwrite.Service,
promTypeMigrationProvider promtypemigration.PromTypeMigrationProvider,
) (*ProvisioningServiceImpl, error) {
s := &ProvisioningServiceImpl{
Cfg: cfg,
@@ -85,6 +87,7 @@ func ProvideService(
folderService: folderService,
resourcePermissions: resourcePermissions,
tracer: tracer,
migratePrometheusType: promTypeMigrationProvider.Run,
}
if err := s.setDashboardProvisioner(); err != nil {
@@ -120,6 +123,7 @@ func newProvisioningServiceImpl(
newDashboardProvisioner dashboards.DashboardProvisionerFactory,
provisionDatasources func(context.Context, string, datasources.BaseDataSourceService, datasources.CorrelationsStore, org.Service) error,
provisionPlugins func(context.Context, string, pluginstore.Store, pluginsettings.Service, org.Service) error,
migratePrometheusType func(context.Context) error,
searchService searchV2.SearchService,
) (*ProvisioningServiceImpl, error) {
s := &ProvisioningServiceImpl{
@@ -129,6 +133,7 @@ func newProvisioningServiceImpl(
provisionPlugins: provisionPlugins,
Cfg: setting.NewCfg(),
searchService: searchService,
migratePrometheusType: migratePrometheusType,
}
if err := s.setDashboardProvisioner(); err != nil {
@@ -168,6 +173,7 @@ type ProvisioningServiceImpl struct {
tracer tracing.Tracer
dual dualwrite.Service
onceInitProvisioners sync.Once
migratePrometheusType func(context.Context) error
}
func (ps *ProvisioningServiceImpl) RunInitProvisioners(ctx context.Context) error {
@@ -201,6 +207,15 @@ func (ps *ProvisioningServiceImpl) Run(ctx context.Context) error {
ps.log.Error("Failed to provision alerting", "error", err)
return
}
// Migrating prom types relies on data source provisioning to already be completed
// If we can make services depend on other services completing first,
// then we should remove this from provisioning
err = ps.migratePrometheusType(ctx)
if err != nil {
ps.log.Error("Failed to migrate Prometheus type", "error", err)
return
}
})
if err != nil {
@@ -170,6 +170,9 @@ func setup(t *testing.T) *serviceTestStruct {
func(context.Context, string, pluginstore.Store, pluginsettings.Service, org.Service) error {
return nil
},
func(context.Context) error {
return nil
},
searchStub,
)
service.provisionAlerting = func(context.Context, prov_alerting.ProvisionerConfig) error {