CloudMigrations: Add sorting and error filtering to Snapshot Results backend (#102753)
* implement sorting * swagger gen * minor fixes * clean up param reading * add todo * add errors only prop * codegen stuff * fix copy paste error * forgot the api gen * cleanup * remove tests that are obe * fix test
This commit is contained in:
@@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
@@ -364,19 +365,25 @@ func (cma *CloudMigrationAPI) GetSnapshot(c *contextmodel.ReqContext) response.R
|
||||
return response.ErrOrFallback(http.StatusBadRequest, "invalid snapshot uid", err)
|
||||
}
|
||||
|
||||
page := getQueryPageParams(c.QueryInt("resultPage"), cloudmigration.ResultPage(1))
|
||||
lim := getQueryPageParams(c.QueryInt("resultLimit"), cloudmigration.ResultLimit(100))
|
||||
col := getQueryCol(c.Query("resultSortColumn"), cloudmigration.SortColumnID)
|
||||
order := getQueryOrder(c.Query("resultSortOrder"), cloudmigration.SortOrderAsc)
|
||||
errorsOnly := c.QueryBool("errorsOnly")
|
||||
|
||||
q := cloudmigration.GetSnapshotsQuery{
|
||||
SnapshotUID: snapshotUid,
|
||||
SessionUID: sessUid,
|
||||
ResultPage: c.QueryInt("resultPage"),
|
||||
ResultLimit: c.QueryInt("resultLimit"),
|
||||
OrgID: c.SignedInUser.OrgID,
|
||||
SnapshotResultQueryParams: cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: page,
|
||||
ResultLimit: lim,
|
||||
SortColumn: col,
|
||||
SortOrder: order,
|
||||
ErrorsOnly: errorsOnly,
|
||||
},
|
||||
}
|
||||
if q.ResultLimit == 0 {
|
||||
q.ResultLimit = 100
|
||||
}
|
||||
if q.ResultPage < 1 {
|
||||
q.ResultPage = 1
|
||||
}
|
||||
|
||||
snapshot, err := cma.cloudMigrationService.GetSnapshot(ctx, q)
|
||||
if err != nil {
|
||||
span.SetStatus(codes.Error, "error retrieving snapshot")
|
||||
@@ -387,6 +394,7 @@ func (cma *CloudMigrationAPI) GetSnapshot(c *contextmodel.ReqContext) response.R
|
||||
|
||||
results := snapshot.Resources
|
||||
|
||||
// convert the results to DTOs
|
||||
dtoResults := make([]MigrateDataResponseItemDTO, len(results))
|
||||
for i := 0; i < len(results); i++ {
|
||||
dtoResults[i] = MigrateDataResponseItemDTO{
|
||||
@@ -427,6 +435,43 @@ func (cma *CloudMigrationAPI) GetSnapshot(c *contextmodel.ReqContext) response.R
|
||||
return response.JSON(http.StatusOK, respDto)
|
||||
}
|
||||
|
||||
type PageParam interface {
|
||||
~int // any int or underlying int type
|
||||
}
|
||||
|
||||
func getQueryPageParams[D PageParam](page int, def D) D {
|
||||
if page < 1 || page > 10000 {
|
||||
return def
|
||||
}
|
||||
return D(page)
|
||||
}
|
||||
|
||||
func getQueryCol(col string, defaultCol cloudmigration.ResultSortColumn) cloudmigration.ResultSortColumn {
|
||||
switch strings.ToLower(col) {
|
||||
case string(cloudmigration.SortColumnID):
|
||||
return cloudmigration.SortColumnID
|
||||
case string(cloudmigration.SortColumnName):
|
||||
return cloudmigration.SortColumnName
|
||||
case string(cloudmigration.SortColumnType):
|
||||
return cloudmigration.SortColumnType
|
||||
case string(cloudmigration.SortColumnStatus):
|
||||
return cloudmigration.SortColumnStatus
|
||||
default:
|
||||
return defaultCol
|
||||
}
|
||||
}
|
||||
|
||||
func getQueryOrder(order string, defaultOrder cloudmigration.SortOrder) cloudmigration.SortOrder {
|
||||
switch strings.ToUpper(order) {
|
||||
case string(cloudmigration.SortOrderAsc):
|
||||
return cloudmigration.SortOrderAsc
|
||||
case string(cloudmigration.SortOrderDesc):
|
||||
return cloudmigration.SortOrderDesc
|
||||
default:
|
||||
return defaultOrder
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /cloudmigration/migration/{uid}/snapshots migrations getShapshotList
|
||||
//
|
||||
// Get a list of snapshots for a session.
|
||||
@@ -450,16 +495,11 @@ func (cma *CloudMigrationAPI) GetSnapshotList(c *contextmodel.ReqContext) respon
|
||||
}
|
||||
q := cloudmigration.ListSnapshotsQuery{
|
||||
SessionUID: uid,
|
||||
Limit: c.QueryInt("limit"),
|
||||
Page: c.QueryInt("page"),
|
||||
Sort: c.Query("sort"),
|
||||
OrgID: c.SignedInUser.OrgID,
|
||||
}
|
||||
if q.Limit == 0 {
|
||||
q.Limit = 100
|
||||
}
|
||||
if q.Page < 1 {
|
||||
q.Page = 1
|
||||
Limit: getQueryPageParams(c.QueryInt("limit"), 100),
|
||||
Page: getQueryPageParams(c.QueryInt("page"), 1),
|
||||
// TODO: change to pattern used by GetSnapshot results
|
||||
Sort: c.Query("sort"),
|
||||
OrgID: c.SignedInUser.OrgID,
|
||||
}
|
||||
|
||||
snapshotList, err := cma.cloudMigrationService.GetSnapshotList(ctx, q)
|
||||
|
||||
@@ -601,3 +601,138 @@ func runSimpleApiTest(tt TestCase) func(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetQueryPageParams(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
page int
|
||||
def int
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
name: "returns default when page is 0",
|
||||
page: 0,
|
||||
def: 1,
|
||||
expected: 1,
|
||||
},
|
||||
{
|
||||
name: "returns default when page is negative",
|
||||
page: -1,
|
||||
def: 1,
|
||||
expected: 1,
|
||||
},
|
||||
{
|
||||
name: "returns default when page exceeds max",
|
||||
page: 10001,
|
||||
def: 1,
|
||||
expected: 1,
|
||||
},
|
||||
{
|
||||
name: "returns page when within valid range",
|
||||
page: 100,
|
||||
def: 1,
|
||||
expected: 100,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := getQueryPageParams(tt.page, tt.def)
|
||||
require.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetQueryCol(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
col string
|
||||
defaultCol cloudmigration.ResultSortColumn
|
||||
expected cloudmigration.ResultSortColumn
|
||||
}{
|
||||
{
|
||||
name: "returns id column",
|
||||
col: "id",
|
||||
defaultCol: cloudmigration.SortColumnName,
|
||||
expected: cloudmigration.SortColumnID,
|
||||
},
|
||||
{
|
||||
name: "returns name column",
|
||||
col: "name",
|
||||
defaultCol: cloudmigration.SortColumnID,
|
||||
expected: cloudmigration.SortColumnName,
|
||||
},
|
||||
{
|
||||
name: "returns type column",
|
||||
col: "resource_type",
|
||||
defaultCol: cloudmigration.SortColumnID,
|
||||
expected: cloudmigration.SortColumnType,
|
||||
},
|
||||
{
|
||||
name: "returns status column",
|
||||
col: "status",
|
||||
defaultCol: cloudmigration.SortColumnID,
|
||||
expected: cloudmigration.SortColumnStatus,
|
||||
},
|
||||
{
|
||||
name: "returns default for unknown column",
|
||||
col: "unknown",
|
||||
defaultCol: cloudmigration.SortColumnID,
|
||||
expected: cloudmigration.SortColumnID,
|
||||
},
|
||||
{
|
||||
name: "case insensitive column matching",
|
||||
col: "NaMe",
|
||||
defaultCol: cloudmigration.SortColumnID,
|
||||
expected: cloudmigration.SortColumnName,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := getQueryCol(tt.col, tt.defaultCol)
|
||||
require.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetQueryOrder(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
order string
|
||||
defaultOrder cloudmigration.SortOrder
|
||||
expected cloudmigration.SortOrder
|
||||
}{
|
||||
{
|
||||
name: "returns ASC order",
|
||||
order: "ASC",
|
||||
defaultOrder: cloudmigration.SortOrderDesc,
|
||||
expected: cloudmigration.SortOrderAsc,
|
||||
},
|
||||
{
|
||||
name: "returns DESC order",
|
||||
order: "DESC",
|
||||
defaultOrder: cloudmigration.SortOrderAsc,
|
||||
expected: cloudmigration.SortOrderDesc,
|
||||
},
|
||||
{
|
||||
name: "returns default for unknown order",
|
||||
order: "unknown",
|
||||
defaultOrder: cloudmigration.SortOrderAsc,
|
||||
expected: cloudmigration.SortOrderAsc,
|
||||
},
|
||||
{
|
||||
name: "case insensitive order matching",
|
||||
order: "aSc",
|
||||
defaultOrder: cloudmigration.SortOrderDesc,
|
||||
expected: cloudmigration.SortOrderAsc,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := getQueryOrder(tt.order, tt.defaultOrder)
|
||||
require.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,6 +295,24 @@ type GetSnapshotParams struct {
|
||||
// default: 100
|
||||
ResultLimit int `json:"resultLimit"`
|
||||
|
||||
// ResultSortColumn can be used to override the default system sort. Valid values are "name", "resource_type", and "status".
|
||||
// in:query
|
||||
// required:false
|
||||
// default: default
|
||||
ResultSortColumn string `json:"resultSortColumn"`
|
||||
|
||||
// ResultSortOrder is used with ResultSortColumn. Valid values are ASC and DESC.
|
||||
// in:query
|
||||
// required:false
|
||||
// default: ASC
|
||||
ResultSortOrder string `json:"resultSortOrder"`
|
||||
|
||||
// ErrorsOnly is used to only return resources with error statuses
|
||||
// in:query
|
||||
// required:false
|
||||
// default: false
|
||||
ErrorsOnly bool `json:"errorsOnly"`
|
||||
|
||||
// Session UID of a session
|
||||
// in: path
|
||||
UID string `json:"uid"`
|
||||
|
||||
@@ -566,7 +566,7 @@ func (s *Service) GetSnapshot(ctx context.Context, query cloudmigration.GetSnaps
|
||||
defer span.End()
|
||||
|
||||
orgID, sessionUid, snapshotUid := query.OrgID, query.SessionUID, query.SnapshotUID
|
||||
snapshot, err := s.store.GetSnapshotByUID(ctx, orgID, sessionUid, snapshotUid, query.ResultPage, query.ResultLimit)
|
||||
snapshot, err := s.store.GetSnapshotByUID(ctx, orgID, sessionUid, snapshotUid, query.SnapshotResultQueryParams)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fetching snapshot for uid %s: %w", snapshotUid, err)
|
||||
}
|
||||
@@ -615,7 +615,7 @@ func (s *Service) GetSnapshot(ctx context.Context, query cloudmigration.GetSnaps
|
||||
}
|
||||
|
||||
// Refresh the snapshot after the update
|
||||
snapshot, err = s.store.GetSnapshotByUID(ctx, orgID, sessionUid, snapshotUid, query.ResultPage, query.ResultLimit)
|
||||
snapshot, err = s.store.GetSnapshotByUID(ctx, orgID, sessionUid, snapshotUid, query.SnapshotResultQueryParams)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fetching snapshot for uid %s: %w", snapshotUid, err)
|
||||
}
|
||||
|
||||
@@ -343,6 +343,12 @@ func Test_GetSnapshotStatusFromGMS(t *testing.T) {
|
||||
snapshot, err = s.GetSnapshot(context.Background(), cloudmigration.GetSnapshotsQuery{
|
||||
SnapshotUID: snapshotUID,
|
||||
SessionUID: sessionUID,
|
||||
SnapshotResultQueryParams: cloudmigration.SnapshotResultQueryParams{
|
||||
ResultLimit: 10,
|
||||
ResultPage: 1,
|
||||
SortColumn: cloudmigration.SortColumnID,
|
||||
SortOrder: cloudmigration.SortOrderAsc,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, snapshot)
|
||||
|
||||
@@ -14,6 +14,6 @@ type store interface {
|
||||
|
||||
CreateSnapshot(ctx context.Context, snapshot cloudmigration.CloudMigrationSnapshot) (string, error)
|
||||
UpdateSnapshot(ctx context.Context, snapshot cloudmigration.UpdateSnapshotCmd) error
|
||||
GetSnapshotByUID(ctx context.Context, orgID int64, sessUid, id string, resultPage int, resultLimit int) (*cloudmigration.CloudMigrationSnapshot, error)
|
||||
GetSnapshotByUID(ctx context.Context, orgID int64, sessUid, id string, params cloudmigration.SnapshotResultQueryParams) (*cloudmigration.CloudMigrationSnapshot, error)
|
||||
GetSnapshotList(ctx context.Context, query cloudmigration.ListSnapshotsQuery) ([]cloudmigration.CloudMigrationSnapshot, error)
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ func (ss *sqlStore) deleteSnapshot(ctx context.Context, snapshotUid string) erro
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *sqlStore) GetSnapshotByUID(ctx context.Context, orgID int64, sessionUid, uid string, resultPage int, resultLimit int) (*cloudmigration.CloudMigrationSnapshot, error) {
|
||||
func (ss *sqlStore) GetSnapshotByUID(ctx context.Context, orgID int64, sessionUid, uid string, params cloudmigration.SnapshotResultQueryParams) (*cloudmigration.CloudMigrationSnapshot, error) {
|
||||
// first we check if the session exists, using orgId and sessionUid
|
||||
session, err := ss.GetMigrationSessionByUID(ctx, orgID, sessionUid)
|
||||
if err != nil || session == nil {
|
||||
@@ -272,7 +272,7 @@ func (ss *sqlStore) GetSnapshotByUID(ctx context.Context, orgID int64, sessionUi
|
||||
snapshot.EncryptionKey = []byte(secret)
|
||||
}
|
||||
|
||||
resources, err := ss.getSnapshotResources(ctx, uid, resultPage, resultLimit)
|
||||
resources, err := ss.getSnapshotResources(ctx, uid, params)
|
||||
if err == nil {
|
||||
snapshot.Resources = resources
|
||||
}
|
||||
@@ -421,19 +421,17 @@ func (ss *sqlStore) UpdateSnapshotResources(ctx context.Context, snapshotUid str
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *sqlStore) getSnapshotResources(ctx context.Context, snapshotUid string, page int, limit int) ([]cloudmigration.CloudMigrationResource, error) {
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if limit == 0 {
|
||||
limit = 100
|
||||
}
|
||||
func (ss *sqlStore) getSnapshotResources(ctx context.Context, snapshotUid string, params cloudmigration.SnapshotResultQueryParams) ([]cloudmigration.CloudMigrationResource, error) {
|
||||
page, limit, col, dir, errorsOnly := int(params.ResultPage), int(params.ResultLimit), string(params.SortColumn), string(params.SortOrder), params.ErrorsOnly
|
||||
|
||||
var resources []cloudmigration.CloudMigrationResource
|
||||
err := ss.db.WithDbSession(ctx, func(sess *db.Session) error {
|
||||
offset := (page - 1) * limit
|
||||
sess.Limit(limit, offset)
|
||||
return sess.OrderBy("id ASC").Find(&resources, &cloudmigration.CloudMigrationResource{
|
||||
if errorsOnly {
|
||||
sess.Where("status = ?", cloudmigration.ItemStatusError)
|
||||
}
|
||||
return sess.OrderBy(fmt.Sprintf("%s %s", col, dir)).Find(&resources, &cloudmigration.CloudMigrationResource{
|
||||
SnapshotUID: snapshotUid,
|
||||
})
|
||||
})
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/services/cloudmigration"
|
||||
fakeSecrets "github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
secretskv "github.com/grafana/grafana/pkg/services/secrets/kvstore"
|
||||
@@ -138,7 +139,12 @@ func Test_SnapshotManagement(t *testing.T) {
|
||||
require.NotEmpty(t, snapshotUid)
|
||||
|
||||
//retrieve it from the db
|
||||
snapshot, err := s.GetSnapshotByUID(ctx, 1, session.UID, snapshotUid, 0, 0)
|
||||
snapshot, err := s.GetSnapshotByUID(ctx, 1, session.UID, snapshotUid, cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 1,
|
||||
ResultLimit: 100,
|
||||
SortColumn: cloudmigration.SortColumnID,
|
||||
SortOrder: cloudmigration.SortOrderAsc,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, cloudmigration.SnapshotStatusCreating, snapshot.Status)
|
||||
|
||||
@@ -147,7 +153,12 @@ func Test_SnapshotManagement(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
//retrieve it again
|
||||
snapshot, err = s.GetSnapshotByUID(ctx, 1, session.UID, snapshotUid, 0, 0)
|
||||
snapshot, err = s.GetSnapshotByUID(ctx, 1, session.UID, snapshotUid, cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 1,
|
||||
ResultLimit: 100,
|
||||
SortColumn: cloudmigration.SortColumnID,
|
||||
SortOrder: cloudmigration.SortOrderAsc,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, cloudmigration.SnapshotStatusCreating, snapshot.Status)
|
||||
|
||||
@@ -162,7 +173,12 @@ func Test_SnapshotManagement(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// now we expect not to find the snapshot
|
||||
snapshot, err = s.GetSnapshotByUID(ctx, 1, session.UID, snapshotUid, 0, 0)
|
||||
snapshot, err = s.GetSnapshotByUID(ctx, 1, session.UID, snapshotUid, cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 1,
|
||||
ResultLimit: 100,
|
||||
SortColumn: cloudmigration.SortColumnID,
|
||||
SortOrder: cloudmigration.SortOrderAsc,
|
||||
})
|
||||
require.ErrorIs(t, err, cloudmigration.ErrSnapshotNotFound)
|
||||
require.Nil(t, snapshot)
|
||||
})
|
||||
@@ -174,9 +190,14 @@ func Test_SnapshotResources(t *testing.T) {
|
||||
_, s := setUpTest(t)
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("tests CRUD of snapshot resources", func(t *testing.T) {
|
||||
t.Run("test CRUD of snapshot resources", func(t *testing.T) {
|
||||
// Get the default rows from the test
|
||||
resources, err := s.getSnapshotResources(ctx, "poiuy", 0, 100)
|
||||
resources, err := s.getSnapshotResources(ctx, "poiuy", cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 1,
|
||||
ResultLimit: 100,
|
||||
SortColumn: cloudmigration.SortColumnID,
|
||||
SortOrder: cloudmigration.SortOrderAsc,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, resources, 3)
|
||||
for _, r := range resources {
|
||||
@@ -204,7 +225,12 @@ func Test_SnapshotResources(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Get resources again
|
||||
resources, err = s.getSnapshotResources(ctx, "poiuy", 0, 100)
|
||||
resources, err = s.getSnapshotResources(ctx, "poiuy", cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 1,
|
||||
ResultLimit: 100,
|
||||
SortColumn: cloudmigration.SortColumnID,
|
||||
SortOrder: cloudmigration.SortOrderAsc,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, resources, 4)
|
||||
// ensure existing resource was updated from ERROR
|
||||
@@ -240,10 +266,97 @@ func Test_SnapshotResources(t *testing.T) {
|
||||
err = s.deleteSnapshotResources(ctx, "poiuy")
|
||||
assert.NoError(t, err)
|
||||
// make sure they're gone
|
||||
resources, err = s.getSnapshotResources(ctx, "poiuy", 0, 100)
|
||||
resources, err = s.getSnapshotResources(ctx, "poiuy", cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 1,
|
||||
ResultLimit: 100,
|
||||
SortColumn: cloudmigration.SortColumnID,
|
||||
SortOrder: cloudmigration.SortOrderAsc,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, resources, 0)
|
||||
})
|
||||
|
||||
t.Run("test pagination and sorting", func(t *testing.T) {
|
||||
// Create test data
|
||||
resources := []cloudmigration.CloudMigrationResource{
|
||||
{UID: "1", SnapshotUID: "abc123", Name: "Dashboard 1", Type: cloudmigration.DashboardDataType, Status: cloudmigration.ItemStatusOK},
|
||||
{UID: "2", SnapshotUID: "abc123", Name: "Alert 1", Type: cloudmigration.AlertRuleType, Status: cloudmigration.ItemStatusError},
|
||||
{UID: "3", SnapshotUID: "abc123", Name: "Dashboard 2", Type: cloudmigration.DashboardDataType, Status: cloudmigration.ItemStatusPending},
|
||||
{UID: "4", SnapshotUID: "abc123", Name: "Folder 1", Type: cloudmigration.FolderDataType, Status: cloudmigration.ItemStatusOK},
|
||||
{UID: "5", SnapshotUID: "abc123", Name: "Alert 2", Type: cloudmigration.AlertRuleType, Status: cloudmigration.ItemStatusOK},
|
||||
}
|
||||
|
||||
err := s.db.WithDbSession(ctx, func(sess *db.Session) error {
|
||||
_, err := sess.Insert(resources)
|
||||
return err
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("default sorting and paging and default params", func(t *testing.T) {
|
||||
results, err := s.getSnapshotResources(ctx, "abc123", cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 1,
|
||||
ResultLimit: 100,
|
||||
SortColumn: cloudmigration.SortColumnID,
|
||||
SortOrder: cloudmigration.SortOrderAsc,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, results, 5)
|
||||
// Default sort is by ID ascending
|
||||
assert.Equal(t, "1", results[0].UID)
|
||||
assert.Equal(t, "5", results[4].UID)
|
||||
})
|
||||
|
||||
t.Run("sort by name descending", func(t *testing.T) {
|
||||
results, err := s.getSnapshotResources(ctx, "abc123", cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 1,
|
||||
ResultLimit: 100,
|
||||
SortColumn: cloudmigration.SortColumnName,
|
||||
SortOrder: cloudmigration.SortOrderDesc,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "Folder 1", results[0].Name)
|
||||
assert.Equal(t, "Alert 1", results[4].Name)
|
||||
})
|
||||
|
||||
t.Run("sort by type ascending", func(t *testing.T) {
|
||||
results, err := s.getSnapshotResources(ctx, "abc123", cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 1,
|
||||
ResultLimit: 100,
|
||||
SortColumn: cloudmigration.SortColumnType,
|
||||
SortOrder: cloudmigration.SortOrderAsc,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "2", results[0].UID)
|
||||
assert.Equal(t, "5", results[1].UID)
|
||||
})
|
||||
|
||||
t.Run("sort by status with pagination", func(t *testing.T) {
|
||||
results, err := s.getSnapshotResources(ctx, "abc123", cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 2,
|
||||
ResultLimit: 2,
|
||||
SortColumn: cloudmigration.SortColumnStatus,
|
||||
SortOrder: cloudmigration.SortOrderAsc,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, results, 2)
|
||||
// secondary sort is by ID ascending by default
|
||||
assert.Equal(t, "4", results[0].UID)
|
||||
assert.Equal(t, "5", results[1].UID)
|
||||
})
|
||||
|
||||
t.Run("only errors filter returns only error status resources", func(t *testing.T) {
|
||||
results, err := s.getSnapshotResources(ctx, "abc123", cloudmigration.SnapshotResultQueryParams{
|
||||
ResultPage: 1,
|
||||
ResultLimit: 100,
|
||||
SortColumn: cloudmigration.SortColumnID,
|
||||
SortOrder: cloudmigration.SortOrderAsc,
|
||||
ErrorsOnly: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, results, 1)
|
||||
assert.Equal(t, "2", results[0].UID)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetSnapshotList(t *testing.T) {
|
||||
|
||||
@@ -162,12 +162,41 @@ type CloudMigrationSessionListResponse struct {
|
||||
Sessions []CloudMigrationSessionResponse
|
||||
}
|
||||
|
||||
type ResultSortColumn string
|
||||
|
||||
const (
|
||||
SortColumnID ResultSortColumn = "id"
|
||||
SortColumnName ResultSortColumn = "name"
|
||||
SortColumnType ResultSortColumn = "resource_type"
|
||||
SortColumnStatus ResultSortColumn = "status"
|
||||
)
|
||||
|
||||
type SortOrder string
|
||||
|
||||
const (
|
||||
SortOrderAsc SortOrder = "ASC"
|
||||
SortOrderDesc SortOrder = "DESC"
|
||||
)
|
||||
|
||||
// ResultPage should be in the range [1, 10000]
|
||||
type ResultPage int
|
||||
|
||||
// ResultLimit should be in the rage [1, 10000]
|
||||
type ResultLimit int
|
||||
|
||||
type SnapshotResultQueryParams struct {
|
||||
ResultPage ResultPage
|
||||
ResultLimit ResultLimit
|
||||
SortColumn ResultSortColumn
|
||||
SortOrder SortOrder
|
||||
ErrorsOnly bool
|
||||
}
|
||||
|
||||
type GetSnapshotsQuery struct {
|
||||
SnapshotUID string
|
||||
OrgID int64
|
||||
SessionUID string
|
||||
ResultPage int
|
||||
ResultLimit int
|
||||
SnapshotResultQueryParams
|
||||
}
|
||||
|
||||
type ListSnapshotsQuery struct {
|
||||
|
||||
@@ -2457,6 +2457,27 @@
|
||||
"name": "resultLimit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"default": "default",
|
||||
"description": "ResultSortColumn can be used to override the default system sort. Valid values are \"name\", \"resource_type\", and \"status\".",
|
||||
"name": "resultSortColumn",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"default": "ASC",
|
||||
"description": "ResultSortOrder is used with ResultSortColumn. Valid values are ASC and DESC.",
|
||||
"name": "resultSortOrder",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "ErrorsOnly is used to only return resources with error statuses",
|
||||
"name": "errorsOnly",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Session UID of a session",
|
||||
|
||||
@@ -4,3 +4,5 @@ The [`endpoints.gen.ts`](./endpoints.gen.ts) file is machine generated. In order
|
||||
|
||||
- Run: `make swagger-clean && make openapi3-gen`
|
||||
- Run: `yarn generate-apis`
|
||||
|
||||
If you run into issues, try updating your Node.js version.
|
||||
|
||||
@@ -26,6 +26,9 @@ const injectedRtkApi = api.injectEndpoints({
|
||||
params: {
|
||||
resultPage: queryArg.resultPage,
|
||||
resultLimit: queryArg.resultLimit,
|
||||
resultSortColumn: queryArg.resultSortColumn,
|
||||
resultSortOrder: queryArg.resultSortOrder,
|
||||
errorsOnly: queryArg.errorsOnly,
|
||||
},
|
||||
}),
|
||||
}),
|
||||
@@ -97,6 +100,12 @@ export type GetSnapshotApiArg = {
|
||||
resultPage?: number;
|
||||
/** Max limit for snapshot results returned. */
|
||||
resultLimit?: number;
|
||||
/** ResultSortColumn can be used to override the default system sort. Valid values are "name", "resource_type", and "status". */
|
||||
resultSortColumn?: string;
|
||||
/** ResultSortOrder is used with ResultSortColumn. Valid values are ASC and DESC. */
|
||||
resultSortOrder?: string;
|
||||
/** ErrorsOnly is used to only return resources with error statuses */
|
||||
errorsOnly?: boolean;
|
||||
/** Session UID of a session */
|
||||
uid: string;
|
||||
/** UID of a snapshot */
|
||||
|
||||
@@ -16009,6 +16009,33 @@
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "ResultSortColumn can be used to override the default system sort. Valid values are \"name\", \"resource_type\", and \"status\".",
|
||||
"in": "query",
|
||||
"name": "resultSortColumn",
|
||||
"schema": {
|
||||
"default": "default",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "ResultSortOrder is used with ResultSortColumn. Valid values are ASC and DESC.",
|
||||
"in": "query",
|
||||
"name": "resultSortOrder",
|
||||
"schema": {
|
||||
"default": "ASC",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "ErrorsOnly is used to only return resources with error statuses",
|
||||
"in": "query",
|
||||
"name": "errorsOnly",
|
||||
"schema": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Session UID of a session",
|
||||
"in": "path",
|
||||
|
||||
Reference in New Issue
Block a user