diff --git a/internal/cmd/project/create/create.go b/internal/cmd/project/create/create.go index 19d20beed..99f62fadd 100644 --- a/internal/cmd/project/create/create.go +++ b/internal/cmd/project/create/create.go @@ -95,7 +95,7 @@ func NewCmd(p *print.Printer) *cobra.Command { return fmt.Errorf("create project: %w", err) } - return outputResult(p, model, resp) + return outputResult(p, *model, resp) }, } configureFlags(cmd) @@ -212,7 +212,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *resourceman return req, nil } -func outputResult(p *print.Printer, model *inputModel, resp *resourcemanager.Project) error { +func outputResult(p *print.Printer, model inputModel, resp *resourcemanager.Project) error { + if resp == nil { + return fmt.Errorf("response is empty") + } + if model.GlobalFlagModel == nil { + return fmt.Errorf("globalflags are empty") + } switch model.OutputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(resp, "", " ") diff --git a/internal/cmd/project/create/create_test.go b/internal/cmd/project/create/create_test.go index 43fa09b92..8c977d3c6 100644 --- a/internal/cmd/project/create/create_test.go +++ b/internal/cmd/project/create/create_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "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/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/uuid" "github.com/stackitcloud/stackit-sdk-go/services/resourcemanager" "github.com/zalando/go-keyring" ) @@ -359,3 +358,28 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + model inputModel + resp *resourcemanager.Project + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{model: inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}}, true}, + {"base", args{inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}, &resourcemanager.Project{}}, 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.model, tt.args.resp); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/project/describe/describe.go b/internal/cmd/project/describe/describe.go index 62b997b64..26162f859 100644 --- a/internal/cmd/project/describe/describe.go +++ b/internal/cmd/project/describe/describe.go @@ -119,6 +119,9 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *resourceman } func outputResult(p *print.Printer, outputFormat string, project *resourcemanager.GetProjectResponse) error { + if project == nil { + return fmt.Errorf("response not set") + } switch outputFormat { case print.JSONOutputFormat: details, err := json.MarshalIndent(project, "", " ") @@ -146,7 +149,9 @@ func outputResult(p *print.Printer, outputFormat string, project *resourcemanage table.AddSeparator() table.AddRow("STATE", utils.PtrString(project.LifecycleState)) table.AddSeparator() - table.AddRow("PARENT ID", utils.PtrString(project.Parent.Id)) + if project.Parent != nil { + table.AddRow("PARENT ID", utils.PtrString(project.Parent.Id)) + } err := table.Display(p) if err != nil { return fmt.Errorf("render table: %w", err) diff --git a/internal/cmd/project/describe/describe_test.go b/internal/cmd/project/describe/describe_test.go index 8d8cd7490..3c2e5f658 100644 --- a/internal/cmd/project/describe/describe_test.go +++ b/internal/cmd/project/describe/describe_test.go @@ -3,13 +3,14 @@ package describe import ( "context" "testing" - - "github.com/stackitcloud/stackit-cli/internal/pkg/globalflags" - "github.com/stackitcloud/stackit-cli/internal/pkg/print" + "time" "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/resourcemanager" ) @@ -214,3 +215,35 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + project *resourcemanager.GetProjectResponse + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{}, true}, + {"base", args{"", &resourcemanager.GetProjectResponse{}}, false}, + {"complete", args{"", &resourcemanager.GetProjectResponse{ + ProjectId: utils.Ptr("4711"), + Name: utils.Ptr("name"), + CreationTime: utils.Ptr(time.Now()), + LifecycleState: utils.Ptr(resourcemanager.LIFECYCLESTATE_CREATING), + Parent: &resourcemanager.Parent{Id: utils.Ptr("parent id")}, + }, + }, 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.project); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/project/list/list.go b/internal/cmd/project/list/list.go index 99afb9b1f..9051dc145 100644 --- a/internal/cmd/project/list/list.go +++ b/internal/cmd/project/list/list.go @@ -242,11 +242,16 @@ func outputResult(p *print.Printer, outputFormat string, projects []resourcemana table.SetHeader("ID", "NAME", "STATE", "PARENT ID") for i := range projects { p := projects[i] + + var parentId *string + if p.Parent != nil { + parentId = p.Parent.Id + } table.AddRow( utils.PtrString(p.ProjectId), utils.PtrString(p.Name), utils.PtrString(p.LifecycleState), - utils.PtrString(p.Parent.Id), + utils.PtrString(parentId), ) } diff --git a/internal/cmd/project/list/list_test.go b/internal/cmd/project/list/list_test.go index 2f5bc9e98..7c6e73cee 100644 --- a/internal/cmd/project/list/list_test.go +++ b/internal/cmd/project/list/list_test.go @@ -9,17 +9,16 @@ import ( "testing" "time" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" "github.com/stackitcloud/stackit-cli/internal/pkg/auth" "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/zalando/go-keyring" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/google/uuid" sdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/services/resourcemanager" + "github.com/zalando/go-keyring" ) type testCtxKey struct{} @@ -495,3 +494,53 @@ func TestFetchProjects(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + outputFormat string + projects []resourcemanager.Project + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{}, false}, + {"base", args{"", []resourcemanager.Project{{}}}, false}, + {"complete", args{"", []resourcemanager.Project{ + { + ContainerId: utils.Ptr("container-id1"), + CreationTime: utils.Ptr(time.Now()), + Labels: &map[string]string{"foo": "bar"}, + LifecycleState: utils.Ptr(resourcemanager.LIFECYCLESTATE_CREATING), + Name: utils.Ptr("some name"), + Parent: &resourcemanager.Parent{ + Id: utils.Ptr("parent-id"), + }, + ProjectId: utils.Ptr("project-id1"), + }, + { + ContainerId: utils.Ptr("container-id2"), + CreationTime: utils.Ptr(time.Now()), + Labels: &map[string]string{"foo": "bar"}, + LifecycleState: utils.Ptr(resourcemanager.LIFECYCLESTATE_CREATING), + Name: utils.Ptr("some name"), + Parent: &resourcemanager.Parent{ + Id: utils.Ptr("parent-id"), + }, + ProjectId: utils.Ptr("project-id2"), + }, + }}, 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.projects); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/project/member/list/list.go b/internal/cmd/project/member/list/list.go index 1d5056303..861423dc5 100644 --- a/internal/cmd/project/member/list/list.go +++ b/internal/cmd/project/member/list/list.go @@ -89,7 +89,7 @@ func NewCmd(p *print.Printer) *cobra.Command { members = members[:*model.Limit] } - return outputResult(p, model, members) + return outputResult(p, *model, members) }, } configureFlags(cmd) @@ -145,13 +145,16 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *authorizati return req } -func outputResult(p *print.Printer, model *inputModel, members []authorization.Member) error { +func outputResult(p *print.Printer, model inputModel, members []authorization.Member) error { + if model.GlobalFlagModel == nil { + return fmt.Errorf("globalflags are empty") + } sortFn := func(i, j int) bool { switch model.SortBy { case "subject": - return *members[i].Subject < *members[j].Subject + return utils.PtrString(members[i].Subject) < utils.PtrString(members[j].Subject) case "role": - return *members[i].Role < *members[j].Role + return utils.PtrString(members[i].Role) < utils.PtrString(members[j].Role) default: return false } diff --git a/internal/cmd/project/member/list/list_test.go b/internal/cmd/project/member/list/list_test.go index 1e4050d4e..4aecdee12 100644 --- a/internal/cmd/project/member/list/list_test.go +++ b/internal/cmd/project/member/list/list_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" - "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/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "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/authorization" ) @@ -209,3 +208,44 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputResult(t *testing.T) { + type args struct { + model inputModel + members []authorization.Member + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{model: inputModel{GlobalFlagModel: &globalflags.GlobalFlagModel{}}}, false}, + {"base", args{inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, + Subject: utils.Ptr("subject"), + Limit: nil, + SortBy: "", + }, nil}, false}, + {"complete", args{inputModel{ + GlobalFlagModel: &globalflags.GlobalFlagModel{}, + Subject: utils.Ptr("subject"), + Limit: nil, + SortBy: "", + }, + []authorization.Member{ + {Role: utils.Ptr("role1"), Subject: utils.Ptr("subject1")}, + {Role: utils.Ptr("role2"), Subject: utils.Ptr("subject2")}, + {Role: utils.Ptr("role3"), Subject: utils.Ptr("subject3")}, + }}, + 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.model, tt.args.members); (err != nil) != tt.wantErr { + t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/internal/cmd/project/role/list/list_test.go b/internal/cmd/project/role/list/list_test.go index 59c8f9855..4e8744528 100644 --- a/internal/cmd/project/role/list/list_test.go +++ b/internal/cmd/project/role/list/list_test.go @@ -4,14 +4,13 @@ import ( "context" "testing" - "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/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/google/uuid" "github.com/spf13/cobra" + "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/authorization" ) @@ -172,3 +171,37 @@ func TestBuildRequest(t *testing.T) { }) } } + +func Test_outputRolesResult(t *testing.T) { + type args struct { + outputFormat string + roles []authorization.Role + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"empty", args{}, false}, + {"standard", args{"", nil}, false}, + {"complete", args{"", []authorization.Role{ + { + Description: utils.Ptr("description"), + Id: utils.Ptr("id"), + Name: utils.Ptr("name"), + Permissions: &[]authorization.Permission{ + {Description: utils.Ptr("description"), Name: utils.Ptr("name")}, + }, + }, + }}, false}, + } + p := print.NewPrinter() + p.Cmd = NewCmd(p) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := outputRolesResult(p, tt.args.outputFormat, tt.args.roles); (err != nil) != tt.wantErr { + t.Errorf("outputRolesResult() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +}