diff --git a/internal/cmd/opensearch/credentials/create/create.go b/internal/cmd/opensearch/credentials/create/create.go index b2e4dde55..9a4174db8 100644 --- a/internal/cmd/opensearch/credentials/create/create.go +++ b/internal/cmd/opensearch/credentials/create/create.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -15,8 +16,6 @@ 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/utils" - - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) @@ -79,7 +78,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create OpenSearch credentials: %w", err) } - return outputResult(p, model, instanceLabel, resp) + return outputResult(p, model.OutputFormat, model.ShowPassword, instanceLabel, resp) }, } configureFlags(cmd) @@ -123,11 +122,15 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch. return req } -func outputResult(p *print.Printer, model *inputModel, instanceLabel string, resp *opensearch.CredentialsResponse) error { - if !model.ShowPassword { +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 { + return fmt.Errorf("response or response content is nil") + } + + if !showPassword { resp.Raw.Credentials.Password = utils.Ptr("hidden") } - switch model.OutputFormat { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -151,7 +154,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel string, res if username := resp.Raw.Credentials.Username; username != nil && *username != "" { p.Outputf("Username: %s\n", *username) } - if !model.ShowPassword { + if !showPassword { p.Outputf("Password: \n") } else { p.Outputf("Password: %s\n", utils.PtrString(resp.Raw.Credentials.Password)) diff --git a/internal/cmd/opensearch/credentials/create/create_test.go b/internal/cmd/opensearch/credentials/create/create_test.go index cd8559b64..1424c9729 100644 --- a/internal/cmd/opensearch/credentials/create/create_test.go +++ b/internal/cmd/opensearch/credentials/create/create_test.go @@ -4,12 +4,12 @@ import ( "context" "testing" - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" - "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" + "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" + "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) @@ -200,3 +200,83 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + showPassword bool + instanceLabel string + resp *opensearch.CredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + 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", + args: args{ + resp: &opensearch.CredentialsResponse{ + Raw: &opensearch.RawCredentials{ + Credentials: &opensearch.Credentials{}, + }, + }, + }, + wantErr: true, + }, + { + name: "set uri but no raw in response", + args: args{ + resp: &opensearch.CredentialsResponse{ + Uri: utils.Ptr("https://opensearch.example.com"), + }, + }, + wantErr: true, + }, + { + name: "set response correctly", + args: args{ + resp: &opensearch.CredentialsResponse{ + Raw: &opensearch.RawCredentials{ + Credentials: &opensearch.Credentials{}, + }, + Uri: utils.Ptr("https://opensearch.example.com"), + }, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.showPassword, 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/describe/describe.go b/internal/cmd/opensearch/credentials/describe/describe.go index 64817d66a..fb8012012 100644 --- a/internal/cmd/opensearch/credentials/describe/describe.go +++ b/internal/cmd/opensearch/credentials/describe/describe.go @@ -112,6 +112,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch. } func outputResult(p *print.Printer, outputFormat string, credentials *opensearch.CredentialsResponse) error { + if credentials == nil { + return fmt.Errorf("credentials is nil") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(credentials, "", " ") diff --git a/internal/cmd/opensearch/credentials/describe/describe_test.go b/internal/cmd/opensearch/credentials/describe/describe_test.go index 30fb04ded..3618a4cc7 100644 --- a/internal/cmd/opensearch/credentials/describe/describe_test.go +++ b/internal/cmd/opensearch/credentials/describe/describe_test.go @@ -243,3 +243,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + credentials *opensearch.CredentialsResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty credentials", + args: args{ + credentials: &opensearch.CredentialsResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/opensearch/credentials/list/list_test.go b/internal/cmd/opensearch/credentials/list/list_test.go index 44336f34b..d6b041f57 100644 --- a/internal/cmd/opensearch/credentials/list/list_test.go +++ b/internal/cmd/opensearch/credentials/list/list_test.go @@ -207,3 +207,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + credentials []opensearch.CredentialsListItem + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty credentials slice", + args: args{ + credentials: []opensearch.CredentialsListItem{}, + }, + wantErr: false, + }, + { + name: "set empty credential in credentials slice", + args: args{ + credentials: []opensearch.CredentialsListItem{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.credentials); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/opensearch/instance/create/create.go b/internal/cmd/opensearch/instance/create/create.go index d6eeaf951..62d447f82 100644 --- a/internal/cmd/opensearch/instance/create/create.go +++ b/internal/cmd/opensearch/instance/create/create.go @@ -127,7 +127,7 @@ func NewCmd(p *print.Printer) *cobra.Command { s.Stop() } - return outputResult(p, model, projectLabel, instanceId, resp) + return outputResult(p, model.OutputFormat, model.Async, projectLabel, instanceId, resp) }, } configureFlags(cmd) @@ -256,8 +256,8 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient openSearchCl return req, nil } -func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId string, resp *opensearch.CreateInstanceResponse) error { - switch model.OutputFormat { +func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel, instanceId string, resp *opensearch.CreateInstanceResponse) error { + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") if err != nil { @@ -276,7 +276,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId return nil default: operationState := "Created" - if model.Async { + if async { operationState = "Triggered creation of" } p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId) diff --git a/internal/cmd/opensearch/instance/create/create_test.go b/internal/cmd/opensearch/instance/create/create_test.go index 7fd34113f..3aceed814 100644 --- a/internal/cmd/opensearch/instance/create/create_test.go +++ b/internal/cmd/opensearch/instance/create/create_test.go @@ -488,3 +488,40 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + async bool + projectLabel string + instanceId string + resp *opensearch.CreateInstanceResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty response", + args: args{ + resp: &opensearch.CreateInstanceResponse{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/opensearch/instance/describe/describe.go b/internal/cmd/opensearch/instance/describe/describe.go index fffdc1f86..1358aef39 100644 --- a/internal/cmd/opensearch/instance/describe/describe.go +++ b/internal/cmd/opensearch/instance/describe/describe.go @@ -100,6 +100,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *opensearch. } func outputResult(p *print.Printer, outputFormat string, instance *opensearch.Instance) error { + if instance == nil { + return fmt.Errorf("instance is nil") + } + switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(instance, "", " ") @@ -123,18 +127,22 @@ func outputResult(p *print.Printer, outputFormat string, instance *opensearch.In table.AddSeparator() table.AddRow("NAME", utils.PtrString(instance.Name)) table.AddSeparator() - table.AddRow("LAST OPERATION TYPE", utils.PtrString(instance.LastOperation.Type)) - table.AddSeparator() - table.AddRow("LAST OPERATION STATE", utils.PtrString(instance.LastOperation.State)) - 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)) // Only show ACL if it's present and not empty - acl := (*instance.Parameters)[aclParameterKey] - aclStr, ok := acl.(string) - if ok { - if aclStr != "" { - table.AddSeparator() - table.AddRow("ACL", aclStr) + if instance.Parameters != nil { + acl := (*instance.Parameters)[aclParameterKey] + aclStr, ok := acl.(string) + if ok { + if aclStr != "" { + table.AddSeparator() + table.AddRow("ACL", aclStr) + } } } err := table.Display(p) diff --git a/internal/cmd/opensearch/instance/describe/describe_test.go b/internal/cmd/opensearch/instance/describe/describe_test.go index b7c27a2b7..d4b58656f 100644 --- a/internal/cmd/opensearch/instance/describe/describe_test.go +++ b/internal/cmd/opensearch/instance/describe/describe_test.go @@ -216,3 +216,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instance *opensearch.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: true, + }, + { + name: "set empty instance", + args: args{ + instance: &opensearch.Instance{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instance); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/opensearch/instance/list/list_test.go b/internal/cmd/opensearch/instance/list/list_test.go index 4036a79b7..baa22ac9f 100644 --- a/internal/cmd/opensearch/instance/list/list_test.go +++ b/internal/cmd/opensearch/instance/list/list_test.go @@ -186,3 +186,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + instances []opensearch.Instance + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty instances slice", + args: args{ + instances: []opensearch.Instance{}, + }, + wantErr: false, + }, + { + name: "set empty instance in instances slice", + args: args{ + instances: []opensearch.Instance{}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.instances); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/opensearch/plans/plans.go b/internal/cmd/opensearch/plans/plans.go index 50be3aae8..013e486e1 100644 --- a/internal/cmd/opensearch/plans/plans.go +++ b/internal/cmd/opensearch/plans/plans.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/goccy/go-yaml" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -16,8 +17,6 @@ import ( "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" - - "github.com/spf13/cobra" "github.com/stackitcloud/stackit-sdk-go/services/opensearch" ) @@ -153,15 +152,17 @@ func outputResult(p *print.Printer, outputFormat string, plans []opensearch.Offe table.SetHeader("OFFERING NAME", "VERSION", "ID", "NAME", "DESCRIPTION") for i := range plans { o := plans[i] - 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), - ) + if o.Plans != nil { + 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), + ) + } } table.AddSeparator() } diff --git a/internal/cmd/opensearch/plans/plans_test.go b/internal/cmd/opensearch/plans/plans_test.go index bff8c20ef..a1d162d4a 100644 --- a/internal/cmd/opensearch/plans/plans_test.go +++ b/internal/cmd/opensearch/plans/plans_test.go @@ -186,3 +186,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func TestOutputResult(t *testing.T) { + type args struct { + outputFormat string + plans []opensearch.Offering + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "empty", + args: args{}, + wantErr: false, + }, + { + name: "set empty plans slice", + args: args{ + plans: []opensearch.Offering{}, + }, + wantErr: false, + }, + { + name: "set empty plan in plans slice", + args: args{ + plans: []opensearch.Offering{{}}, + }, + wantErr: false, + }, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputResult(p, tt.args.outputFormat, tt.args.plans); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +}