mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
CloudMigrations: Limit frontend query to get latest snapshots (#93639)
* latest param to endpoint and adapt frontend query * change to sort param * api * remove description
This commit is contained in:
parent
8b6cbae96b
commit
1a31abe254
@ -392,6 +392,7 @@ func (cma *CloudMigrationAPI) GetSnapshotList(c *contextmodel.ReqContext) respon
|
|||||||
SessionUID: uid,
|
SessionUID: uid,
|
||||||
Limit: c.QueryInt("limit"),
|
Limit: c.QueryInt("limit"),
|
||||||
Page: c.QueryInt("page"),
|
Page: c.QueryInt("page"),
|
||||||
|
Sort: c.Query("sort"),
|
||||||
}
|
}
|
||||||
if q.Limit == 0 {
|
if q.Limit == 0 {
|
||||||
q.Limit = 100
|
q.Limit = 100
|
||||||
|
@ -395,7 +395,23 @@ func TestCloudMigrationAPI_GetSnapshotList(t *testing.T) {
|
|||||||
requestUrl: "/api/cloudmigration/migration/1234/snapshots",
|
requestUrl: "/api/cloudmigration/migration/1234/snapshots",
|
||||||
basicRole: org.RoleAdmin,
|
basicRole: org.RoleAdmin,
|
||||||
expectedHttpResult: http.StatusOK,
|
expectedHttpResult: http.StatusOK,
|
||||||
expectedBody: `{"snapshots":[{"uid":"fake_uid","status":"CREATING","sessionUid":"1234","created":"0001-01-01T00:00:00Z","finished":"0001-01-01T00:00:00Z"},{"uid":"fake_uid","status":"CREATING","sessionUid":"1234","created":"0001-01-01T00:00:00Z","finished":"0001-01-01T00:00:00Z"}]}`,
|
expectedBody: `{"snapshots":[{"uid":"fake_uid","status":"CREATING","sessionUid":"1234","created":"2024-06-05T17:30:40Z","finished":"0001-01-01T00:00:00Z"},{"uid":"fake_uid","status":"CREATING","sessionUid":"1234","created":"2024-06-05T18:30:40Z","finished":"0001-01-01T00:00:00Z"}]}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "with limit query param should return 200 if everything is ok",
|
||||||
|
requestHttpMethod: http.MethodGet,
|
||||||
|
requestUrl: "/api/cloudmigration/migration/1234/snapshots?limit=1",
|
||||||
|
basicRole: org.RoleAdmin,
|
||||||
|
expectedHttpResult: http.StatusOK,
|
||||||
|
expectedBody: `{"snapshots":[{"uid":"fake_uid","status":"CREATING","sessionUid":"1234","created":"2024-06-05T17:30:40Z","finished":"0001-01-01T00:00:00Z"}]}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "with sort query param should return 200 if everything is ok",
|
||||||
|
requestHttpMethod: http.MethodGet,
|
||||||
|
requestUrl: "/api/cloudmigration/migration/1234/snapshots?sort=latest",
|
||||||
|
basicRole: org.RoleAdmin,
|
||||||
|
expectedHttpResult: http.StatusOK,
|
||||||
|
expectedBody: `{"snapshots":[{"uid":"fake_uid","status":"CREATING","sessionUid":"1234","created":"2024-06-05T18:30:40Z","finished":"0001-01-01T00:00:00Z"},{"uid":"fake_uid","status":"CREATING","sessionUid":"1234","created":"2024-06-05T17:30:40Z","finished":"0001-01-01T00:00:00Z"}]}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "should return 403 if no used is not admin",
|
desc: "should return 403 if no used is not admin",
|
||||||
|
@ -3,6 +3,7 @@ package fake
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/cloudmigration"
|
"github.com/grafana/grafana/pkg/services/cloudmigration"
|
||||||
@ -108,18 +109,31 @@ func (m FakeServiceImpl) GetSnapshotList(ctx context.Context, query cloudmigrati
|
|||||||
if m.ReturnError {
|
if m.ReturnError {
|
||||||
return nil, fmt.Errorf("mock error")
|
return nil, fmt.Errorf("mock error")
|
||||||
}
|
}
|
||||||
return []cloudmigration.CloudMigrationSnapshot{
|
|
||||||
|
cloudSnapshots := []cloudmigration.CloudMigrationSnapshot{
|
||||||
{
|
{
|
||||||
UID: "fake_uid",
|
UID: "fake_uid",
|
||||||
SessionUID: query.SessionUID,
|
SessionUID: query.SessionUID,
|
||||||
Status: cloudmigration.SnapshotStatusCreating,
|
Status: cloudmigration.SnapshotStatusCreating,
|
||||||
|
Created: time.Date(2024, 6, 5, 17, 30, 40, 0, time.UTC),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
UID: "fake_uid",
|
UID: "fake_uid",
|
||||||
SessionUID: query.SessionUID,
|
SessionUID: query.SessionUID,
|
||||||
Status: cloudmigration.SnapshotStatusCreating,
|
Status: cloudmigration.SnapshotStatusCreating,
|
||||||
|
Created: time.Date(2024, 6, 5, 18, 30, 40, 0, time.UTC),
|
||||||
},
|
},
|
||||||
}, nil
|
}
|
||||||
|
|
||||||
|
if query.Sort == "latest" {
|
||||||
|
sort.Slice(cloudSnapshots, func(first, second int) bool {
|
||||||
|
return cloudSnapshots[first].Created.After(cloudSnapshots[second].Created)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if query.Limit > 0 {
|
||||||
|
return cloudSnapshots[0:min(len(cloudSnapshots), query.Limit)], nil
|
||||||
|
}
|
||||||
|
return cloudSnapshots, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m FakeServiceImpl) UploadSnapshot(ctx context.Context, sessionUid string, snapshotUid string) error {
|
func (m FakeServiceImpl) UploadSnapshot(ctx context.Context, sessionUid string, snapshotUid string) error {
|
||||||
|
@ -23,9 +23,10 @@ type sqlStore struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tableName = "cloud_migration_resource"
|
tableName = "cloud_migration_resource"
|
||||||
secretType = "cloudmigration-snapshot-encryption-key"
|
secretType = "cloudmigration-snapshot-encryption-key"
|
||||||
GetAllSnapshots = -1
|
GetAllSnapshots = -1
|
||||||
|
GetSnapshotListSortingLatest = "latest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ss *sqlStore) GetMigrationSessionByUID(ctx context.Context, uid string) (*cloudmigration.CloudMigrationSession, error) {
|
func (ss *sqlStore) GetMigrationSessionByUID(ctx context.Context, uid string) (*cloudmigration.CloudMigrationSession, error) {
|
||||||
@ -278,7 +279,9 @@ func (ss *sqlStore) GetSnapshotList(ctx context.Context, query cloudmigration.Li
|
|||||||
offset := (query.Page - 1) * query.Limit
|
offset := (query.Page - 1) * query.Limit
|
||||||
sess.Limit(query.Limit, offset)
|
sess.Limit(query.Limit, offset)
|
||||||
}
|
}
|
||||||
sess.OrderBy("cloud_migration_snapshot.created DESC")
|
if query.Sort == GetSnapshotListSortingLatest {
|
||||||
|
sess.OrderBy("cloud_migration_snapshot.created DESC")
|
||||||
|
}
|
||||||
return sess.Find(&snapshots, &cloudmigration.CloudMigrationSnapshot{
|
return sess.Find(&snapshots, &cloudmigration.CloudMigrationSnapshot{
|
||||||
SessionUID: query.SessionUID,
|
SessionUID: query.SessionUID,
|
||||||
})
|
})
|
||||||
|
@ -3,7 +3,6 @@ package cloudmigrationimpl
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"slices"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -241,9 +240,46 @@ func TestGetSnapshotList(t *testing.T) {
|
|||||||
for _, snapshot := range snapshots {
|
for _, snapshot := range snapshots {
|
||||||
ids = append(ids, snapshot.UID)
|
ids = append(ids, snapshot.UID)
|
||||||
}
|
}
|
||||||
slices.Sort(ids)
|
|
||||||
|
|
||||||
// There are 3 snapshots in the db but only 2 of them belong to this specific session.
|
// There are 3 snapshots in the db but only 2 of them belong to this specific session.
|
||||||
|
assert.Equal(t, []string{"poiuy", "lkjhg"}, ids)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("returns only one snapshot that belongs to a session", func(t *testing.T) {
|
||||||
|
snapshots, err := s.GetSnapshotList(ctx, cloudmigration.ListSnapshotsQuery{SessionUID: sessionUID, Page: 1, Limit: 1})
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, snapshots, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
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})
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Empty(t, snapshots)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("returns paginated snapshot that belongs to a session", func(t *testing.T) {
|
||||||
|
snapshots, err := s.GetSnapshotList(ctx, cloudmigration.ListSnapshotsQuery{SessionUID: sessionUID, Page: 2, Limit: 1})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
ids := make([]string, 0)
|
||||||
|
for _, snapshot := range snapshots {
|
||||||
|
ids = append(ids, snapshot.UID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return paginated snapshot of the 2 belonging to this specific session
|
||||||
|
assert.Equal(t, []string{"lkjhg"}, ids)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("returns desc sorted list of snapshots that belong to a session", func(t *testing.T) {
|
||||||
|
snapshots, err := s.GetSnapshotList(ctx, cloudmigration.ListSnapshotsQuery{SessionUID: sessionUID, Page: 1, Limit: 100, Sort: "latest"})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
ids := make([]string, 0)
|
||||||
|
for _, snapshot := range snapshots {
|
||||||
|
ids = append(ids, snapshot.UID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return desc sorted snapshots belonging to this specific session
|
||||||
assert.Equal(t, []string{"lkjhg", "poiuy"}, ids)
|
assert.Equal(t, []string{"lkjhg", "poiuy"}, ids)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -345,7 +381,7 @@ func setUpTest(t *testing.T) (*sqlstore.SQLStore, *sqlStore) {
|
|||||||
cloud_migration_snapshot (session_uid, uid, created, updated, finished, status)
|
cloud_migration_snapshot (session_uid, uid, created, updated, finished, status)
|
||||||
VALUES
|
VALUES
|
||||||
('qwerty', 'poiuy', '2024-03-25 15:30:36.000', '2024-03-27 15:30:43.000', '2024-03-27 15:30:43.000', "finished"),
|
('qwerty', 'poiuy', '2024-03-25 15:30:36.000', '2024-03-27 15:30:43.000', '2024-03-27 15:30:43.000', "finished"),
|
||||||
('qwerty', 'lkjhg', '2024-03-25 15:30:36.000', '2024-03-27 15:30:43.000', '2024-03-27 15:30:43.000', "finished"),
|
('qwerty', 'lkjhg', '2024-03-26 15:30:36.000', '2024-03-27 15:30:43.000', '2024-03-27 15:30:43.000', "finished"),
|
||||||
('zxcvbn', 'mnbvvc', '2024-03-25 15:30:36.000', '2024-03-27 15:30:43.000', '2024-03-27 15:30:43.000', "finished");
|
('zxcvbn', 'mnbvvc', '2024-03-25 15:30:36.000', '2024-03-27 15:30:43.000', '2024-03-27 15:30:43.000', "finished");
|
||||||
`,
|
`,
|
||||||
)
|
)
|
||||||
|
@ -144,6 +144,7 @@ type ListSnapshotsQuery struct {
|
|||||||
SessionUID string
|
SessionUID string
|
||||||
Page int
|
Page int
|
||||||
Limit int
|
Limit int
|
||||||
|
Sort string
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateSnapshotCmd struct {
|
type UpdateSnapshotCmd struct {
|
||||||
|
@ -5416,6 +5416,9 @@
|
|||||||
"message": {
|
"message": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"refId": {
|
"refId": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
@ -41,7 +41,7 @@ const injectedRtkApi = api.injectEndpoints({
|
|||||||
getShapshotList: build.query<GetShapshotListApiResponse, GetShapshotListApiArg>({
|
getShapshotList: build.query<GetShapshotListApiResponse, GetShapshotListApiArg>({
|
||||||
query: (queryArg) => ({
|
query: (queryArg) => ({
|
||||||
url: `/cloudmigration/migration/${queryArg.uid}/snapshots`,
|
url: `/cloudmigration/migration/${queryArg.uid}/snapshots`,
|
||||||
params: { page: queryArg.page, limit: queryArg.limit },
|
params: { page: queryArg.page, limit: queryArg.limit, sort: queryArg.sort },
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
getCloudMigrationToken: build.query<GetCloudMigrationTokenApiResponse, GetCloudMigrationTokenApiArg>({
|
getCloudMigrationToken: build.query<GetCloudMigrationTokenApiResponse, GetCloudMigrationTokenApiArg>({
|
||||||
@ -112,6 +112,8 @@ export type GetShapshotListApiArg = {
|
|||||||
page?: number;
|
page?: number;
|
||||||
/** Max limit for results returned. */
|
/** Max limit for results returned. */
|
||||||
limit?: number;
|
limit?: number;
|
||||||
|
/** Sort with value latest to return results sorted in descending order */
|
||||||
|
sort?: string;
|
||||||
/** Session UID of a session */
|
/** Session UID of a session */
|
||||||
uid: string;
|
uid: string;
|
||||||
};
|
};
|
||||||
|
@ -70,7 +70,9 @@ const PAGE_SIZE = 50;
|
|||||||
function useGetLatestSnapshot(sessionUid?: string, page = 1) {
|
function useGetLatestSnapshot(sessionUid?: string, page = 1) {
|
||||||
const [shouldPoll, setShouldPoll] = useState(false);
|
const [shouldPoll, setShouldPoll] = useState(false);
|
||||||
|
|
||||||
const listResult = useGetShapshotListQuery(sessionUid ? { uid: sessionUid } : skipToken);
|
const listResult = useGetShapshotListQuery(
|
||||||
|
sessionUid ? { uid: sessionUid, page: 1, limit: 1, sort: 'latest' } : skipToken
|
||||||
|
);
|
||||||
const lastItem = listResult.currentData?.snapshots?.at(0);
|
const lastItem = listResult.currentData?.snapshots?.at(0);
|
||||||
|
|
||||||
const getSnapshotQueryArgs =
|
const getSnapshotQueryArgs =
|
||||||
|
Loading…
Reference in New Issue
Block a user