func (env *azureEnviron) deleteControllerManagedResourceGroups(controllerUUID string) error { filter := fmt.Sprintf( "tagname eq '%s' and tagvalue eq '%s'", tags.JujuController, controllerUUID, ) client := resources.GroupsClient{env.resources} var result resources.ResourceGroupListResult if err := env.callAPI(func() (autorest.Response, error) { var err error result, err = client.List(filter, nil) return result.Response, err }); err != nil { return errors.Annotate(err, "listing resource groups") } if result.Value == nil { return nil } // Deleting groups can take a long time, so make sure they are // deleted in parallel. var wg sync.WaitGroup errs := make([]error, len(*result.Value)) for i, group := range *result.Value { groupName := to.String(group.Name) logger.Debugf(" - deleting resource group %q", groupName) wg.Add(1) go func(i int) { defer wg.Done() if err := env.deleteResourceGroup(groupName); err != nil { errs[i] = errors.Annotatef( err, "deleting resource group %q", groupName, ) } }(i) } wg.Wait() // If there is just one error, return it. If there are multiple, // then combine their messages. var nonNilErrs []error for _, err := range errs { if err != nil { nonNilErrs = append(nonNilErrs, err) } } switch len(nonNilErrs) { case 0: return nil case 1: return nonNilErrs[0] } combined := make([]string, len(nonNilErrs)) for i, err := range nonNilErrs { combined[i] = err.Error() } return errors.New(strings.Join(combined, "; ")) }