Cloud migrations: store snapshots in the database (#108551)
* Cloud migrations: store snapshots in the database * update github.com/grafana/grafana-cloud-migration-snapshot to v1.9.0 * make update-workspace * use new field name in test * return error after call to fmt.Errorf * create methods for readability / fix session deletiong not deleting snapshots * remove debugging changes * update sample.ini * update tests to include OrgID in ListSnapshotsQuery * lint * lint * Update pkg/services/cloudmigration/cloudmigrationimpl/snapshot_mgmt.go Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com> * remove TODO * Update pkg/services/cloudmigration/cloudmigrationimpl/snapshot_mgmt.go Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com> * remove one of the debug logs --------- Co-authored-by: Matheus Macabu <macabu@users.noreply.github.com>
This commit is contained in:
@@ -1,13 +1,18 @@
|
||||
package cloudmigrationimpl
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
cryptoRand "crypto/rand"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
snapshot "github.com/grafana/grafana-cloud-migration-snapshot/src"
|
||||
"github.com/grafana/grafana-cloud-migration-snapshot/src/contracts"
|
||||
"github.com/grafana/grafana-cloud-migration-snapshot/src/infra/crypto"
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/services/cloudmigration"
|
||||
fakeSecrets "github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
@@ -15,6 +20,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/crypto/nacl/box"
|
||||
)
|
||||
|
||||
func Test_GetAllCloudMigrationSessions(t *testing.T) {
|
||||
@@ -112,17 +118,18 @@ func Test_SnapshotManagement(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// create a snapshot
|
||||
uid := uuid.NewString()
|
||||
cmr := cloudmigration.CloudMigrationSnapshot{
|
||||
UID: uid,
|
||||
SessionUID: session.UID,
|
||||
Status: cloudmigration.SnapshotStatusCreating,
|
||||
}
|
||||
|
||||
snapshotUid, err := s.CreateSnapshot(ctx, cmr)
|
||||
err = s.CreateSnapshot(ctx, cmr)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, snapshotUid)
|
||||
|
||||
//retrieve it from the db
|
||||
snapshot, err := s.GetSnapshotByUID(ctx, 1, session.UID, snapshotUid, cloudmigration.SnapshotResultQueryParams{
|
||||
snapshot, err := s.GetSnapshotByUID(ctx, 1, session.UID, uid, cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 1,
|
||||
ResultLimit: 100,
|
||||
SortColumn: cloudmigration.SortColumnID,
|
||||
@@ -132,11 +139,11 @@ func Test_SnapshotManagement(t *testing.T) {
|
||||
require.Equal(t, cloudmigration.SnapshotStatusCreating, snapshot.Status)
|
||||
|
||||
// update its status
|
||||
err = s.UpdateSnapshot(ctx, cloudmigration.UpdateSnapshotCmd{UID: snapshotUid, Status: cloudmigration.SnapshotStatusCreating, SessionID: session.UID})
|
||||
err = s.UpdateSnapshot(ctx, cloudmigration.UpdateSnapshotCmd{UID: uid, Status: cloudmigration.SnapshotStatusCreating, SessionID: session.UID})
|
||||
require.NoError(t, err)
|
||||
|
||||
//retrieve it again
|
||||
snapshot, err = s.GetSnapshotByUID(ctx, 1, session.UID, snapshotUid, cloudmigration.SnapshotResultQueryParams{
|
||||
snapshot, err = s.GetSnapshotByUID(ctx, 1, session.UID, uid, cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 1,
|
||||
ResultLimit: 100,
|
||||
SortColumn: cloudmigration.SortColumnID,
|
||||
@@ -152,11 +159,11 @@ func Test_SnapshotManagement(t *testing.T) {
|
||||
require.Equal(t, *snapshot, snapshots[0])
|
||||
|
||||
// delete snapshot
|
||||
err = s.deleteSnapshot(ctx, snapshotUid)
|
||||
err = s.deleteSnapshot(ctx, uid)
|
||||
require.NoError(t, err)
|
||||
|
||||
// now we expect not to find the snapshot
|
||||
snapshot, err = s.GetSnapshotByUID(ctx, 1, session.UID, snapshotUid, cloudmigration.SnapshotResultQueryParams{
|
||||
snapshot, err = s.GetSnapshotByUID(ctx, 1, session.UID, uid, cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 1,
|
||||
ResultLimit: 100,
|
||||
SortColumn: cloudmigration.SortColumnID,
|
||||
@@ -174,12 +181,13 @@ func Test_SnapshotManagement(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// create a snapshot
|
||||
snapshotUid, err := s.CreateSnapshot(ctx, cloudmigration.CloudMigrationSnapshot{
|
||||
uid := uuid.NewString()
|
||||
err = s.CreateSnapshot(ctx, cloudmigration.CloudMigrationSnapshot{
|
||||
UID: uid,
|
||||
SessionUID: session.UID,
|
||||
Status: cloudmigration.SnapshotStatusCreating,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, snapshotUid)
|
||||
|
||||
// Generate 50,001 test resources in order to test both update conditions (reached the batch limit or reached the end)
|
||||
const numResources = 50001
|
||||
@@ -196,7 +204,7 @@ func Test_SnapshotManagement(t *testing.T) {
|
||||
|
||||
// Update the snapshot with the resources to create
|
||||
err = s.UpdateSnapshot(ctx, cloudmigration.UpdateSnapshotCmd{
|
||||
UID: snapshotUid,
|
||||
UID: uid,
|
||||
Status: cloudmigration.SnapshotStatusPendingUpload,
|
||||
SessionID: session.UID,
|
||||
LocalResourcesToCreate: resources,
|
||||
@@ -204,7 +212,7 @@ func Test_SnapshotManagement(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Get the Snapshot and ensure it's in the right state
|
||||
snapshot, err := s.GetSnapshotByUID(ctx, 1, session.UID, snapshotUid, cloudmigration.SnapshotResultQueryParams{
|
||||
snapshot, err := s.GetSnapshotByUID(ctx, 1, session.UID, uid, cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 1,
|
||||
ResultLimit: numResources,
|
||||
SortColumn: cloudmigration.SortColumnID,
|
||||
@@ -226,7 +234,7 @@ func Test_SnapshotManagement(t *testing.T) {
|
||||
|
||||
// Update the snapshot with the resources to update
|
||||
err = s.UpdateSnapshot(ctx, cloudmigration.UpdateSnapshotCmd{
|
||||
UID: snapshotUid,
|
||||
UID: uid,
|
||||
Status: cloudmigration.SnapshotStatusFinished,
|
||||
SessionID: session.UID,
|
||||
CloudResourcesToUpdate: snapshot.Resources,
|
||||
@@ -234,7 +242,7 @@ func Test_SnapshotManagement(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Get the Snapshot and ensure it's in the right state
|
||||
snapshot, err = s.GetSnapshotByUID(ctx, 1, session.UID, snapshotUid, cloudmigration.SnapshotResultQueryParams{
|
||||
snapshot, err = s.GetSnapshotByUID(ctx, 1, session.UID, uid, cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 1,
|
||||
ResultLimit: numResources,
|
||||
SortColumn: cloudmigration.SortColumnID,
|
||||
@@ -637,7 +645,7 @@ func TestGetSnapshotList(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("return no snapshots if limit is set to 0", func(t *testing.T) {
|
||||
snapshots, err := s.GetSnapshotList(ctx, cloudmigration.ListSnapshotsQuery{SessionUID: sessionUID, Page: 1, Limit: 0})
|
||||
snapshots, err := s.GetSnapshotList(ctx, cloudmigration.ListSnapshotsQuery{SessionUID: sessionUID, OrgID: 1, Page: 1, Limit: 0})
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, snapshots)
|
||||
})
|
||||
@@ -669,7 +677,7 @@ func TestGetSnapshotList(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("only the snapshots that belong to a specific session are returned", func(t *testing.T) {
|
||||
snapshots, err := s.GetSnapshotList(ctx, cloudmigration.ListSnapshotsQuery{SessionUID: "session-uid-that-doesnt-exist", Page: 1, Limit: 100})
|
||||
snapshots, err := s.GetSnapshotList(ctx, cloudmigration.ListSnapshotsQuery{SessionUID: "session-uid-that-doesnt-exist", OrgID: 1, Page: 1, Limit: 100})
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, snapshots)
|
||||
})
|
||||
@@ -680,7 +688,7 @@ func TestGetSnapshotList(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Fetch the snapshots that belong to the deleted session.
|
||||
snapshots, err := s.GetSnapshotList(ctx, cloudmigration.ListSnapshotsQuery{SessionUID: sessionUID, Page: 1, Limit: 100})
|
||||
snapshots, err := s.GetSnapshotList(ctx, cloudmigration.ListSnapshotsQuery{SessionUID: sessionUID, OrgID: 1, Page: 1, Limit: 100})
|
||||
require.NoError(t, err)
|
||||
|
||||
// No snapshots should be returned because the session that
|
||||
@@ -801,3 +809,42 @@ func setUpTest(t *testing.T) (*sqlstore.SQLStore, *sqlStore) {
|
||||
func encodeToken(t string) string {
|
||||
return base64.StdEncoding.EncodeToString([]byte(t))
|
||||
}
|
||||
|
||||
func TestEncodeDecode(t *testing.T) {
|
||||
gmsPublicKey, gmsPrivateKey, err := box.GenerateKey(cryptoRand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
grafanaPublicKey, grafanaPrivateKey, err := box.GenerateKey(cryptoRand.Reader)
|
||||
require.NoError(t, err)
|
||||
|
||||
snapshotWriter, err := snapshot.NewSnapshotWriter(contracts.AssymetricKeys{
|
||||
Public: gmsPublicKey[:],
|
||||
Private: grafanaPrivateKey[:],
|
||||
},
|
||||
crypto.NewNacl(),
|
||||
"",
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
chunk := []snapshot.MigrateDataRequestItemDTO{{
|
||||
Type: snapshot.AlertRuleGroupType,
|
||||
RefID: "foo",
|
||||
Name: "name",
|
||||
Data: map[string]any{"a": "b"},
|
||||
}}
|
||||
encoded, err := snapshotWriter.EncodePartition(chunk)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, snapshotWriter.Write("RESOURCE_TYPE", chunk))
|
||||
|
||||
reader := snapshot.NewSnapshotReader(contracts.AssymetricKeys{
|
||||
Public: grafanaPublicKey[:],
|
||||
Private: gmsPrivateKey[:],
|
||||
},
|
||||
crypto.NewNacl())
|
||||
|
||||
partition, err := reader.ReadFile(bytes.NewReader(encoded))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, chunk, partition.Items)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user