Skip to content

Commit 3f4d14a

Browse files
authored
fix(ske): add nil pointer checks for cmd outputs (#634)
relates to STACKITCLI-115
1 parent f7d9744 commit 3f4d14a

File tree

16 files changed

+435
-26
lines changed

16 files changed

+435
-26
lines changed

internal/cmd/ske/cluster/create/create.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ func NewCmd(p *print.Printer) *cobra.Command {
143143
s.Stop()
144144
}
145145

146-
return outputResult(p, model, projectLabel, resp)
146+
return outputResult(p, model.OutputFormat, model.Async, projectLabel, resp)
147147
},
148148
}
149149
configureFlags(cmd)
@@ -197,18 +197,22 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClie
197197
return req
198198
}
199199

200-
func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp *ske.Cluster) error {
201-
switch model.OutputFormat {
200+
func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel string, cluster *ske.Cluster) error {
201+
if cluster == nil {
202+
return fmt.Errorf("cluster is nil")
203+
}
204+
205+
switch outputFormat {
202206
case print.JSONOutputFormat:
203-
details, err := json.MarshalIndent(resp, "", " ")
207+
details, err := json.MarshalIndent(cluster, "", " ")
204208
if err != nil {
205209
return fmt.Errorf("marshal SKE cluster: %w", err)
206210
}
207211
p.Outputln(string(details))
208212

209213
return nil
210214
case print.YAMLOutputFormat:
211-
details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler())
215+
details, err := yaml.MarshalWithOptions(cluster, yaml.IndentSequence(true), yaml.UseJSONMarshaler())
212216
if err != nil {
213217
return fmt.Errorf("marshal SKE cluster: %w", err)
214218
}
@@ -217,10 +221,10 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, resp
217221
return nil
218222
default:
219223
operationState := "Created"
220-
if model.Async {
224+
if async {
221225
operationState = "Triggered creation of"
222226
}
223-
p.Outputf("%s cluster for project %q. Cluster name: %s\n", operationState, projectLabel, utils.PtrString(resp.Name))
227+
p.Outputf("%s cluster for project %q. Cluster name: %s\n", operationState, projectLabel, utils.PtrString(cluster.Name))
224228
return nil
225229
}
226230
}

internal/cmd/ske/cluster/create/create_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,3 +315,39 @@ func TestBuildRequest(t *testing.T) {
315315
})
316316
}
317317
}
318+
319+
func TestOutputResult(t *testing.T) {
320+
type args struct {
321+
outputFormat string
322+
async bool
323+
projectLabel string
324+
cluster *ske.Cluster
325+
}
326+
tests := []struct {
327+
name string
328+
args args
329+
wantErr bool
330+
}{
331+
{
332+
name: "empty",
333+
args: args{},
334+
wantErr: true,
335+
},
336+
{
337+
name: "empty cluster",
338+
args: args{
339+
cluster: &ske.Cluster{},
340+
},
341+
wantErr: false,
342+
},
343+
}
344+
p := print.NewPrinter()
345+
p.Cmd = NewCmd(p)
346+
for _, tt := range tests {
347+
t.Run(tt.name, func(t *testing.T) {
348+
if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.cluster); (err != nil) != tt.wantErr {
349+
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
350+
}
351+
})
352+
}
353+
}

internal/cmd/ske/cluster/describe/describe.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClie
9797
}
9898

9999
func outputResult(p *print.Printer, outputFormat string, cluster *ske.Cluster) error {
100+
if cluster == nil {
101+
return fmt.Errorf("cluster is nil")
102+
}
103+
100104
switch outputFormat {
101105
case print.JSONOutputFormat:
102106
details, err := json.MarshalIndent(cluster, "", " ")
@@ -123,10 +127,14 @@ func outputResult(p *print.Printer, outputFormat string, cluster *ske.Cluster) e
123127
table := tables.NewTable()
124128
table.AddRow("NAME", utils.PtrString(cluster.Name))
125129
table.AddSeparator()
126-
table.AddRow("STATE", utils.PtrString(cluster.Status.Aggregated))
127-
table.AddSeparator()
128-
table.AddRow("VERSION", utils.PtrString(cluster.Kubernetes.Version))
129-
table.AddSeparator()
130+
if cluster.HasStatus() {
131+
table.AddRow("STATE", utils.PtrString(cluster.Status.Aggregated))
132+
table.AddSeparator()
133+
}
134+
if cluster.Kubernetes != nil {
135+
table.AddRow("VERSION", utils.PtrString(cluster.Kubernetes.Version))
136+
table.AddSeparator()
137+
}
130138
table.AddRow("ACL", acl)
131139
err := table.Display(p)
132140
if err != nil {

internal/cmd/ske/cluster/describe/describe_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,37 @@ func TestBuildRequest(t *testing.T) {
206206
})
207207
}
208208
}
209+
210+
func TestOutputResult(t *testing.T) {
211+
type args struct {
212+
outputFormat string
213+
cluster *ske.Cluster
214+
}
215+
tests := []struct {
216+
name string
217+
args args
218+
wantErr bool
219+
}{
220+
{
221+
name: "empty",
222+
args: args{},
223+
wantErr: true,
224+
},
225+
{
226+
name: "empty cluster",
227+
args: args{
228+
cluster: &ske.Cluster{},
229+
},
230+
wantErr: false,
231+
},
232+
}
233+
p := print.NewPrinter()
234+
p.Cmd = NewCmd(p)
235+
for _, tt := range tests {
236+
t.Run(tt.name, func(t *testing.T) {
237+
if err := outputResult(p, tt.args.outputFormat, tt.args.cluster); (err != nil) != tt.wantErr {
238+
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
239+
}
240+
})
241+
}
242+
}

internal/cmd/ske/cluster/generate-payload/generate_payload.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClie
134134
}
135135

136136
func outputResult(p *print.Printer, filePath *string, payload *ske.CreateOrUpdateClusterPayload) error {
137+
if payload == nil {
138+
return fmt.Errorf("payload is nil")
139+
}
140+
137141
payloadBytes, err := json.MarshalIndent(*payload, "", " ")
138142
if err != nil {
139143
return fmt.Errorf("marshal payload: %w", err)

internal/cmd/ske/cluster/generate-payload/generate_payload_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,3 +208,45 @@ func TestBuildRequest(t *testing.T) {
208208
})
209209
}
210210
}
211+
212+
func TestOutputResult(t *testing.T) {
213+
type args struct {
214+
filePath *string
215+
payload *ske.CreateOrUpdateClusterPayload
216+
}
217+
filePathDummy := "/dummy.txt"
218+
tests := []struct {
219+
name string
220+
args args
221+
wantErr bool
222+
}{
223+
{
224+
name: "empty",
225+
args: args{},
226+
wantErr: true,
227+
},
228+
{
229+
name: "missing payload",
230+
args: args{
231+
filePath: &filePathDummy,
232+
},
233+
wantErr: true,
234+
},
235+
{
236+
name: "missing file path",
237+
args: args{
238+
payload: &ske.CreateOrUpdateClusterPayload{},
239+
},
240+
wantErr: false,
241+
},
242+
}
243+
p := print.NewPrinter()
244+
p.Cmd = NewCmd(p)
245+
for _, tt := range tests {
246+
t.Run(tt.name, func(t *testing.T) {
247+
if err := outputResult(p, tt.args.filePath, tt.args.payload); (err != nil) != tt.wantErr {
248+
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
249+
}
250+
})
251+
}
252+
}

internal/cmd/ske/cluster/list/list.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,22 @@ func outputResult(p *print.Printer, outputFormat string, clusters []ske.Cluster)
174174
if c.Extensions != nil && c.Extensions.Argus != nil && *c.Extensions.Argus.Enabled {
175175
monitoring = "Enabled"
176176
}
177+
statusAggregated, kubernetesVersion := "", ""
178+
if c.HasStatus() {
179+
statusAggregated = utils.PtrString(c.Status.Aggregated)
180+
}
181+
if c.Kubernetes != nil {
182+
kubernetesVersion = utils.PtrString(c.Kubernetes.Version)
183+
}
184+
countNodepools := 0
185+
if c.Nodepools != nil {
186+
countNodepools = len(*c.Nodepools)
187+
}
177188
table.AddRow(
178189
utils.PtrString(c.Name),
179-
utils.PtrString(c.Status.Aggregated),
180-
utils.PtrString(c.Kubernetes.Version),
181-
len(*c.Nodepools),
190+
statusAggregated,
191+
kubernetesVersion,
192+
countNodepools,
182193
monitoring,
183194
)
184195
}

internal/cmd/ske/cluster/list/list_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,44 @@ func TestBuildRequest(t *testing.T) {
186186
})
187187
}
188188
}
189+
190+
func TestOutputResult(t *testing.T) {
191+
type args struct {
192+
outputFormat string
193+
clusters []ske.Cluster
194+
}
195+
tests := []struct {
196+
name string
197+
args args
198+
wantErr bool
199+
}{
200+
{
201+
name: "empty",
202+
args: args{},
203+
wantErr: false,
204+
},
205+
{
206+
name: "empty clusters slice",
207+
args: args{
208+
clusters: []ske.Cluster{},
209+
},
210+
wantErr: false,
211+
},
212+
{
213+
name: "empty cluster in clusters slice",
214+
args: args{
215+
clusters: []ske.Cluster{{}},
216+
},
217+
wantErr: false,
218+
},
219+
}
220+
p := print.NewPrinter()
221+
p.Cmd = NewCmd(p)
222+
for _, tt := range tests {
223+
t.Run(tt.name, func(t *testing.T) {
224+
if err := outputResult(p, tt.args.outputFormat, tt.args.clusters); (err != nil) != tt.wantErr {
225+
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
226+
}
227+
})
228+
}
229+
}

internal/cmd/ske/cluster/update/update.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func NewCmd(p *print.Printer) *cobra.Command {
105105
s.Stop()
106106
}
107107

108-
return outputResult(p, model, resp)
108+
return outputResult(p, model.OutputFormat, model.Async, model.ClusterName, resp)
109109
},
110110
}
111111
configureFlags(cmd)
@@ -159,18 +159,22 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *ske.APIClie
159159
return req
160160
}
161161

162-
func outputResult(p *print.Printer, model *inputModel, resp *ske.Cluster) error {
163-
switch model.OutputFormat {
162+
func outputResult(p *print.Printer, outputFormat string, async bool, clusterName string, cluster *ske.Cluster) error {
163+
if cluster == nil {
164+
return fmt.Errorf("cluster is nil")
165+
}
166+
167+
switch outputFormat {
164168
case print.JSONOutputFormat:
165-
details, err := json.MarshalIndent(resp, "", " ")
169+
details, err := json.MarshalIndent(cluster, "", " ")
166170
if err != nil {
167171
return fmt.Errorf("marshal SKE cluster: %w", err)
168172
}
169173
p.Outputln(string(details))
170174

171175
return nil
172176
case print.YAMLOutputFormat:
173-
details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler())
177+
details, err := yaml.MarshalWithOptions(cluster, yaml.IndentSequence(true), yaml.UseJSONMarshaler())
174178
if err != nil {
175179
return fmt.Errorf("marshal SKE cluster: %w", err)
176180
}
@@ -179,10 +183,10 @@ func outputResult(p *print.Printer, model *inputModel, resp *ske.Cluster) error
179183
return nil
180184
default:
181185
operationState := "Updated"
182-
if model.Async {
186+
if async {
183187
operationState = "Triggered update of"
184188
}
185-
p.Info("%s cluster %q\n", operationState, model.ClusterName)
189+
p.Info("%s cluster %q\n", operationState, clusterName)
186190
return nil
187191
}
188192
}

internal/cmd/ske/cluster/update/update_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,3 +295,39 @@ func TestBuildRequest(t *testing.T) {
295295
})
296296
}
297297
}
298+
299+
func TestOutputResult(t *testing.T) {
300+
type args struct {
301+
outputFormat string
302+
async bool
303+
clusterName string
304+
cluster *ske.Cluster
305+
}
306+
tests := []struct {
307+
name string
308+
args args
309+
wantErr bool
310+
}{
311+
{
312+
name: "empty",
313+
args: args{},
314+
wantErr: true,
315+
},
316+
{
317+
name: "empty cluster",
318+
args: args{
319+
cluster: &ske.Cluster{},
320+
},
321+
wantErr: false,
322+
},
323+
}
324+
p := print.NewPrinter()
325+
p.Cmd = NewCmd(p)
326+
for _, tt := range tests {
327+
t.Run(tt.name, func(t *testing.T) {
328+
if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.clusterName, tt.args.cluster); (err != nil) != tt.wantErr {
329+
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
330+
}
331+
})
332+
}
333+
}

0 commit comments

Comments
 (0)