mirror of
https://github.com/grafana/grafana.git
synced 2025-02-11 08:05:43 -06:00
* Improve error handling for secrets manager plugin * Update sever lock log for secret migration to Error * Move plugin started check to a separate function * Fix nil pointer exception on HasPluginStarted
106 lines
3.7 KiB
Go
106 lines
3.7 KiB
Go
package migrations
|
|
|
|
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/setting"
|
|
)
|
|
|
|
var logger = log.New("secret.migration")
|
|
|
|
const actionName = "secret migration task "
|
|
|
|
// SecretMigrationService is used to migrate legacy secrets to new unified secrets.
|
|
type SecretMigrationService interface {
|
|
Migrate(ctx context.Context) error
|
|
}
|
|
|
|
type SecretMigrationProvider interface {
|
|
registry.BackgroundService
|
|
TriggerPluginMigration(ctx context.Context, toPlugin bool) error
|
|
}
|
|
|
|
type SecretMigrationProviderImpl struct {
|
|
services []SecretMigrationService
|
|
ServerLockService *serverlock.ServerLockService
|
|
migrateToPluginService *MigrateToPluginService
|
|
migrateFromPluginService *MigrateFromPluginService
|
|
}
|
|
|
|
func ProvideSecretMigrationProvider(
|
|
cfg *setting.Cfg,
|
|
serverLockService *serverlock.ServerLockService,
|
|
dataSourceSecretMigrationService *DataSourceSecretMigrationService,
|
|
migrateToPluginService *MigrateToPluginService,
|
|
migrateFromPluginService *MigrateFromPluginService,
|
|
) *SecretMigrationProviderImpl {
|
|
services := make([]SecretMigrationService, 0)
|
|
services = append(services, dataSourceSecretMigrationService)
|
|
// Plugin migration should always be last; should either migrate to or from, not both
|
|
// This is because the migrateTo checks for use_plugin = true, in which case we should always
|
|
// migrate by default to ensure users don't lose access to secrets. If migration has
|
|
// already occurred, the migrateTo function will be called but it won't do anything
|
|
if cfg.SectionWithEnvOverrides("secrets").Key("migrate_from_plugin").MustBool(false) {
|
|
services = append(services, migrateFromPluginService)
|
|
} else {
|
|
services = append(services, migrateToPluginService)
|
|
}
|
|
|
|
return &SecretMigrationProviderImpl{
|
|
ServerLockService: serverLockService,
|
|
services: services,
|
|
migrateToPluginService: migrateToPluginService,
|
|
migrateFromPluginService: migrateFromPluginService,
|
|
}
|
|
}
|
|
|
|
func (s *SecretMigrationProviderImpl) Run(ctx context.Context) error {
|
|
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 *SecretMigrationProviderImpl) Migrate(ctx context.Context) error {
|
|
// Start migration services.
|
|
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 secret migration service", "service", serviceName)
|
|
err := service.Migrate(ctx)
|
|
if err != nil {
|
|
logger.Error("Stopped secret migration service", "service", serviceName, "reason", err)
|
|
}
|
|
logger.Debug("Finished secret migration service", "service", serviceName)
|
|
}
|
|
})
|
|
if err != nil {
|
|
logger.Error("Server lock for secret migration already exists")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// TriggerPluginMigration Kick off a migration to or from the plugin. This will block until all services have exited.
|
|
func (s *SecretMigrationProviderImpl) TriggerPluginMigration(ctx context.Context, toPlugin bool) error {
|
|
// Don't migrate if there is already one happening
|
|
return s.ServerLockService.LockExecuteAndRelease(ctx, actionName, time.Minute*10, func(context.Context) {
|
|
var err error
|
|
if toPlugin {
|
|
err = s.migrateToPluginService.Migrate(ctx)
|
|
} else {
|
|
err = s.migrateFromPluginService.Migrate(ctx)
|
|
}
|
|
if err != nil {
|
|
direction := "from_plugin"
|
|
if toPlugin {
|
|
direction = "to_plugin"
|
|
}
|
|
logger.Error("Failed to migrate plugin secrets", "direction", direction, "error", err.Error())
|
|
}
|
|
})
|
|
}
|