diff --git a/docs/stackit_opensearch_instance_create.md b/docs/stackit_opensearch_instance_create.md index ba979af69..8e3534d0a 100644 --- a/docs/stackit_opensearch_instance_create.md +++ b/docs/stackit_opensearch_instance_create.md @@ -30,13 +30,13 @@ stackit opensearch instance create [flags] --enable-monitoring Enable monitoring --graphite string Graphite host -h, --help Help for "stackit opensearch instance create" - --metrics-frequency int Metrics frequency + --metrics-frequency int32 Metrics frequency --metrics-prefix string Metrics prefix --monitoring-instance-id string Monitoring instance ID -n, --name string Instance name --plan-id string Plan ID --plan-name string Plan name - --plugin strings Plugin + --plugin strings Plugins (multiple of: [repository-s3, repository-azure, analysis-phonetic]) (default []) --syslog strings Syslog --version string Instance OpenSearch version ``` diff --git a/docs/stackit_opensearch_instance_update.md b/docs/stackit_opensearch_instance_update.md index 33b2b817b..508f46a05 100644 --- a/docs/stackit_opensearch_instance_update.md +++ b/docs/stackit_opensearch_instance_update.md @@ -27,12 +27,12 @@ stackit opensearch instance update INSTANCE_ID [flags] --enable-monitoring Enable monitoring --graphite string Graphite host -h, --help Help for "stackit opensearch instance update" - --metrics-frequency int Metrics frequency + --metrics-frequency int32 Metrics frequency --metrics-prefix string Metrics prefix --monitoring-instance-id string Monitoring instance ID --plan-id string Plan ID --plan-name string Plan name - --plugin strings Plugin + --plugin strings Plugins (multiple of: [repository-s3, repository-azure, analysis-phonetic]) (default []) --syslog strings Syslog --version string Instance OpenSearch version ``` diff --git a/go.mod b/go.mod index ee06a565d..2353b9927 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/stackitcloud/stackit-sdk-go/services/intake v0.7.1 github.com/stackitcloud/stackit-sdk-go/services/logs v0.5.2 github.com/stackitcloud/stackit-sdk-go/services/mongodbflex v1.12.0 - github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.6 + github.com/stackitcloud/stackit-sdk-go/services/opensearch v1.1.0 github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.5 github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.24.0 github.com/stackitcloud/stackit-sdk-go/services/runcommand v1.4.3 diff --git a/go.sum b/go.sum index 5ec138a79..5ec24b922 100644 --- a/go.sum +++ b/go.sum @@ -624,8 +624,8 @@ github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.9.0 h1:T+ll3lS0 github.com/stackitcloud/stackit-sdk-go/services/objectstorage v1.9.0/go.mod h1:QsPtoqAYvumyPU6ToX/5j1PbudN+VSTuvh6mp154ecM= github.com/stackitcloud/stackit-sdk-go/services/observability v0.24.0 h1:KhuWPXr1hl8BFLGLSi6wjxh5o6OQXH9amfquMhYQROU= github.com/stackitcloud/stackit-sdk-go/services/observability v0.24.0/go.mod h1:0fEZQHm729mBdvg4sNrAhM6KmHROHJSeS2FwCMRk46k= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.6 h1:oTVx1+O177Ojn8OvXIOUbRSwtx7L59jhxDPrZEQFOfQ= -github.com/stackitcloud/stackit-sdk-go/services/opensearch v0.24.6/go.mod h1:6ZBeCCY6qG8w1oK7osf61Egyv3mp7Ahv6GDGxiarDGo= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v1.1.0 h1:hooc/E9Qabn8xno1NUd3uJQfUbW5KoY6mgURlnd776c= +github.com/stackitcloud/stackit-sdk-go/services/opensearch v1.1.0/go.mod h1:L+NlfC1hilLOqlLLukCj/UDnxlnNrc/oMikcw3Ansyw= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.5 h1:H67e3KnHQx954yI8fuQmxXwRf/myqAdLg2KvxImp00g= github.com/stackitcloud/stackit-sdk-go/services/postgresflex v1.3.5/go.mod h1:xmAWk9eom8wznvLuLfm0F4xyeiBX8LaggXsKFmos+dw= github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v1.1.0 h1:HRJwodJX4aOn/487zaqJIKw13yIj4T6dn7/kEHLxeTg= diff --git a/internal/cmd/opensearch/credentials/create/create.go b/internal/cmd/opensearch/credentials/create/create.go index cfc9bd5f3..7e9eb5ee7 100644 --- a/internal/cmd/opensearch/credentials/create/create.go +++ b/internal/cmd/opensearch/credentials/create/create.go @@ -7,7 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -17,7 +17,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/opensearch/client" opensearchUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/opensearch/utils" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) const ( @@ -58,7 +57,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.InstanceId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -77,7 +76,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return fmt.Errorf("create OpenSearch credentials: %w", err) } - return outputResult(params.Printer, model.OutputFormat, model.ShowPassword, instanceLabel, resp) + return outputResult(params.Printer, *model, instanceLabel, resp) }, } configureFlags(cmd) @@ -109,35 +108,38 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch.APIClient) opensearch.ApiCreateCredentialsRequest { - req := apiClient.CreateCredentials(ctx, model.ProjectId, model.InstanceId) + req := apiClient.DefaultAPI.CreateCredentials(ctx, model.ProjectId, model.Region, model.InstanceId) return req } -func outputResult(p *print.Printer, outputFormat string, showPassword bool, instanceLabel string, resp *opensearch.CredentialsResponse) error { - if resp == nil || resp.Raw == nil || resp.Raw.Credentials == nil || resp.Uri == nil { +func outputResult(p *print.Printer, model inputModel, instanceLabel string, resp *opensearch.CredentialsResponse) error { + if model.GlobalFlagModel == nil { + return fmt.Errorf("no global flags defined") + } + if resp == nil || resp.Raw == nil { return fmt.Errorf("response or response content is nil") } - if !showPassword { - resp.Raw.Credentials.Password = utils.Ptr("hidden") + if !model.ShowPassword { + resp.Raw.Credentials.Password = "hidden" } - return p.OutputResult(outputFormat, resp, func() error { - p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, utils.PtrString(resp.Id)) + return p.OutputResult(model.OutputFormat, resp, func() error { + p.Outputf("Created credentials for instance %q. Credentials ID: %s\n\n", instanceLabel, resp.Id) // The username field cannot be set by the user so we only display it if it's not returned empty - if resp.HasRaw() && resp.Raw.Credentials != nil { - if username := resp.Raw.Credentials.Username; username != nil && *username != "" { - p.Outputf("Username: %s\n", *username) + if resp.HasRaw() { + if username := resp.Raw.Credentials.Username; username != "" { + p.Outputf("Username: %s\n", username) } - if !showPassword { + if !model.ShowPassword { p.Outputf("Password: \n") } else { - p.Outputf("Password: %s\n", utils.PtrString(resp.Raw.Credentials.Password)) + p.Outputf("Password: %s\n", resp.Raw.Credentials.Password) } - p.Outputf("Host: %s\n", utils.PtrString(resp.Raw.Credentials.Host)) - p.Outputf("Port: %s\n", utils.PtrString(resp.Raw.Credentials.Port)) + p.Outputf("Host: %s\n", resp.Raw.Credentials.Host) + p.Outputf("Port: %d\n", resp.Raw.Credentials.Port) } - p.Outputf("URI: %s\n", *resp.Uri) + p.Outputf("URI: %s\n", resp.Uri) return nil }) } diff --git a/internal/cmd/opensearch/credentials/create/create_test.go b/internal/cmd/opensearch/credentials/create/create_test.go index 309291ed3..f6cd78b76 100644 --- a/internal/cmd/opensearch/credentials/create/create_test.go +++ b/internal/cmd/opensearch/credentials/create/create_test.go @@ -7,24 +7,27 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/testparams" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) type testCtxKey struct{} -var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &opensearch.APIClient{} -var testProjectId = uuid.NewString() -var testInstanceId = uuid.NewString() +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &opensearch.APIClient{DefaultAPI: &opensearch.DefaultAPIService{}} + testProjectId = uuid.NewString() + testRegion = "eu01" + testInstanceId = uuid.NewString() +) func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, instanceIdFlag: testInstanceId, } for _, mod := range mods { @@ -37,6 +40,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -48,7 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *opensearch.ApiCreateCredentialsRequest)) opensearch.ApiCreateCredentialsRequest { - request := testClient.CreateCredentials(testCtx, testProjectId, testInstanceId) + request := testClient.DefaultAPI.CreateCredentials(testCtx, testProjectId, testRegion, testInstanceId) for _, mod := range mods { mod(&request) } @@ -154,7 +158,7 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), - cmpopts.EquateComparable(testCtx), + cmpopts.EquateComparable(testCtx, opensearch.DefaultAPIService{}), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) @@ -165,8 +169,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { - outputFormat string - showPassword bool + model inputModel instanceLabel string resp *opensearch.CredentialsResponse } @@ -181,40 +184,20 @@ func TestOutputResult(t *testing.T) { wantErr: true, }, { - name: "set no raw in response", - args: args{ - resp: &opensearch.CredentialsResponse{ - Uri: utils.Ptr("https://opensearch.example.com"), - }, - }, - wantErr: true, - }, - { - name: "set empty raw in response", - args: args{ - resp: &opensearch.CredentialsResponse{ - Raw: &opensearch.RawCredentials{}, - Uri: utils.Ptr("https://opensearch.example.com"), - }, - }, - wantErr: true, - }, - { - name: "set raw but no uri in response", + name: "set uri but no raw in response", args: args{ resp: &opensearch.CredentialsResponse{ - Raw: &opensearch.RawCredentials{ - Credentials: &opensearch.Credentials{}, - }, + Uri: "https://opensearch.example.com", }, }, wantErr: true, }, { - name: "set uri but no raw in response", + name: "empty response should not cause panic when password should be hidden", args: args{ - resp: &opensearch.CredentialsResponse{ - Uri: utils.Ptr("https://opensearch.example.com"), + model: inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, + ShowPassword: false, }, }, wantErr: true, @@ -224,9 +207,12 @@ func TestOutputResult(t *testing.T) { args: args{ resp: &opensearch.CredentialsResponse{ Raw: &opensearch.RawCredentials{ - Credentials: &opensearch.Credentials{}, + Credentials: opensearch.Credentials{}, }, - Uri: utils.Ptr("https://opensearch.example.com"), + Uri: "https://opensearch.example.com", + }, + model: inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, }, }, wantErr: false, @@ -235,7 +221,7 @@ func TestOutputResult(t *testing.T) { params := testparams.NewTestParams() for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(params.Printer, tt.args.outputFormat, tt.args.showPassword, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { + if err := outputResult(params.Printer, tt.args.model, tt.args.instanceLabel, tt.args.resp); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/opensearch/credentials/delete/delete.go b/internal/cmd/opensearch/credentials/delete/delete.go index 236b9c626..15661c6cf 100644 --- a/internal/cmd/opensearch/credentials/delete/delete.go +++ b/internal/cmd/opensearch/credentials/delete/delete.go @@ -17,7 +17,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" ) const ( @@ -56,13 +56,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.InstanceId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId } - credentialsLabel, err := opensearchUtils.GetCredentialsUsername(ctx, apiClient, model.ProjectId, model.InstanceId, model.CredentialsId) + credentialsLabel, err := opensearchUtils.GetCredentialsUsername(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.InstanceId, model.CredentialsId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get credentials user name: %v", err) credentialsLabel = model.CredentialsId @@ -115,6 +115,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch.APIClient) opensearch.ApiDeleteCredentialsRequest { - req := apiClient.DeleteCredentials(ctx, model.ProjectId, model.InstanceId, model.CredentialsId) + req := apiClient.DefaultAPI.DeleteCredentials(ctx, model.ProjectId, model.Region, model.InstanceId, model.CredentialsId) return req } diff --git a/internal/cmd/opensearch/credentials/delete/delete_test.go b/internal/cmd/opensearch/credentials/delete/delete_test.go index dcaa66ee1..1f236627a 100644 --- a/internal/cmd/opensearch/credentials/delete/delete_test.go +++ b/internal/cmd/opensearch/credentials/delete/delete_test.go @@ -10,16 +10,19 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" ) type testCtxKey struct{} -var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &opensearch.APIClient{} -var testProjectId = uuid.NewString() -var testInstanceId = uuid.NewString() -var testCredentialsId = uuid.NewString() +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &opensearch.APIClient{DefaultAPI: &opensearch.DefaultAPIService{}} + testProjectId = uuid.NewString() + testRegion = "eu01" + testInstanceId = uuid.NewString() + testCredentialsId = uuid.NewString() +) func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -34,6 +37,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, instanceIdFlag: testInstanceId, } for _, mod := range mods { @@ -46,6 +50,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -58,7 +63,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *opensearch.ApiDeleteCredentialsRequest)) opensearch.ApiDeleteCredentialsRequest { - request := testClient.DeleteCredentials(testCtx, testProjectId, testInstanceId, testCredentialsId) + request := testClient.DefaultAPI.DeleteCredentials(testCtx, testProjectId, testRegion, testInstanceId, testCredentialsId) for _, mod := range mods { mod(&request) } @@ -186,7 +191,7 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), - cmpopts.EquateComparable(testCtx), + cmpopts.EquateComparable(testCtx, opensearch.DefaultAPIService{}), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) diff --git a/internal/cmd/opensearch/credentials/describe/describe.go b/internal/cmd/opensearch/credentials/describe/describe.go index 50a495940..3d37ed7c1 100644 --- a/internal/cmd/opensearch/credentials/describe/describe.go +++ b/internal/cmd/opensearch/credentials/describe/describe.go @@ -18,7 +18,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" ) const ( @@ -100,34 +100,33 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch.APIClient) opensearch.ApiGetCredentialsRequest { - req := apiClient.GetCredentials(ctx, model.ProjectId, model.InstanceId, model.CredentialsId) + req := apiClient.DefaultAPI.GetCredentials(ctx, model.ProjectId, model.Region, model.InstanceId, model.CredentialsId) return req } func outputResult(p *print.Printer, outputFormat string, credentials *opensearch.CredentialsResponse) error { - if credentials == nil { - return fmt.Errorf("credentials is nil") - } - return p.OutputResult(outputFormat, credentials, func() error { + if credentials == nil { + return fmt.Errorf("credentials is nil") + } table := tables.NewTable() - table.AddRow("ID", utils.PtrString(credentials.Id)) + table.AddRow("ID", credentials.Id) table.AddSeparator() // The username field cannot be set by the user so we only display it if it's not returned empty - if credentials.HasRaw() && credentials.Raw.Credentials != nil { - if username := credentials.Raw.Credentials.Username; username != nil && *username != "" { - table.AddRow("USERNAME", *username) + if credentials.HasRaw() { + if username := credentials.Raw.Credentials.Username; username != "" { + table.AddRow("USERNAME", username) table.AddSeparator() } - table.AddRow("PASSWORD", utils.PtrString(credentials.Raw.Credentials.Password)) + table.AddRow("PASSWORD", credentials.Raw.Credentials.Password) table.AddSeparator() table.AddRow("URI", utils.PtrString(credentials.Raw.Credentials.Uri)) table.AddSeparator() - table.AddRow("HOST", utils.PtrString(credentials.Raw.Credentials.Host)) + table.AddRow("HOST", credentials.Raw.Credentials.Host) hosts := credentials.Raw.Credentials.Hosts - if hosts != nil && len(*hosts) > 0 { + if len(hosts) > 0 { table.AddSeparator() - table.AddRow("HOSTS", strings.Join(*hosts, "\n")) + table.AddRow("HOSTS", strings.Join(hosts, "\n")) } } err := table.Display(p) diff --git a/internal/cmd/opensearch/credentials/describe/describe_test.go b/internal/cmd/opensearch/credentials/describe/describe_test.go index 61b5bb2c6..7ac6737c3 100644 --- a/internal/cmd/opensearch/credentials/describe/describe_test.go +++ b/internal/cmd/opensearch/credentials/describe/describe_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/pkg/testparams" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" @@ -13,16 +12,19 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" ) type testCtxKey struct{} -var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &opensearch.APIClient{} -var testProjectId = uuid.NewString() -var testInstanceId = uuid.NewString() -var testCredentialsId = uuid.NewString() +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &opensearch.APIClient{DefaultAPI: &opensearch.DefaultAPIService{}} + testProjectId = uuid.NewString() + testRegion = "eu01" + testInstanceId = uuid.NewString() + testCredentialsId = uuid.NewString() +) func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -37,6 +39,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, instanceIdFlag: testInstanceId, } for _, mod := range mods { @@ -49,6 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -61,7 +65,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *opensearch.ApiGetCredentialsRequest)) opensearch.ApiGetCredentialsRequest { - request := testClient.GetCredentials(testCtx, testProjectId, testInstanceId, testCredentialsId) + request := testClient.DefaultAPI.GetCredentials(testCtx, testProjectId, testRegion, testInstanceId, testCredentialsId) for _, mod := range mods { mod(&request) } @@ -189,7 +193,7 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), - cmpopts.EquateComparable(testCtx), + cmpopts.EquateComparable(testCtx, opensearch.DefaultAPIService{}), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) @@ -225,24 +229,23 @@ func TestOutputResult(t *testing.T) { args: args{ credentials: &opensearch.CredentialsResponse{ Raw: &opensearch.RawCredentials{ - Credentials: &opensearch.Credentials{ - Host: utils.Ptr("host"), - Hosts: utils.Ptr([]string{ + Credentials: opensearch.Credentials{ + Host: "host", + Hosts: []string{ "hosts-a", "hosts-b", - }), + }, }, }, }, }, }, { - name: "raw credentials nil host & hosts", + name: "raw credentials and nil hosts", args: args{ credentials: &opensearch.CredentialsResponse{ Raw: &opensearch.RawCredentials{ - Credentials: &opensearch.Credentials{ - Host: nil, + Credentials: opensearch.Credentials{ Hosts: nil, }, }, diff --git a/internal/cmd/opensearch/credentials/list/list.go b/internal/cmd/opensearch/credentials/list/list.go index 05f4e8ef8..85a083e71 100644 --- a/internal/cmd/opensearch/credentials/list/list.go +++ b/internal/cmd/opensearch/credentials/list/list.go @@ -15,10 +15,9 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/opensearch/client" opensearchUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/opensearch/utils" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" ) const ( @@ -70,7 +69,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } credentials := resp.GetCredentialsList() - instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.InstanceId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -121,7 +120,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch.APIClient) opensearch.ApiListCredentialsRequest { - req := apiClient.ListCredentials(ctx, model.ProjectId, model.InstanceId) + req := apiClient.DefaultAPI.ListCredentials(ctx, model.ProjectId, model.Region, model.InstanceId) return req } @@ -136,7 +135,7 @@ func outputResult(p *print.Printer, outputFormat, instanceLabel string, credenti table.SetHeader("ID") for i := range credentials { c := credentials[i] - table.AddRow(utils.PtrString(c.Id)) + table.AddRow(c.Id) } err := table.Display(p) if err != nil { diff --git a/internal/cmd/opensearch/credentials/list/list_test.go b/internal/cmd/opensearch/credentials/list/list_test.go index 14fc8cf40..d965e574a 100644 --- a/internal/cmd/opensearch/credentials/list/list_test.go +++ b/internal/cmd/opensearch/credentials/list/list_test.go @@ -12,19 +12,23 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" ) type testCtxKey struct{} -var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &opensearch.APIClient{} -var testProjectId = uuid.NewString() -var testInstanceId = uuid.NewString() +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &opensearch.APIClient{DefaultAPI: &opensearch.DefaultAPIService{}} + testProjectId = uuid.NewString() + testRegion = "eu01" + testInstanceId = uuid.NewString() +) func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, instanceIdFlag: testInstanceId, limitFlag: "10", } @@ -38,6 +42,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -50,7 +55,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *opensearch.ApiListCredentialsRequest)) opensearch.ApiListCredentialsRequest { - request := testClient.ListCredentials(testCtx, testProjectId, testInstanceId) + request := testClient.DefaultAPI.ListCredentials(testCtx, testProjectId, testRegion, testInstanceId) for _, mod := range mods { mod(&request) } @@ -160,7 +165,7 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), - cmpopts.EquateComparable(testCtx), + cmpopts.EquateComparable(testCtx, opensearch.DefaultAPIService{}), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) diff --git a/internal/cmd/opensearch/instance/create/create.go b/internal/cmd/opensearch/instance/create/create.go index 776e6b86f..b7694de96 100644 --- a/internal/cmd/opensearch/instance/create/create.go +++ b/internal/cmd/opensearch/instance/create/create.go @@ -21,8 +21,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch/wait" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" + wait "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api/wait" ) const ( @@ -32,7 +32,6 @@ const ( metricsFrequencyFlag = "metrics-frequency" metricsPrefixFlag = "metrics-prefix" monitoringInstanceIdFlag = "monitoring-instance-id" - pluginFlag = "plugin" sgwAclFlag = "acl" syslogFlag = "syslog" planIdFlag = "plan-id" @@ -40,21 +39,23 @@ const ( versionFlag = "version" ) +var flagPlugins = flags.StringEnumSliceFlag("plugin", opensearch.AllowedInstanceParametersPluginsInnerEnumValues, "Plugins") + type inputModel struct { *globalflags.GlobalFlagModel PlanName string Version string - InstanceName *string + InstanceName string EnableMonitoring *bool Graphite *string - MetricsFrequency *int64 + MetricsFrequency *int32 MetricsPrefix *string MonitoringInstanceId *string - Plugin *[]string + Plugin []opensearch.InstanceParametersPluginsInner SgwAcl *[]string - Syslog *[]string - PlanId *string + Syslog []string + PlanId string } func NewCmd(params *types.CmdParams) *cobra.Command { @@ -100,7 +101,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } // Call API - req, err := buildRequest(ctx, model, apiClient) + req, err := buildRequest(ctx, model, apiClient.DefaultAPI) if err != nil { var dsaInvalidPlanError *cliErr.DSAInvalidPlanError if !errors.As(err, &dsaInvalidPlanError) { @@ -112,12 +113,11 @@ func NewCmd(params *types.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("create OpenSearch instance: %w", err) } - instanceId := *resp.InstanceId // Wait for async operation, if async mode not enabled if !model.Async { err := spinner.Run(params.Printer, "Creating instance", func() error { - _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + _, err = wait.CreateInstanceWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, resp.InstanceId).WaitWithContext(ctx) return err }) if err != nil { @@ -125,7 +125,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } } - return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, instanceId, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp.InstanceId, resp) }, } configureFlags(cmd) @@ -136,10 +136,10 @@ func configureFlags(cmd *cobra.Command) { cmd.Flags().StringP(instanceNameFlag, "n", "", "Instance name") cmd.Flags().Bool(enableMonitoringFlag, false, "Enable monitoring") cmd.Flags().String(graphiteFlag, "", "Graphite host") - cmd.Flags().Int64(metricsFrequencyFlag, 0, "Metrics frequency") + cmd.Flags().Int32(metricsFrequencyFlag, 0, "Metrics frequency") cmd.Flags().String(metricsPrefixFlag, "", "Metrics prefix") cmd.Flags().Var(flags.UUIDFlag(), monitoringInstanceIdFlag, "Monitoring instance ID") - cmd.Flags().StringSlice(pluginFlag, []string{}, "Plugin") + flagPlugins.Register(cmd) cmd.Flags().Var(flags.CIDRSliceFlag(), sgwAclFlag, "List of IP networks in CIDR notation which are allowed to access this instance") cmd.Flags().StringSlice(syslogFlag, []string{}, "Syslog") cmd.Flags().Var(flags.UUIDFlag(), planIdFlag, "Plan ID") @@ -156,16 +156,16 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, return nil, &cliErr.ProjectIdError{} } - planId := flags.FlagToStringPointer(p, cmd, planIdFlag) + planId := flags.FlagToStringValue(p, cmd, planIdFlag) planName := flags.FlagToStringValue(p, cmd, planNameFlag) version := flags.FlagToStringValue(p, cmd, versionFlag) - if planId == nil && (planName == "" || version == "") { + if planId == "" && (planName == "" || version == "") { return nil, &cliErr.DSAInputPlanError{ Cmd: cmd, } } - if planId != nil && (planName != "" || version != "") { + if planId != "" && (planName != "" || version != "") { return nil, &cliErr.DSAInputPlanError{ Cmd: cmd, } @@ -173,15 +173,15 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, model := inputModel{ GlobalFlagModel: globalFlags, - InstanceName: flags.FlagToStringPointer(p, cmd, instanceNameFlag), + InstanceName: flags.FlagToStringValue(p, cmd, instanceNameFlag), EnableMonitoring: flags.FlagToBoolPointer(p, cmd, enableMonitoringFlag), MonitoringInstanceId: flags.FlagToStringPointer(p, cmd, monitoringInstanceIdFlag), Graphite: flags.FlagToStringPointer(p, cmd, graphiteFlag), - MetricsFrequency: flags.FlagToInt64Pointer(p, cmd, metricsFrequencyFlag), + MetricsFrequency: flags.FlagToInt32Pointer(p, cmd, metricsFrequencyFlag), MetricsPrefix: flags.FlagToStringPointer(p, cmd, metricsPrefixFlag), - Plugin: flags.FlagToStringSlicePointer(p, cmd, pluginFlag), + Plugin: flagPlugins.Get(), SgwAcl: flags.FlagToStringSlicePointer(p, cmd, sgwAclFlag), - Syslog: flags.FlagToStringSlicePointer(p, cmd, syslogFlag), + Syslog: flags.FlagToStringSliceValue(p, cmd, syslogFlag), PlanId: planId, PlanName: planName, Version: version, @@ -192,22 +192,22 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } type openSearchClient interface { - CreateInstance(ctx context.Context, projectId string) opensearch.ApiCreateInstanceRequest - ListOfferingsExecute(ctx context.Context, projectId string) (*opensearch.ListOfferingsResponse, error) + CreateInstance(ctx context.Context, projectId, region string) opensearch.ApiCreateInstanceRequest + ListOfferings(ctx context.Context, projectId, region string) opensearch.ApiListOfferingsRequest } func buildRequest(ctx context.Context, model *inputModel, apiClient openSearchClient) (opensearch.ApiCreateInstanceRequest, error) { - req := apiClient.CreateInstance(ctx, model.ProjectId) + req := apiClient.CreateInstance(ctx, model.ProjectId, model.Region) - var planId *string + var planId string var err error - offerings, err := apiClient.ListOfferingsExecute(ctx, model.ProjectId) + offerings, err := apiClient.ListOfferings(ctx, model.ProjectId, model.Region).Execute() if err != nil { return req, fmt.Errorf("get OpenSearch offerings: %w", err) } - if model.PlanId == nil { + if model.PlanId == "" { planId, err = opensearchUtils.LoadPlanId(model.PlanName, model.Version, offerings) if err != nil { var dsaInvalidPlanError *cliErr.DSAInvalidPlanError @@ -217,7 +217,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient openSearchCl return req, err } } else { - err := opensearchUtils.ValidatePlanId(*model.PlanId, offerings) + err := opensearchUtils.ValidatePlanId(model.PlanId, offerings) if err != nil { return req, err } diff --git a/internal/cmd/opensearch/instance/create/create_test.go b/internal/cmd/opensearch/instance/create/create_test.go index 5341b00af..ba50a359e 100644 --- a/internal/cmd/opensearch/instance/create/create_test.go +++ b/internal/cmd/opensearch/instance/create/create_test.go @@ -14,44 +14,46 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" ) type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &opensearch.APIClient{} +var testClient = &opensearch.APIClient{DefaultAPI: &opensearch.DefaultAPIService{}} -type openSearchClientMocked struct { - returnError bool - listOfferingsResp *opensearch.ListOfferingsResponse +type mockSettings struct { + getOfferingsFails bool + getOfferingsResp *opensearch.ListOfferingsResponse } -func (c *openSearchClientMocked) CreateInstance(ctx context.Context, projectId string) opensearch.ApiCreateInstanceRequest { - return testClient.CreateInstance(ctx, projectId) -} - -func (c *openSearchClientMocked) ListOfferingsExecute(_ context.Context, _ string) (*opensearch.ListOfferingsResponse, error) { - if c.returnError { - return nil, fmt.Errorf("list flavors failed") +func newAPIClientMock(c mockSettings) opensearch.DefaultAPI { + return opensearch.DefaultAPIServiceMock{ + ListOfferingsExecuteMock: utils.Ptr(func(_ opensearch.ApiListOfferingsRequest) (*opensearch.ListOfferingsResponse, error) { + if c.getOfferingsFails { + return nil, fmt.Errorf("list flavors failed") + } + return c.getOfferingsResp, nil + }), } - return c.listOfferingsResp, nil } var testProjectId = uuid.NewString() +var testRegion = "eu01" var testPlanId = uuid.NewString() var testMonitoringInstanceId = uuid.NewString() func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, instanceNameFlag: "example-name", enableMonitoringFlag: "true", graphiteFlag: "example-graphite", metricsFrequencyFlag: "100", metricsPrefixFlag: "example-prefix", monitoringInstanceIdFlag: testMonitoringInstanceId, - pluginFlag: "example-plugin", + flagPlugins.Name(): string(opensearch.INSTANCEPARAMETERSPLUGINSINNER_REPOSITORY_AZURE), sgwAclFlag: "198.51.100.14/24", syslogFlag: "example-syslog", planIdFlag: testPlanId, @@ -66,18 +68,19 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, - InstanceName: utils.Ptr("example-name"), + InstanceName: "example-name", EnableMonitoring: utils.Ptr(true), Graphite: utils.Ptr("example-graphite"), - MetricsFrequency: utils.Ptr(int64(100)), + MetricsFrequency: utils.Ptr(int32(100)), MetricsPrefix: utils.Ptr("example-prefix"), MonitoringInstanceId: utils.Ptr(testMonitoringInstanceId), - Plugin: utils.Ptr([]string{"example-plugin"}), + Plugin: []opensearch.InstanceParametersPluginsInner{opensearch.INSTANCEPARAMETERSPLUGINSINNER_REPOSITORY_AZURE}, SgwAcl: utils.Ptr([]string{"198.51.100.14/24"}), - Syslog: utils.Ptr([]string{"example-syslog"}), - PlanId: utils.Ptr(testPlanId), + Syslog: []string{"example-syslog"}, + PlanId: testPlanId, } for _, mod := range mods { mod(model) @@ -86,20 +89,20 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *opensearch.ApiCreateInstanceRequest)) opensearch.ApiCreateInstanceRequest { - request := testClient.CreateInstance(testCtx, testProjectId) + request := testClient.DefaultAPI.CreateInstance(testCtx, testProjectId, testRegion) request = request.CreateInstancePayload(opensearch.CreateInstancePayload{ - InstanceName: utils.Ptr("example-name"), + InstanceName: "example-name", Parameters: &opensearch.InstanceParameters{ EnableMonitoring: utils.Ptr(true), Graphite: utils.Ptr("example-graphite"), - MetricsFrequency: utils.Ptr(int64(100)), + MetricsFrequency: utils.Ptr(int32(100)), MetricsPrefix: utils.Ptr("example-prefix"), MonitoringInstanceId: utils.Ptr(testMonitoringInstanceId), - Plugins: utils.Ptr([]string{"example-plugin"}), + Plugins: []opensearch.InstanceParametersPluginsInner{opensearch.INSTANCEPARAMETERSPLUGINSINNER_REPOSITORY_AZURE}, SgwAcl: utils.Ptr("198.51.100.14/24"), - Syslog: utils.Ptr([]string{"example-syslog"}), + Syslog: []string{"example-syslog"}, }, - PlanId: utils.Ptr(testPlanId), + PlanId: testPlanId, }) for _, mod := range mods { mod(&request) @@ -133,7 +136,7 @@ func TestParseInput(t *testing.T) { }), isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { - model.PlanId = nil + model.PlanId = "" model.PlanName = "plan-name" model.Version = "6" }), @@ -156,8 +159,8 @@ func TestParseInput(t *testing.T) { ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, }, - InstanceName: utils.Ptr("example-name"), - PlanId: utils.Ptr(testPlanId), + InstanceName: "example-name", + PlanId: testPlanId, }, }, { @@ -177,11 +180,11 @@ func TestParseInput(t *testing.T) { ProjectId: testProjectId, Verbosity: globalflags.VerbosityDefault, }, - PlanId: utils.Ptr(testPlanId), - InstanceName: utils.Ptr(""), + PlanId: testPlanId, + InstanceName: "", EnableMonitoring: utils.Ptr(false), Graphite: utils.Ptr(""), - MetricsFrequency: utils.Ptr(int64(0)), + MetricsFrequency: utils.Ptr(int32(0)), MetricsPrefix: utils.Ptr(""), }, }, @@ -254,12 +257,11 @@ func TestParseInput(t *testing.T) { { description: "repeated plugin flags", flagValues: fixtureFlagValues(), - pluginValues: []string{"example-plugin-1", "example-plugin-2"}, + pluginValues: []string{string(opensearch.INSTANCEPARAMETERSPLUGINSINNER_REPOSITORY_AZURE), string(opensearch.INSTANCEPARAMETERSPLUGINSINNER_ANALYSIS_PHONETIC)}, isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { - model.Plugin = utils.Ptr( - append(*model.Plugin, "example-plugin-1", "example-plugin-2"), - ) + model.Plugin = + append(model.Plugin, opensearch.INSTANCEPARAMETERSPLUGINSINNER_REPOSITORY_AZURE, opensearch.INSTANCEPARAMETERSPLUGINSINNER_ANALYSIS_PHONETIC) }), }, { @@ -268,9 +270,8 @@ func TestParseInput(t *testing.T) { syslogValues: []string{"example-syslog-1", "example-syslog-2"}, isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { - model.Syslog = utils.Ptr( - append(*model.Syslog, "example-syslog-1", "example-syslog-2"), - ) + model.Syslog = + append(model.Syslog, "example-syslog-1", "example-syslog-2") }), }, } @@ -278,9 +279,9 @@ func TestParseInput(t *testing.T) { for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { testutils.TestParseInputWithAdditionalFlags(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, map[string][]string{ - sgwAclFlag: tt.sgwAclValues, - pluginFlag: tt.pluginValues, - syslogFlag: tt.syslogValues, + sgwAclFlag: tt.sgwAclValues, + flagPlugins.Name(): tt.pluginValues, + syslogFlag: tt.syslogValues, }, tt.isValid) }) } @@ -288,25 +289,26 @@ func TestParseInput(t *testing.T) { func TestBuildRequest(t *testing.T) { tests := []struct { - description string - model *inputModel - expectedRequest opensearch.ApiCreateInstanceRequest - getOfferingsFails bool - getOfferingsResp *opensearch.ListOfferingsResponse - isValid bool + description string + model *inputModel + expectedRequest opensearch.ApiCreateInstanceRequest + mockClientSettings mockSettings + isValid bool }{ { description: "base", model: fixtureInputModel(), expectedRequest: fixtureRequest(), - getOfferingsResp: &opensearch.ListOfferingsResponse{ - Offerings: &[]opensearch.Offering{ - { - Version: utils.Ptr("example-version"), - Plans: &[]opensearch.Plan{ - { - Name: utils.Ptr("example-plan-name"), - Id: utils.Ptr(testPlanId), + mockClientSettings: mockSettings{ + getOfferingsResp: &opensearch.ListOfferingsResponse{ + Offerings: []opensearch.Offering{ + { + Version: "example-version", + Plans: []opensearch.Plan{ + { + Name: "example-plan-name", + Id: testPlanId, + }, }, }, }, @@ -317,20 +319,22 @@ func TestBuildRequest(t *testing.T) { description: "use plan name and version", model: fixtureInputModel( func(model *inputModel) { - model.PlanId = nil + model.PlanId = "" model.PlanName = "example-plan-name" model.Version = "example-version" }, ), expectedRequest: fixtureRequest(), - getOfferingsResp: &opensearch.ListOfferingsResponse{ - Offerings: &[]opensearch.Offering{ - { - Version: utils.Ptr("example-version"), - Plans: &[]opensearch.Plan{ - { - Name: utils.Ptr("example-plan-name"), - Id: utils.Ptr(testPlanId), + mockClientSettings: mockSettings{ + getOfferingsResp: &opensearch.ListOfferingsResponse{ + Offerings: []opensearch.Offering{ + { + Version: "example-version", + Plans: []opensearch.Plan{ + { + Name: "example-plan-name", + Id: testPlanId, + }, }, }, }, @@ -341,31 +345,35 @@ func TestBuildRequest(t *testing.T) { description: "get offering fails", model: fixtureInputModel( func(model *inputModel) { - model.PlanId = nil + model.PlanId = "" model.PlanName = "example-plan-name" model.Version = "example-version" }, ), - getOfferingsFails: true, - isValid: false, + mockClientSettings: mockSettings{ + getOfferingsFails: true, + }, + isValid: false, }, { description: "plan name not found", model: fixtureInputModel( func(model *inputModel) { - model.PlanId = nil + model.PlanId = "" model.PlanName = "example-plan-name" model.Version = "example-version" }, ), - getOfferingsResp: &opensearch.ListOfferingsResponse{ - Offerings: &[]opensearch.Offering{ - { - Version: utils.Ptr("example-version"), - Plans: &[]opensearch.Plan{ - { - Name: utils.Ptr("other-plan-name"), - Id: utils.Ptr(testPlanId), + mockClientSettings: mockSettings{ + getOfferingsResp: &opensearch.ListOfferingsResponse{ + Offerings: []opensearch.Offering{ + { + Version: "example-version", + Plans: []opensearch.Plan{ + { + Name: "other-plan-name", + Id: testPlanId, + }, }, }, }, @@ -378,35 +386,34 @@ func TestBuildRequest(t *testing.T) { model: &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, - PlanId: utils.Ptr(testPlanId), + PlanId: testPlanId, }, - getOfferingsResp: &opensearch.ListOfferingsResponse{ - Offerings: &[]opensearch.Offering{ - { - Version: utils.Ptr("example-version"), - Plans: &[]opensearch.Plan{ - { - Name: utils.Ptr("example-plan-name"), - Id: utils.Ptr(testPlanId), + mockClientSettings: mockSettings{ + getOfferingsResp: &opensearch.ListOfferingsResponse{ + Offerings: []opensearch.Offering{ + { + Version: "example-version", + Plans: []opensearch.Plan{ + { + Name: "example-plan-name", + Id: testPlanId, + }, }, }, }, }, }, - expectedRequest: testClient.CreateInstance(testCtx, testProjectId). - CreateInstancePayload(opensearch.CreateInstancePayload{PlanId: utils.Ptr(testPlanId), Parameters: &opensearch.InstanceParameters{}}), + expectedRequest: testClient.DefaultAPI.CreateInstance(testCtx, testProjectId, testRegion). + CreateInstancePayload(opensearch.CreateInstancePayload{PlanId: testPlanId, Parameters: &opensearch.InstanceParameters{}}), }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - client := &openSearchClientMocked{ - returnError: tt.getOfferingsFails, - listOfferingsResp: tt.getOfferingsResp, - } - request, err := buildRequest(testCtx, tt.model, client) + request, err := buildRequest(testCtx, tt.model, newAPIClientMock(tt.mockClientSettings)) if err != nil { if !tt.isValid { return @@ -417,6 +424,7 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), cmpopts.EquateComparable(testCtx), + cmpopts.IgnoreFields(tt.expectedRequest, "ApiService"), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) diff --git a/internal/cmd/opensearch/instance/delete/delete.go b/internal/cmd/opensearch/instance/delete/delete.go index 58f4f59d1..34463c499 100644 --- a/internal/cmd/opensearch/instance/delete/delete.go +++ b/internal/cmd/opensearch/instance/delete/delete.go @@ -17,8 +17,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch/wait" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" + wait "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api/wait" ) const ( @@ -54,7 +54,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.InstanceId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -76,7 +76,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { err := spinner.Run(params.Printer, "Deleting instance", func() error { - _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.InstanceId).WaitWithContext(ctx) return err }) if err != nil { @@ -113,6 +113,6 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch.APIClient) opensearch.ApiDeleteInstanceRequest { - req := apiClient.DeleteInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.DefaultAPI.DeleteInstance(ctx, model.ProjectId, model.Region, model.InstanceId) return req } diff --git a/internal/cmd/opensearch/instance/delete/delete_test.go b/internal/cmd/opensearch/instance/delete/delete_test.go index f9943acf7..29d85b31b 100644 --- a/internal/cmd/opensearch/instance/delete/delete_test.go +++ b/internal/cmd/opensearch/instance/delete/delete_test.go @@ -10,15 +10,18 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" ) type testCtxKey struct{} -var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &opensearch.APIClient{} -var testProjectId = uuid.NewString() -var testInstanceId = uuid.NewString() +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &opensearch.APIClient{DefaultAPI: &opensearch.DefaultAPIService{}} + testProjectId = uuid.NewString() + testRegion = "eu01" + testInstanceId = uuid.NewString() +) func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -33,6 +36,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -44,6 +48,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -55,7 +60,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *opensearch.ApiDeleteInstanceRequest)) opensearch.ApiDeleteInstanceRequest { - request := testClient.DeleteInstance(testCtx, testProjectId, testInstanceId) + request := testClient.DefaultAPI.DeleteInstance(testCtx, testProjectId, testRegion, testInstanceId) for _, mod := range mods { mod(&request) } @@ -159,7 +164,7 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), - cmpopts.EquateComparable(testCtx), + cmpopts.EquateComparable(testCtx, opensearch.DefaultAPIService{}), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) diff --git a/internal/cmd/opensearch/instance/describe/describe.go b/internal/cmd/opensearch/instance/describe/describe.go index 663ce82de..0bc1345b2 100644 --- a/internal/cmd/opensearch/instance/describe/describe.go +++ b/internal/cmd/opensearch/instance/describe/describe.go @@ -16,7 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" ) const ( @@ -87,31 +87,28 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch.APIClient) opensearch.ApiGetInstanceRequest { - req := apiClient.GetInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.DefaultAPI.GetInstance(ctx, model.ProjectId, model.Region, model.InstanceId) return req } func outputResult(p *print.Printer, outputFormat string, instance *opensearch.Instance) error { - if instance == nil { - return fmt.Errorf("instance is nil") - } - return p.OutputResult(outputFormat, instance, func() error { + if instance == nil { + return fmt.Errorf("instance is nil") + } table := tables.NewTable() table.AddRow("ID", utils.PtrString(instance.InstanceId)) table.AddSeparator() - table.AddRow("NAME", utils.PtrString(instance.Name)) + table.AddRow("NAME", instance.Name) table.AddSeparator() - if instance.LastOperation != nil { - table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) - table.AddSeparator() - table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) - table.AddSeparator() - } - table.AddRow("PLAN ID", utils.PtrString(instance.PlanId)) + table.AddRow("LAST OPERATION TYPE", instance.LastOperation.Type) + table.AddSeparator() + table.AddRow("LAST OPERATION STATE", instance.LastOperation.State) + table.AddSeparator() + table.AddRow("PLAN ID", instance.PlanId) // Only show ACL if it's present and not empty if instance.Parameters != nil { - acl := (*instance.Parameters)[aclParameterKey] + acl := instance.Parameters[aclParameterKey] aclStr, ok := acl.(string) if ok { if aclStr != "" { diff --git a/internal/cmd/opensearch/instance/describe/describe_test.go b/internal/cmd/opensearch/instance/describe/describe_test.go index cbbd064b2..dd5c0619a 100644 --- a/internal/cmd/opensearch/instance/describe/describe_test.go +++ b/internal/cmd/opensearch/instance/describe/describe_test.go @@ -11,15 +11,18 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" ) type testCtxKey struct{} -var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &opensearch.APIClient{} -var testProjectId = uuid.NewString() -var testInstanceId = uuid.NewString() +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &opensearch.APIClient{DefaultAPI: &opensearch.DefaultAPIService{}} + testProjectId = uuid.NewString() + testRegion = "eu01" + testInstanceId = uuid.NewString() +) func fixtureArgValues(mods ...func(argValues []string)) []string { argValues := []string{ @@ -34,6 +37,7 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, } for _, mod := range mods { mod(flagValues) @@ -45,6 +49,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, @@ -56,7 +61,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *opensearch.ApiGetInstanceRequest)) opensearch.ApiGetInstanceRequest { - request := testClient.GetInstance(testCtx, testProjectId, testInstanceId) + request := testClient.DefaultAPI.GetInstance(testCtx, testProjectId, testRegion, testInstanceId) for _, mod := range mods { mod(&request) } @@ -160,7 +165,7 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), - cmpopts.EquateComparable(testCtx), + cmpopts.EquateComparable(testCtx, opensearch.DefaultAPIService{}), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) diff --git a/internal/cmd/opensearch/instance/list/list.go b/internal/cmd/opensearch/instance/list/list.go index 48f7e986b..48ce861df 100644 --- a/internal/cmd/opensearch/instance/list/list.go +++ b/internal/cmd/opensearch/instance/list/list.go @@ -7,7 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -115,7 +115,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch.APIClient) opensearch.ApiListInstancesRequest { - req := apiClient.ListInstances(ctx, model.ProjectId) + req := apiClient.DefaultAPI.ListInstances(ctx, model.ProjectId, model.Region) return req } @@ -132,9 +132,9 @@ func outputResult(p *print.Printer, outputFormat, projectLabel string, instances instance := instances[i] table.AddRow( utils.PtrString(instance.InstanceId), - utils.PtrString(instance.Name), - utils.PtrString(instance.LastOperation.Type), - utils.PtrString(instance.LastOperation.State), + instance.Name, + instance.LastOperation.Type, + instance.LastOperation.State, ) } err := table.Display(p) diff --git a/internal/cmd/opensearch/instance/list/list_test.go b/internal/cmd/opensearch/instance/list/list_test.go index ad5ea76eb..c7d53f585 100644 --- a/internal/cmd/opensearch/instance/list/list_test.go +++ b/internal/cmd/opensearch/instance/list/list_test.go @@ -12,18 +12,22 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" ) type testCtxKey struct{} -var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &opensearch.APIClient{} -var testProjectId = uuid.NewString() +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &opensearch.APIClient{DefaultAPI: &opensearch.DefaultAPIService{}} + testProjectId = uuid.NewString() + testRegion = "eu01" +) func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, limitFlag: "10", } for _, mod := range mods { @@ -36,6 +40,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Limit: utils.Ptr(int64(10)), @@ -47,7 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *opensearch.ApiListInstancesRequest)) opensearch.ApiListInstancesRequest { - request := testClient.ListInstances(testCtx, testProjectId) + request := testClient.DefaultAPI.ListInstances(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } @@ -136,7 +141,7 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), - cmpopts.EquateComparable(testCtx), + cmpopts.EquateComparable(testCtx, opensearch.DefaultAPIService{}), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) diff --git a/internal/cmd/opensearch/instance/update/update.go b/internal/cmd/opensearch/instance/update/update.go index 557fb1712..e5772dc63 100644 --- a/internal/cmd/opensearch/instance/update/update.go +++ b/internal/cmd/opensearch/instance/update/update.go @@ -20,8 +20,8 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch/wait" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" + wait "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api/wait" ) const ( @@ -33,7 +33,6 @@ const ( metricsFrequencyFlag = "metrics-frequency" metricsPrefixFlag = "metrics-prefix" monitoringInstanceIdFlag = "monitoring-instance-id" - pluginFlag = "plugin" sgwAclFlag = "acl" syslogFlag = "syslog" planIdFlag = "plan-id" @@ -41,6 +40,12 @@ const ( versionFlag = "version" ) +var flagPlugins = flags.StringEnumSliceFlag( + "plugin", + opensearch.AllowedInstanceParametersPluginsInnerEnumValues, + "Plugins", +) + type inputModel struct { *globalflags.GlobalFlagModel InstanceId string @@ -49,12 +54,12 @@ type inputModel struct { EnableMonitoring *bool Graphite *string - MetricsFrequency *int64 + MetricsFrequency *int32 MetricsPrefix *string MonitoringInstanceId *string - Plugin *[]string + Plugin []opensearch.InstanceParametersPluginsInner SgwAcl *[]string - Syslog *[]string + Syslog []string PlanId *string } @@ -85,7 +90,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return err } - instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId) + instanceLabel, err := opensearchUtils.GetInstanceName(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.InstanceId) if err != nil { params.Printer.Debug(print.ErrorLevel, "get instance name: %v", err) instanceLabel = model.InstanceId @@ -98,7 +103,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } // Call API - req, err := buildRequest(ctx, model, apiClient) + req, err := buildRequest(ctx, model, apiClient.DefaultAPI) if err != nil { var dsaInvalidPlanError *cliErr.DSAInvalidPlanError if !errors.As(err, &dsaInvalidPlanError) { @@ -115,7 +120,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { err := spinner.Run(params.Printer, "Updating instance", func() error { - _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) return err }) if err != nil { @@ -138,10 +143,10 @@ func NewCmd(params *types.CmdParams) *cobra.Command { func configureFlags(cmd *cobra.Command) { cmd.Flags().Bool(enableMonitoringFlag, false, "Enable monitoring") cmd.Flags().String(graphiteFlag, "", "Graphite host") - cmd.Flags().Int64(metricsFrequencyFlag, 0, "Metrics frequency") + cmd.Flags().Int32(metricsFrequencyFlag, 0, "Metrics frequency") cmd.Flags().String(metricsPrefixFlag, "", "Metrics prefix") cmd.Flags().Var(flags.UUIDFlag(), monitoringInstanceIdFlag, "Monitoring instance ID") - cmd.Flags().StringSlice(pluginFlag, []string{}, "Plugin") + flagPlugins.Register(cmd) cmd.Flags().Var(flags.CIDRSliceFlag(), sgwAclFlag, "List of IP networks in CIDR notation which are allowed to access this instance") cmd.Flags().StringSlice(syslogFlag, []string{}, "Syslog") cmd.Flags().Var(flags.UUIDFlag(), planIdFlag, "Plan ID") @@ -160,11 +165,11 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu enableMonitoring := flags.FlagToBoolPointer(p, cmd, enableMonitoringFlag) monitoringInstanceId := flags.FlagToStringPointer(p, cmd, monitoringInstanceIdFlag) graphite := flags.FlagToStringPointer(p, cmd, graphiteFlag) - metricsFrequency := flags.FlagToInt64Pointer(p, cmd, metricsFrequencyFlag) + metricsFrequency := flags.FlagToInt32Pointer(p, cmd, metricsFrequencyFlag) metricsPrefix := flags.FlagToStringPointer(p, cmd, metricsPrefixFlag) - plugin := flags.FlagToStringSlicePointer(p, cmd, pluginFlag) + plugin := flagPlugins.Get() sgwAcl := flags.FlagToStringSlicePointer(p, cmd, sgwAclFlag) - syslog := flags.FlagToStringSlicePointer(p, cmd, syslogFlag) + syslog := flags.FlagToStringSliceValue(p, cmd, syslogFlag) planId := flags.FlagToStringPointer(p, cmd, planIdFlag) planName := flags.FlagToStringValue(p, cmd, planNameFlag) version := flags.FlagToStringValue(p, cmd, versionFlag) @@ -178,7 +183,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu if enableMonitoring == nil && monitoringInstanceId == nil && graphite == nil && metricsFrequency == nil && metricsPrefix == nil && plugin == nil && - sgwAcl == nil && syslog == nil && planId == nil && + sgwAcl == nil && planId == nil && planName == "" && version == "" { return nil, &cliErr.EmptyUpdateError{} } @@ -204,23 +209,23 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu } type openSearchClient interface { - PartialUpdateInstance(ctx context.Context, projectId, instanceId string) opensearch.ApiPartialUpdateInstanceRequest - ListOfferingsExecute(ctx context.Context, projectId string) (*opensearch.ListOfferingsResponse, error) + PartialUpdateInstance(ctx context.Context, projectId, region, instanceId string) opensearch.ApiPartialUpdateInstanceRequest + ListOfferings(ctx context.Context, projectId, region string) opensearch.ApiListOfferingsRequest } func buildRequest(ctx context.Context, model *inputModel, apiClient openSearchClient) (opensearch.ApiPartialUpdateInstanceRequest, error) { - req := apiClient.PartialUpdateInstance(ctx, model.ProjectId, model.InstanceId) + req := apiClient.PartialUpdateInstance(ctx, model.ProjectId, model.Region, model.InstanceId) var planId *string var err error - offerings, err := apiClient.ListOfferingsExecute(ctx, model.ProjectId) + offerings, err := apiClient.ListOfferings(ctx, model.ProjectId, model.Region).Execute() if err != nil { return req, fmt.Errorf("get OpenSearch offerings: %w", err) } if model.PlanId == nil && model.PlanName != "" && model.Version != "" { - planId, err = opensearchUtils.LoadPlanId(model.PlanName, model.Version, offerings) + foundPlanId, err := opensearchUtils.LoadPlanId(model.PlanName, model.Version, offerings) if err != nil { var dsaInvalidPlanError *cliErr.DSAInvalidPlanError if !errors.As(err, &dsaInvalidPlanError) { @@ -228,13 +233,12 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient openSearchCl } return req, err } - } else { + planId = &foundPlanId + } else if model.PlanId != nil { // planId is not required for update operation - if model.PlanId != nil { - err := opensearchUtils.ValidatePlanId(*model.PlanId, offerings) - if err != nil { - return req, err - } + err := opensearchUtils.ValidatePlanId(*model.PlanId, offerings) + if err != nil { + return req, err } planId = model.PlanId } diff --git a/internal/cmd/opensearch/instance/update/update_test.go b/internal/cmd/opensearch/instance/update/update_test.go index 433927c8d..4124a1af0 100644 --- a/internal/cmd/opensearch/instance/update/update_test.go +++ b/internal/cmd/opensearch/instance/update/update_test.go @@ -6,38 +6,39 @@ import ( "testing" "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/testparams" + "github.com/stackitcloud/stackit-cli/internal/pkg/testutils" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" ) type testCtxKey struct{} var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &opensearch.APIClient{} +var testClient = &opensearch.APIClient{DefaultAPI: &opensearch.DefaultAPIService{}} -type openSearchClientMocked struct { - returnError bool +type mockSettings struct { + getOfferingsFails bool listOfferingsResp *opensearch.ListOfferingsResponse } -func (c *openSearchClientMocked) PartialUpdateInstance(ctx context.Context, projectId, instanceId string) opensearch.ApiPartialUpdateInstanceRequest { - return testClient.PartialUpdateInstance(ctx, projectId, instanceId) -} - -func (c *openSearchClientMocked) ListOfferingsExecute(_ context.Context, _ string) (*opensearch.ListOfferingsResponse, error) { - if c.returnError { - return nil, fmt.Errorf("list flavors failed") +func newAPIClientMock(c mockSettings) opensearch.DefaultAPI { + return opensearch.DefaultAPIServiceMock{ + ListOfferingsExecuteMock: utils.Ptr(func(_ opensearch.ApiListOfferingsRequest) (*opensearch.ListOfferingsResponse, error) { + if c.getOfferingsFails { + return nil, fmt.Errorf("list flavors failed") + } + return c.listOfferingsResp, nil + }), } - return c.listOfferingsResp, nil } var ( testProjectId = uuid.NewString() + testRegion = "eu01" testInstanceId = uuid.NewString() testPlanId = uuid.NewString() testMonitoringInstanceId = uuid.NewString() @@ -56,12 +57,13 @@ func fixtureArgValues(mods ...func(argValues []string)) []string { func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, enableMonitoringFlag: "true", graphiteFlag: "example-graphite", metricsFrequencyFlag: "100", metricsPrefixFlag: "example-prefix", monitoringInstanceIdFlag: testMonitoringInstanceId, - pluginFlag: "example-plugin", + flagPlugins.Name(): string(opensearch.INSTANCEPARAMETERSPLUGINSINNER_REPOSITORY_AZURE), sgwAclFlag: "198.51.100.14/24", syslogFlag: "example-syslog", planIdFlag: testPlanId, @@ -76,17 +78,18 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, EnableMonitoring: utils.Ptr(true), Graphite: utils.Ptr("example-graphite"), - MetricsFrequency: utils.Ptr(int64(100)), + MetricsFrequency: utils.Ptr(int32(100)), MetricsPrefix: utils.Ptr("example-prefix"), MonitoringInstanceId: utils.Ptr(testMonitoringInstanceId), - Plugin: utils.Ptr([]string{"example-plugin"}), + Plugin: []opensearch.InstanceParametersPluginsInner{opensearch.INSTANCEPARAMETERSPLUGINSINNER_REPOSITORY_AZURE}, SgwAcl: utils.Ptr([]string{"198.51.100.14/24"}), - Syslog: utils.Ptr([]string{"example-syslog"}), + Syslog: []string{"example-syslog"}, PlanId: utils.Ptr(testPlanId), } for _, mod := range mods { @@ -96,17 +99,17 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *opensearch.ApiPartialUpdateInstanceRequest)) opensearch.ApiPartialUpdateInstanceRequest { - request := testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId) + request := testClient.DefaultAPI.PartialUpdateInstance(testCtx, testProjectId, testRegion, testInstanceId) request = request.PartialUpdateInstancePayload(opensearch.PartialUpdateInstancePayload{ Parameters: &opensearch.InstanceParameters{ EnableMonitoring: utils.Ptr(true), Graphite: utils.Ptr("example-graphite"), - MetricsFrequency: utils.Ptr(int64(100)), + MetricsFrequency: utils.Ptr(int32(100)), MetricsPrefix: utils.Ptr("example-prefix"), MonitoringInstanceId: utils.Ptr(testMonitoringInstanceId), - Plugins: utils.Ptr([]string{"example-plugin"}), + Plugins: []opensearch.InstanceParametersPluginsInner{opensearch.INSTANCEPARAMETERSPLUGINSINNER_REPOSITORY_AZURE}, SgwAcl: utils.Ptr("198.51.100.14/24"), - Syslog: utils.Ptr([]string{"example-syslog"}), + Syslog: []string{"example-syslog"}, }, PlanId: utils.Ptr(testPlanId), }) @@ -188,7 +191,7 @@ func TestParseInput(t *testing.T) { PlanId: utils.Ptr(testPlanId), EnableMonitoring: utils.Ptr(false), Graphite: utils.Ptr(""), - MetricsFrequency: utils.Ptr(int64(0)), + MetricsFrequency: utils.Ptr(int32(0)), MetricsPrefix: utils.Ptr(""), }, }, @@ -267,12 +270,11 @@ func TestParseInput(t *testing.T) { description: "repeated plugin flags", argValues: fixtureArgValues(), flagValues: fixtureFlagValues(), - pluginValues: []string{"example-plugin-1", "example-plugin-2"}, + pluginValues: []string{string(opensearch.INSTANCEPARAMETERSPLUGINSINNER_REPOSITORY_AZURE), string(opensearch.INSTANCEPARAMETERSPLUGINSINNER_ANALYSIS_PHONETIC)}, isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { - model.Plugin = utils.Ptr( - append(*model.Plugin, "example-plugin-1", "example-plugin-2"), - ) + model.Plugin = + append(model.Plugin, opensearch.INSTANCEPARAMETERSPLUGINSINNER_REPOSITORY_AZURE, opensearch.INSTANCEPARAMETERSPLUGINSINNER_ANALYSIS_PHONETIC) }), }, { @@ -282,118 +284,45 @@ func TestParseInput(t *testing.T) { syslogValues: []string{"example-syslog-1", "example-syslog-2"}, isValid: true, expectedModel: fixtureInputModel(func(model *inputModel) { - model.Syslog = utils.Ptr( - append(*model.Syslog, "example-syslog-1", "example-syslog-2"), - ) + model.Syslog = + append(model.Syslog, "example-syslog-1", "example-syslog-2") }), }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - params := testparams.NewTestParams() - cmd := NewCmd(params.CmdParams) - err := globalflags.Configure(cmd.Flags()) - if err != nil { - t.Fatalf("configure global flags: %v", err) - } - - for flag, value := range tt.flagValues { - err := cmd.Flags().Set(flag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", flag, value, err) - } - } - - for _, value := range tt.sgwAclValues { - err := cmd.Flags().Set(sgwAclFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", sgwAclFlag, value, err) - } - } - - for _, value := range tt.pluginValues { - err := cmd.Flags().Set(pluginFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", pluginFlag, value, err) - } - } - - for _, value := range tt.syslogValues { - err := cmd.Flags().Set(syslogFlag, value) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("setting flag --%s=%s: %v", syslogFlag, value, err) - } - } - - err = cmd.ValidateArgs(tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating args: %v", err) - } - - err = cmd.ValidateRequiredFlags() - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error validating flags: %v", err) - } - - model, err := parseInput(params.Printer, cmd, tt.argValues) - if err != nil { - if !tt.isValid { - return - } - t.Fatalf("error parsing flags: %v", err) - } - - if !tt.isValid { - t.Fatalf("did not fail on invalid input") - } - diff := cmp.Diff(model, tt.expectedModel) - if diff != "" { - t.Fatalf("Data does not match: %s", diff) - } + testutils.TestParseInputWithAdditionalFlags(t, NewCmd, parseInput, tt.expectedModel, tt.argValues, tt.flagValues, map[string][]string{ + sgwAclFlag: tt.sgwAclValues, + flagPlugins.Name(): tt.pluginValues, + syslogFlag: tt.syslogValues, + }, tt.isValid) }) } } func TestBuildRequest(t *testing.T) { tests := []struct { - description string - model *inputModel - expectedRequest opensearch.ApiPartialUpdateInstanceRequest - getOfferingsFails bool - listOfferingsResp *opensearch.ListOfferingsResponse - isValid bool + description string + model *inputModel + expectedRequest opensearch.ApiPartialUpdateInstanceRequest + mockClientSettings mockSettings + isValid bool }{ { description: "base", model: fixtureInputModel(), expectedRequest: fixtureRequest(), - listOfferingsResp: &opensearch.ListOfferingsResponse{ - Offerings: &[]opensearch.Offering{ - { - Version: utils.Ptr("example-version"), - Plans: &[]opensearch.Plan{ - { - Name: utils.Ptr("example-plan-name"), - Id: utils.Ptr(testPlanId), + mockClientSettings: mockSettings{ + listOfferingsResp: &opensearch.ListOfferingsResponse{ + Offerings: []opensearch.Offering{ + { + Version: "example-version", + Plans: []opensearch.Plan{ + { + Name: "example-plan-name", + Id: testPlanId, + }, }, }, }, @@ -410,14 +339,16 @@ func TestBuildRequest(t *testing.T) { }, ), expectedRequest: fixtureRequest(), - listOfferingsResp: &opensearch.ListOfferingsResponse{ - Offerings: &[]opensearch.Offering{ - { - Version: utils.Ptr("example-version"), - Plans: &[]opensearch.Plan{ - { - Name: utils.Ptr("example-plan-name"), - Id: utils.Ptr(testPlanId), + mockClientSettings: mockSettings{ + listOfferingsResp: &opensearch.ListOfferingsResponse{ + Offerings: []opensearch.Offering{ + { + Version: "example-version", + Plans: []opensearch.Plan{ + { + Name: "example-plan-name", + Id: testPlanId, + }, }, }, }, @@ -433,8 +364,10 @@ func TestBuildRequest(t *testing.T) { model.Version = "example-version" }, ), - getOfferingsFails: true, - isValid: false, + mockClientSettings: mockSettings{ + getOfferingsFails: true, + }, + isValid: false, }, { description: "plan name not found", @@ -445,14 +378,16 @@ func TestBuildRequest(t *testing.T) { model.Version = "example-version" }, ), - listOfferingsResp: &opensearch.ListOfferingsResponse{ - Offerings: &[]opensearch.Offering{ - { - Version: utils.Ptr("example-version"), - Plans: &[]opensearch.Plan{ - { - Name: utils.Ptr("other-plan-name"), - Id: utils.Ptr(testPlanId), + mockClientSettings: mockSettings{ + listOfferingsResp: &opensearch.ListOfferingsResponse{ + Offerings: []opensearch.Offering{ + { + Version: "example-version", + Plans: []opensearch.Plan{ + { + Name: "other-plan-name", + Id: testPlanId, + }, }, }, }, @@ -465,22 +400,19 @@ func TestBuildRequest(t *testing.T) { model: &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, InstanceId: testInstanceId, }, - expectedRequest: testClient.PartialUpdateInstance(testCtx, testProjectId, testInstanceId). + expectedRequest: testClient.DefaultAPI.PartialUpdateInstance(testCtx, testProjectId, testRegion, testInstanceId). PartialUpdateInstancePayload(opensearch.PartialUpdateInstancePayload{Parameters: &opensearch.InstanceParameters{}}), }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - client := &openSearchClientMocked{ - returnError: tt.getOfferingsFails, - listOfferingsResp: tt.listOfferingsResp, - } - request, err := buildRequest(testCtx, tt.model, client) + request, err := buildRequest(testCtx, tt.model, newAPIClientMock(tt.mockClientSettings)) if err != nil { if !tt.isValid { return @@ -491,6 +423,7 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), cmpopts.EquateComparable(testCtx), + cmpopts.IgnoreFields(tt.expectedRequest, "ApiService"), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) diff --git a/internal/cmd/opensearch/plans/plans.go b/internal/cmd/opensearch/plans/plans.go index f5705879e..b8fbce408 100644 --- a/internal/cmd/opensearch/plans/plans.go +++ b/internal/cmd/opensearch/plans/plans.go @@ -7,7 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/types" "github.com/spf13/cobra" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -18,7 +18,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/projectname" "github.com/stackitcloud/stackit-cli/internal/pkg/services/opensearch/client" "github.com/stackitcloud/stackit-cli/internal/pkg/tables" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) const ( @@ -115,7 +114,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, } func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch.APIClient) opensearch.ApiListOfferingsRequest { - req := apiClient.ListOfferings(ctx, model.ProjectId) + req := apiClient.DefaultAPI.ListOfferings(ctx, model.ProjectId, model.Region) return req } @@ -131,14 +130,14 @@ func outputResult(p *print.Printer, outputFormat, projectLabel string, plans []o for i := range plans { o := plans[i] if o.Plans != nil { - for j := range *o.Plans { - plan := (*o.Plans)[j] + for j := range o.Plans { + plan := o.Plans[j] table.AddRow( - utils.PtrString(o.Name), - utils.PtrString(o.Version), - utils.PtrString(plan.Id), - utils.PtrString(plan.Name), - utils.PtrString(plan.Description), + o.Name, + o.Version, + plan.Id, + plan.Name, + plan.Description, ) } } diff --git a/internal/cmd/opensearch/plans/plans_test.go b/internal/cmd/opensearch/plans/plans_test.go index 7a44e1335..349c30754 100644 --- a/internal/cmd/opensearch/plans/plans_test.go +++ b/internal/cmd/opensearch/plans/plans_test.go @@ -12,18 +12,22 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" ) type testCtxKey struct{} -var testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") -var testClient = &opensearch.APIClient{} -var testProjectId = uuid.NewString() +var ( + testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo") + testClient = &opensearch.APIClient{DefaultAPI: &opensearch.DefaultAPIService{}} + testProjectId = uuid.NewString() + testRegion = "eu01" +) func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string { flagValues := map[string]string{ globalflags.ProjectIdFlag: testProjectId, + globalflags.RegionFlag: testRegion, limitFlag: "10", } for _, mod := range mods { @@ -36,6 +40,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { model := &inputModel{ GlobalFlagModel: &globalflags.GlobalFlagModel{ ProjectId: testProjectId, + Region: testRegion, Verbosity: globalflags.VerbosityDefault, }, Limit: utils.Ptr(int64(10)), @@ -47,7 +52,7 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel { } func fixtureRequest(mods ...func(request *opensearch.ApiListOfferingsRequest)) opensearch.ApiListOfferingsRequest { - request := testClient.ListOfferings(testCtx, testProjectId) + request := testClient.DefaultAPI.ListOfferings(testCtx, testProjectId, testRegion) for _, mod := range mods { mod(&request) } @@ -136,7 +141,7 @@ func TestBuildRequest(t *testing.T) { diff := cmp.Diff(request, tt.expectedRequest, cmp.AllowUnexported(tt.expectedRequest), - cmpopts.EquateComparable(testCtx), + cmpopts.EquateComparable(testCtx, opensearch.DefaultAPIService{}), ) if diff != "" { t.Fatalf("Data does not match: %s", diff) diff --git a/internal/pkg/services/opensearch/client/client.go b/internal/pkg/services/opensearch/client/client.go index fb7d218a3..f151d34e6 100644 --- a/internal/pkg/services/opensearch/client/client.go +++ b/internal/pkg/services/opensearch/client/client.go @@ -6,9 +6,9 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/spf13/viper" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" ) func ConfigureClient(p *print.Printer, cliVersion string) (*opensearch.APIClient, error) { - return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.OpenSearchCustomEndpointKey), true, genericclient.CreateApiClient[*opensearch.APIClient](opensearch.NewAPIClient)) + return genericclient.ConfigureClientGeneric(p, cliVersion, viper.GetString(config.OpenSearchCustomEndpointKey), false, genericclient.CreateApiClient[*opensearch.APIClient](opensearch.NewAPIClient)) } diff --git a/internal/pkg/services/opensearch/utils/utils.go b/internal/pkg/services/opensearch/utils/utils.go index 58219f52c..9bc51b92b 100644 --- a/internal/pkg/services/opensearch/utils/utils.go +++ b/internal/pkg/services/opensearch/utils/utils.go @@ -7,7 +7,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/errors" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" ) const ( @@ -15,9 +15,9 @@ const ( ) func ValidatePlanId(planId string, offerings *opensearch.ListOfferingsResponse) error { - for _, offer := range *offerings.Offerings { - for _, plan := range *offer.Plans { - if plan.Id != nil && strings.EqualFold(*plan.Id, planId) { + for _, offer := range offerings.Offerings { + for _, plan := range offer.Plans { + if strings.EqualFold(plan.Id, planId) { return nil } } @@ -29,59 +29,51 @@ func ValidatePlanId(planId string, offerings *opensearch.ListOfferingsResponse) } } -func LoadPlanId(planName, version string, offerings *opensearch.ListOfferingsResponse) (*string, error) { +func LoadPlanId(planName, version string, offerings *opensearch.ListOfferingsResponse) (string, error) { availableVersions := "" availablePlanNames := "" isValidVersion := false - for _, offer := range *offerings.Offerings { - if !strings.EqualFold(*offer.Version, version) { - availableVersions = fmt.Sprintf("%s\n- %s", availableVersions, *offer.Version) + for _, offer := range offerings.Offerings { + if !strings.EqualFold(offer.Version, version) { + availableVersions = fmt.Sprintf("%s\n- %s", availableVersions, offer.Version) continue } isValidVersion = true - for _, plan := range *offer.Plans { - if plan.Name == nil { - continue - } - if strings.EqualFold(*plan.Name, planName) && plan.Id != nil { + for _, plan := range offer.Plans { + if strings.EqualFold(plan.Name, planName) { return plan.Id, nil } - availablePlanNames = fmt.Sprintf("%s\n- %s", availablePlanNames, *plan.Name) + availablePlanNames = fmt.Sprintf("%s\n- %s", availablePlanNames, plan.Name) } } if !isValidVersion { details := fmt.Sprintf("You provided version %q, which is invalid. Available versions are: %s", version, availableVersions) - return nil, &errors.DSAInvalidPlanError{ + return "", &errors.DSAInvalidPlanError{ Service: service, Details: details, } } details := fmt.Sprintf("You provided plan_name %q for version %s, which is invalid. Available plan names for that version are: %s", planName, version, availablePlanNames) - return nil, &errors.DSAInvalidPlanError{ + return "", &errors.DSAInvalidPlanError{ Service: service, Details: details, } } -type OpenSearchClient interface { - GetInstanceExecute(ctx context.Context, projectId, instanceId string) (*opensearch.Instance, error) - GetCredentialsExecute(ctx context.Context, projectId, instanceId, credentialsId string) (*opensearch.CredentialsResponse, error) -} - -func GetInstanceName(ctx context.Context, apiClient OpenSearchClient, projectId, instanceId string) (string, error) { - resp, err := apiClient.GetInstanceExecute(ctx, projectId, instanceId) +func GetInstanceName(ctx context.Context, apiClient opensearch.DefaultAPI, projectId, region, instanceId string) (string, error) { + resp, err := apiClient.GetInstance(ctx, projectId, region, instanceId).Execute() if err != nil { return "", fmt.Errorf("get OpenSearch instance: %w", err) } - return *resp.Name, nil + return resp.Name, nil } -func GetCredentialsUsername(ctx context.Context, apiClient OpenSearchClient, projectId, instanceId, credentialsId string) (string, error) { - resp, err := apiClient.GetCredentialsExecute(ctx, projectId, instanceId, credentialsId) +func GetCredentialsUsername(ctx context.Context, apiClient opensearch.DefaultAPI, projectId, region, instanceId, credentialsId string) (string, error) { + resp, err := apiClient.GetCredentials(ctx, projectId, region, instanceId, credentialsId).Execute() if err != nil { return "", fmt.Errorf("get OpenSearch credentials: %w", err) } - return *resp.Raw.Credentials.Username, nil + return resp.Raw.Credentials.Username, nil } diff --git a/internal/pkg/services/opensearch/utils/utils_test.go b/internal/pkg/services/opensearch/utils/utils_test.go index 8ebe3391b..114e8230b 100644 --- a/internal/pkg/services/opensearch/utils/utils_test.go +++ b/internal/pkg/services/opensearch/utils/utils_test.go @@ -5,10 +5,10 @@ import ( "fmt" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" - "github.com/google/uuid" - "github.com/stackitcloud/stackit-sdk-go/services/opensearch" + opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api" + + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" ) var ( @@ -18,62 +18,64 @@ var ( ) const ( + testRegion = "eu01" testInstanceName = "instance" testCredentialsUsername = "username" ) -type openSearchClientMocked struct { +type mockSettings struct { getInstanceFails bool getInstanceResp *opensearch.Instance getCredentialsFails bool getCredentialsResp *opensearch.CredentialsResponse } -func (m *openSearchClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*opensearch.Instance, error) { - if m.getInstanceFails { - return nil, fmt.Errorf("could not get instance") - } - return m.getInstanceResp, nil -} - -func (m *openSearchClientMocked) GetCredentialsExecute(_ context.Context, _, _, _ string) (*opensearch.CredentialsResponse, error) { - if m.getCredentialsFails { - return nil, fmt.Errorf("could not get user") +func newAPIClientMock(m mockSettings) opensearch.DefaultAPI { + return opensearch.DefaultAPIServiceMock{ + GetInstanceExecuteMock: utils.Ptr(func(_ opensearch.ApiGetInstanceRequest) (*opensearch.Instance, error) { + if m.getInstanceFails { + return nil, fmt.Errorf("could not get instance") + } + return m.getInstanceResp, nil + }), + GetCredentialsExecuteMock: utils.Ptr(func(_ opensearch.ApiGetCredentialsRequest) (*opensearch.CredentialsResponse, error) { + if m.getCredentialsFails { + return nil, fmt.Errorf("could not get user") + } + return m.getCredentialsResp, nil + }), } - return m.getCredentialsResp, nil } func TestGetInstanceName(t *testing.T) { tests := []struct { - description string - getInstanceFails bool - getInstanceResp *opensearch.Instance - isValid bool - expectedOutput string + description string + mockClientSettings mockSettings + isValid bool + expectedOutput string }{ { description: "base", - getInstanceResp: &opensearch.Instance{ - Name: utils.Ptr(testInstanceName), + mockClientSettings: mockSettings{ + getInstanceResp: &opensearch.Instance{ + Name: testInstanceName, + }, }, isValid: true, expectedOutput: testInstanceName, }, { - description: "get instance fails", - getInstanceFails: true, - isValid: false, + description: "get instance fails", + mockClientSettings: mockSettings{ + getInstanceFails: true, + }, + isValid: false, }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - client := &openSearchClientMocked{ - getInstanceFails: tt.getInstanceFails, - getInstanceResp: tt.getInstanceResp, - } - - output, err := GetInstanceName(context.Background(), client, testProjectId, testInstanceId) + output, err := GetInstanceName(context.Background(), newAPIClientMock(tt.mockClientSettings), testProjectId, testRegion, testInstanceId) if tt.isValid && err != nil { t.Errorf("failed on valid input") @@ -93,18 +95,19 @@ func TestGetInstanceName(t *testing.T) { func TestGetCredentialsUsername(t *testing.T) { tests := []struct { - description string - getCredentialsFails bool - getCredentialsResp *opensearch.CredentialsResponse - isValid bool - expectedOutput string + description string + mockClientSettings mockSettings + isValid bool + expectedOutput string }{ { description: "base", - getCredentialsResp: &opensearch.CredentialsResponse{ - Raw: &opensearch.RawCredentials{ - Credentials: &opensearch.Credentials{ - Username: utils.Ptr(testCredentialsUsername), + mockClientSettings: mockSettings{ + getCredentialsResp: &opensearch.CredentialsResponse{ + Raw: &opensearch.RawCredentials{ + Credentials: opensearch.Credentials{ + Username: testCredentialsUsername, + }, }, }, }, @@ -112,20 +115,17 @@ func TestGetCredentialsUsername(t *testing.T) { expectedOutput: testCredentialsUsername, }, { - description: "get credentials fails", - getCredentialsFails: true, - isValid: false, + description: "get credentials fails", + mockClientSettings: mockSettings{ + getCredentialsFails: true, + }, + isValid: false, }, } for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - client := &openSearchClientMocked{ - getCredentialsFails: tt.getCredentialsFails, - getCredentialsResp: tt.getCredentialsResp, - } - - output, err := GetCredentialsUsername(context.Background(), client, testProjectId, testInstanceId, testCredentialsId) + output, err := GetCredentialsUsername(context.Background(), newAPIClientMock(tt.mockClientSettings), testProjectId, testRegion, testInstanceId, testCredentialsId) if tt.isValid && err != nil { t.Errorf("failed on valid input")