diff --git a/cmd/private_network_list.go b/cmd/private_network_list.go index b6c83d88..c8bfe249 100644 --- a/cmd/private_network_list.go +++ b/cmd/private_network_list.go @@ -9,6 +9,7 @@ import ( "github.com/exoscale/cli/pkg/globalstate" "github.com/exoscale/cli/pkg/output" + "github.com/exoscale/cli/utils" v3 "github.com/exoscale/egoscale/v3" ) @@ -62,35 +63,45 @@ func (c *privateNetworkListCmd) cmdRun(_ *cobra.Command, _ []string) error { if err != nil { return err } - zones = []v3.Zone{{APIEndpoint: endpoint}} } out := make(privateNetworkListOutput, 0) + res := make(chan privateNetworkListItemOutput) + done := make(chan struct{}) - var responseError error - var errorZones []string - - for _, zone := range zones { - c := client.WithEndpoint(zone.APIEndpoint) + go func() { + for nlb := range res { + out = append(out, nlb) + } + done <- struct{}{} + }() + err = utils.ForEveryZone(zones, func(zone v3.Zone) error { + c := client.WithEndpoint((zone.APIEndpoint)) resp, err := c.ListPrivateNetworks(ctx) if err != nil { - responseError = err - errorZones = append(errorZones, string(zone.Name)) - } else { - for _, p := range resp.PrivateNetworks { - out = append(out, privateNetworkListItemOutput{ - ID: p.ID, - Name: p.Name, - Zone: zone.Name, - }) + return fmt.Errorf("unable to list Private Networks in zone %s: %w", zone, err) + } + + for _, p := range resp.PrivateNetworks { + res <- privateNetworkListItemOutput{ + ID: p.ID, + Name: p.Name, + Zone: zone.Name, } } + + return nil + }) + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, + "warning: errors during listing, results might be incomplete.\n%s\n", err) // nolint:golint } - if responseError != nil { - fmt.Fprintf(os.Stderr, "warning: error during listing private networks in %s zones, results might be incomplete:\n%s\n", errorZones, responseError) // nolint:golint - } + + close(res) + <-done + return c.outputFunc(&out, nil) } diff --git a/utils/utils.go b/utils/utils.go index 734b66dd..f8b940ed 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -238,6 +238,24 @@ func ForEachZone(zones []string, f func(zone string) error) error { return meg.Wait().ErrorOrNil() } +// ForEveryZone executes the function f for every specified zone, and return a multierror.Error containing all +// errors that may have occurred during execution. + +// TODO: This is a copy paste from the function above, but suitable for egoscale v3 calls. +// remove the old one +func ForEveryZone(zones []v3.Zone, f func(zone v3.Zone) error) error { + meg := new(multierror.Group) + + for _, zone := range zones { + zone := zone + meg.Go(func() error { + return f(zone) + }) + } + + return meg.Wait().ErrorOrNil() +} + // ParseInstanceType returns an v3.InstanceType with family and name. func ParseInstanceType(instanceType string) v3.InstanceType { var typeFamily, typeSize string