From a60a216e7d47a4615dc26a8232adf382399a782f Mon Sep 17 00:00:00 2001 From: Carlo Goetz Date: Thu, 26 Mar 2026 15:19:25 +0100 Subject: [PATCH] fix(cli) stop spinner on error Most usages of spinner did not stop the spinner on error. Introduced helper functions Run and Run2 (result arity 2) to make correct spinner usage easier. Refactored spinner usages to use new helper funcs. STACKITCLI-310 --- internal/cmd/beta/alb/create/create.go | 8 ++--- internal/cmd/beta/alb/update/update.go | 10 +++--- .../cmd/beta/edge/instance/create/create.go | 19 ++++++------ .../cmd/beta/edge/instance/delete/delete.go | 29 ++++++++--------- .../cmd/beta/edge/instance/update/update.go | 29 ++++++++--------- internal/cmd/beta/intake/create/create.go | 8 ++--- internal/cmd/beta/intake/delete/delete.go | 8 ++--- .../cmd/beta/intake/runner/create/create.go | 8 ++--- .../cmd/beta/intake/runner/delete/delete.go | 8 ++--- .../cmd/beta/intake/runner/update/update.go | 8 ++--- internal/cmd/beta/intake/update/update.go | 8 ++--- .../beta/sfs/resource-pool/create/create.go | 8 ++--- .../beta/sfs/resource-pool/delete/delete.go | 8 ++--- .../beta/sfs/resource-pool/update/update.go | 8 ++--- internal/cmd/beta/sfs/share/create/create.go | 8 ++--- internal/cmd/beta/sfs/share/delete/delete.go | 8 ++--- internal/cmd/beta/sfs/share/update/update.go | 8 ++--- .../sqlserverflex/database/create/create.go | 8 ++--- .../sqlserverflex/database/delete/delete.go | 9 +++--- .../sqlserverflex/instance/create/create.go | 8 ++--- .../sqlserverflex/instance/delete/delete.go | 8 ++--- .../sqlserverflex/instance/update/update.go | 8 ++--- internal/cmd/dns/record-set/create/create.go | 10 +++--- internal/cmd/dns/record-set/delete/delete.go | 8 ++--- internal/cmd/dns/record-set/update/update.go | 8 ++--- internal/cmd/dns/zone/clone/clone.go | 8 ++--- internal/cmd/dns/zone/create/create.go | 8 ++--- internal/cmd/dns/zone/delete/delete.go | 8 ++--- internal/cmd/dns/zone/update/update.go | 8 ++--- internal/cmd/git/instance/create/create.go | 8 ++--- internal/cmd/git/instance/delete/delete.go | 8 ++--- internal/cmd/kms/key/create/create.go | 8 ++--- internal/cmd/kms/keyring/create/create.go | 8 ++--- internal/cmd/kms/version/disable/disable.go | 8 ++--- internal/cmd/kms/version/enable/enable.go | 8 ++--- internal/cmd/kms/wrappingkey/create/create.go | 8 ++--- internal/cmd/load-balancer/create/create.go | 8 ++--- internal/cmd/load-balancer/delete/delete.go | 8 ++--- internal/cmd/logme/instance/create/create.go | 8 ++--- internal/cmd/logme/instance/delete/delete.go | 8 ++--- internal/cmd/logme/instance/update/update.go | 8 ++--- internal/cmd/logs/instance/create/create.go | 8 ++--- internal/cmd/logs/instance/delete/delete.go | 8 ++--- .../cmd/mariadb/instance/create/create.go | 8 ++--- .../cmd/mariadb/instance/delete/delete.go | 8 ++--- .../cmd/mariadb/instance/update/update.go | 8 ++--- .../cmd/mongodbflex/backup/restore/restore.go | 16 +++++----- .../cmd/mongodbflex/instance/create/create.go | 8 ++--- .../cmd/mongodbflex/instance/delete/delete.go | 8 ++--- .../cmd/mongodbflex/instance/update/update.go | 8 ++--- internal/cmd/network-area/create/create.go | 8 ++--- .../cmd/network-area/region/create/create.go | 8 ++--- .../cmd/network-area/region/delete/delete.go | 8 ++--- internal/cmd/network/create/create.go | 9 +++--- internal/cmd/network/delete/delete.go | 8 ++--- internal/cmd/network/update/update.go | 9 +++--- .../object-storage/bucket/create/create.go | 8 ++--- .../object-storage/bucket/delete/delete.go | 8 ++--- .../observability/instance/create/create.go | 8 ++--- .../observability/instance/delete/delete.go | 8 ++--- .../observability/instance/update/update.go | 8 ++--- .../scrape-config/create/create.go | 8 ++--- .../scrape-config/delete/delete.go | 8 ++--- .../cmd/opensearch/instance/create/create.go | 8 ++--- .../cmd/opensearch/instance/delete/delete.go | 8 ++--- .../cmd/opensearch/instance/update/update.go | 8 ++--- .../cmd/postgresflex/instance/clone/clone.go | 8 ++--- .../postgresflex/instance/create/create.go | 8 ++--- .../postgresflex/instance/delete/delete.go | 16 +++++----- .../postgresflex/instance/update/update.go | 8 ++--- .../cmd/rabbitmq/instance/create/create.go | 8 ++--- .../cmd/rabbitmq/instance/delete/delete.go | 8 ++--- .../cmd/rabbitmq/instance/update/update.go | 8 ++--- internal/cmd/redis/instance/create/create.go | 8 ++--- internal/cmd/redis/instance/delete/delete.go | 8 ++--- internal/cmd/redis/instance/update/update.go | 8 ++--- internal/cmd/server/create/create.go | 8 ++--- internal/cmd/server/deallocate/deallocate.go | 8 ++--- internal/cmd/server/delete/delete.go | 13 ++++---- internal/cmd/server/rescue/rescue.go | 8 ++--- internal/cmd/server/resize/resize.go | 8 ++--- internal/cmd/server/start/start.go | 8 ++--- internal/cmd/server/stop/stop.go | 8 ++--- internal/cmd/server/unrescue/unrescue.go | 8 ++--- internal/cmd/ske/cluster/create/create.go | 8 ++--- internal/cmd/ske/cluster/delete/delete.go | 8 ++--- .../cmd/ske/cluster/hibernate/hibernate.go | 10 +++--- .../ske/cluster/maintenance/maintenance.go | 8 ++--- .../cmd/ske/cluster/reconcile/reconcile.go | 8 ++--- internal/cmd/ske/cluster/update/update.go | 8 ++--- internal/cmd/ske/cluster/wakeup/wakeup.go | 8 ++--- .../complete-rotation/complete_rotation.go | 8 ++--- .../start-rotation/start_rotation.go | 8 ++--- internal/cmd/ske/disable/disable.go | 8 ++--- internal/cmd/ske/enable/enable.go | 8 ++--- internal/cmd/volume/backup/create/create.go | 7 ++--- internal/cmd/volume/backup/delete/delete.go | 8 ++--- internal/cmd/volume/backup/restore/restore.go | 8 ++--- internal/cmd/volume/create/create.go | 8 ++--- internal/cmd/volume/delete/delete.go | 8 ++--- internal/cmd/volume/snapshot/create/create.go | 7 ++--- internal/cmd/volume/snapshot/delete/delete.go | 8 ++--- internal/pkg/spinner/spinner.go | 31 ++++++++++++++++--- 103 files changed, 472 insertions(+), 456 deletions(-) diff --git a/internal/cmd/beta/alb/create/create.go b/internal/cmd/beta/alb/create/create.go index 2232d7aad..ddd1a1a0d 100644 --- a/internal/cmd/beta/alb/create/create.go +++ b/internal/cmd/beta/alb/create/create.go @@ -84,13 +84,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating loadbalancer") - _, err = wait.CreateOrUpdateLoadbalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Name).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating loadbalancer", func() error { + _, err := wait.CreateOrUpdateLoadbalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Name).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for loadbalancer creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model, projectLabel, resp) diff --git a/internal/cmd/beta/alb/update/update.go b/internal/cmd/beta/alb/update/update.go index 1221cba4f..910c78773 100644 --- a/internal/cmd/beta/alb/update/update.go +++ b/internal/cmd/beta/alb/update/update.go @@ -90,14 +90,14 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("updating loadbalancer") - _, err = wait.CreateOrUpdateLoadbalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Name). - WaitWithContext(ctx) + err := spinner.Run(params.Printer, "updating loadbalancer", func() error { + _, err = wait.CreateOrUpdateLoadbalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Name). + WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for loadbalancer update: %w", err) } - s.Stop() } return outputResult(params.Printer, model, projectLabel, resp) diff --git a/internal/cmd/beta/edge/instance/create/create.go b/internal/cmd/beta/edge/instance/create/create.go index 72f7ec2d2..b6b3d4e7c 100755 --- a/internal/cmd/beta/edge/instance/create/create.go +++ b/internal/cmd/beta/edge/instance/create/create.go @@ -87,19 +87,18 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating instance") - // The waiter handler needs a concrete client type. We can safely cast here as the real implementation will always match. - client, ok := apiClient.(*edge.APIClient) - if !ok { - return fmt.Errorf("failed to configure API client") - } - _, err = wait.CreateOrUpdateInstanceWaitHandler(ctx, client, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) - + err := spinner.Run(params.Printer, "Creating instance", func() error { + // The waiter handler needs a concrete concreteClient type. We can safely cast here as the real implementation will always match. + concreteClient, ok := apiClient.(*edge.APIClient) + if !ok { + return fmt.Errorf("failed to configure API concreteClient") + } + _, err = wait.CreateOrUpdateInstanceWaitHandler(ctx, concreteClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for edge instance creation: %w", err) } - s.Stop() } // Handle output to printer diff --git a/internal/cmd/beta/edge/instance/delete/delete.go b/internal/cmd/beta/edge/instance/delete/delete.go index d6650e7e6..4bf5e44ad 100755 --- a/internal/cmd/beta/edge/instance/delete/delete.go +++ b/internal/cmd/beta/edge/instance/delete/delete.go @@ -110,25 +110,26 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled operationState := "Triggered deletion of" if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting instance") - // Determine identifier and waiter to use - waiterFactory, err := getWaiterFactory(ctx, model) - if err != nil { + err := spinner.Run(params.Printer, "Deleting instance", func() error { + // Determine identifier and waiter to use + waiterFactory, err := getWaiterFactory(ctx, model) + if err != nil { + return err + } + // The waiter factory needs a concrete concreteClient type. We can safely cast here as the real implementation will always match. + concreteClient, ok := apiClient.(*edge.APIClient) + if !ok { + return fmt.Errorf("failed to configure API concreteClient") + } + waiter := waiterFactory(concreteClient) + _, err = waiter.WaitWithContext(ctx) return err - } - // The waiter factory needs a concrete client type. We can safely cast here as the real implementation will always match. - client, ok := apiClient.(*edge.APIClient) - if !ok { - return fmt.Errorf("failed to configure API client") - } - waiter := waiterFactory(client) + }) - if _, err = waiter.WaitWithContext(ctx); err != nil { + if err != nil { return fmt.Errorf("wait for edge instance deletion: %w", err) } operationState = "Deleted" - s.Stop() } params.Printer.Info("%s instance with %q %q of project %q.\n", operationState, model.identifier.Flag, model.identifier.Value, projectLabel) diff --git a/internal/cmd/beta/edge/instance/update/update.go b/internal/cmd/beta/edge/instance/update/update.go index 28ec3437a..4faf512ef 100755 --- a/internal/cmd/beta/edge/instance/update/update.go +++ b/internal/cmd/beta/edge/instance/update/update.go @@ -120,25 +120,26 @@ func NewCmd(params *types.CmdParams) *cobra.Command { if !model.Async { // Wait for async operation, if async mode not enabled // Show spinner while waiting - s := spinner.New(params.Printer) - s.Start("Updating instance") - // Determine identifier and waiter to use - waiterFactory, err := getWaiterFactory(ctx, model) - if err != nil { + err := spinner.Run(params.Printer, "Updating instance", func() error { + // Determine identifier and waiter to use + waiterFactory, err := getWaiterFactory(ctx, model) + if err != nil { + return err + } + // The waiter handler needs a concrete concreteClient type. We can safely cast here as the real implementation will always match. + concreteClient, ok := apiClient.(*edge.APIClient) + if !ok { + return fmt.Errorf("failed to configure API concreteClient") + } + waiter := waiterFactory(concreteClient) + _, err = waiter.WaitWithContext(ctx) return err - } - // The waiter handler needs a concrete client type. We can safely cast here as the real implementation will always match. - client, ok := apiClient.(*edge.APIClient) - if !ok { - return fmt.Errorf("failed to configure API client") - } - waiter := waiterFactory(client) + }) - if _, err = waiter.WaitWithContext(ctx); err != nil { + if err != nil { return fmt.Errorf("wait for edge instance update: %w", err) } operationState = "Updated" - s.Stop() } params.Printer.Info("%s instance with %q %q of project %q.\n", operationState, model.identifier.Flag, model.identifier.Value, projectLabel) diff --git a/internal/cmd/beta/intake/create/create.go b/internal/cmd/beta/intake/create/create.go index 820e13b90..4ce75fd94 100644 --- a/internal/cmd/beta/intake/create/create.go +++ b/internal/cmd/beta/intake/create/create.go @@ -111,13 +111,13 @@ func NewCmd(p *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p.Printer) - s.Start("Creating STACKIT Intake instance") - _, err = wait.CreateOrUpdateIntakeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, resp.GetId()).WaitWithContext(ctx) + err := spinner.Run(p.Printer, "Creating STACKIT Intake instance", func() error { + _, err = wait.CreateOrUpdateIntakeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, resp.GetId()).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for STACKIT Instance creation: %w", err) } - s.Stop() } return outputResult(p.Printer, model, projectLabel, resp) diff --git a/internal/cmd/beta/intake/delete/delete.go b/internal/cmd/beta/intake/delete/delete.go index b55d9997e..6aeb77ee2 100644 --- a/internal/cmd/beta/intake/delete/delete.go +++ b/internal/cmd/beta/intake/delete/delete.go @@ -68,13 +68,13 @@ func NewCmd(p *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p.Printer) - s.Start("Deleting STACKIT Intake instance") - _, err = wait.DeleteIntakeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.IntakeId).WaitWithContext(ctx) + err := spinner.Run(p.Printer, "Deleting STACKIT Intake instance", func() error { + _, err = wait.DeleteIntakeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.IntakeId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for STACKIT Instance deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/beta/intake/runner/create/create.go b/internal/cmd/beta/intake/runner/create/create.go index 72cff3b29..b64a116f9 100644 --- a/internal/cmd/beta/intake/runner/create/create.go +++ b/internal/cmd/beta/intake/runner/create/create.go @@ -88,13 +88,13 @@ func NewCmd(p *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p.Printer) - s.Start("Creating STACKIT Intake Runner") - _, err = wait.CreateOrUpdateIntakeRunnerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, resp.GetId()).WaitWithContext(ctx) + err := spinner.Run(p.Printer, "Creating STACKIT Intake Runner", func() error { + _, err = wait.CreateOrUpdateIntakeRunnerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, resp.GetId()).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for STACKIT Intake Runner creation: %w", err) } - s.Stop() } return outputResult(p.Printer, model, projectLabel, resp) diff --git a/internal/cmd/beta/intake/runner/delete/delete.go b/internal/cmd/beta/intake/runner/delete/delete.go index 92d5b1acf..a8f3d6a88 100644 --- a/internal/cmd/beta/intake/runner/delete/delete.go +++ b/internal/cmd/beta/intake/runner/delete/delete.go @@ -68,13 +68,13 @@ func NewCmd(p *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p.Printer) - s.Start("Deleting STACKIT Intake Runner") - _, err = wait.DeleteIntakeRunnerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.RunnerId).WaitWithContext(ctx) + err := spinner.Run(p.Printer, "Deleting STACKIT Intake Runner", func() error { + _, err = wait.DeleteIntakeRunnerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.RunnerId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for STACKIT Intake Runner deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/beta/intake/runner/update/update.go b/internal/cmd/beta/intake/runner/update/update.go index a5f5bb55a..bd2c637e9 100644 --- a/internal/cmd/beta/intake/runner/update/update.go +++ b/internal/cmd/beta/intake/runner/update/update.go @@ -86,13 +86,13 @@ func NewCmd(p *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p.Printer) - s.Start("Updating STACKIT Intake Runner") - _, err = wait.CreateOrUpdateIntakeRunnerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.RunnerId).WaitWithContext(ctx) + err := spinner.Run(p.Printer, "Updating STACKIT Intake Runner", func() error { + _, err = wait.CreateOrUpdateIntakeRunnerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.RunnerId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for STACKIT Intake Runner update: %w", err) } - s.Stop() } return outputResult(p.Printer, model, projectLabel, resp) diff --git a/internal/cmd/beta/intake/update/update.go b/internal/cmd/beta/intake/update/update.go index e531e2c91..c21640e5d 100644 --- a/internal/cmd/beta/intake/update/update.go +++ b/internal/cmd/beta/intake/update/update.go @@ -106,13 +106,13 @@ func NewCmd(p *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(p.Printer) - s.Start("Updating STACKIT Intake Runner instance") - _, err = wait.CreateOrUpdateIntakeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.IntakeId).WaitWithContext(ctx) + err := spinner.Run(p.Printer, "Updating STACKIT Intake Runner instance", func() error { + _, err = wait.CreateOrUpdateIntakeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.IntakeId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for STACKIT Instance creation: %w", err) } - s.Stop() } return outputResult(p.Printer, model, projectLabel, resp) diff --git a/internal/cmd/beta/sfs/resource-pool/create/create.go b/internal/cmd/beta/sfs/resource-pool/create/create.go index 8df0145a2..526ef296f 100644 --- a/internal/cmd/beta/sfs/resource-pool/create/create.go +++ b/internal/cmd/beta/sfs/resource-pool/create/create.go @@ -100,13 +100,13 @@ The available performance class values can be obtained by running: // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Create resource pool") - _, err = wait.CreateResourcePoolWaitHandler(ctx, apiClient, model.ProjectId, model.Region, resourcePoolId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Create resource pool", func() error { + _, err = wait.CreateResourcePoolWaitHandler(ctx, apiClient, model.ProjectId, model.Region, resourcePoolId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for resource pool creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) diff --git a/internal/cmd/beta/sfs/resource-pool/delete/delete.go b/internal/cmd/beta/sfs/resource-pool/delete/delete.go index 105dd37af..17f8a6187 100644 --- a/internal/cmd/beta/sfs/resource-pool/delete/delete.go +++ b/internal/cmd/beta/sfs/resource-pool/delete/delete.go @@ -73,13 +73,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Delete resource pool") - _, err = wait.DeleteResourcePoolWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Delete resource pool", func() error { + _, err = wait.DeleteResourcePoolWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for resource pool deletion: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, resourcePoolName, resp) diff --git a/internal/cmd/beta/sfs/resource-pool/update/update.go b/internal/cmd/beta/sfs/resource-pool/update/update.go index 82d54f6cd..4c471440f 100644 --- a/internal/cmd/beta/sfs/resource-pool/update/update.go +++ b/internal/cmd/beta/sfs/resource-pool/update/update.go @@ -101,13 +101,13 @@ The available performance class values can be obtained by running: // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Update resource pool") - _, err = wait.UpdateResourcePoolWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Update resource pool", func() error { + _, err = wait.UpdateResourcePoolWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for resource pool update: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, resp) diff --git a/internal/cmd/beta/sfs/share/create/create.go b/internal/cmd/beta/sfs/share/create/create.go index c2b2246b8..b455f173d 100644 --- a/internal/cmd/beta/sfs/share/create/create.go +++ b/internal/cmd/beta/sfs/share/create/create.go @@ -91,13 +91,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating share") - _, err = wait.CreateShareWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId, shareId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating share", func() error { + _, err = wait.CreateShareWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId, shareId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("waiting for share creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, resourcePoolLabel, resp) diff --git a/internal/cmd/beta/sfs/share/delete/delete.go b/internal/cmd/beta/sfs/share/delete/delete.go index aed603d52..1b98b0473 100644 --- a/internal/cmd/beta/sfs/share/delete/delete.go +++ b/internal/cmd/beta/sfs/share/delete/delete.go @@ -80,13 +80,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting share") - _, err = wait.DeleteShareWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId, model.ShareId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting share", func() error { + _, err = wait.DeleteShareWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId, model.ShareId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("waiting for share deletion: %w", err) } - s.Stop() } operation := "Deleted" diff --git a/internal/cmd/beta/sfs/share/update/update.go b/internal/cmd/beta/sfs/share/update/update.go index 7f368fa3d..785d672cc 100644 --- a/internal/cmd/beta/sfs/share/update/update.go +++ b/internal/cmd/beta/sfs/share/update/update.go @@ -96,13 +96,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Updating share") - _, err = wait.UpdateShareWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId, model.ShareId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Updating share", func() error { + _, err = wait.UpdateShareWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ResourcePoolId, model.ShareId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("waiting for share update: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, resourcePoolLabel, resp) diff --git a/internal/cmd/beta/sqlserverflex/database/create/create.go b/internal/cmd/beta/sqlserverflex/database/create/create.go index 9a2b8c2e0..00ae39bf2 100644 --- a/internal/cmd/beta/sqlserverflex/database/create/create.go +++ b/internal/cmd/beta/sqlserverflex/database/create/create.go @@ -68,14 +68,12 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Call API req := buildRequest(ctx, model, apiClient) - s := spinner.New(params.Printer) - s.Start("Creating database") - resp, err := req.Execute() + resp, err := spinner.Run2(params.Printer, "Creating database", func() (*sqlserverflex.CreateDatabaseResponse, error) { + return req.Execute() + }) if err != nil { - s.StopWithError() return fmt.Errorf("create SQLServer Flex database: %w", err) } - s.Stop() return outputResult(params.Printer, model.OutputFormat, model.DatabaseName, resp) }, diff --git a/internal/cmd/beta/sqlserverflex/database/delete/delete.go b/internal/cmd/beta/sqlserverflex/database/delete/delete.go index 3408cc85d..ae8148ec2 100644 --- a/internal/cmd/beta/sqlserverflex/database/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/database/delete/delete.go @@ -66,14 +66,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Call API req := buildRequest(ctx, model, apiClient) - s := spinner.New(params.Printer) - s.Start("Deleting database") - err = req.Execute() + err = spinner.Run(params.Printer, "Deleting database", func() error { + err := req.Execute() + return err + }) if err != nil { - s.StopWithError() return fmt.Errorf("delete SQLServer Flex database: %w", err) } - s.Stop() params.Printer.Info("Deleted database %q\n", model.DatabaseName) return nil diff --git a/internal/cmd/beta/sqlserverflex/instance/create/create.go b/internal/cmd/beta/sqlserverflex/instance/create/create.go index 4cc0469e5..34499a3bc 100644 --- a/internal/cmd/beta/sqlserverflex/instance/create/create.go +++ b/internal/cmd/beta/sqlserverflex/instance/create/create.go @@ -122,13 +122,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating instance") - _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating instance", func() error { + _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for SQLServer Flex instance creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model, projectLabel, resp) diff --git a/internal/cmd/beta/sqlserverflex/instance/delete/delete.go b/internal/cmd/beta/sqlserverflex/instance/delete/delete.go index 74840b4db..429dbb364 100644 --- a/internal/cmd/beta/sqlserverflex/instance/delete/delete.go +++ b/internal/cmd/beta/sqlserverflex/instance/delete/delete.go @@ -75,13 +75,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting instance") - _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting instance", func() error { + _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for SQLServer Flex instance deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/beta/sqlserverflex/instance/update/update.go b/internal/cmd/beta/sqlserverflex/instance/update/update.go index 81a4b5008..3a5c497b8 100644 --- a/internal/cmd/beta/sqlserverflex/instance/update/update.go +++ b/internal/cmd/beta/sqlserverflex/instance/update/update.go @@ -113,13 +113,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Updating instance") - _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Updating instance", func() error { + _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for SQLServer Flex instance update: %w", err) } - s.Stop() } return outputResult(params.Printer, model, instanceLabel, resp) diff --git a/internal/cmd/dns/record-set/create/create.go b/internal/cmd/dns/record-set/create/create.go index 2687b34da..ef20922b5 100644 --- a/internal/cmd/dns/record-set/create/create.go +++ b/internal/cmd/dns/record-set/create/create.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-sdk-go/services/dns/wait" "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" @@ -18,7 +19,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/dns" - "github.com/stackitcloud/stackit-sdk-go/services/dns/wait" ) const ( @@ -89,13 +89,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating record set") - _, err = wait.CreateRecordSetWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId, recordSetId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating record set", func() error { + _, err = wait.CreateRecordSetWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId, recordSetId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for DNS record set creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model, zoneLabel, resp) diff --git a/internal/cmd/dns/record-set/delete/delete.go b/internal/cmd/dns/record-set/delete/delete.go index 09337b89e..ff1478ccc 100644 --- a/internal/cmd/dns/record-set/delete/delete.go +++ b/internal/cmd/dns/record-set/delete/delete.go @@ -88,13 +88,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting record set") - _, err = wait.DeleteRecordSetWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId, model.RecordSetId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting record set", func() error { + _, err = wait.DeleteRecordSetWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId, model.RecordSetId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for DNS record set deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/dns/record-set/update/update.go b/internal/cmd/dns/record-set/update/update.go index b9fb0e942..6246ff58f 100644 --- a/internal/cmd/dns/record-set/update/update.go +++ b/internal/cmd/dns/record-set/update/update.go @@ -108,13 +108,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Updating record set") - _, err = wait.PartialUpdateRecordSetWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId, model.RecordSetId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Updating record set", func() error { + _, err = wait.PartialUpdateRecordSetWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId, model.RecordSetId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for DNS record set update: %w", err) } - s.Stop() } operationState := "Updated" diff --git a/internal/cmd/dns/zone/clone/clone.go b/internal/cmd/dns/zone/clone/clone.go index 6bc02546d..de171a2be 100644 --- a/internal/cmd/dns/zone/clone/clone.go +++ b/internal/cmd/dns/zone/clone/clone.go @@ -91,13 +91,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Cloning zone") - _, err = wait.CreateZoneWaitHandler(ctx, apiClient, model.ProjectId, zoneId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Cloning zone", func() error { + _, err = wait.CreateZoneWaitHandler(ctx, apiClient, model.ProjectId, zoneId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for DNS zone cloning: %w", err) } - s.Stop() } return outputResult(params.Printer, model, zoneLabel, resp) diff --git a/internal/cmd/dns/zone/create/create.go b/internal/cmd/dns/zone/create/create.go index 75ef0a3e5..5b68f97b8 100644 --- a/internal/cmd/dns/zone/create/create.go +++ b/internal/cmd/dns/zone/create/create.go @@ -104,13 +104,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating zone") - _, err = wait.CreateZoneWaitHandler(ctx, apiClient, model.ProjectId, zoneId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating zone", func() error { + _, err = wait.CreateZoneWaitHandler(ctx, apiClient, model.ProjectId, zoneId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for DNS zone creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model, projectLabel, resp) diff --git a/internal/cmd/dns/zone/delete/delete.go b/internal/cmd/dns/zone/delete/delete.go index a204a5dbe..9945054ee 100644 --- a/internal/cmd/dns/zone/delete/delete.go +++ b/internal/cmd/dns/zone/delete/delete.go @@ -77,13 +77,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting zone") - _, err = wait.DeleteZoneWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting zone", func() error { + _, err = wait.DeleteZoneWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for DNS zone deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/dns/zone/update/update.go b/internal/cmd/dns/zone/update/update.go index a3c31b097..c44ba724b 100644 --- a/internal/cmd/dns/zone/update/update.go +++ b/internal/cmd/dns/zone/update/update.go @@ -100,13 +100,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Updating zone") - _, err = wait.PartialUpdateZoneWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Updating zone", func() error { + _, err = wait.PartialUpdateZoneWaitHandler(ctx, apiClient, model.ProjectId, model.ZoneId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for DNS zone update: %w", err) } - s.Stop() } operationState := "Updated" diff --git a/internal/cmd/git/instance/create/create.go b/internal/cmd/git/instance/create/create.go index ef4f5c5e8..70693a546 100644 --- a/internal/cmd/git/instance/create/create.go +++ b/internal/cmd/git/instance/create/create.go @@ -81,13 +81,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // 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, *result.Id).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating STACKIT git instance", func() error { + _, err = wait.CreateGitInstanceWaitHandler(ctx, apiClient, model.ProjectId, *result.Id).WaitWithContext(ctx) + return err + }) 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, result) diff --git a/internal/cmd/git/instance/delete/delete.go b/internal/cmd/git/instance/delete/delete.go index 7c056829a..b1aee9a2c 100644 --- a/internal/cmd/git/instance/delete/delete.go +++ b/internal/cmd/git/instance/delete/delete.go @@ -81,13 +81,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting stackit git instance") - _, err = wait.DeleteGitInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting STACKIT git instance", func() error { + _, err = wait.DeleteGitInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for stackit git instance deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/kms/key/create/create.go b/internal/cmd/kms/key/create/create.go index 01668fa75..801f389a1 100644 --- a/internal/cmd/kms/key/create/create.go +++ b/internal/cmd/kms/key/create/create.go @@ -97,13 +97,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating key") - _, err = wait.CreateOrUpdateKeyWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, *resp.Id).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating key", func() error { + _, err = wait.CreateOrUpdateKeyWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, *resp.Id).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for KMS key creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model, resp) diff --git a/internal/cmd/kms/keyring/create/create.go b/internal/cmd/kms/keyring/create/create.go index b663cbfb2..e51822dff 100644 --- a/internal/cmd/kms/keyring/create/create.go +++ b/internal/cmd/kms/keyring/create/create.go @@ -84,13 +84,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating key ring") - _, err = wait.CreateKeyRingWaitHandler(ctx, apiClient, model.ProjectId, model.Region, keyRingId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating key ring", func() error { + _, err = wait.CreateKeyRingWaitHandler(ctx, apiClient, model.ProjectId, model.Region, keyRingId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for KMS key ring creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model, keyRing) diff --git a/internal/cmd/kms/version/disable/disable.go b/internal/cmd/kms/version/disable/disable.go index 760b909c7..2a57afd36 100644 --- a/internal/cmd/kms/version/disable/disable.go +++ b/internal/cmd/kms/version/disable/disable.go @@ -70,13 +70,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Disabling key version") - _, err = wait.DisableKeyVersionWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Disabling key version", func() error { + _, err = wait.DisableKeyVersionWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for key version to be disabled: %w", err) } - s.Stop() } // Get the key version in its state afterwards diff --git a/internal/cmd/kms/version/enable/enable.go b/internal/cmd/kms/version/enable/enable.go index 711792a94..8f83cccb2 100644 --- a/internal/cmd/kms/version/enable/enable.go +++ b/internal/cmd/kms/version/enable/enable.go @@ -70,13 +70,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Enabling key version") - _, err = wait.EnableKeyVersionWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Enabling key version", func() error { + _, err = wait.EnableKeyVersionWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.KeyRingId, model.KeyId, model.VersionNumber).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for key version to be enabled: %w", err) } - s.Stop() } // Get the key version in its state afterwards diff --git a/internal/cmd/kms/wrappingkey/create/create.go b/internal/cmd/kms/wrappingkey/create/create.go index 1f43c6e67..3a751b59e 100644 --- a/internal/cmd/kms/wrappingkey/create/create.go +++ b/internal/cmd/kms/wrappingkey/create/create.go @@ -83,13 +83,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating wrapping key") - _, err = wait.CreateWrappingKeyWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *wrappingKey.KeyRingId, *wrappingKey.Id).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating wrapping key", func() error { + _, err = wait.CreateWrappingKeyWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *wrappingKey.KeyRingId, *wrappingKey.Id).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for KMS wrapping key creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model, wrappingKey) diff --git a/internal/cmd/load-balancer/create/create.go b/internal/cmd/load-balancer/create/create.go index 31e74d9ba..fa7e8658f 100644 --- a/internal/cmd/load-balancer/create/create.go +++ b/internal/cmd/load-balancer/create/create.go @@ -93,13 +93,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating load balancer") - _, err = wait.CreateLoadBalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *model.Payload.Name).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating load balancer", func() error { + _, err = wait.CreateLoadBalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *model.Payload.Name).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for load balancer creation: %w", err) } - s.Stop() } operationState := "Created" diff --git a/internal/cmd/load-balancer/delete/delete.go b/internal/cmd/load-balancer/delete/delete.go index e1c3a33af..c60100607 100644 --- a/internal/cmd/load-balancer/delete/delete.go +++ b/internal/cmd/load-balancer/delete/delete.go @@ -66,13 +66,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting load balancer") - _, err = wait.DeleteLoadBalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.LoadBalancerName).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting load balancer", func() error { + _, err = wait.DeleteLoadBalancerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.LoadBalancerName).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for load balancer deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/logme/instance/create/create.go b/internal/cmd/logme/instance/create/create.go index c0b1fcd48..367c9cc60 100644 --- a/internal/cmd/logme/instance/create/create.go +++ b/internal/cmd/logme/instance/create/create.go @@ -114,13 +114,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating instance") - _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating instance", func() error { + _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for LogMe instance creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) diff --git a/internal/cmd/logme/instance/delete/delete.go b/internal/cmd/logme/instance/delete/delete.go index 9cdfac9d0..0dc766e3b 100644 --- a/internal/cmd/logme/instance/delete/delete.go +++ b/internal/cmd/logme/instance/delete/delete.go @@ -75,13 +75,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting instance") - _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting instacne", func() error { + _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for LogMe instance deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/logme/instance/update/update.go b/internal/cmd/logme/instance/update/update.go index 4cefddf26..9a16545ad 100644 --- a/internal/cmd/logme/instance/update/update.go +++ b/internal/cmd/logme/instance/update/update.go @@ -113,13 +113,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Updating instance") - _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Updating instance", func() error { + _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for LogMe instance update: %w", err) } - s.Stop() } operationState := "Updated" diff --git a/internal/cmd/logs/instance/create/create.go b/internal/cmd/logs/instance/create/create.go index 30c45de7a..3ea20c774 100644 --- a/internal/cmd/logs/instance/create/create.go +++ b/internal/cmd/logs/instance/create/create.go @@ -102,13 +102,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating instance") - _, err = wait.CreateLogsInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating instance", func() error { + _, err = wait.CreateLogsInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for logs instance creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model, projectLabel, resp) diff --git a/internal/cmd/logs/instance/delete/delete.go b/internal/cmd/logs/instance/delete/delete.go index 937239fc2..6b889e54d 100644 --- a/internal/cmd/logs/instance/delete/delete.go +++ b/internal/cmd/logs/instance/delete/delete.go @@ -85,13 +85,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting instance") - _, err = wait.DeleteLogsInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceID).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting instance", func() error { + _, err = wait.DeleteLogsInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceID).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for Logs instance deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/mariadb/instance/create/create.go b/internal/cmd/mariadb/instance/create/create.go index 22a8a2b91..de4c22b70 100644 --- a/internal/cmd/mariadb/instance/create/create.go +++ b/internal/cmd/mariadb/instance/create/create.go @@ -114,13 +114,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating instance") - _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating instance", func() error { + _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for MariaDB instance creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) diff --git a/internal/cmd/mariadb/instance/delete/delete.go b/internal/cmd/mariadb/instance/delete/delete.go index 1cd809204..db499df05 100644 --- a/internal/cmd/mariadb/instance/delete/delete.go +++ b/internal/cmd/mariadb/instance/delete/delete.go @@ -75,13 +75,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting instance") - _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting instance", func() error { + _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for MariaDB instance deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/mariadb/instance/update/update.go b/internal/cmd/mariadb/instance/update/update.go index ebb48e315..94a7a871d 100644 --- a/internal/cmd/mariadb/instance/update/update.go +++ b/internal/cmd/mariadb/instance/update/update.go @@ -111,13 +111,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Updating instance") - _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Updating instance", func() error { + _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for MariaDB instance update: %w", err) } - s.Stop() } operationState := "Updated" diff --git a/internal/cmd/mongodbflex/backup/restore/restore.go b/internal/cmd/mongodbflex/backup/restore/restore.go index 44b611669..25171f7cb 100644 --- a/internal/cmd/mongodbflex/backup/restore/restore.go +++ b/internal/cmd/mongodbflex/backup/restore/restore.go @@ -99,13 +99,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } if !model.Async { - s := spinner.New(params.Printer) - s.Start("Restoring instance") - _, err = wait.RestoreInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.BackupId, model.Region).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Restoring instance", func() error { + _, err = wait.RestoreInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.BackupId, model.Region).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for MongoDB Flex instance restoration: %w", err) } - s.Stop() } operationState := "Restored" @@ -124,13 +124,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } if !model.Async { - s := spinner.New(params.Printer) - s.Start("Cloning instance") - _, err = wait.CloneInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Cloning instance", func() error { + _, err = wait.CloneInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for MongoDB Flex instance cloning: %w", err) } - s.Stop() } operationState := "Cloned" diff --git a/internal/cmd/mongodbflex/instance/create/create.go b/internal/cmd/mongodbflex/instance/create/create.go index e0239d2f5..17cce56a3 100644 --- a/internal/cmd/mongodbflex/instance/create/create.go +++ b/internal/cmd/mongodbflex/instance/create/create.go @@ -121,13 +121,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating instance") - _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating instance", func() error { + _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for MongoDB Flex instance creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) diff --git a/internal/cmd/mongodbflex/instance/delete/delete.go b/internal/cmd/mongodbflex/instance/delete/delete.go index cb4a2be9c..8c34e1533 100644 --- a/internal/cmd/mongodbflex/instance/delete/delete.go +++ b/internal/cmd/mongodbflex/instance/delete/delete.go @@ -75,13 +75,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting instance") - _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting instance", func() error { + _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId, model.Region).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for MongoDB Flex instance deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/mongodbflex/instance/update/update.go b/internal/cmd/mongodbflex/instance/update/update.go index bcd4bb894..e340f95d2 100644 --- a/internal/cmd/mongodbflex/instance/update/update.go +++ b/internal/cmd/mongodbflex/instance/update/update.go @@ -107,13 +107,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Updating instance") - _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Updating instance", func() error { + _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId, model.Region).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for MongoDB Flex instance update: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, instanceLabel, resp) diff --git a/internal/cmd/network-area/create/create.go b/internal/cmd/network-area/create/create.go index 078a6568c..a99fafb57 100644 --- a/internal/cmd/network-area/create/create.go +++ b/internal/cmd/network-area/create/create.go @@ -146,13 +146,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { return fmt.Errorf("create network area region: %w", err) } if !model.Async { - s := spinner.New(params.Printer) - s.Start("Create network area region") - _, err = wait.CreateNetworkAreaRegionWaitHandler(ctx, apiClient, model.OrganizationId, *resp.Id, model.Region).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Create network area region", func() error { + _, err = wait.CreateNetworkAreaRegionWaitHandler(ctx, apiClient, model.OrganizationId, *resp.Id, model.Region).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for creating network area region %w", err) } - s.Stop() } responses.RegionalArea = respNetworkArea } diff --git a/internal/cmd/network-area/region/create/create.go b/internal/cmd/network-area/region/create/create.go index 0b59fa852..41ec64c0d 100644 --- a/internal/cmd/network-area/region/create/create.go +++ b/internal/cmd/network-area/region/create/create.go @@ -108,13 +108,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } if !model.Async { - s := spinner.New(params.Printer) - s.Start("Create network area region") - _, err = wait.CreateNetworkAreaRegionWaitHandler(ctx, apiClient, model.OrganizationId, model.NetworkAreaId, model.Region).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Create network area region", func() error { + _, err = wait.CreateNetworkAreaRegionWaitHandler(ctx, apiClient, model.OrganizationId, model.NetworkAreaId, model.Region).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for network area region creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, model.Region, networkAreaLabel, *resp) diff --git a/internal/cmd/network-area/region/delete/delete.go b/internal/cmd/network-area/region/delete/delete.go index bbbd44262..9c8586a94 100644 --- a/internal/cmd/network-area/region/delete/delete.go +++ b/internal/cmd/network-area/region/delete/delete.go @@ -82,13 +82,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { } if !model.Async { - s := spinner.New(params.Printer) - s.Start("Delete network area region") - _, err = wait.DeleteNetworkAreaRegionWaitHandler(ctx, apiClient, model.OrganizationId, model.NetworkAreaId, model.Region).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Delete network area region", func() error { + _, err = wait.DeleteNetworkAreaRegionWaitHandler(ctx, apiClient, model.OrganizationId, model.NetworkAreaId, model.Region).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for network area region deletion: %w", err) } - s.Stop() } params.Printer.Outputf("Delete regional network area %q for %q\n", model.Region, networkAreaName) diff --git a/internal/cmd/network/create/create.go b/internal/cmd/network/create/create.go index bb180a176..0c1f8d75d 100644 --- a/internal/cmd/network/create/create.go +++ b/internal/cmd/network/create/create.go @@ -134,15 +134,14 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating network") - _, err = wait.CreateNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.Region, networkId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating network", func() error { + _, err = wait.CreateNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.Region, networkId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for network creation: %w", err) } - s.Stop() } - return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) }, } diff --git a/internal/cmd/network/delete/delete.go b/internal/cmd/network/delete/delete.go index 1f3b00b95..998506a0a 100644 --- a/internal/cmd/network/delete/delete.go +++ b/internal/cmd/network/delete/delete.go @@ -81,13 +81,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting network") - _, err = wait.DeleteNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.NetworkId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting network", func() error { + _, err = wait.DeleteNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.NetworkId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for network deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/network/update/update.go b/internal/cmd/network/update/update.go index ba496a3ec..b85b7e6ab 100644 --- a/internal/cmd/network/update/update.go +++ b/internal/cmd/network/update/update.go @@ -115,15 +115,14 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Updating network") - _, err = wait.UpdateNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.Region, networkId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Updating network", func() error { + _, err = wait.UpdateNetworkWaitHandler(ctx, apiClient, model.ProjectId, model.Region, networkId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for network update: %w", err) } - s.Stop() } - operationState := "Updated" if model.Async { operationState = "Triggered update of" diff --git a/internal/cmd/object-storage/bucket/create/create.go b/internal/cmd/object-storage/bucket/create/create.go index ea10274db..577d244d0 100644 --- a/internal/cmd/object-storage/bucket/create/create.go +++ b/internal/cmd/object-storage/bucket/create/create.go @@ -85,13 +85,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating bucket") - _, err = wait.CreateBucketWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.BucketName).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating bucket", func() error { + _, err = wait.CreateBucketWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.BucketName).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for Object Storage bucket creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, model.BucketName, resp) diff --git a/internal/cmd/object-storage/bucket/delete/delete.go b/internal/cmd/object-storage/bucket/delete/delete.go index 99a82da85..c6cc396f8 100644 --- a/internal/cmd/object-storage/bucket/delete/delete.go +++ b/internal/cmd/object-storage/bucket/delete/delete.go @@ -67,13 +67,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting bucket") - _, err = wait.DeleteBucketWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.BucketName).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting bucket", func() error { + _, err = wait.DeleteBucketWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.BucketName).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for Object Storage bucket deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/observability/instance/create/create.go b/internal/cmd/observability/instance/create/create.go index c492902e5..769160b7b 100644 --- a/internal/cmd/observability/instance/create/create.go +++ b/internal/cmd/observability/instance/create/create.go @@ -94,13 +94,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating instance") - _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, instanceId, model.ProjectId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating instance", func() error { + _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, instanceId, model.ProjectId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for Observability instance creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) diff --git a/internal/cmd/observability/instance/delete/delete.go b/internal/cmd/observability/instance/delete/delete.go index 0aec201da..d9fc972ab 100644 --- a/internal/cmd/observability/instance/delete/delete.go +++ b/internal/cmd/observability/instance/delete/delete.go @@ -75,13 +75,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting instance") - _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.InstanceId, model.ProjectId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting instance", func() error { + _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.InstanceId, model.ProjectId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for Observability instance deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/observability/instance/update/update.go b/internal/cmd/observability/instance/update/update.go index 51d0b9f56..38b2fe693 100644 --- a/internal/cmd/observability/instance/update/update.go +++ b/internal/cmd/observability/instance/update/update.go @@ -100,13 +100,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Updating instance") - _, err = wait.UpdateInstanceWaitHandler(ctx, apiClient, instanceId, model.ProjectId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Updating instance", func() error { + _, err = wait.UpdateInstanceWaitHandler(ctx, apiClient, instanceId, model.ProjectId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for Observability instance update: %w", err) } - s.Stop() } operationState := "Updated" diff --git a/internal/cmd/observability/scrape-config/create/create.go b/internal/cmd/observability/scrape-config/create/create.go index f3e9a0515..87d206cfe 100644 --- a/internal/cmd/observability/scrape-config/create/create.go +++ b/internal/cmd/observability/scrape-config/create/create.go @@ -106,13 +106,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating scrape config") - _, err = wait.CreateScrapeConfigWaitHandler(ctx, apiClient, model.InstanceId, *jobName, model.ProjectId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating scrape config", func() error { + _, err = wait.CreateScrapeConfigWaitHandler(ctx, apiClient, model.InstanceId, *jobName, model.ProjectId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for scrape configuration creation: %w", err) } - s.Stop() } operationState := "Created" diff --git a/internal/cmd/observability/scrape-config/delete/delete.go b/internal/cmd/observability/scrape-config/delete/delete.go index 4cd15229b..7ec1e8ccf 100644 --- a/internal/cmd/observability/scrape-config/delete/delete.go +++ b/internal/cmd/observability/scrape-config/delete/delete.go @@ -78,13 +78,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting scrape config") - _, err = wait.DeleteScrapeConfigWaitHandler(ctx, apiClient, model.InstanceId, model.JobName, model.ProjectId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting scrape config", func() error { + _, err = wait.DeleteScrapeConfigWaitHandler(ctx, apiClient, model.InstanceId, model.JobName, model.ProjectId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for scrape config deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/opensearch/instance/create/create.go b/internal/cmd/opensearch/instance/create/create.go index bc03d82dd..776e6b86f 100644 --- a/internal/cmd/opensearch/instance/create/create.go +++ b/internal/cmd/opensearch/instance/create/create.go @@ -116,13 +116,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating instance") - _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating instance", func() error { + _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for OpenSearch instance creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, instanceId, resp) diff --git a/internal/cmd/opensearch/instance/delete/delete.go b/internal/cmd/opensearch/instance/delete/delete.go index e1cc328fb..58f4f59d1 100644 --- a/internal/cmd/opensearch/instance/delete/delete.go +++ b/internal/cmd/opensearch/instance/delete/delete.go @@ -75,13 +75,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting instance") - _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting instance", func() error { + _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for OpenSearch instance deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/opensearch/instance/update/update.go b/internal/cmd/opensearch/instance/update/update.go index aa9b90eb5..557fb1712 100644 --- a/internal/cmd/opensearch/instance/update/update.go +++ b/internal/cmd/opensearch/instance/update/update.go @@ -114,13 +114,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Updating instance") - _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Updating instance", func() error { + _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for OpenSearch instance update: %w", err) } - s.Stop() } operationState := "Updated" diff --git a/internal/cmd/postgresflex/instance/clone/clone.go b/internal/cmd/postgresflex/instance/clone/clone.go index d9a784d2a..facfdf105 100644 --- a/internal/cmd/postgresflex/instance/clone/clone.go +++ b/internal/cmd/postgresflex/instance/clone/clone.go @@ -97,13 +97,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Cloning instance") - _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Cloning instance", func() error { + _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for PostgreSQL Flex instance cloning: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, instanceLabel, instanceId, resp) diff --git a/internal/cmd/postgresflex/instance/create/create.go b/internal/cmd/postgresflex/instance/create/create.go index 8359ad2f7..7cad848d6 100644 --- a/internal/cmd/postgresflex/instance/create/create.go +++ b/internal/cmd/postgresflex/instance/create/create.go @@ -122,13 +122,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating instance") - _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating instance", func() error { + _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for PostgreSQL Flex instance creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, instanceId, resp) diff --git a/internal/cmd/postgresflex/instance/delete/delete.go b/internal/cmd/postgresflex/instance/delete/delete.go index 2108d31c3..3a8aa4cfe 100644 --- a/internal/cmd/postgresflex/instance/delete/delete.go +++ b/internal/cmd/postgresflex/instance/delete/delete.go @@ -92,13 +92,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting instance") - _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting instance", func() error { + _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for PostgreSQL Flex instance deletion: %w", err) } - s.Stop() } } @@ -112,13 +112,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Forcing deletion of instance") - _, err = wait.ForceDeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Forcing deletion of instance", func() error { + _, err = wait.ForceDeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.InstanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for PostgreSQL Flex instance force deletion: %w", err) } - s.Stop() } } diff --git a/internal/cmd/postgresflex/instance/update/update.go b/internal/cmd/postgresflex/instance/update/update.go index 8623a78f4..74a3a402d 100644 --- a/internal/cmd/postgresflex/instance/update/update.go +++ b/internal/cmd/postgresflex/instance/update/update.go @@ -107,13 +107,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Updating instance") - _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Updating instance", func() error { + _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.Region, instanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for PostgreSQL Flex instance update: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, instanceLabel, resp) diff --git a/internal/cmd/rabbitmq/instance/create/create.go b/internal/cmd/rabbitmq/instance/create/create.go index 1ac8e7cc2..cb2bf470a 100644 --- a/internal/cmd/rabbitmq/instance/create/create.go +++ b/internal/cmd/rabbitmq/instance/create/create.go @@ -116,13 +116,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating instance") - _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating instance", func() error { + _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for RabbitMQ instance creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model, projectLabel, instanceId, resp) diff --git a/internal/cmd/rabbitmq/instance/delete/delete.go b/internal/cmd/rabbitmq/instance/delete/delete.go index 766ced827..ec5c35104 100644 --- a/internal/cmd/rabbitmq/instance/delete/delete.go +++ b/internal/cmd/rabbitmq/instance/delete/delete.go @@ -75,13 +75,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting instance") - _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting instance", func() error { + _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for RabbitMQ instance deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/rabbitmq/instance/update/update.go b/internal/cmd/rabbitmq/instance/update/update.go index d3cf53603..b58590a6e 100644 --- a/internal/cmd/rabbitmq/instance/update/update.go +++ b/internal/cmd/rabbitmq/instance/update/update.go @@ -114,13 +114,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Updating instance") - _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Updating instance", func() error { + _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for RabbitMQ instance update: %w", err) } - s.Stop() } operationState := "Updated" diff --git a/internal/cmd/redis/instance/create/create.go b/internal/cmd/redis/instance/create/create.go index 8993b98ca..817a769ce 100644 --- a/internal/cmd/redis/instance/create/create.go +++ b/internal/cmd/redis/instance/create/create.go @@ -114,13 +114,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating instance") - _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating instance", func() error { + _, err = wait.CreateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for Redis instance creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model, projectLabel, instanceId, resp) diff --git a/internal/cmd/redis/instance/delete/delete.go b/internal/cmd/redis/instance/delete/delete.go index 0c8124906..f54412008 100644 --- a/internal/cmd/redis/instance/delete/delete.go +++ b/internal/cmd/redis/instance/delete/delete.go @@ -75,13 +75,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting instance") - _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting instance", func() error { + _, err = wait.DeleteInstanceWaitHandler(ctx, apiClient, model.ProjectId, model.InstanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for Redis instance deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/redis/instance/update/update.go b/internal/cmd/redis/instance/update/update.go index 3fcc2e7b4..ca078eb82 100644 --- a/internal/cmd/redis/instance/update/update.go +++ b/internal/cmd/redis/instance/update/update.go @@ -111,13 +111,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Updating instance") - _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Updating instance", func() error { + _, err = wait.PartialUpdateInstanceWaitHandler(ctx, apiClient, model.ProjectId, instanceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for Redis instance update: %w", err) } - s.Stop() } operationState := "Updated" diff --git a/internal/cmd/server/create/create.go b/internal/cmd/server/create/create.go index ab5253af0..c4f0450d9 100644 --- a/internal/cmd/server/create/create.go +++ b/internal/cmd/server/create/create.go @@ -144,13 +144,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating server") - _, err = wait.CreateServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, serverId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating server", func() error { + _, err = wait.CreateServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, serverId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for server creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) diff --git a/internal/cmd/server/deallocate/deallocate.go b/internal/cmd/server/deallocate/deallocate.go index bed42bf7a..f10fb670b 100644 --- a/internal/cmd/server/deallocate/deallocate.go +++ b/internal/cmd/server/deallocate/deallocate.go @@ -78,13 +78,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deallocating server") - _, err = wait.DeallocateServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deallocating server", func() error { + _, err = wait.DeallocateServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for server deallocating: %w", err) } - s.Stop() } operationState := "Deallocated" diff --git a/internal/cmd/server/delete/delete.go b/internal/cmd/server/delete/delete.go index 412c099dc..d24acf388 100644 --- a/internal/cmd/server/delete/delete.go +++ b/internal/cmd/server/delete/delete.go @@ -5,7 +5,9 @@ import ( "fmt" "github.com/stackitcloud/stackit-cli/internal/pkg/types" + "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" + "github.com/spf13/cobra" "github.com/stackitcloud/stackit-cli/internal/pkg/args" "github.com/stackitcloud/stackit-cli/internal/pkg/errors" "github.com/stackitcloud/stackit-cli/internal/pkg/examples" @@ -16,9 +18,6 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" "github.com/stackitcloud/stackit-cli/internal/pkg/utils" "github.com/stackitcloud/stackit-sdk-go/services/iaas" - "github.com/stackitcloud/stackit-sdk-go/services/iaas/wait" - - "github.com/spf13/cobra" ) const ( @@ -81,13 +80,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting server") - _, err = wait.DeleteServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting server", func() error { + _, err = wait.DeleteServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for server deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/server/rescue/rescue.go b/internal/cmd/server/rescue/rescue.go index dd77e4625..ee5d9b68c 100644 --- a/internal/cmd/server/rescue/rescue.go +++ b/internal/cmd/server/rescue/rescue.go @@ -82,13 +82,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Rescuing server") - _, err = wait.RescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Rescuing server", func() error { + _, err = wait.RescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for server rescuing: %w", err) } - s.Stop() } operationState := "Rescued" diff --git a/internal/cmd/server/resize/resize.go b/internal/cmd/server/resize/resize.go index 804dbce1a..34eb1bddb 100644 --- a/internal/cmd/server/resize/resize.go +++ b/internal/cmd/server/resize/resize.go @@ -82,13 +82,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Resizing server") - _, err = wait.ResizeServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Resizing server", func() error { + _, err = wait.ResizeServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for server resizing: %w", err) } - s.Stop() } operationState := "Resized" diff --git a/internal/cmd/server/start/start.go b/internal/cmd/server/start/start.go index 3dc23ff31..9d0c3e056 100644 --- a/internal/cmd/server/start/start.go +++ b/internal/cmd/server/start/start.go @@ -72,13 +72,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Starting server") - _, err = wait.StartServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Starting server", func() error { + _, err = wait.StartServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for server starting: %w", err) } - s.Stop() } operationState := "Started" diff --git a/internal/cmd/server/stop/stop.go b/internal/cmd/server/stop/stop.go index a7a9b4604..936d2ae6c 100644 --- a/internal/cmd/server/stop/stop.go +++ b/internal/cmd/server/stop/stop.go @@ -78,13 +78,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Stopping server") - _, err = wait.StopServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Stopping server", func() error { + _, err = wait.StopServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for server stopping: %w", err) } - s.Stop() } operationState := "Stopped" diff --git a/internal/cmd/server/unrescue/unrescue.go b/internal/cmd/server/unrescue/unrescue.go index f47ef6794..16f9d5351 100644 --- a/internal/cmd/server/unrescue/unrescue.go +++ b/internal/cmd/server/unrescue/unrescue.go @@ -78,13 +78,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Unrescuing server") - _, err = wait.UnrescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Unrescuing server", func() error { + _, err = wait.UnrescueServerWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.ServerId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for server unrescuing: %w", err) } - s.Stop() } operationState := "Unrescued" diff --git a/internal/cmd/ske/cluster/create/create.go b/internal/cmd/ske/cluster/create/create.go index faca273bb..38263ec9e 100644 --- a/internal/cmd/ske/cluster/create/create.go +++ b/internal/cmd/ske/cluster/create/create.go @@ -133,13 +133,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating cluster") - _, err = wait.CreateOrUpdateClusterWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, name).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating cluster", func() error { + _, err = wait.CreateOrUpdateClusterWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, name).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for SKE cluster creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, projectLabel, resp) diff --git a/internal/cmd/ske/cluster/delete/delete.go b/internal/cmd/ske/cluster/delete/delete.go index f172b495b..f8833c202 100644 --- a/internal/cmd/ske/cluster/delete/delete.go +++ b/internal/cmd/ske/cluster/delete/delete.go @@ -67,13 +67,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting cluster") - _, err = wait.DeleteClusterWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting cluster", func() error { + _, err = wait.DeleteClusterWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for SKE cluster deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/ske/cluster/hibernate/hibernate.go b/internal/cmd/ske/cluster/hibernate/hibernate.go index 259ae868f..a409c4890 100644 --- a/internal/cmd/ske/cluster/hibernate/hibernate.go +++ b/internal/cmd/ske/cluster/hibernate/hibernate.go @@ -16,7 +16,7 @@ import ( "github.com/stackitcloud/stackit-cli/internal/pkg/services/ske/client" "github.com/stackitcloud/stackit-cli/internal/pkg/spinner" ske "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api" - wait "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api/wait" + "github.com/stackitcloud/stackit-sdk-go/services/ske/v2api/wait" ) const ( @@ -72,13 +72,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Hibernating cluster") - _, err = wait.TriggerClusterHibernationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Hibernating cluster", func() error { + _, err = wait.TriggerClusterHibernationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for SKE cluster hibernation: %w", err) } - s.Stop() } operationState := "Hibernated" diff --git a/internal/cmd/ske/cluster/maintenance/maintenance.go b/internal/cmd/ske/cluster/maintenance/maintenance.go index 8fda38bb6..444e22117 100644 --- a/internal/cmd/ske/cluster/maintenance/maintenance.go +++ b/internal/cmd/ske/cluster/maintenance/maintenance.go @@ -72,13 +72,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Performing cluster maintenance") - _, err = wait.TriggerClusterMaintenanceWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Performing cluster maintenance", func() error { + _, err = wait.TriggerClusterMaintenanceWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for SKE cluster maintenance to complete: %w", err) } - s.Stop() } operationState := "Performed maintenance for" diff --git a/internal/cmd/ske/cluster/reconcile/reconcile.go b/internal/cmd/ske/cluster/reconcile/reconcile.go index faf3e6da5..00bc11a9e 100644 --- a/internal/cmd/ske/cluster/reconcile/reconcile.go +++ b/internal/cmd/ske/cluster/reconcile/reconcile.go @@ -60,13 +60,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Performing cluster reconciliation") - _, err = wait.TriggerClusterReconciliationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Performing cluster reconciliation", func() error { + _, err = wait.TriggerClusterReconciliationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for SKE cluster reconciliation: %w", err) } - s.Stop() } operationState := "Performed reconciliation for" diff --git a/internal/cmd/ske/cluster/update/update.go b/internal/cmd/ske/cluster/update/update.go index 7abd56eb1..bd1facd7a 100644 --- a/internal/cmd/ske/cluster/update/update.go +++ b/internal/cmd/ske/cluster/update/update.go @@ -95,13 +95,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Updating cluster") - _, err = wait.CreateOrUpdateClusterWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, name).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Updating cluster", func() error { + _, err = wait.CreateOrUpdateClusterWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, name).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for SKE cluster update: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, model.ClusterName, resp) diff --git a/internal/cmd/ske/cluster/wakeup/wakeup.go b/internal/cmd/ske/cluster/wakeup/wakeup.go index 44b1d976f..b53077ef3 100644 --- a/internal/cmd/ske/cluster/wakeup/wakeup.go +++ b/internal/cmd/ske/cluster/wakeup/wakeup.go @@ -60,13 +60,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Performing cluster wakeup") - _, err = wait.TriggerClusterWakeupWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Performing cluster wakeup", func() error { + _, err = wait.TriggerClusterWakeupWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for SKE cluster wakeup: %w", err) } - s.Stop() } operationState := "Performed wakeup of" diff --git a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go index a4a5d53af..734a89735 100644 --- a/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go +++ b/internal/cmd/ske/credentials/complete-rotation/complete_rotation.go @@ -84,13 +84,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Completing credentials rotation") - _, err = wait.CompleteCredentialsRotationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Completing credentials rotation", func() error { + _, err = wait.CompleteCredentialsRotationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for completing SKE credentials rotation %w", err) } - s.Stop() } operationState := "Rotation of credentials is completed" diff --git a/internal/cmd/ske/credentials/start-rotation/start_rotation.go b/internal/cmd/ske/credentials/start-rotation/start_rotation.go index b2daa7c87..ea2933fab 100644 --- a/internal/cmd/ske/credentials/start-rotation/start_rotation.go +++ b/internal/cmd/ske/credentials/start-rotation/start_rotation.go @@ -87,13 +87,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Starting credentials rotation") - _, err = wait.StartCredentialsRotationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Starting credentials rotation", func() error { + _, err = wait.StartCredentialsRotationWaitHandler(ctx, apiClient.DefaultAPI, model.ProjectId, model.Region, model.ClusterName).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for start SKE credentials rotation %w", err) } - s.Stop() } operationState := "Rotation of credentials is ready to be completed" diff --git a/internal/cmd/ske/disable/disable.go b/internal/cmd/ske/disable/disable.go index 075711b1a..43c103e7b 100644 --- a/internal/cmd/ske/disable/disable.go +++ b/internal/cmd/ske/disable/disable.go @@ -70,13 +70,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Disabling SKE") - _, err = wait.DisableServiceWaitHandler(ctx, apiClient, model.Region, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Disabling SKE", func() error { + _, err = wait.DisableServiceWaitHandler(ctx, apiClient, model.Region, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for SKE disabling: %w", err) } - s.Stop() } operationState := "Disabled" diff --git a/internal/cmd/ske/enable/enable.go b/internal/cmd/ske/enable/enable.go index 366f8d5f2..ea83a337b 100644 --- a/internal/cmd/ske/enable/enable.go +++ b/internal/cmd/ske/enable/enable.go @@ -70,13 +70,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Enabling SKE") - _, err = wait.EnableServiceWaitHandler(ctx, apiClient, model.Region, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Enabling SKE", func() error { + _, err = wait.EnableServiceWaitHandler(ctx, apiClient, model.Region, model.ProjectId, utils.SKEServiceId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for SKE enabling: %w", err) } - s.Stop() } operationState := "Enabled" diff --git a/internal/cmd/volume/backup/create/create.go b/internal/cmd/volume/backup/create/create.go index fc9e0b3cd..c2211a3ad 100644 --- a/internal/cmd/volume/backup/create/create.go +++ b/internal/cmd/volume/backup/create/create.go @@ -115,13 +115,12 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating backup") - resp, err = wait.CreateBackupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, volumeId).WaitWithContext(ctx) + resp, err = spinner.Run2(params.Printer, "Creating backup", func() (*iaas.Backup, error) { + return wait.CreateBackupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, volumeId).WaitWithContext(ctx) + }) if err != nil { return fmt.Errorf("wait for backup creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model.OutputFormat, model.Async, sourceLabel, projectLabel, resp) diff --git a/internal/cmd/volume/backup/delete/delete.go b/internal/cmd/volume/backup/delete/delete.go index 9c9717427..e5b113075 100644 --- a/internal/cmd/volume/backup/delete/delete.go +++ b/internal/cmd/volume/backup/delete/delete.go @@ -73,13 +73,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting backup") - _, err = wait.DeleteBackupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.BackupId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting backup", func() error { + _, err = wait.DeleteBackupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.BackupId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for backup deletion: %w", err) } - s.Stop() } if model.Async { diff --git a/internal/cmd/volume/backup/restore/restore.go b/internal/cmd/volume/backup/restore/restore.go index 63fc0d915..ebcb5f917 100644 --- a/internal/cmd/volume/backup/restore/restore.go +++ b/internal/cmd/volume/backup/restore/restore.go @@ -86,13 +86,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Restoring backup") - _, err = wait.RestoreBackupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.BackupId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Restoring backup", func() error { + _, err = wait.RestoreBackupWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.BackupId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for backup restore: %w", err) } - s.Stop() } if model.Async { diff --git a/internal/cmd/volume/create/create.go b/internal/cmd/volume/create/create.go index f82725de6..5b7a21ffd 100644 --- a/internal/cmd/volume/create/create.go +++ b/internal/cmd/volume/create/create.go @@ -104,13 +104,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating volume") - _, err = wait.CreateVolumeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, volumeId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Creating volume", func() error { + _, err = wait.CreateVolumeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, volumeId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for volume creation: %w", err) } - s.Stop() } return outputResult(params.Printer, model, projectLabel, resp) diff --git a/internal/cmd/volume/delete/delete.go b/internal/cmd/volume/delete/delete.go index 599f3bf56..abf99a53f 100644 --- a/internal/cmd/volume/delete/delete.go +++ b/internal/cmd/volume/delete/delete.go @@ -79,13 +79,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting volume") - _, err = wait.DeleteVolumeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.VolumeId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting volume", func() error { + _, err = wait.DeleteVolumeWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.VolumeId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for volume deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/cmd/volume/snapshot/create/create.go b/internal/cmd/volume/snapshot/create/create.go index f63a38b16..da209bf7b 100644 --- a/internal/cmd/volume/snapshot/create/create.go +++ b/internal/cmd/volume/snapshot/create/create.go @@ -94,13 +94,12 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Creating snapshot") - resp, err = wait.CreateSnapshotWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Id).WaitWithContext(ctx) + resp, err = spinner.Run2(params.Printer, "Creating snapshot", func() (*iaas.Snapshot, error) { + return wait.CreateSnapshotWaitHandler(ctx, apiClient, model.ProjectId, model.Region, *resp.Id).WaitWithContext(ctx) + }) if err != nil { return fmt.Errorf("wait for snapshot creation: %w", err) } - s.Stop() } operationState := "Created" diff --git a/internal/cmd/volume/snapshot/delete/delete.go b/internal/cmd/volume/snapshot/delete/delete.go index 7334cac51..fca923a29 100644 --- a/internal/cmd/volume/snapshot/delete/delete.go +++ b/internal/cmd/volume/snapshot/delete/delete.go @@ -76,13 +76,13 @@ func NewCmd(params *types.CmdParams) *cobra.Command { // Wait for async operation, if async mode not enabled if !model.Async { - s := spinner.New(params.Printer) - s.Start("Deleting snapshot") - _, err = wait.DeleteSnapshotWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.SnapshotId).WaitWithContext(ctx) + err := spinner.Run(params.Printer, "Deleting snapshot", func() error { + _, err = wait.DeleteSnapshotWaitHandler(ctx, apiClient, model.ProjectId, model.Region, model.SnapshotId).WaitWithContext(ctx) + return err + }) if err != nil { return fmt.Errorf("wait for snapshot deletion: %w", err) } - s.Stop() } operationState := "Deleted" diff --git a/internal/pkg/spinner/spinner.go b/internal/pkg/spinner/spinner.go index 9c530f1ca..fa76ef2b8 100644 --- a/internal/pkg/spinner/spinner.go +++ b/internal/pkg/spinner/spinner.go @@ -15,7 +15,30 @@ type Spinner struct { done chan bool } -func New(p *print.Printer) *Spinner { +// Run starts a spinner and stops it when f completes +func Run(p *print.Printer, message string, f func() error) error { + _, err := Run2(p, message, func() (struct{}, error) { + err := f() + return struct{}{}, err + }) + return err +} + +// Run2 starts a spinner and stops it when f (result arity 2) completes. +func Run2[T any](p *print.Printer, message string, f func() (T, error)) (T, error) { + var r T + spinner := newSpinner(p) + spinner.start(message) + r, err := f() + if err != nil { + spinner.stopWithError() + return r, err + } + spinner.stop() + return r, nil +} + +func newSpinner(p *print.Printer) *Spinner { return &Spinner{ printer: p, states: []string{"|", "/", "-", "\\"}, @@ -25,18 +48,18 @@ func New(p *print.Printer) *Spinner { } } -func (s *Spinner) Start(message string) { +func (s *Spinner) start(message string) { s.message = message go s.animate() } -func (s *Spinner) Stop() { +func (s *Spinner) stop() { s.done <- true close(s.done) s.printer.Info("\r%s ✓ \n", s.message) } -func (s *Spinner) StopWithError() { +func (s *Spinner) stopWithError() { s.done <- true close(s.done) s.printer.Info("\r%s ✗ \n", s.message)