@@ -3,7 +3,8 @@ package base
33import (
44 "errors"
55 "fmt"
6- "reflect"
6+ "strings"
7+ "sync"
78
89 "github.com/spf13/cobra"
910
@@ -17,11 +18,12 @@ import (
1718// DeleteCmd allows defining commands for deleting a resource.
1819type DeleteCmd struct {
1920 ResourceNameSingular string // e.g. "server"
21+ ResourceNamePlural string // e.g. "servers"
2022 ShortDescription string
2123 NameSuggestions func (client hcapi2.Client ) func () []string
2224 AdditionalFlags func (* cobra.Command )
2325 Fetch func (s state.State , cmd * cobra.Command , idOrName string ) (interface {}, * hcloud.Response , error )
24- Delete func (s state.State , cmd * cobra.Command , resource interface {}) error
26+ Delete func (s state.State , cmd * cobra.Command , resource interface {}) ( * hcloud. Action , error )
2527}
2628
2729// CobraCommand creates a command that can be registered with cobra.
@@ -49,29 +51,50 @@ func (dc *DeleteCmd) CobraCommand(s state.State) *cobra.Command {
4951 return cmd
5052}
5153
52- // Run executes a describe command.
54+ // Run executes a delete command.
5355func (dc * DeleteCmd ) Run (s state.State , cmd * cobra.Command , args []string ) error {
54- var cmdErr error
5556
56- for _ , idOrName := range args {
57- resource , _ , err := dc .Fetch (s , cmd , idOrName )
58- if err != nil {
59- cmdErr = errors .Join (cmdErr , err )
60- continue
61- }
57+ wg := sync.WaitGroup {}
58+ wg .Add (len (args ))
59+ actions , errs :=
60+ make ([]* hcloud.Action , len (args )),
61+ make ([]error , len (args ))
6262
63- // resource is an interface that always has a type, so the interface is never nil
64- // (i.e. == nil) is always false.
65- if reflect .ValueOf (resource ).IsNil () {
66- cmdErr = errors .Join (cmdErr , fmt .Errorf ("%s not found: %s" , dc .ResourceNameSingular , idOrName ))
67- continue
68- }
63+ for i , idOrName := range args {
64+ i , idOrName := i , idOrName
65+ go func () {
66+ defer wg .Done ()
67+ resource , _ , err := dc .Fetch (s , cmd , idOrName )
68+ if err != nil {
69+ errs [i ] = err
70+ return
71+ }
72+ if util .IsNil (resource ) {
73+ errs [i ] = fmt .Errorf ("%s not found: %s" , dc .ResourceNameSingular , idOrName )
74+ return
75+ }
76+ actions [i ], errs [i ] = dc .Delete (s , cmd , resource )
77+ }()
78+ }
6979
70- if err = dc .Delete (s , cmd , resource ); err != nil {
71- cmdErr = errors .Join (cmdErr , fmt .Errorf ("deleting %s %s failed: %s" , dc .ResourceNameSingular , idOrName , err ))
80+ wg .Wait ()
81+ filtered := util .FilterNil (actions )
82+ var err error
83+ if len (filtered ) > 0 {
84+ err = s .WaitForActions (cmd , s , filtered ... )
85+ }
86+
87+ var actuallyDeleted []string
88+ for i , idOrName := range args {
89+ if errs [i ] == nil {
90+ actuallyDeleted = append (actuallyDeleted , idOrName )
7291 }
73- cmd .Printf ("%s %v deleted\n " , dc .ResourceNameSingular , idOrName )
7492 }
7593
76- return cmdErr
94+ if len (actuallyDeleted ) == 1 {
95+ cmd .Printf ("%s %s deleted\n " , dc .ResourceNameSingular , actuallyDeleted [0 ])
96+ } else if len (actuallyDeleted ) > 1 {
97+ cmd .Printf ("%s %s deleted\n " , dc .ResourceNamePlural , strings .Join (actuallyDeleted , ", " ))
98+ }
99+ return errors .Join (append (errs , err )... )
77100}
0 commit comments