2024-02-26 21:52:16 +08:00
|
|
|
package cloudmigrationimpl
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"testing"
|
|
|
|
|
2024-06-08 00:46:19 +08:00
|
|
|
"github.com/grafana/grafana/pkg/api/routing"
|
|
|
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
|
|
|
"github.com/grafana/grafana/pkg/infra/db"
|
|
|
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
2024-02-26 21:52:16 +08:00
|
|
|
"github.com/grafana/grafana/pkg/services/cloudmigration"
|
2024-06-08 00:46:19 +08:00
|
|
|
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
|
|
|
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
|
|
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
|
|
|
"github.com/grafana/grafana/pkg/services/datasources"
|
|
|
|
datafakes "github.com/grafana/grafana/pkg/services/datasources/fakes"
|
|
|
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
|
|
"github.com/grafana/grafana/pkg/services/folder"
|
|
|
|
"github.com/grafana/grafana/pkg/services/folder/foldertest"
|
|
|
|
secretsfakes "github.com/grafana/grafana/pkg/services/secrets/fakes"
|
|
|
|
"github.com/grafana/grafana/pkg/services/user"
|
|
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
2024-02-26 21:52:16 +08:00
|
|
|
"github.com/stretchr/testify/assert"
|
2024-06-08 00:46:19 +08:00
|
|
|
"github.com/stretchr/testify/mock"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"go.opentelemetry.io/otel/sdk/trace/tracetest"
|
2024-02-26 21:52:16 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
func Test_NoopServiceDoesNothing(t *testing.T) {
|
|
|
|
s := &NoopServiceImpl{}
|
2024-05-13 12:22:19 +08:00
|
|
|
_, e := s.CreateToken(context.Background())
|
2024-02-26 21:52:16 +08:00
|
|
|
assert.ErrorIs(t, e, cloudmigration.ErrFeatureDisabledError)
|
|
|
|
}
|
2024-06-08 00:46:19 +08:00
|
|
|
|
|
|
|
func Test_CreateGetAndDeleteToken(t *testing.T) {
|
|
|
|
s := setUpServiceTest(t, false)
|
|
|
|
|
|
|
|
createResp, err := s.CreateToken(context.Background())
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotEmpty(t, createResp.Token)
|
|
|
|
|
|
|
|
token, err := s.GetToken(context.Background())
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotEmpty(t, token.Name)
|
|
|
|
|
|
|
|
err = s.DeleteToken(context.Background(), token.ID)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = s.GetToken(context.Background())
|
|
|
|
assert.ErrorIs(t, cloudmigration.ErrTokenNotFound, err)
|
|
|
|
|
|
|
|
cm := cloudmigration.CloudMigration{}
|
|
|
|
err = s.ValidateToken(context.Background(), cm)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_CreateGetRunMigrationsAndRuns(t *testing.T) {
|
|
|
|
s := setUpServiceTest(t, true)
|
|
|
|
|
|
|
|
createTokenResp, err := s.CreateToken(context.Background())
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotEmpty(t, createTokenResp.Token)
|
|
|
|
|
|
|
|
cmd := cloudmigration.CloudMigrationRequest{
|
|
|
|
AuthToken: createTokenResp.Token,
|
|
|
|
}
|
|
|
|
|
|
|
|
createResp, err := s.CreateMigration(context.Background(), cmd)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotEmpty(t, createResp.UID)
|
|
|
|
require.NotEmpty(t, createResp.Stack)
|
|
|
|
|
|
|
|
getMigResp, err := s.GetMigration(context.Background(), createResp.UID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, getMigResp)
|
|
|
|
require.Equal(t, createResp.UID, getMigResp.UID)
|
|
|
|
require.Equal(t, createResp.Stack, getMigResp.Stack)
|
|
|
|
|
|
|
|
listResp, err := s.GetMigrationList(context.Background())
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, listResp)
|
|
|
|
require.Equal(t, 1, len(listResp.Migrations))
|
|
|
|
require.Equal(t, createResp.UID, listResp.Migrations[0].UID)
|
|
|
|
require.Equal(t, createResp.Stack, listResp.Migrations[0].Stack)
|
|
|
|
|
|
|
|
runResp, err := s.RunMigration(ctxWithSignedInUser(), createResp.UID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, runResp)
|
|
|
|
resultItemsByType := make(map[string]int)
|
|
|
|
for _, item := range runResp.Items {
|
|
|
|
resultItemsByType[string(item.Type)] = resultItemsByType[string(item.Type)] + 1
|
|
|
|
}
|
|
|
|
require.Equal(t, 1, resultItemsByType["DASHBOARD"])
|
|
|
|
require.Equal(t, 2, resultItemsByType["DATASOURCE"])
|
|
|
|
require.Equal(t, 2, len(resultItemsByType))
|
|
|
|
|
|
|
|
runStatusResp, err := s.GetMigrationStatus(context.Background(), runResp.RunUID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, runResp.RunUID, runStatusResp.UID)
|
|
|
|
|
|
|
|
listRunResp, err := s.GetMigrationRunList(context.Background(), createResp.UID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 1, len(listRunResp.Runs))
|
|
|
|
require.Equal(t, runResp.RunUID, listRunResp.Runs[0].RunUID)
|
|
|
|
|
|
|
|
delMigResp, err := s.DeleteMigration(context.Background(), createResp.UID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotNil(t, createResp.UID, delMigResp.UID)
|
|
|
|
}
|
|
|
|
|
|
|
|
func ctxWithSignedInUser() context.Context {
|
|
|
|
c := &contextmodel.ReqContext{
|
|
|
|
SignedInUser: &user.SignedInUser{OrgID: 1},
|
|
|
|
}
|
|
|
|
k := ctxkey.Key{}
|
|
|
|
ctx := context.WithValue(context.Background(), k, c)
|
|
|
|
return ctx
|
|
|
|
}
|
|
|
|
|
|
|
|
func setUpServiceTest(t *testing.T, withDashboardMock bool) cloudmigration.Service {
|
|
|
|
sqlStore := db.InitTestDB(t)
|
|
|
|
secretsService := secretsfakes.NewFakeSecretsService()
|
|
|
|
rr := routing.NewRouteRegister()
|
|
|
|
spanRecorder := tracetest.NewSpanRecorder()
|
|
|
|
tracer := tracing.InitializeTracerForTest(tracing.WithSpanProcessor(spanRecorder))
|
|
|
|
mockFolder := &foldertest.FakeService{
|
|
|
|
ExpectedFolder: &folder.Folder{UID: "folderUID", Title: "Folder"},
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg := setting.NewCfg()
|
|
|
|
section, err := cfg.Raw.NewSection("cloud_migration")
|
|
|
|
require.NoError(t, err)
|
|
|
|
_, err = section.NewKey("domain", "localhost:1234")
|
|
|
|
require.NoError(t, err)
|
|
|
|
// dont know if this is the best, but dont want to refactor at the moment
|
|
|
|
cfg.CloudMigration.IsDeveloperMode = true
|
|
|
|
|
|
|
|
dashboardService := dashboards.NewFakeDashboardService(t)
|
|
|
|
if withDashboardMock {
|
|
|
|
dashboardService.On("GetAllDashboards", mock.Anything).Return(
|
|
|
|
[]*dashboards.Dashboard{
|
|
|
|
{
|
|
|
|
UID: "1",
|
|
|
|
Data: simplejson.New(),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
dsService := &datafakes.FakeDataSourceService{
|
|
|
|
DataSources: []*datasources.DataSource{
|
|
|
|
{Name: "mmm", Type: "mysql"},
|
|
|
|
{Name: "ZZZ", Type: "infinity"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
s, err := ProvideService(
|
|
|
|
cfg,
|
|
|
|
featuremgmt.WithFeatures(featuremgmt.FlagOnPremToCloudMigrations),
|
|
|
|
sqlStore,
|
|
|
|
dsService,
|
|
|
|
secretsService,
|
|
|
|
rr,
|
|
|
|
prometheus.DefaultRegisterer,
|
|
|
|
tracer,
|
|
|
|
dashboardService,
|
|
|
|
mockFolder,
|
|
|
|
)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
return s
|
|
|
|
}
|