From 386dc1053ae459767c0e71c8df5d0191df744324 Mon Sep 17 00:00:00 2001 From: "Inter, Sven" Date: Wed, 4 Mar 2026 15:09:48 +0100 Subject: [PATCH 01/14] feat(server): add async output handling for server creation --- internal/cmd/server/create/create.go | 10 +++++++--- internal/cmd/server/create/create_test.go | 3 ++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/internal/cmd/server/create/create.go b/internal/cmd/server/create/create.go index a93efcbf7..ab5253af0 100644 --- a/internal/cmd/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -153,7 +153,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { s.Stop() } - return outputResult(params.Printer, model.OutputFormat, projectLabel, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) }, } configureFlags(cmd) @@ -322,12 +322,16 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.CreateServerPayload(payload) } -func outputResult(p *print.Printer, outputFormat, projectLabel string, server *iaas.Server) error { +func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel string, server *iaas.Server) error { if server == nil { return fmt.Errorf("server response is empty") } return p.OutputResult(outputFormat, server, func() error { - p.Outputf("Created server for project %q.\nServer ID: %s\n", projectLabel, utils.PtrString(server.Id)) + operationState := "Created" + if async { + operationState = "Triggered creation of" + } + p.Outputf("%s server for project %q.\nServer ID: %s\n", operationState, projectLabel, utils.PtrString(server.Id)) return nil }) } diff --git a/internal/cmd/server/create/create_test.go b/internal/cmd/server/create/create_test.go index 521b80922..7ab029013 100644 --- a/internal/cmd/server/create/create_test.go +++ b/internal/cmd/server/create/create_test.go @@ -382,6 +382,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + async bool projectLabel string server *iaas.Server } @@ -407,7 +408,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.server); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.server); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) From e0ca2d716997192380567e43ce79e54152d916fd Mon Sep 17 00:00:00 2001 From: "Inter, Sven" Date: Mon, 9 Mar 2026 11:13:44 +0100 Subject: [PATCH 02/14] feat(volume): add async output handling --- internal/cmd/volume/create/create.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/cmd/volume/create/create.go b/internal/cmd/volume/create/create.go index f0bda5f69..f82725de6 100644 --- a/internal/cmd/volume/create/create.go +++ b/internal/cmd/volume/create/create.go @@ -184,7 +184,11 @@ func outputResult(p *print.Printer, model *inputModel, projectLabel string, volu return fmt.Errorf("volume response is empty") } return p.OutputResult(model.OutputFormat, volume, func() error { - p.Outputf("Created volume for project %q.\nVolume ID: %s\n", projectLabel, utils.PtrString(volume.Id)) + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + p.Outputf("%s volume for project %q.\nVolume ID: %s\n", operationState, projectLabel, utils.PtrString(volume.Id)) return nil }) } From 902910228737b6309543099ec4b6ec8775e7e240 Mon Sep 17 00:00:00 2001 From: "Inter, Sven" Date: Mon, 9 Mar 2026 11:18:08 +0100 Subject: [PATCH 03/14] feat(network-area): add async output handling --- internal/cmd/network-area/region/create/create.go | 10 +++++++--- internal/cmd/network-area/region/create/create_test.go | 3 ++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/internal/cmd/network-area/region/create/create.go b/internal/cmd/network-area/region/create/create.go index 63a8c6348..0b59fa852 100644 --- a/internal/cmd/network-area/region/create/create.go +++ b/internal/cmd/network-area/region/create/create.go @@ -117,7 +117,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { s.Stop() } - return outputResult(params.Printer, model.OutputFormat, model.Region, networkAreaLabel, *resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, model.Region, networkAreaLabel, *resp) }, } configureFlags(cmd) @@ -186,9 +186,13 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli return req.CreateNetworkAreaRegionPayload(payload) } -func outputResult(p *print.Printer, outputFormat, region, networkAreaLabel string, regionalArea iaas.RegionalArea) error { +func outputResult(p *print.Printer, outputFormat string, async bool, region, networkAreaLabel string, regionalArea iaas.RegionalArea) error { return p.OutputResult(outputFormat, regionalArea, func() error { - p.Outputf("Create region configuration for SNA %q.\nRegion: %s\n", networkAreaLabel, region) + operationState := "Created" + if async { + operationState = "Triggered creation of" + } + p.Outputf("%s region configuration for SNA %q.\nRegion: %s\n", operationState, networkAreaLabel, region) return nil }) } diff --git a/internal/cmd/network-area/region/create/create_test.go b/internal/cmd/network-area/region/create/create_test.go index cf92c59c3..cff70a377 100644 --- a/internal/cmd/network-area/region/create/create_test.go +++ b/internal/cmd/network-area/region/create/create_test.go @@ -267,6 +267,7 @@ func TestBuildRequest(t *testing.T) { func Test_outputResult(t *testing.T) { type args struct { outputFormat string + async bool region string networkAreaLabel string regionalArea iaas.RegionalArea @@ -300,7 +301,7 @@ func Test_outputResult(t *testing.T) { p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.region, tt.args.networkAreaLabel, tt.args.regionalArea); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.region, tt.args.networkAreaLabel, tt.args.regionalArea); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) From 1f89580bc80d294b034ea2b3d15a3f28465f8e72 Mon Sep 17 00:00:00 2001 From: "Inter, Sven" Date: Mon, 9 Mar 2026 14:19:17 +0100 Subject: [PATCH 04/14] feat(git): add async output handling for instance creation --- internal/cmd/git/instance/create/create.go | 13 ++++++++++++- internal/cmd/git/instance/create/create_test.go | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/internal/cmd/git/instance/create/create.go b/internal/cmd/git/instance/create/create.go index b11bb16a6..1729e3eb9 100644 --- a/internal/cmd/git/instance/create/create.go +++ b/internal/cmd/git/instance/create/create.go @@ -153,7 +153,18 @@ func outputResult(p *print.Printer, model *inputModel, resp *git.Instance) error } return p.OutputResult(outputFormat, resp, func() error { - p.Outputf("Created instance %q with id %s\n", model.Name, utils.PtrString(model.Id)) + if resp == nil { + return nil + } + operationState := "Created" + if model.Async { + operationState = "Triggered creation of" + } + id := utils.PtrString(model.Id) + if resp.Id != nil { + id = *resp.Id + } + p.Outputf("%s instance %q with id %s\n", operationState, model.Name, id) return nil }) } diff --git a/internal/cmd/git/instance/create/create_test.go b/internal/cmd/git/instance/create/create_test.go index bde352a95..c68384ed6 100644 --- a/internal/cmd/git/instance/create/create_test.go +++ b/internal/cmd/git/instance/create/create_test.go @@ -194,7 +194,7 @@ func TestOutputResult(t *testing.T) { { name: "empty input", args: args{ - model: &inputModel{}, + model: fixtureInputModel(), resp: &git.Instance{}, }, wantErr: false, From b04519ae44710a0b6c12442c67621208a36351da Mon Sep 17 00:00:00 2001 From: "Inter, Sven" Date: Mon, 9 Mar 2026 15:26:48 +0100 Subject: [PATCH 05/14] feat(mongodbflex): add async output handling in restore and clone commands --- internal/cmd/mongodbflex/backup/restore/restore.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/internal/cmd/mongodbflex/backup/restore/restore.go b/internal/cmd/mongodbflex/backup/restore/restore.go index a4b6e5ca9..44b611669 100644 --- a/internal/cmd/mongodbflex/backup/restore/restore.go +++ b/internal/cmd/mongodbflex/backup/restore/restore.go @@ -108,7 +108,11 @@ func NewCmd(params *types.CmdParams) *cobra.Command { s.Stop() } - params.Printer.Outputf("Restored instance %q with backup %q\n", model.InstanceId, model.BackupId) + operationState := "Restored" + if model.Async { + operationState = "Triggered restore of" + } + params.Printer.Outputf("%s instance %q with backup %q\n", operationState, model.InstanceId, model.BackupId) return nil } @@ -129,7 +133,11 @@ func NewCmd(params *types.CmdParams) *cobra.Command { s.Stop() } - params.Printer.Outputf("Cloned instance %q from backup with timestamp %q\n", model.InstanceId, model.Timestamp) + operationState := "Cloned" + if model.Async { + operationState = "Triggered clone of" + } + params.Printer.Outputf("%s instance %q from backup with timestamp %q\n", operationState, model.InstanceId, model.Timestamp) return nil }, } From 3667ecd24873666cccee9a0f54cc524de93f78a8 Mon Sep 17 00:00:00 2001 From: "Inter, Sven" Date: Tue, 10 Mar 2026 13:43:43 +0100 Subject: [PATCH 06/14] feat(kms): add async output handling --- internal/cmd/beta/kms/version/disable/disable.go | 10 +++++++--- internal/cmd/beta/kms/version/disable/disable_test.go | 2 +- internal/cmd/beta/kms/version/enable/enable.go | 10 +++++++--- internal/cmd/beta/kms/version/enable/enable_test.go | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/internal/cmd/beta/kms/version/disable/disable.go b/internal/cmd/beta/kms/version/disable/disable.go index 9260c8e6a..9004cdfa1 100644 --- a/internal/cmd/beta/kms/version/disable/disable.go +++ b/internal/cmd/beta/kms/version/disable/disable.go @@ -87,7 +87,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { params.Printer.Debug(print.ErrorLevel, "get key version: %v", err) } - return outputResult(params.Printer, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, resp) }, } @@ -133,7 +133,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func outputResult(p *print.Printer, outputFormat string, resp *kms.Version) error { +func outputResult(p *print.Printer, outputFormat string, async bool, resp *kms.Version) error { if resp == nil { return fmt.Errorf("response is nil") } @@ -154,7 +154,11 @@ func outputResult(p *print.Printer, outputFormat string, resp *kms.Version) erro p.Outputln(string(details)) default: - p.Outputf("Disabled version %d of the key %q\n", utils.PtrValue(resp.Number), utils.PtrValue(resp.KeyId)) + operationState := "Disabled" + if async { + operationState = "Triggered disable of" + } + p.Outputf("%s version %d of the key %q\n", operationState, utils.PtrValue(resp.Number), utils.PtrValue(resp.KeyId)) } return nil diff --git a/internal/cmd/beta/kms/version/disable/disable_test.go b/internal/cmd/beta/kms/version/disable/disable_test.go index 8108ea4b9..02a809f18 100644 --- a/internal/cmd/beta/kms/version/disable/disable_test.go +++ b/internal/cmd/beta/kms/version/disable/disable_test.go @@ -312,7 +312,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - err := outputResult(p, tt.outputFormat, tt.resp) + err := outputResult(p, tt.outputFormat, false, tt.resp) if (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } diff --git a/internal/cmd/beta/kms/version/enable/enable.go b/internal/cmd/beta/kms/version/enable/enable.go index 06d8a85ec..8052e203f 100644 --- a/internal/cmd/beta/kms/version/enable/enable.go +++ b/internal/cmd/beta/kms/version/enable/enable.go @@ -87,7 +87,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { params.Printer.Debug(print.ErrorLevel, "get key version: %v", err) } - return outputResult(params.Printer, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, resp) }, } @@ -133,7 +133,7 @@ func configureFlags(cmd *cobra.Command) { cobra.CheckErr(err) } -func outputResult(p *print.Printer, outputFormat string, resp *kms.Version) error { +func outputResult(p *print.Printer, outputFormat string, async bool, resp *kms.Version) error { if resp == nil { return fmt.Errorf("response is nil") } @@ -154,7 +154,11 @@ func outputResult(p *print.Printer, outputFormat string, resp *kms.Version) erro p.Outputln(string(details)) default: - p.Outputf("Enabled version %d of the key %q\n", utils.PtrValue(resp.Number), utils.PtrValue(resp.KeyId)) + operationState := "Enabled" + if async { + operationState = "Triggered enable of" + } + p.Outputf("%s version %d of the key %q\n", operationState, utils.PtrValue(resp.Number), utils.PtrValue(resp.KeyId)) } return nil diff --git a/internal/cmd/beta/kms/version/enable/enable_test.go b/internal/cmd/beta/kms/version/enable/enable_test.go index 0cc35d43f..25c49e9e5 100644 --- a/internal/cmd/beta/kms/version/enable/enable_test.go +++ b/internal/cmd/beta/kms/version/enable/enable_test.go @@ -312,7 +312,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - err := outputResult(p, tt.outputFormat, tt.resp) + err := outputResult(p, tt.outputFormat, false, tt.resp) if (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } From 424852403bc4f2ce8fe2ee75457b6d397c8e7dfd Mon Sep 17 00:00:00 2001 From: "Inter, Sven" Date: Tue, 10 Mar 2026 13:43:58 +0100 Subject: [PATCH 07/14] feat(sfs): add async output handling --- internal/cmd/beta/sfs/resource-pool/create/create.go | 10 +++++++--- .../cmd/beta/sfs/resource-pool/create/create_test.go | 2 +- internal/cmd/beta/sfs/resource-pool/delete/delete.go | 10 +++++++--- .../cmd/beta/sfs/resource-pool/delete/delete_test.go | 2 +- internal/cmd/beta/sfs/resource-pool/update/update.go | 10 +++++++--- .../cmd/beta/sfs/resource-pool/update/update_test.go | 2 +- 6 files changed, 24 insertions(+), 12 deletions(-) diff --git a/internal/cmd/beta/sfs/resource-pool/create/create.go b/internal/cmd/beta/sfs/resource-pool/create/create.go index 4b97f16bb..8df0145a2 100644 --- a/internal/cmd/beta/sfs/resource-pool/create/create.go +++ b/internal/cmd/beta/sfs/resource-pool/create/create.go @@ -109,7 +109,7 @@ The available performance class values can be obtained by running: s.Stop() } - return outputResult(params.Printer, model.OutputFormat, projectLabel, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) }, } configureFlags(cmd) @@ -170,13 +170,17 @@ func parseInput(p *print.Printer, cmd *cobra.Command, _ []string) (*inputModel, return &model, nil } -func outputResult(p *print.Printer, outputFormat, projectLabel string, resp *sfs.CreateResourcePoolResponse) error { +func outputResult(p *print.Printer, outputFormat string, async bool, projectLabel string, resp *sfs.CreateResourcePoolResponse) error { return p.OutputResult(outputFormat, resp, func() error { if resp == nil || resp.ResourcePool == nil { p.Outputln("Resource pool response is empty") return nil } - p.Outputf("Created resource pool for project %q. Resource pool ID: %s\n", projectLabel, utils.PtrString(resp.ResourcePool.Id)) + operationState := "Created" + if async { + operationState = "Triggered creation of" + } + p.Outputf("%s resource pool for project %q. Resource pool ID: %s\n", operationState, projectLabel, utils.PtrString(resp.ResourcePool.Id)) return nil }) } diff --git a/internal/cmd/beta/sfs/resource-pool/create/create_test.go b/internal/cmd/beta/sfs/resource-pool/create/create_test.go index 5dd65f643..5e01c65fa 100644 --- a/internal/cmd/beta/sfs/resource-pool/create/create_test.go +++ b/internal/cmd/beta/sfs/resource-pool/create/create_test.go @@ -287,7 +287,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, false, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/beta/sfs/resource-pool/delete/delete.go b/internal/cmd/beta/sfs/resource-pool/delete/delete.go index 6883c3987..105dd37af 100644 --- a/internal/cmd/beta/sfs/resource-pool/delete/delete.go +++ b/internal/cmd/beta/sfs/resource-pool/delete/delete.go @@ -82,7 +82,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { s.Stop() } - return outputResult(params.Printer, model.OutputFormat, resourcePoolName, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, resourcePoolName, resp) }, } return cmd @@ -110,9 +110,13 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu return &model, nil } -func outputResult(p *print.Printer, outputFormat, resourcePoolName string, response map[string]interface{}) error { +func outputResult(p *print.Printer, outputFormat string, async bool, resourcePoolName string, response map[string]interface{}) error { return p.OutputResult(outputFormat, response, func() error { - p.Outputf("Deleted resource pool %q\n", resourcePoolName) + operationState := "Deleted" + if async { + operationState = "Triggered deletion of" + } + p.Outputf("%s resource pool %q\n", operationState, resourcePoolName) return nil }) } diff --git a/internal/cmd/beta/sfs/resource-pool/delete/delete_test.go b/internal/cmd/beta/sfs/resource-pool/delete/delete_test.go index b41ed2626..87be4fbe6 100644 --- a/internal/cmd/beta/sfs/resource-pool/delete/delete_test.go +++ b/internal/cmd/beta/sfs/resource-pool/delete/delete_test.go @@ -201,7 +201,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.resourcePoolName, tt.args.response); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, false, tt.args.resourcePoolName, tt.args.response); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/beta/sfs/resource-pool/update/update.go b/internal/cmd/beta/sfs/resource-pool/update/update.go index a276fb91e..82d54f6cd 100644 --- a/internal/cmd/beta/sfs/resource-pool/update/update.go +++ b/internal/cmd/beta/sfs/resource-pool/update/update.go @@ -110,7 +110,7 @@ The available performance class values can be obtained by running: s.Stop() } - return outputResult(params.Printer, model.OutputFormat, resp) + return outputResult(params.Printer, model.OutputFormat, model.Async, resp) }, } configureFlags(cmd) @@ -165,13 +165,17 @@ func parseInput(p *print.Printer, cmd *cobra.Command, inputArgs []string) (*inpu return &model, nil } -func outputResult(p *print.Printer, outputFormat string, resp *sfs.UpdateResourcePoolResponse) error { +func outputResult(p *print.Printer, outputFormat string, async bool, resp *sfs.UpdateResourcePoolResponse) error { return p.OutputResult(outputFormat, resp, func() error { if resp == nil || resp.ResourcePool == nil { p.Outputln("Resource pool response is empty") return nil } - p.Outputf("Updated resource pool %s\n", utils.PtrString(resp.ResourcePool.Name)) + operationState := "Updated" + if async { + operationState = "Triggered update of" + } + p.Outputf("%s resource pool %s\n", operationState, utils.PtrString(resp.ResourcePool.Name)) return nil }) } diff --git a/internal/cmd/beta/sfs/resource-pool/update/update_test.go b/internal/cmd/beta/sfs/resource-pool/update/update_test.go index c94b79b92..bcb4ed8f8 100644 --- a/internal/cmd/beta/sfs/resource-pool/update/update_test.go +++ b/internal/cmd/beta/sfs/resource-pool/update/update_test.go @@ -353,7 +353,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, tt.args.resp); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, false, tt.args.resp); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) From ec0972e040b58df2943bbe436d1461213bda7552 Mon Sep 17 00:00:00 2001 From: "Inter, Sven" Date: Mon, 16 Mar 2026 09:26:52 +0100 Subject: [PATCH 08/14] fix(kms): remove hardcoded async in outputResult tests --- internal/cmd/kms/version/disable/disable_test.go | 3 ++- internal/cmd/kms/version/enable/enable_test.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/cmd/kms/version/disable/disable_test.go b/internal/cmd/kms/version/disable/disable_test.go index 02a809f18..c7ecf0825 100644 --- a/internal/cmd/kms/version/disable/disable_test.go +++ b/internal/cmd/kms/version/disable/disable_test.go @@ -282,6 +282,7 @@ func TestOutputResult(t *testing.T) { description string wantErr bool outputFormat string + async bool resp *kms.Version }{ { @@ -312,7 +313,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - err := outputResult(p, tt.outputFormat, false, tt.resp) + err := outputResult(p, tt.outputFormat, tt.async, tt.resp) if (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } diff --git a/internal/cmd/kms/version/enable/enable_test.go b/internal/cmd/kms/version/enable/enable_test.go index 25c49e9e5..fe0edda01 100644 --- a/internal/cmd/kms/version/enable/enable_test.go +++ b/internal/cmd/kms/version/enable/enable_test.go @@ -282,6 +282,7 @@ func TestOutputResult(t *testing.T) { description string wantErr bool outputFormat string + async bool resp *kms.Version }{ { @@ -312,7 +313,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.description, func(t *testing.T) { - err := outputResult(p, tt.outputFormat, false, tt.resp) + err := outputResult(p, tt.outputFormat, tt.async, tt.resp) if (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } From 1edb1e25b29b07bfdfa350d5c1b31b49a28ecfef Mon Sep 17 00:00:00 2001 From: "Inter, Sven" Date: Mon, 16 Mar 2026 09:30:19 +0100 Subject: [PATCH 09/14] fix(sfs): remove hardcoded async in outputResult tests --- internal/cmd/beta/sfs/resource-pool/create/create_test.go | 3 ++- internal/cmd/beta/sfs/resource-pool/delete/delete_test.go | 3 ++- internal/cmd/beta/sfs/resource-pool/update/update_test.go | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/internal/cmd/beta/sfs/resource-pool/create/create_test.go b/internal/cmd/beta/sfs/resource-pool/create/create_test.go index 5e01c65fa..4b096c97d 100644 --- a/internal/cmd/beta/sfs/resource-pool/create/create_test.go +++ b/internal/cmd/beta/sfs/resource-pool/create/create_test.go @@ -252,6 +252,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + async bool projectLabel string resp *sfs.CreateResourcePoolResponse } @@ -287,7 +288,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, false, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.projectLabel, tt.args.resp); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/beta/sfs/resource-pool/delete/delete_test.go b/internal/cmd/beta/sfs/resource-pool/delete/delete_test.go index 87be4fbe6..ebdb37dd1 100644 --- a/internal/cmd/beta/sfs/resource-pool/delete/delete_test.go +++ b/internal/cmd/beta/sfs/resource-pool/delete/delete_test.go @@ -175,6 +175,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + async bool resourcePoolName string response map[string]interface{} } @@ -201,7 +202,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, false, tt.args.resourcePoolName, tt.args.response); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.resourcePoolName, tt.args.response); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/cmd/beta/sfs/resource-pool/update/update_test.go b/internal/cmd/beta/sfs/resource-pool/update/update_test.go index bcb4ed8f8..bc47336c5 100644 --- a/internal/cmd/beta/sfs/resource-pool/update/update_test.go +++ b/internal/cmd/beta/sfs/resource-pool/update/update_test.go @@ -308,6 +308,7 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { outputFormat string + async bool resp *sfs.UpdateResourcePoolResponse } tests := []struct { @@ -353,7 +354,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(&types.CmdParams{Printer: p}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := outputResult(p, tt.args.outputFormat, false, tt.args.resp); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.resp); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) From 6e7d725fb8c741bdd942d09fd92a1596c4f9a0da Mon Sep 17 00:00:00 2001 From: "Inter, Sven" Date: Mon, 16 Mar 2026 13:29:09 +0100 Subject: [PATCH 10/14] refactor(kms): unify output handling for async operations --- internal/cmd/kms/key/create/create.go | 23 +++--------------- internal/cmd/kms/key/delete/delete.go | 22 +++-------------- internal/cmd/kms/key/importKey/importKey.go | 24 +++---------------- internal/cmd/kms/key/list/list.go | 23 +++--------------- internal/cmd/kms/key/restore/restore.go | 22 +++-------------- internal/cmd/kms/key/rotate/rotate.go | 24 +++---------------- internal/cmd/kms/keyring/create/create.go | 23 +++--------------- internal/cmd/kms/keyring/list/list.go | 24 +++---------------- internal/cmd/kms/version/destroy/destroy.go | 24 +++---------------- internal/cmd/kms/version/disable/disable.go | 24 +++---------------- internal/cmd/kms/version/enable/enable.go | 24 +++---------------- internal/cmd/kms/version/list/list.go | 24 +++---------------- internal/cmd/kms/version/restore/restore.go | 22 +++-------------- internal/cmd/kms/wrappingkey/create/create.go | 24 +++---------------- internal/cmd/kms/wrappingkey/list/list.go | 24 +++---------------- 15 files changed, 45 insertions(+), 306 deletions(-) diff --git a/internal/cmd/kms/key/create/create.go b/internal/cmd/kms/key/create/create.go index 076a2ffa7..01668fa75 100644 --- a/internal/cmd/kms/key/create/create.go +++ b/internal/cmd/kms/key/create/create.go @@ -2,12 +2,10 @@ package create import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -159,29 +157,14 @@ func outputResult(p *print.Printer, model *inputModel, resp *kms.Key) error { return fmt.Errorf("response is nil") } - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal KMS key: %w", err) - } - p.Outputln(string(details)) - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal KMS key: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(model.OutputFormat, resp, func() error { operationState := "Created" if model.Async { operationState = "Triggered creation of" } p.Outputf("%s the KMS key %q. Key ID: %s\n", operationState, utils.PtrString(resp.DisplayName), utils.PtrString(resp.Id)) - } - return nil + return nil + }) } func configureFlags(cmd *cobra.Command) { diff --git a/internal/cmd/kms/key/delete/delete.go b/internal/cmd/kms/key/delete/delete.go index a2fb3b3b0..b4001df2a 100644 --- a/internal/cmd/kms/key/delete/delete.go +++ b/internal/cmd/kms/key/delete/delete.go @@ -2,12 +2,10 @@ package delete import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "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" @@ -127,22 +125,8 @@ func outputResult(p *print.Printer, outputFormat string, resp *kms.Key) error { return fmt.Errorf("response is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal output to JSON: %w", err) - } - p.Outputln(string(details)) - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal output to YAML: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Deletion of KMS key %s scheduled successfully for the deletion date: %s\n", utils.PtrString(resp.DisplayName), utils.PtrString(resp.DeletionDate)) - } - return nil + return nil + }) } diff --git a/internal/cmd/kms/key/importKey/importKey.go b/internal/cmd/kms/key/importKey/importKey.go index a04c9e3c5..01896fed6 100644 --- a/internal/cmd/kms/key/importKey/importKey.go +++ b/internal/cmd/kms/key/importKey/importKey.go @@ -3,12 +3,10 @@ package importKey import ( "context" "encoding/base64" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -148,26 +146,10 @@ func outputResult(p *print.Printer, outputFormat, keyRingName, keyName string, r return fmt.Errorf("response is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal KMS key: %w", err) - } - p.Outputln(string(details)) - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal KMS key: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Imported a new version for the key %q inside the key ring %q\n", keyName, keyRingName) - } - - return nil + return nil + }) } func configureFlags(cmd *cobra.Command) { diff --git a/internal/cmd/kms/key/list/list.go b/internal/cmd/kms/key/list/list.go index 911b63cb1..d437bff59 100644 --- a/internal/cmd/kms/key/list/list.go +++ b/internal/cmd/kms/key/list/list.go @@ -2,12 +2,10 @@ package list import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "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" @@ -106,22 +104,7 @@ func outputResult(p *print.Printer, outputFormat, projectId, keyRingId string, r keys := *resp.Keys - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(keys, "", " ") - if err != nil { - return fmt.Errorf("marshal KMS Keys list: %w", err) - } - p.Outputln(string(details)) - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(keys, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal KMS Keys list: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(outputFormat, keys, func() error { if len(keys) == 0 { p.Outputf("No keys found for project %q under the key ring %q\n", projectId, keyRingId) return nil @@ -144,6 +127,6 @@ func outputResult(p *print.Printer, outputFormat, projectId, keyRingId string, r if err != nil { return fmt.Errorf("render table: %w", err) } - } - return nil + return nil + }) } diff --git a/internal/cmd/kms/key/restore/restore.go b/internal/cmd/kms/key/restore/restore.go index 85cab6c89..8fb333e98 100644 --- a/internal/cmd/kms/key/restore/restore.go +++ b/internal/cmd/kms/key/restore/restore.go @@ -2,12 +2,10 @@ package restore import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "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" @@ -126,22 +124,8 @@ func outputResult(p *print.Printer, outputFormat string, resp *kms.Key) error { return fmt.Errorf("response is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal output to JSON: %w", err) - } - p.Outputln(string(details)) - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal output to YAML: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Successfully restored KMS key %q\n", utils.PtrString(resp.DisplayName)) - } - return nil + return nil + }) } diff --git a/internal/cmd/kms/key/rotate/rotate.go b/internal/cmd/kms/key/rotate/rotate.go index e02d58384..8b6619a4a 100644 --- a/internal/cmd/kms/key/rotate/rotate.go +++ b/internal/cmd/kms/key/rotate/rotate.go @@ -2,12 +2,10 @@ package rotate import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "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" @@ -120,24 +118,8 @@ func outputResult(p *print.Printer, outputFormat string, resp *kms.Version) erro return fmt.Errorf("response is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal KMS key version: %w", err) - } - p.Outputln(string(details)) - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal KMS key version: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Rotated key %s\n", utils.PtrString(resp.KeyId)) - } - - return nil + return nil + }) } diff --git a/internal/cmd/kms/keyring/create/create.go b/internal/cmd/kms/keyring/create/create.go index 433cd4c7c..b663cbfb2 100644 --- a/internal/cmd/kms/keyring/create/create.go +++ b/internal/cmd/kms/keyring/create/create.go @@ -2,12 +2,10 @@ package create import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -147,29 +145,14 @@ func outputResult(p *print.Printer, model *inputModel, resp *kms.KeyRing) error return fmt.Errorf("response is nil") } - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal KMS key ring: %w", err) - } - p.Outputln(string(details)) - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal KMS key ring: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(model.OutputFormat, resp, func() error { operationState := "Created" if model.Async { operationState = "Triggered creation of" } p.Outputf("%s key ring. KMS key ring ID: %s\n", operationState, utils.PtrString(resp.Id)) - } - return nil + return nil + }) } func configureFlags(cmd *cobra.Command) { diff --git a/internal/cmd/kms/keyring/list/list.go b/internal/cmd/kms/keyring/list/list.go index 4928d67d3..01153a6d4 100644 --- a/internal/cmd/kms/keyring/list/list.go +++ b/internal/cmd/kms/keyring/list/list.go @@ -2,12 +2,10 @@ package list import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "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" @@ -91,22 +89,7 @@ func outputResult(p *print.Printer, outputFormat, projectId string, resp *kms.Ke keyRings := *resp.KeyRings - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(keyRings, "", " ") - if err != nil { - return fmt.Errorf("marshal KMS key rings list: %w", err) - } - p.Outputln(string(details)) - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(keyRings, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal KMS key rings list: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(outputFormat, keyRings, func() error { if len(keyRings) == 0 { p.Outputf("No key rings found for project %q\n", projectId) return nil @@ -128,7 +111,6 @@ func outputResult(p *print.Printer, outputFormat, projectId string, resp *kms.Ke if err != nil { return fmt.Errorf("render table: %w", err) } - } - - return nil + return nil + }) } diff --git a/internal/cmd/kms/version/destroy/destroy.go b/internal/cmd/kms/version/destroy/destroy.go index 3b15e6e06..48b40d469 100644 --- a/internal/cmd/kms/version/destroy/destroy.go +++ b/internal/cmd/kms/version/destroy/destroy.go @@ -2,13 +2,11 @@ package destroy import ( "context" - "encoding/json" "fmt" "strconv" "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "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" @@ -125,24 +123,8 @@ func outputResult(p *print.Printer, outputFormat string, resp *kms.Version) erro return fmt.Errorf("response is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal KMS key: %w", err) - } - p.Outputln(string(details)) - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal KMS key: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Destroyed version %d of the key %q\n", utils.PtrValue(resp.Number), utils.PtrValue(resp.KeyId)) - } - - return nil + return nil + }) } diff --git a/internal/cmd/kms/version/disable/disable.go b/internal/cmd/kms/version/disable/disable.go index 21ca854b3..760b909c7 100644 --- a/internal/cmd/kms/version/disable/disable.go +++ b/internal/cmd/kms/version/disable/disable.go @@ -2,13 +2,11 @@ package disable import ( "context" - "encoding/json" "fmt" "strconv" "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "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" @@ -138,28 +136,12 @@ func outputResult(p *print.Printer, outputFormat string, async bool, resp *kms.V return fmt.Errorf("response is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal KMS key: %w", err) - } - p.Outputln(string(details)) - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal KMS key: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(outputFormat, resp, func() error { operationState := "Disabled" if async { operationState = "Triggered disable of" } p.Outputf("%s version %d of the key %q\n", operationState, utils.PtrValue(resp.Number), utils.PtrValue(resp.KeyId)) - } - - return nil + return nil + }) } diff --git a/internal/cmd/kms/version/enable/enable.go b/internal/cmd/kms/version/enable/enable.go index 29719f8df..711792a94 100644 --- a/internal/cmd/kms/version/enable/enable.go +++ b/internal/cmd/kms/version/enable/enable.go @@ -2,13 +2,11 @@ package enable import ( "context" - "encoding/json" "fmt" "strconv" "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "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" @@ -138,28 +136,12 @@ func outputResult(p *print.Printer, outputFormat string, async bool, resp *kms.V return fmt.Errorf("response is nil") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal KMS key: %w", err) - } - p.Outputln(string(details)) - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal KMS key: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(outputFormat, resp, func() error { operationState := "Enabled" if async { operationState = "Triggered enable of" } p.Outputf("%s version %d of the key %q\n", operationState, utils.PtrValue(resp.Number), utils.PtrValue(resp.KeyId)) - } - - return nil + return nil + }) } diff --git a/internal/cmd/kms/version/list/list.go b/internal/cmd/kms/version/list/list.go index 7d3fcccc9..80361455a 100644 --- a/internal/cmd/kms/version/list/list.go +++ b/internal/cmd/kms/version/list/list.go @@ -2,12 +2,10 @@ package list import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "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" @@ -100,22 +98,7 @@ func outputResult(p *print.Printer, outputFormat, projectId, keyId string, resp } versions := *resp.Versions - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(versions, "", " ") - if err != nil { - return fmt.Errorf("marshal key versions list: %w", err) - } - p.Outputln(string(details)) - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(versions, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal key versions list: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(outputFormat, versions, func() error { if len(versions) == 0 { p.Outputf("No key versions found for project %q for the key %q\n", projectId, keyId) return nil @@ -137,9 +120,8 @@ func outputResult(p *print.Printer, outputFormat, projectId, keyId string, resp if err != nil { return fmt.Errorf("render table: %w", err) } - } - - return nil + return nil + }) } func configureFlags(cmd *cobra.Command) { diff --git a/internal/cmd/kms/version/restore/restore.go b/internal/cmd/kms/version/restore/restore.go index 304f5a146..b87b6165c 100644 --- a/internal/cmd/kms/version/restore/restore.go +++ b/internal/cmd/kms/version/restore/restore.go @@ -2,13 +2,11 @@ package restore import ( "context" - "encoding/json" "fmt" "strconv" "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "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" @@ -125,22 +123,8 @@ func outputResult(p *print.Printer, outputFormat string, resp *kms.Version) erro return fmt.Errorf("response is nil / empty") } - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal output to JSON: %w", err) - } - p.Outputln(string(details)) - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal output to YAML: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(outputFormat, resp, func() error { p.Outputf("Restored version %d of the key %q\n", utils.PtrValue(resp.Number), utils.PtrValue(resp.KeyId)) - } - return nil + return nil + }) } diff --git a/internal/cmd/kms/wrappingkey/create/create.go b/internal/cmd/kms/wrappingkey/create/create.go index fc972126c..1f43c6e67 100644 --- a/internal/cmd/kms/wrappingkey/create/create.go +++ b/internal/cmd/kms/wrappingkey/create/create.go @@ -2,12 +2,10 @@ package create import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "github.com/goccy/go-yaml" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors" @@ -144,30 +142,14 @@ func outputResult(p *print.Printer, model *inputModel, resp *kms.WrappingKey) er return fmt.Errorf("response is nil") } - switch model.OutputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(resp, "", " ") - if err != nil { - return fmt.Errorf("marshal KMS wrapping key: %w", err) - } - p.Outputln(string(details)) - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(resp, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal KMS wrapping key: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(model.OutputFormat, resp, func() error { operationState := "Created" if model.Async { operationState = "Triggered creation of" } p.Outputf("%s wrapping key. Wrapping key ID: %s\n", operationState, utils.PtrString(resp.Id)) - } - - return nil + return nil + }) } func configureFlags(cmd *cobra.Command) { diff --git a/internal/cmd/kms/wrappingkey/list/list.go b/internal/cmd/kms/wrappingkey/list/list.go index 2046f6392..6f1498f76 100644 --- a/internal/cmd/kms/wrappingkey/list/list.go +++ b/internal/cmd/kms/wrappingkey/list/list.go @@ -2,12 +2,10 @@ package list import ( "context" - "encoding/json" "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/types" - "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" @@ -105,22 +103,7 @@ func outputResult(p *print.Printer, outputFormat, keyRingId string, resp *kms.Wr wrappingKeys := *resp.WrappingKeys - switch outputFormat { - case print.JSONOutputFormat: - details, err := json.MarshalIndent(wrappingKeys, "", " ") - if err != nil { - return fmt.Errorf("marshal KMS wrapping keys list: %w", err) - } - p.Outputln(string(details)) - - case print.YAMLOutputFormat: - details, err := yaml.MarshalWithOptions(wrappingKeys, yaml.IndentSequence(true), yaml.UseJSONMarshaler()) - if err != nil { - return fmt.Errorf("marshal KMS wrapping keys list: %w", err) - } - p.Outputln(string(details)) - - default: + return p.OutputResult(outputFormat, wrappingKeys, func() error { if len(wrappingKeys) == 0 { p.Outputf("No wrapping keys found under the key ring %q\n", keyRingId) return nil @@ -144,7 +127,6 @@ func outputResult(p *print.Printer, outputFormat, keyRingId string, resp *kms.Wr if err != nil { return fmt.Errorf("render table: %w", err) } - } - - return nil + return nil + }) } From 1f45c265d7333145c6eb21e906722a6d26994892 Mon Sep 17 00:00:00 2001 From: Sven Inter <102514411+s-inter@users.noreply.github.com> Date: Fri, 20 Mar 2026 12:21:07 +0100 Subject: [PATCH 11/14] Update internal/cmd/git/instance/create/create.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ruben Hönle --- internal/cmd/git/instance/create/create.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cmd/git/instance/create/create.go b/internal/cmd/git/instance/create/create.go index 1729e3eb9..64e2dc406 100644 --- a/internal/cmd/git/instance/create/create.go +++ b/internal/cmd/git/instance/create/create.go @@ -154,7 +154,7 @@ func outputResult(p *print.Printer, model *inputModel, resp *git.Instance) error return p.OutputResult(outputFormat, resp, func() error { if resp == nil { - return nil + return fmt.Errorf("API resp is nil") } operationState := "Created" if model.Async { From 6d2255019db67d1dd2d932f749b8bafc5263373c Mon Sep 17 00:00:00 2001 From: "Inter, Sven" Date: Fri, 20 Mar 2026 12:58:35 +0100 Subject: [PATCH 12/14] refactor(git): clean up outputResult function by passing only required fields --- internal/cmd/git/instance/create/create.go | 25 ++++++++-------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/internal/cmd/git/instance/create/create.go b/internal/cmd/git/instance/create/create.go index 64e2dc406..6c716190f 100644 --- a/internal/cmd/git/instance/create/create.go +++ b/internal/cmd/git/instance/create/create.go @@ -93,7 +93,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { s.Stop() } - return outputResult(params.Printer, model, result) + return outputResult(params.Printer, model.OutputFormat, model.Async, model.Name, model.Id, result) }, } @@ -143,28 +143,21 @@ func createPayload(model *inputModel) git.CreateInstancePayload { } } -func outputResult(p *print.Printer, model *inputModel, resp *git.Instance) error { - if model == nil { - return fmt.Errorf("input model is nil") +func outputResult(p *print.Printer, outputFormat string, async bool, instanceName string, modelId *string, resp *git.Instance) error { + if resp == nil { + return fmt.Errorf("API resp is nil") } - var outputFormat string - if model.GlobalFlagModel != nil { - outputFormat = model.OutputFormat + id := utils.PtrString(modelId) + if resp.Id != nil { + id = *resp.Id } return p.OutputResult(outputFormat, resp, func() error { - if resp == nil { - return fmt.Errorf("API resp is nil") - } operationState := "Created" - if model.Async { + if async { operationState = "Triggered creation of" } - id := utils.PtrString(model.Id) - if resp.Id != nil { - id = *resp.Id - } - p.Outputf("%s instance %q with id %s\n", operationState, model.Name, id) + p.Outputf("%s instance %q with id %s\n", operationState, instanceName, id) return nil }) } From c153566def25d002d2e8f727c1e5b524aad280c5 Mon Sep 17 00:00:00 2001 From: "Inter, Sven" Date: Fri, 20 Mar 2026 14:22:34 +0100 Subject: [PATCH 13/14] refactor(git): fix tests & removed redundant checks --- internal/cmd/git/instance/create/create.go | 11 ++---- .../cmd/git/instance/create/create_test.go | 36 +++++++++++-------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/internal/cmd/git/instance/create/create.go b/internal/cmd/git/instance/create/create.go index 6c716190f..054587ce2 100644 --- a/internal/cmd/git/instance/create/create.go +++ b/internal/cmd/git/instance/create/create.go @@ -15,7 +15,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/print" "github.com/stackitcloud/stackit-cli/internal/pkg/services/git/client" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" - "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/git" "github.com/stackitcloud/stackit-sdk-go/services/git/wait" ) @@ -93,7 +92,7 @@ func NewCmd(params *types.CmdParams) *cobra.Command { s.Stop() } - return outputResult(params.Printer, model.OutputFormat, model.Async, model.Name, model.Id, result) + return outputResult(params.Printer, model.OutputFormat, model.Async, model.Name, *model.Id, result) }, } @@ -143,21 +142,17 @@ func createPayload(model *inputModel) git.CreateInstancePayload { } } -func outputResult(p *print.Printer, outputFormat string, async bool, instanceName string, modelId *string, resp *git.Instance) error { +func outputResult(p *print.Printer, outputFormat string, async bool, instanceName, modelId string, resp *git.Instance) error { if resp == nil { return fmt.Errorf("API resp is nil") } - id := utils.PtrString(modelId) - if resp.Id != nil { - id = *resp.Id - } return p.OutputResult(outputFormat, resp, func() error { operationState := "Created" if async { operationState = "Triggered creation of" } - p.Outputf("%s instance %q with id %s\n", operationState, instanceName, id) + p.Outputf("%s instance %q with id %s\n", operationState, instanceName, modelId) return nil }) } diff --git a/internal/cmd/git/instance/create/create_test.go b/internal/cmd/git/instance/create/create_test.go index c68384ed6..b14024781 100644 --- a/internal/cmd/git/instance/create/create_test.go +++ b/internal/cmd/git/instance/create/create_test.go @@ -175,8 +175,11 @@ func TestBuildRequest(t *testing.T) { func TestOutputResult(t *testing.T) { type args struct { - model *inputModel - resp *git.Instance + outputFormat string + async bool + instanceName string + modelId string + resp *git.Instance } tests := []struct { name string @@ -184,30 +187,35 @@ func TestOutputResult(t *testing.T) { wantErr bool }{ { - name: "nil", + name: "nil response", args: args{ - model: nil, - resp: nil, + outputFormat: "", + async: false, + instanceName: "", + modelId: "", + resp: nil, }, wantErr: true, }, { name: "empty input", args: args{ - model: fixtureInputModel(), - resp: &git.Instance{}, + outputFormat: "", + async: false, + instanceName: "", + modelId: "", + resp: &git.Instance{}, }, wantErr: false, }, { name: "output json", args: args{ - model: &inputModel{ - GlobalFlagModel: &globalflags.GlobalFlagModel{ - OutputFormat: print.JSONOutputFormat, - }, - }, - resp: nil, + outputFormat: print.JSONOutputFormat, + async: true, + instanceName: testName, + modelId: uuid.NewString(), + resp: &git.Instance{}, }, wantErr: false, }, @@ -216,7 +224,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(&types.CmdParams{Printer: 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 { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.instanceName, tt.args.modelId, tt.args.resp); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } }) From 89bac06f39b55f37346f72c38a6bc698cacb4a73 Mon Sep 17 00:00:00 2001 From: "Inter, Sven" Date: Fri, 20 Mar 2026 17:03:06 +0100 Subject: [PATCH 14/14] fix(git): remove Id from inputModel --- internal/cmd/git/instance/create/create.go | 13 +++++++------ internal/cmd/git/instance/create/create_test.go | 10 +++------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/internal/cmd/git/instance/create/create.go b/internal/cmd/git/instance/create/create.go index 054587ce2..ef4f5c5e8 100644 --- a/internal/cmd/git/instance/create/create.go +++ b/internal/cmd/git/instance/create/create.go @@ -27,7 +27,6 @@ const ( type inputModel struct { *globalflags.GlobalFlagModel - Id *string Name string Flavor string Acl []string @@ -79,20 +78,19 @@ func NewCmd(params *types.CmdParams) *cobra.Command { if err != nil { return fmt.Errorf("create stackit git instance: %w", err) } - model.Id = result.Id // Wait for async operation, if async mode not enabled if !model.Async { s := spinner.New(params.Printer) s.Start("Creating stackit git instance") - _, err = wait.CreateGitInstanceWaitHandler(ctx, apiClient, model.ProjectId, *model.Id).WaitWithContext(ctx) + _, err = wait.CreateGitInstanceWaitHandler(ctx, apiClient, model.ProjectId, *result.Id).WaitWithContext(ctx) if err != nil { return fmt.Errorf("wait for stackit git Instance creation: %w", err) } s.Stop() } - return outputResult(params.Printer, model.OutputFormat, model.Async, model.Name, *model.Id, result) + return outputResult(params.Printer, model.OutputFormat, model.Async, model.Name, result) }, } @@ -142,17 +140,20 @@ func createPayload(model *inputModel) git.CreateInstancePayload { } } -func outputResult(p *print.Printer, outputFormat string, async bool, instanceName, modelId string, resp *git.Instance) error { +func outputResult(p *print.Printer, outputFormat string, async bool, instanceName string, resp *git.Instance) error { if resp == nil { return fmt.Errorf("API resp is nil") } + if resp.Id == nil { + return fmt.Errorf("API resp is missing instance id") + } return p.OutputResult(outputFormat, resp, func() error { operationState := "Created" if async { operationState = "Triggered creation of" } - p.Outputf("%s instance %q with id %s\n", operationState, instanceName, modelId) + p.Outputf("%s instance %q with id %s\n", operationState, instanceName, *resp.Id) return nil }) } diff --git a/internal/cmd/git/instance/create/create_test.go b/internal/cmd/git/instance/create/create_test.go index b14024781..ba2b24a1e 100644 --- a/internal/cmd/git/instance/create/create_test.go +++ b/internal/cmd/git/instance/create/create_test.go @@ -178,7 +178,6 @@ func TestOutputResult(t *testing.T) { outputFormat string async bool instanceName string - modelId string resp *git.Instance } tests := []struct { @@ -192,7 +191,6 @@ func TestOutputResult(t *testing.T) { outputFormat: "", async: false, instanceName: "", - modelId: "", resp: nil, }, wantErr: true, @@ -203,8 +201,7 @@ func TestOutputResult(t *testing.T) { outputFormat: "", async: false, instanceName: "", - modelId: "", - resp: &git.Instance{}, + resp: &git.Instance{Id: utils.Ptr(uuid.NewString())}, }, wantErr: false, }, @@ -214,8 +211,7 @@ func TestOutputResult(t *testing.T) { outputFormat: print.JSONOutputFormat, async: true, instanceName: testName, - modelId: uuid.NewString(), - resp: &git.Instance{}, + resp: &git.Instance{Id: utils.Ptr(uuid.NewString())}, }, wantErr: false, }, @@ -224,7 +220,7 @@ func TestOutputResult(t *testing.T) { p.Cmd = NewCmd(&types.CmdParams{Printer: 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.instanceName, tt.args.modelId, tt.args.resp); (err != nil) != tt.wantErr { + if err := outputResult(p, tt.args.outputFormat, tt.args.async, tt.args.instanceName, tt.args.resp); (err != nil) != tt.wantErr { t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr) } })