Skip to content

Commit ab5ae06

Browse files
authored
chore (postgresflex): Fix potential nil pointer and add test cases (#626)
* fix: testcase and fixes for nil pointer exceptions in output functions * fix: integrate review findings
1 parent ef291d1 commit ab5ae06

File tree

22 files changed

+580
-86
lines changed

22 files changed

+580
-86
lines changed

internal/cmd/postgresflex/backup/describe/describe.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func NewCmd(p *print.Printer) *cobra.Command {
7272
return fmt.Errorf("describe backup for PostgreSQL Flex instance: %w", err)
7373
}
7474

75-
return outputResult(p, cmd, model.OutputFormat, *resp.Item)
75+
return outputResult(p, model.OutputFormat, *resp.Item)
7676
},
7777
}
7878
configureFlags(cmd)
@@ -106,8 +106,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *postgresfle
106106
return req
107107
}
108108

109-
func outputResult(p *print.Printer, cmd *cobra.Command, outputFormat string, backup postgresflex.Backup) error {
110-
backupStartTime, err := time.Parse(time.RFC3339, *backup.StartTime)
109+
func outputResult(p *print.Printer, outputFormat string, backup postgresflex.Backup) error {
110+
if backup.StartTime == nil || *backup.StartTime == "" {
111+
return fmt.Errorf("start time not defined")
112+
}
113+
backupStartTime, err := time.Parse(time.RFC3339, utils.PtrString(backup.StartTime))
111114
if err != nil {
112115
return fmt.Errorf("parse backup start time: %w", err)
113116
}
@@ -119,7 +122,7 @@ func outputResult(p *print.Printer, cmd *cobra.Command, outputFormat string, bac
119122
if err != nil {
120123
return fmt.Errorf("marshal backup for PostgreSQL Flex backup: %w", err)
121124
}
122-
cmd.Println(string(details))
125+
p.Outputln(string(details))
123126

124127
return nil
125128
case print.YAMLOutputFormat:

internal/cmd/postgresflex/backup/describe/describe_test.go

+38-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ package describe
33
import (
44
"context"
55
"testing"
6-
7-
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
6+
"time"
87

98
"github.com/google/go-cmp/cmp"
109
"github.com/google/go-cmp/cmp/cmpopts"
1110
"github.com/google/uuid"
11+
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
12+
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
13+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
1214
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex"
1315
)
1416

@@ -235,3 +237,37 @@ func TestBuildRequest(t *testing.T) {
235237
})
236238
}
237239
}
240+
241+
func Test_outputResult(t *testing.T) {
242+
type args struct {
243+
outputFormat string
244+
backup postgresflex.Backup
245+
}
246+
tests := []struct {
247+
name string
248+
args args
249+
wantErr bool
250+
}{
251+
{"empty", args{}, true},
252+
{"standard", args{outputFormat: "", backup: postgresflex.Backup{StartTime: utils.Ptr(time.Now().Format(time.RFC3339))}}, false},
253+
{"complete", args{outputFormat: "", backup: postgresflex.Backup{
254+
EndTime: utils.Ptr(time.Now().Format(time.RFC3339)),
255+
Id: utils.Ptr("id"),
256+
Labels: &[]string{"foo", "bar", "baz"},
257+
Name: utils.Ptr("name"),
258+
Options: &map[string]string{"test1": "test1", "test2": "test2"},
259+
Size: utils.Ptr(int64(42)),
260+
StartTime: utils.Ptr(time.Now().Format(time.RFC3339)),
261+
}}, false},
262+
}
263+
p := print.NewPrinter()
264+
p.Cmd = NewCmd(p)
265+
266+
for _, tt := range tests {
267+
t.Run(tt.name, func(t *testing.T) {
268+
if err := outputResult(p, tt.args.outputFormat, tt.args.backup); (err != nil) != tt.wantErr {
269+
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
270+
}
271+
})
272+
}
273+
}

internal/cmd/postgresflex/backup/list/list.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ func outputResult(p *print.Printer, outputFormat string, backups []postgresflex.
157157
for i := range backups {
158158
backup := backups[i]
159159

160-
backupStartTime, err := time.Parse(time.RFC3339, *backup.StartTime)
160+
backupStartTime, err := time.Parse(time.RFC3339, utils.PtrString(backup.StartTime))
161161
if err != nil {
162162
return fmt.Errorf("parse backup start time: %w", err)
163163
}

internal/cmd/postgresflex/backup/list/list_test.go

+50-3
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ package list
33
import (
44
"context"
55
"testing"
6-
7-
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
8-
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
6+
"time"
97

108
"github.com/google/go-cmp/cmp"
119
"github.com/google/go-cmp/cmp/cmpopts"
1210
"github.com/google/uuid"
11+
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
12+
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
13+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
1314
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex"
1415
)
1516

@@ -205,3 +206,49 @@ func TestBuildRequest(t *testing.T) {
205206
})
206207
}
207208
}
209+
210+
func Test_outputResult(t *testing.T) {
211+
type args struct {
212+
outputFormat string
213+
backups []postgresflex.Backup
214+
}
215+
tests := []struct {
216+
name string
217+
args args
218+
wantErr bool
219+
}{
220+
{"empty", args{}, false},
221+
{"standard", args{outputFormat: "", backups: []postgresflex.Backup{}}, false},
222+
{"complete", args{outputFormat: "", backups: []postgresflex.Backup{
223+
{
224+
EndTime: utils.Ptr(time.Now().Format(time.RFC3339)),
225+
Id: utils.Ptr("id"),
226+
Labels: &[]string{"foo", "bar", "baz"},
227+
Name: utils.Ptr("name"),
228+
Options: &map[string]string{"test1": "test1", "test2": "test2"},
229+
Size: utils.Ptr(int64(42)),
230+
StartTime: utils.Ptr(time.Now().Format(time.RFC3339)),
231+
},
232+
{
233+
EndTime: utils.Ptr(time.Now().Format(time.RFC3339)),
234+
Id: utils.Ptr("id"),
235+
Labels: &[]string{"foo", "bar", "baz"},
236+
Name: utils.Ptr("name"),
237+
Options: &map[string]string{"test1": "test1", "test2": "test2"},
238+
Size: utils.Ptr(int64(42)),
239+
StartTime: utils.Ptr(time.Now().Format(time.RFC3339)),
240+
},
241+
},
242+
}, false},
243+
}
244+
p := print.NewPrinter()
245+
p.Cmd = NewCmd(p)
246+
247+
for _, tt := range tests {
248+
t.Run(tt.name, func(t *testing.T) {
249+
if err := outputResult(p, tt.args.outputFormat, tt.args.backups); (err != nil) != tt.wantErr {
250+
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
251+
}
252+
})
253+
}
254+
}

internal/cmd/postgresflex/instance/clone/clone.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func NewCmd(p *print.Printer) *cobra.Command {
108108
s.Stop()
109109
}
110110

111-
return outputResult(p, model, instanceLabel, instanceId, resp)
111+
return outputResult(p, model.OutputFormat, model.Async, instanceLabel, instanceId, resp)
112112
},
113113
}
114114
configureFlags(cmd)
@@ -205,8 +205,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient PostgreSQLFl
205205
return req, nil
206206
}
207207

208-
func outputResult(p *print.Printer, model *inputModel, instanceLabel, instanceId string, resp *postgresflex.CloneInstanceResponse) error {
209-
switch model.OutputFormat {
208+
func outputResult(p *print.Printer, outputFormat string, async bool, instanceLabel, instanceId string, resp *postgresflex.CloneInstanceResponse) error {
209+
if resp == nil {
210+
return fmt.Errorf("response not set")
211+
}
212+
switch outputFormat {
210213
case print.JSONOutputFormat:
211214
details, err := json.MarshalIndent(resp, "", " ")
212215
if err != nil {
@@ -225,7 +228,7 @@ func outputResult(p *print.Printer, model *inputModel, instanceLabel, instanceId
225228
return nil
226229
default:
227230
operationState := "Cloned"
228-
if model.Async {
231+
if async {
229232
operationState = "Triggered cloning of"
230233
}
231234
p.Info("%s instance from instance %q. New Instance ID: %s\n", operationState, instanceLabel, instanceId)

internal/cmd/postgresflex/instance/clone/clone_test.go

+35-4
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@ import (
66
"testing"
77
"time"
88

9-
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
10-
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
11-
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
12-
139
"github.com/google/go-cmp/cmp"
1410
"github.com/google/go-cmp/cmp/cmpopts"
1511
"github.com/google/uuid"
12+
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
13+
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
14+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
1615
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex"
1716
)
1817

@@ -529,3 +528,35 @@ func TestBuildRequest(t *testing.T) {
529528
})
530529
}
531530
}
531+
532+
func Test_outputResult(t *testing.T) {
533+
type args struct {
534+
OutputFormat string
535+
instanceLabel string
536+
instanceId string
537+
async bool
538+
resp *postgresflex.CloneInstanceResponse
539+
}
540+
tests := []struct {
541+
name string
542+
args args
543+
wantErr bool
544+
}{
545+
{"empty", args{}, true},
546+
{"standard", args{
547+
instanceLabel: "foo",
548+
instanceId: "bar",
549+
resp: &postgresflex.CloneInstanceResponse{InstanceId: utils.Ptr("id")},
550+
}, false},
551+
}
552+
p := print.NewPrinter()
553+
p.Cmd = NewCmd(p)
554+
555+
for _, tt := range tests {
556+
t.Run(tt.name, func(t *testing.T) {
557+
if err := outputResult(p, tt.args.OutputFormat, tt.args.async, tt.args.instanceLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr {
558+
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
559+
}
560+
})
561+
}
562+
}

internal/cmd/postgresflex/instance/create/create.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ func NewCmd(p *print.Printer) *cobra.Command {
133133
s.Stop()
134134
}
135135

136-
return outputResult(p, model, projectLabel, instanceId, resp)
136+
return outputResult(p, model.OutputFormat, model.Async, projectLabel, instanceId, resp)
137137
},
138138
}
139139
configureFlags(cmd)
@@ -273,8 +273,11 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient PostgreSQLFl
273273
return req, nil
274274
}
275275

276-
func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId string, resp *postgresflex.CreateInstanceResponse) error {
277-
switch model.OutputFormat {
276+
func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel, instanceId string, resp *postgresflex.CreateInstanceResponse) error {
277+
if resp == nil {
278+
return fmt.Errorf("no response passed")
279+
}
280+
switch outputFormat {
278281
case print.JSONOutputFormat:
279282
details, err := json.MarshalIndent(resp, "", " ")
280283
if err != nil {
@@ -293,7 +296,7 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel, instanceId
293296
return nil
294297
default:
295298
operationState := "Created"
296-
if model.Async {
299+
if async {
297300
operationState = "Triggered creation of"
298301
}
299302
p.Outputf("%s instance for project %q. Instance ID: %s\n", operationState, projectLabel, instanceId)

internal/cmd/postgresflex/instance/create/create_test.go

+38-4
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ import (
55
"fmt"
66
"testing"
77

8-
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
9-
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
10-
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
11-
128
"github.com/google/go-cmp/cmp"
139
"github.com/google/go-cmp/cmp/cmpopts"
1410
"github.com/google/uuid"
11+
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
12+
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
13+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
1514
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex"
1615
)
1716

@@ -521,3 +520,38 @@ func TestBuildRequest(t *testing.T) {
521520
})
522521
}
523522
}
523+
524+
func Test_outputResult(t *testing.T) {
525+
type args struct {
526+
outputFormat string
527+
async bool
528+
projectLabel string
529+
instanceId string
530+
resp *postgresflex.CreateInstanceResponse
531+
}
532+
tests := []struct {
533+
name string
534+
args args
535+
wantErr bool
536+
}{
537+
{"empty", args{}, true},
538+
{"standard", args{
539+
outputFormat: "",
540+
async: false,
541+
projectLabel: "label",
542+
instanceId: "4711",
543+
resp: &postgresflex.CreateInstanceResponse{Id: utils.Ptr("id")},
544+
},
545+
false,
546+
},
547+
}
548+
p := print.NewPrinter()
549+
p.Cmd = NewCmd(p)
550+
for _, tt := range tests {
551+
t.Run(tt.name, func(t *testing.T) {
552+
if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.instanceId, tt.args.resp); (err != nil) != tt.wantErr {
553+
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
554+
}
555+
})
556+
}
557+
}

0 commit comments

Comments
 (0)