Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MongoDBFlex instance creation uses latest available version by default #63

Merged
merged 3 commits into from
Feb 6, 2024
Merged
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
2 changes: 1 addition & 1 deletion docs/stackit_mongodbflex_instance_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ stackit mongodbflex instance create [flags]
--storage-class string Storage class (default "premium-perf2-mongodb")
--storage-size int Storage size (in GB) (default 10)
--type string Instance type, one of ["Replica" "Sharded" "Single"] (default "Replica")
--version string Version (default "6.0")
--version string MongoDB version. Defaults to the latest version available
```

### Options inherited from parent commands
Expand Down
14 changes: 11 additions & 3 deletions internal/cmd/mongodbflex/instance/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ const (
defaultStorageClass = "premium-perf2-mongodb"
defaultStorageSize = 10
defaultType = "Replica"
defaultVersion = "6.0"
)

type inputModel struct {
Expand Down Expand Up @@ -100,6 +99,15 @@ func NewCmd() *cobra.Command {
}
}

// Fill in version, if needed
hcsa73 marked this conversation as resolved.
Show resolved Hide resolved
if model.Version == nil {
version, err := mongodbflexUtils.GetLatestMongoDBVersion(ctx, apiClient, model.ProjectId)
if err != nil {
return fmt.Errorf("get latest MongoDB version: %w", err)
}
model.Version = &version
}

// Call API
req, err := buildRequest(ctx, model, apiClient)
if err != nil {
Expand Down Expand Up @@ -145,7 +153,7 @@ func configureFlags(cmd *cobra.Command) {
cmd.Flags().Int64(ramFlag, 0, "Amount of RAM (in GB)")
cmd.Flags().String(storageClassFlag, defaultStorageClass, "Storage class")
cmd.Flags().Int64(storageSizeFlag, defaultStorageSize, "Storage size (in GB)")
cmd.Flags().String(versionFlag, defaultVersion, "Version")
cmd.Flags().String(versionFlag, "", "MongoDB version. Defaults to the latest version available")
cmd.Flags().Var(flags.EnumFlag(false, defaultType, typeFlagOptions...), typeFlag, fmt.Sprintf("Instance type, one of %q", typeFlagOptions))

err := flags.MarkFlagsRequired(cmd, instanceNameFlag, aclFlag)
Expand Down Expand Up @@ -187,7 +195,7 @@ func parseInput(cmd *cobra.Command) (*inputModel, error) {
RAM: ram,
StorageClass: utils.Ptr(flags.FlagWithDefaultToStringValue(cmd, storageClassFlag)),
StorageSize: &storageSize,
Version: utils.Ptr(flags.FlagWithDefaultToStringValue(cmd, versionFlag)),
Version: flags.FlagToStringPointer(cmd, versionFlag),
Type: utils.Ptr(flags.FlagWithDefaultToStringValue(cmd, typeFlag)),
}, nil
}
Expand Down
11 changes: 10 additions & 1 deletion internal/cmd/mongodbflex/instance/create/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ func TestParseInput(t *testing.T) {
description: "with defaults",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
delete(flagValues, backupScheduleFlag)
delete(flagValues, versionFlag)
delete(flagValues, typeFlag)
}),
isValid: true,
Expand Down Expand Up @@ -204,6 +203,16 @@ func TestParseInput(t *testing.T) {
}),
isValid: false,
},
{
description: "no version",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
delete(flagValues, versionFlag)
}),
isValid: true,
expectedModel: fixtureInputModel(func(model *inputModel) {
model.Version = nil
}),
},
{
description: "repeated acl flags",
flagValues: fixtureFlagValues(),
Expand Down
2 changes: 1 addition & 1 deletion internal/cmd/postgresflex/instance/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func NewCmd() *cobra.Command {
}
}

// Fill in defautl version, if needed
// Fill in version, if needed
if model.Version == nil {
version, err := postgresflexUtils.GetLatestPostgreSQLVersion(ctx, apiClient, model.ProjectId)
if err != nil {
Expand Down
40 changes: 32 additions & 8 deletions internal/pkg/services/mongodbflex/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
"golang.org/x/mod/semver"

"github.com/stackitcloud/stackit-sdk-go/services/mongodbflex"
)
Expand All @@ -17,14 +18,6 @@ var instanceTypeToReplicas = map[string]int64{
"Sharded": 9,
}

func GetUserName(ctx context.Context, apiClient MongoDBFlexClient, projectId, instanceId, userId string) (string, error) {
resp, err := apiClient.GetUserExecute(ctx, projectId, instanceId, userId)
if err != nil {
return "", fmt.Errorf("get MongoDBFlex user: %w", err)
}
return *resp.Item.Username, nil
}

func AvailableInstanceTypes() []string {
instanceTypes := make([]string, len(instanceTypeToReplicas))
i := 0
Expand Down Expand Up @@ -118,14 +111,45 @@ func LoadFlavorId(cpu, ram int64, flavors *[]mongodbflex.HandlersInfraFlavor) (*
}

type MongoDBFlexClient interface {
ListVersionsExecute(ctx context.Context, projectId string) (*mongodbflex.ListVersionsResponse, error)
GetInstanceExecute(ctx context.Context, projectId, instanceId string) (*mongodbflex.GetInstanceResponse, error)
GetUserExecute(ctx context.Context, projectId, instanceId, userId string) (*mongodbflex.GetUserResponse, error)
}

func GetLatestMongoDBVersion(ctx context.Context, apiClient MongoDBFlexClient, projectId string) (string, error) {
resp, err := apiClient.ListVersionsExecute(ctx, projectId)
if err != nil {
return "", fmt.Errorf("get MongoDB versions: %w", err)
}
versions := *resp.Versions

latestVersion := "0"
for i := range versions {
oldSemVer := fmt.Sprintf("v%s", latestVersion)
newSemVer := fmt.Sprintf("v%s", versions[i])
if semver.Compare(newSemVer, oldSemVer) != 1 {
continue
}
latestVersion = versions[i]
}
if latestVersion == "0" {
return "", fmt.Errorf("no MongoDB versions found")
}
return latestVersion, nil
}

func GetInstanceName(ctx context.Context, apiClient MongoDBFlexClient, projectId, instanceId string) (string, error) {
resp, err := apiClient.GetInstanceExecute(ctx, projectId, instanceId)
if err != nil {
return "", fmt.Errorf("get MongoDBFlex instance: %w", err)
}
return *resp.Item.Name, nil
}

func GetUserName(ctx context.Context, apiClient MongoDBFlexClient, projectId, instanceId, userId string) (string, error) {
resp, err := apiClient.GetUserExecute(ctx, projectId, instanceId, userId)
if err != nil {
return "", fmt.Errorf("get MongoDBFlex user: %w", err)
}
return *resp.Item.Username, nil
}
72 changes: 68 additions & 4 deletions internal/pkg/services/mongodbflex/utils/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,19 @@ const (
)

type mongoDBFlexClientMocked struct {
getInstanceFails bool
getInstanceResp *mongodbflex.GetInstanceResponse
getUserFails bool
getUserResp *mongodbflex.GetUserResponse
listVersionsFails bool
listVersionsResp *mongodbflex.ListVersionsResponse
getInstanceFails bool
getInstanceResp *mongodbflex.GetInstanceResponse
getUserFails bool
getUserResp *mongodbflex.GetUserResponse
}

func (m *mongoDBFlexClientMocked) ListVersionsExecute(_ context.Context, _ string) (*mongodbflex.ListVersionsResponse, error) {
if m.listVersionsFails {
return nil, fmt.Errorf("could not list versions")
}
return m.listVersionsResp, nil
}

func (m *mongoDBFlexClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*mongodbflex.GetInstanceResponse, error) {
Expand Down Expand Up @@ -355,6 +364,61 @@ func TestLoadFlavorId(t *testing.T) {
}
}

func TestGetLatestPostgreSQLVersion(t *testing.T) {
tests := []struct {
description string
listVersionsFails bool
listVersionsResp *mongodbflex.ListVersionsResponse
isValid bool
expectedOutput string
}{
{
description: "base",
listVersionsResp: &mongodbflex.ListVersionsResponse{
Versions: &[]string{"8", "10", "9"},
},
isValid: true,
expectedOutput: "10",
},
{
description: "get instance fails",
listVersionsFails: true,
isValid: false,
},
{
description: "no versions",
listVersionsResp: &mongodbflex.ListVersionsResponse{
Versions: &[]string{},
},
isValid: false,
},
}

for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
client := &mongoDBFlexClientMocked{
listVersionsFails: tt.listVersionsFails,
listVersionsResp: tt.listVersionsResp,
}

output, err := GetLatestMongoDBVersion(context.Background(), client, testProjectId)

if tt.isValid && err != nil {
t.Errorf("failed on valid input")
}
if !tt.isValid && err == nil {
t.Errorf("did not fail on invalid input")
}
if !tt.isValid {
return
}
if output != tt.expectedOutput {
t.Errorf("expected output to be %s, got %s", tt.expectedOutput, output)
}
})
}
}

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