Skip to content

Commit 3a8aede

Browse files
s-interrubenhoenle
andauthored
feat: clarify command output when async flag is set (#1329)
* feat(server): add async output handling for server creation * feat(volume): add async output handling * feat(network-area): add async output handling * feat(git): add async output handling for instance creation * feat(mongodbflex): add async output handling in restore and clone commands * feat(kms): add async output handling * feat(sfs): add async output handling * fix(kms): remove hardcoded async in outputResult tests * fix(sfs): remove hardcoded async in outputResult tests * refactor(kms): unify output handling for async operations * Update internal/cmd/git/instance/create/create.go Co-authored-by: Ruben Hönle <Ruben.Hoenle@stackit.cloud> * refactor(git): clean up outputResult function by passing only required fields * refactor(git): fix tests & removed redundant checks * fix(git): remove Id from inputModel --------- Co-authored-by: Ruben Hönle <Ruben.Hoenle@stackit.cloud>
1 parent 7463003 commit 3a8aede

File tree

31 files changed

+151
-361
lines changed

31 files changed

+151
-361
lines changed

internal/cmd/beta/sfs/resource-pool/create/create.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ The available performance class values can be obtained by running:
109109
s.Stop()
110110
}
111111

112-
return outputResult(params.Printer, model.OutputFormat, projectLabel, resp)
112+
return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp)
113113
},
114114
}
115115
configureFlags(cmd)
@@ -170,13 +170,17 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel,
170170
return &model, nil
171171
}
172172

173-
func outputResult(p *print.Printer, outputFormat, projectLabel string, resp *sfs.CreateResourcePoolResponse) error {
173+
func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel string, resp *sfs.CreateResourcePoolResponse) error {
174174
return p.OutputResult(outputFormat, resp, func() error {
175175
if resp == nil || resp.ResourcePool == nil {
176176
p.Outputln("Resource pool response is empty")
177177
return nil
178178
}
179-
p.Outputf("Created resource pool for project %q. Resource pool ID: %s\n", projectLabel, utils.PtrString(resp.ResourcePool.Id))
179+
operationState := "Created"
180+
if async {
181+
operationState = "Triggered creation of"
182+
}
183+
p.Outputf("%s resource pool for project %q. Resource pool ID: %s\n", operationState, projectLabel, utils.PtrString(resp.ResourcePool.Id))
180184
return nil
181185
})
182186
}

internal/cmd/beta/sfs/resource-pool/create/create_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ func TestBuildRequest(t *testing.T) {
252252
func TestOutputResult(t *testing.T) {
253253
type args struct {
254254
outputFormat string
255+
async bool
255256
projectLabel string
256257
resp *sfs.CreateResourcePoolResponse
257258
}
@@ -287,7 +288,7 @@ func TestOutputResult(t *testing.T) {
287288
p.Cmd = NewCmd(&types.CmdParams{Printer: p})
288289
for _, tt := range tests {
289290
t.Run(tt.name, func(t *testing.T) {
290-
if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr {
291+
if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr {
291292
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
292293
}
293294
})

internal/cmd/beta/sfs/resource-pool/delete/delete.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command {
8282
s.Stop()
8383
}
8484

85-
return outputResult(params.Printer, model.OutputFormat, resourcePoolName, resp)
85+
return outputResult(params.Printer, model.OutputFormat, model.Async, resourcePoolName, resp)
8686
},
8787
}
8888
return cmd
@@ -110,9 +110,13 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu
110110
return &model, nil
111111
}
112112

113-
func outputResult(p *print.Printer, outputFormat, resourcePoolName string, response map[string]interface{}) error {
113+
func outputResult(p *print.Printer, outputFormat string, async bool, resourcePoolName string, response map[string]interface{}) error {
114114
return p.OutputResult(outputFormat, response, func() error {
115-
p.Outputf("Deleted resource pool %q\n", resourcePoolName)
115+
operationState := "Deleted"
116+
if async {
117+
operationState = "Triggered deletion of"
118+
}
119+
p.Outputf("%s resource pool %q\n", operationState, resourcePoolName)
116120
return nil
117121
})
118122
}

internal/cmd/beta/sfs/resource-pool/delete/delete_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ func TestBuildRequest(t *testing.T) {
175175
func TestOutputResult(t *testing.T) {
176176
type args struct {
177177
outputFormat string
178+
async bool
178179
resourcePoolName string
179180
response map[string]interface{}
180181
}
@@ -201,7 +202,7 @@ func TestOutputResult(t *testing.T) {
201202
p.Cmd = NewCmd(&types.CmdParams{Printer: p})
202203
for _, tt := range tests {
203204
t.Run(tt.name, func(t *testing.T) {
204-
if err := outputResult(p, tt.args.outputFormat, tt.args.resourcePoolName, tt.args.response); (err != nil) != tt.wantErr {
205+
if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.resourcePoolName, tt.args.response); (err != nil) != tt.wantErr {
205206
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
206207
}
207208
})

internal/cmd/beta/sfs/resource-pool/update/update.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ The available performance class values can be obtained by running:
110110
s.Stop()
111111
}
112112

113-
return outputResult(params.Printer, model.OutputFormat, resp)
113+
return outputResult(params.Printer, model.OutputFormat, model.Async, resp)
114114
},
115115
}
116116
configureFlags(cmd)
@@ -165,13 +165,17 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu
165165
return &model, nil
166166
}
167167

168-
func outputResult(p *print.Printer, outputFormat string, resp *sfs.UpdateResourcePoolResponse) error {
168+
func outputResult(p *print.Printer, outputFormat string, async bool, resp *sfs.UpdateResourcePoolResponse) error {
169169
return p.OutputResult(outputFormat, resp, func() error {
170170
if resp == nil || resp.ResourcePool == nil {
171171
p.Outputln("Resource pool response is empty")
172172
return nil
173173
}
174-
p.Outputf("Updated resource pool %s\n", utils.PtrString(resp.ResourcePool.Name))
174+
operationState := "Updated"
175+
if async {
176+
operationState = "Triggered update of"
177+
}
178+
p.Outputf("%s resource pool %s\n", operationState, utils.PtrString(resp.ResourcePool.Name))
175179
return nil
176180
})
177181
}

internal/cmd/beta/sfs/resource-pool/update/update_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ func TestBuildRequest(t *testing.T) {
308308
func TestOutputResult(t *testing.T) {
309309
type args struct {
310310
outputFormat string
311+
async bool
311312
resp *sfs.UpdateResourcePoolResponse
312313
}
313314
tests := []struct {
@@ -353,7 +354,7 @@ func TestOutputResult(t *testing.T) {
353354
p.Cmd = NewCmd(&types.CmdParams{Printer: p})
354355
for _, tt := range tests {
355356
t.Run(tt.name, func(t *testing.T) {
356-
if err := outputResult(p, tt.args.outputFormat, tt.args.resp); (err != nil) != tt.wantErr {
357+
if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.resp); (err != nil) != tt.wantErr {
357358
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
358359
}
359360
})

internal/cmd/git/instance/create/create.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
1616
"github.com/stackitcloud/stackit-cli/internal/pkg/services/git/client"
1717
"github.com/stackitcloud/stackit-cli/internal/pkg/spinner"
18-
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
1918
"github.com/stackitcloud/stackit-sdk-go/services/git"
2019
"github.com/stackitcloud/stackit-sdk-go/services/git/wait"
2120
)
@@ -28,7 +27,6 @@ const (
2827

2928
type inputModel struct {
3029
*globalflags.GlobalFlagModel
31-
Id *string
3230
Name string
3331
Flavor string
3432
Acl []string
@@ -80,20 +78,19 @@ func NewCmd(params *types.CmdParams) *cobra.Command {
8078
if err != nil {
8179
return fmt.Errorf("create stackit git instance: %w", err)
8280
}
83-
model.Id = result.Id
8481

8582
// Wait for async operation, if async mode not enabled
8683
if !model.Async {
8784
s := spinner.New(params.Printer)
8885
s.Start("Creating stackit git instance")
89-
_, err = wait.CreateGitInstanceWaitHandler(ctx, apiClient, model.ProjectId, *model.Id).WaitWithContext(ctx)
86+
_, err = wait.CreateGitInstanceWaitHandler(ctx, apiClient, model.ProjectId, *result.Id).WaitWithContext(ctx)
9087
if err != nil {
9188
return fmt.Errorf("wait for stackit git Instance creation: %w", err)
9289
}
9390
s.Stop()
9491
}
9592

96-
return outputResult(params.Printer, model, result)
93+
return outputResult(params.Printer, model.OutputFormat, model.Async, model.Name, result)
9794
},
9895
}
9996

@@ -143,17 +140,20 @@ func createPayload(model *inputModel) git.CreateInstancePayload {
143140
}
144141
}
145142

146-
func outputResult(p *print.Printer, model *inputModel, resp *git.Instance) error {
147-
if model == nil {
148-
return fmt.Errorf("input model is nil")
143+
func outputResult(p *print.Printer, outputFormat string, async bool, instanceName string, resp *git.Instance) error {
144+
if resp == nil {
145+
return fmt.Errorf("API resp is nil")
149146
}
150-
var outputFormat string
151-
if model.GlobalFlagModel != nil {
152-
outputFormat = model.OutputFormat
147+
if resp.Id == nil {
148+
return fmt.Errorf("API resp is missing instance id")
153149
}
154150

155151
return p.OutputResult(outputFormat, resp, func() error {
156-
p.Outputf("Created instance %q with id %s\n", model.Name, utils.PtrString(model.Id))
152+
operationState := "Created"
153+
if async {
154+
operationState = "Triggered creation of"
155+
}
156+
p.Outputf("%s instance %q with id %s\n", operationState, instanceName, *resp.Id)
157157
return nil
158158
})
159159
}

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

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -175,39 +175,43 @@ func TestBuildRequest(t *testing.T) {
175175

176176
func TestOutputResult(t *testing.T) {
177177
type args struct {
178-
model *inputModel
179-
resp *git.Instance
178+
outputFormat string
179+
async bool
180+
instanceName string
181+
resp *git.Instance
180182
}
181183
tests := []struct {
182184
name string
183185
args args
184186
wantErr bool
185187
}{
186188
{
187-
name: "nil",
189+
name: "nil response",
188190
args: args{
189-
model: nil,
190-
resp: nil,
191+
outputFormat: "",
192+
async: false,
193+
instanceName: "",
194+
resp: nil,
191195
},
192196
wantErr: true,
193197
},
194198
{
195199
name: "empty input",
196200
args: args{
197-
model: &inputModel{},
198-
resp: &git.Instance{},
201+
outputFormat: "",
202+
async: false,
203+
instanceName: "",
204+
resp: &git.Instance{Id: utils.Ptr(uuid.NewString())},
199205
},
200206
wantErr: false,
201207
},
202208
{
203209
name: "output json",
204210
args: args{
205-
model: &inputModel{
206-
GlobalFlagModel: &globalflags.GlobalFlagModel{
207-
OutputFormat: print.JSONOutputFormat,
208-
},
209-
},
210-
resp: nil,
211+
outputFormat: print.JSONOutputFormat,
212+
async: true,
213+
instanceName: testName,
214+
resp: &git.Instance{Id: utils.Ptr(uuid.NewString())},
211215
},
212216
wantErr: false,
213217
},
@@ -216,7 +220,7 @@ func TestOutputResult(t *testing.T) {
216220
p.Cmd = NewCmd(&types.CmdParams{Printer: p})
217221
for _, tt := range tests {
218222
t.Run(tt.name, func(t *testing.T) {
219-
if err := outputResult(p, tt.args.model, tt.args.resp); (err != nil) != tt.wantErr {
223+
if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.instanceName, tt.args.resp); (err != nil) != tt.wantErr {
220224
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
221225
}
222226
})

internal/cmd/kms/key/create/create.go

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ package create
22

33
import (
44
"context"
5-
"encoding/json"
65
"fmt"
76

87
"github.com/stackitcloud/stackit-cli/internal/pkg/types"
98

10-
"github.com/goccy/go-yaml"
119
"github.com/spf13/cobra"
1210
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
1311
cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors"
@@ -159,29 +157,14 @@ func outputResult(p *print.Printer, model *inputModel, resp *kms.Key) error {
159157
return fmt.Errorf("response is nil")
160158
}
161159

162-
switch model.OutputFormat {
163-
case print.JSONOutputFormat:
164-
details, err := json.MarshalIndent(resp, "", " ")
165-
if err != nil {
166-
return fmt.Errorf("marshal KMS key: %w", err)
167-
}
168-
p.Outputln(string(details))
169-
170-
case print.YAMLOutputFormat:
171-
details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler())
172-
if err != nil {
173-
return fmt.Errorf("marshal KMS key: %w", err)
174-
}
175-
p.Outputln(string(details))
176-
177-
default:
160+
return p.OutputResult(model.OutputFormat, resp, func() error {
178161
operationState := "Created"
179162
if model.Async {
180163
operationState = "Triggered creation of"
181164
}
182165
p.Outputf("%s the KMS key %q. Key ID: %s\n", operationState, utils.PtrString(resp.DisplayName), utils.PtrString(resp.Id))
183-
}
184-
return nil
166+
return nil
167+
})
185168
}
186169

187170
func configureFlags(cmd *cobra.Command) {

internal/cmd/kms/key/delete/delete.go

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ package delete
22

33
import (
44
"context"
5-
"encoding/json"
65
"fmt"
76

87
"github.com/stackitcloud/stackit-cli/internal/pkg/types"
98

10-
"github.com/goccy/go-yaml"
119
"github.com/spf13/cobra"
1210
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
1311
"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
@@ -127,22 +125,8 @@ func outputResult(p *print.Printer, outputFormat string, resp *kms.Key) error {
127125
return fmt.Errorf("response is nil")
128126
}
129127

130-
switch outputFormat {
131-
case print.JSONOutputFormat:
132-
details, err := json.MarshalIndent(resp, "", " ")
133-
if err != nil {
134-
return fmt.Errorf("marshal output to JSON: %w", err)
135-
}
136-
p.Outputln(string(details))
137-
case print.YAMLOutputFormat:
138-
details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler())
139-
if err != nil {
140-
return fmt.Errorf("marshal output to YAML: %w", err)
141-
}
142-
p.Outputln(string(details))
143-
144-
default:
128+
return p.OutputResult(outputFormat, resp, func() error {
145129
p.Outputf("Deletion of KMS key %s scheduled successfully for the deletion date: %s\n", utils.PtrString(resp.DisplayName), utils.PtrString(resp.DeletionDate))
146-
}
147-
return nil
130+
return nil
131+
})
148132
}

0 commit comments

Comments
 (0)