Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions internal/cmd/beta/sqlserverflex/instance/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient sqlserverfle
var flavorId string
var err error

flavors, err := apiClient.ListFlavors(ctx, model.ProjectId, model.Region).Execute()
flavors, err := sqlserverflexUtils.ListAllFlavors(ctx, apiClient, model.ProjectId, model.Region)
if err != nil {
return req, fmt.Errorf("get SQLServer Flex flavors: %w", err)
}

if model.FlavorId == nil {
flavorId, err = sqlserverflexUtils.LoadFlavorId(*model.CPU, *model.RAM, flavors.Flavors)
flavorId, err = sqlserverflexUtils.LoadFlavorId(*model.CPU, *model.RAM, flavors)
if err != nil {
var dsaInvalidPlanError *cliErr.DSAInvalidPlanError
if !errors.As(err, &dsaInvalidPlanError) {
Expand All @@ -201,7 +201,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient sqlserverfle
return req, err
}
} else {
err := sqlserverflexUtils.ValidateFlavorId(*model.FlavorId, flavors.Flavors)
err := sqlserverflexUtils.ValidateFlavorId(*model.FlavorId, flavors)
if err != nil {
return req, err
}
Expand Down
8 changes: 4 additions & 4 deletions internal/cmd/beta/sqlserverflex/instance/update/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient sqlserverfle
var flavorId *string
var err error

flavors, err := apiClient.ListFlavors(ctx, model.ProjectId, model.Region).Execute()
flavors, err := sqlserverflexUtils.ListAllFlavors(ctx, apiClient, model.ProjectId, model.Region)
if err != nil {
return req, fmt.Errorf("get SQLServer Flex flavors: %w", err)
}
Expand All @@ -198,7 +198,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient sqlserverfle
return req, fmt.Errorf("get SQLServer Flex instance: %w", err)
}
var currentFlavor *sqlserverflex.ListFlavors
for _, flavor := range flavors.Flavors {
for _, flavor := range flavors {
if flavor.Id == currentInstance.FlavorId {
currentFlavor = &flavor
}
Expand All @@ -213,7 +213,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient sqlserverfle
cpu = &currentFlavor.Cpu
}
}
loadedId, err := sqlserverflexUtils.LoadFlavorId(*cpu, *ram, flavors.Flavors)
loadedId, err := sqlserverflexUtils.LoadFlavorId(*cpu, *ram, flavors)
if err != nil {
var dsaInvalidPlanError *cliErr.DSAInvalidPlanError
if !errors.As(err, &dsaInvalidPlanError) {
Expand All @@ -223,7 +223,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient sqlserverfle
}
flavorId = &loadedId
} else if model.FlavorId != nil {
err := sqlserverflexUtils.ValidateFlavorId(*model.FlavorId, flavors.Flavors)
err := sqlserverflexUtils.ValidateFlavorId(*model.FlavorId, flavors)
if err != nil {
return req, err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,9 @@ func TestBuildRequest(t *testing.T) {
model: fixtureRequiredInputModel(),
isValid: true,
expectedRequest: fixtureRequest(),
listFlavorsResp: &sqlserverflex.ListFlavorsResponse{
Flavors: make([]sqlserverflex.ListFlavors, 0),
},
},
{
description: "update flavor from id",
Expand Down Expand Up @@ -443,6 +446,9 @@ func TestBuildRequest(t *testing.T) {
),
getInstanceFails: true,
isValid: false,
listFlavorsResp: &sqlserverflex.ListFlavorsResponse{
Flavors: make([]sqlserverflex.ListFlavors, 0),
},
},
{
description: "get storages fails",
Expand Down
9 changes: 5 additions & 4 deletions internal/cmd/beta/sqlserverflex/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"

sqlserverflexUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/sqlserverflex/utils"
"github.com/stackitcloud/stackit-cli/internal/pkg/types"
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"

Expand Down Expand Up @@ -181,7 +182,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel,
}

func buildAndExecuteRequest(ctx context.Context, p *print.Printer, model *inputModel, apiClient sqlserverflex.DefaultAPI) error {
var flavors *sqlserverflex.ListFlavorsResponse
var flavors []sqlserverflex.ListFlavors
var versions *sqlserverflex.ListVersionsResponse
var storages *sqlserverflex.ListStoragesResponse
var userRoles *sqlserverflex.ListRolesResponse
Expand All @@ -190,7 +191,7 @@ func buildAndExecuteRequest(ctx context.Context, p *print.Printer, model *inputM
var err error

if model.Flavors {
flavors, err = apiClient.ListFlavors(ctx, model.ProjectId, model.Region).Execute()
flavors, err = sqlserverflexUtils.ListAllFlavors(ctx, apiClient, model.ProjectId, model.Region)
if err != nil {
return fmt.Errorf("get SQL Server Flex flavors: %w", err)
}
Expand Down Expand Up @@ -229,10 +230,10 @@ func buildAndExecuteRequest(ctx context.Context, p *print.Printer, model *inputM
return outputResult(p, model, flavors, versions, storages, userRoles, dbCollations, dbCompatibilities)
}

func outputResult(p *print.Printer, model *inputModel, flavors *sqlserverflex.ListFlavorsResponse, versions *sqlserverflex.ListVersionsResponse, storages *sqlserverflex.ListStoragesResponse, userRoles *sqlserverflex.ListRolesResponse, dbCollations *sqlserverflex.ListCollationsResponse, dbCompatibilities *sqlserverflex.ListCompatibilityResponse) error {
func outputResult(p *print.Printer, model *inputModel, flavors []sqlserverflex.ListFlavors, versions *sqlserverflex.ListVersionsResponse, storages *sqlserverflex.ListStoragesResponse, userRoles *sqlserverflex.ListRolesResponse, dbCollations *sqlserverflex.ListCollationsResponse, dbCompatibilities *sqlserverflex.ListCompatibilityResponse) error {
options := &options{}
if flavors != nil {
options.Flavors = flavors.Flavors
options.Flavors = flavors
}
if versions != nil {
options.Versions = versions.Versions
Expand Down
4 changes: 2 additions & 2 deletions internal/cmd/beta/sqlserverflex/options/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ func TestBuildAndExecuteRequest(t *testing.T) {
func TestOutputResult(t *testing.T) {
type args struct {
model *inputModel
flavors *sqlserverflex.ListFlavorsResponse
flavors []sqlserverflex.ListFlavors
versions *sqlserverflex.ListVersionsResponse
storages *sqlserverflex.ListStoragesResponse
userRoles *sqlserverflex.ListRolesResponse
Expand All @@ -489,7 +489,7 @@ func TestOutputResult(t *testing.T) {
name: "all input set",
args: args{
model: fixtureInputModelAllTrue(),
flavors: &sqlserverflex.ListFlavorsResponse{Flavors: []sqlserverflex.ListFlavors{}},
flavors: []sqlserverflex.ListFlavors{},
versions: &sqlserverflex.ListVersionsResponse{Versions: []sqlserverflex.Version{}},
storages: &sqlserverflex.ListStoragesResponse{StorageClasses: []sqlserverflex.FlavorStorageClassesStorageClass{}},
userRoles: &sqlserverflex.ListRolesResponse{Roles: []string{}},
Expand Down
23 changes: 20 additions & 3 deletions internal/pkg/services/sqlserverflex/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package utils
import (
"context"
"fmt"
"math"
"strings"

"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
Expand Down Expand Up @@ -75,6 +76,23 @@ func LoadFlavorId(cpu, ram int64, flavors []sqlserverflex.ListFlavors) (string,
}
}

func ListAllFlavors(ctx context.Context, api sqlserverflex.DefaultAPI, projectId, region string) ([]sqlserverflex.ListFlavors, error) {
const pageSize = 100
const sort = sqlserverflex.FLAVORSORT_ID_ASC
totalRows := int64(math.MaxInt64)
var page int64 = 1
var result []sqlserverflex.ListFlavors
for ; int64(len(result)) < totalRows; page++ {
flavors, err := api.ListFlavors(ctx, projectId, region).Page(page).Sort(sort).Size(pageSize).Execute()
if err != nil {
return result, fmt.Errorf("listing flavors: %w", err)
}
result = append(result, flavors.Flavors...)
totalRows = flavors.Pagination.TotalRows
}
return result, nil
}

func GetInstanceName(ctx context.Context, apiClient sqlserverflex.DefaultAPI, projectId, instanceId, region string) (string, error) {
resp, err := apiClient.GetInstance(ctx, projectId, region, instanceId).Execute()
if err != nil {
Expand All @@ -92,12 +110,11 @@ func GetUserName(ctx context.Context, apiClient sqlserverflex.DefaultAPI, projec
}

func GetFlavor(ctx context.Context, client sqlserverflex.DefaultAPI, projectId, region, flavorId string) (*sqlserverflex.ListFlavors, error) {
req := client.ListFlavors(ctx, projectId, region)
flavorsResp, err := client.ListFlavorsExecute(req)
flavors, err := ListAllFlavors(ctx, client, projectId, region)
if err != nil {
return nil, fmt.Errorf("failed to list flavors: %w", err)
}
for _, flavor := range flavorsResp.Flavors {
for _, flavor := range flavors {
if flavor.Id == flavorId {
return &flavor, nil
}
Expand Down
153 changes: 153 additions & 0 deletions internal/pkg/services/sqlserverflex/utils/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ const (
)

type mockSettings struct {
listFlavorsFails bool
listFlavorsResp *sqlserverflex.ListFlavorsResponse
listFlavorsResps []*sqlserverflex.ListFlavorsResponse
listFlavorsCallCount int
listVersionsFails bool
listVersionsResp *sqlserverflex.ListVersionsResponse
getInstanceFails bool
Expand All @@ -37,6 +41,20 @@ type mockSettings struct {

func newApiMock(s *mockSettings) sqlserverflex.DefaultAPI {
return &sqlserverflex.DefaultAPIServiceMock{
ListFlavorsExecuteMock: utils.Ptr(func(_ sqlserverflex.ApiListFlavorsRequest) (*sqlserverflex.ListFlavorsResponse, error) {
if s.listFlavorsFails {
return nil, fmt.Errorf("could not list flavors")
}
if len(s.listFlavorsResps) > 0 {
if s.listFlavorsCallCount >= len(s.listFlavorsResps) {
return nil, fmt.Errorf("no more mock responses")
}
resp := s.listFlavorsResps[s.listFlavorsCallCount]
s.listFlavorsCallCount++
return resp, nil
}
return s.listFlavorsResp, nil
}),
ListVersionsExecuteMock: utils.Ptr(func(_ sqlserverflex.ApiListVersionsRequest) (*sqlserverflex.ListVersionsResponse, error) {
if s.listVersionsFails {
return nil, fmt.Errorf("could not list versions")
Expand Down Expand Up @@ -64,6 +82,141 @@ func newApiMock(s *mockSettings) sqlserverflex.DefaultAPI {
}
}

func TestListAllFlavors(t *testing.T) {
tests := []struct {
description string
listFlavorsFails bool
listFlavorsResp *sqlserverflex.ListFlavorsResponse
listFlavorsResps []*sqlserverflex.ListFlavorsResponse
isValid bool
expectedOutput []sqlserverflex.ListFlavors
}{
{
description: "base",
listFlavorsResp: &sqlserverflex.ListFlavorsResponse{
Flavors: []sqlserverflex.ListFlavors{
{
Id: "flavor-1",
},
{
Id: "flavor-2",
},
},
Pagination: sqlserverflex.Pagination{
TotalRows: 2,
},
},
isValid: true,
expectedOutput: []sqlserverflex.ListFlavors{
{
Id: "flavor-1",
},
{
Id: "flavor-2",
},
},
},
{
description: "multiple pages",
listFlavorsResps: []*sqlserverflex.ListFlavorsResponse{
{
Flavors: []sqlserverflex.ListFlavors{
{
Id: "flavor-1",
},
{
Id: "flavor-2",
},
},
Pagination: sqlserverflex.Pagination{
TotalRows: 3,
},
},
{
Flavors: []sqlserverflex.ListFlavors{
{
Id: "flavor-3",
},
},
Pagination: sqlserverflex.Pagination{
TotalRows: 3,
},
},
},
isValid: true,
expectedOutput: []sqlserverflex.ListFlavors{
{
Id: "flavor-1",
},
{
Id: "flavor-2",
},
{
Id: "flavor-3",
},
},
},
{
description: "empty response",
listFlavorsResp: &sqlserverflex.ListFlavorsResponse{
Flavors: []sqlserverflex.ListFlavors{},
Pagination: sqlserverflex.Pagination{
TotalRows: 0,
},
},
isValid: true,
expectedOutput: nil,
},
{
description: "list flavors fails",
listFlavorsFails: true,
isValid: false,
},
{
description: "page 2 fails",
listFlavorsResps: []*sqlserverflex.ListFlavorsResponse{
{
Flavors: []sqlserverflex.ListFlavors{
{
Id: "flavor-1",
},
},
Pagination: sqlserverflex.Pagination{
TotalRows: 2,
},
},
},
isValid: false,
},
}

for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
settings := &mockSettings{
listFlavorsFails: tt.listFlavorsFails,
listFlavorsResp: tt.listFlavorsResp,
listFlavorsResps: tt.listFlavorsResps,
}

output, err := ListAllFlavors(context.Background(), newApiMock(settings), testProjectId, testRegion)

if tt.isValid && err != nil {
t.Fatalf("failed on valid input: %v", err)
}
if !tt.isValid && err == nil {
t.Fatalf("did not fail on invalid input")
}
if !tt.isValid {
return
}
diff := cmp.Diff(output, tt.expectedOutput)
if diff != "" {
t.Fatalf("outputs do not match: %s", diff)
}
})
}
}

func TestValidateStorage(t *testing.T) {
tests := []struct {
description string
Expand Down
Loading