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"`
|
||||
|
||||
Reference in New Issue
Block a user