// MultilineError returns a string representing an error that splits sub errors into their own // lines. The returned string will end with a newline. func MultilineError(prefix string, err error) string { if agg, ok := err.(utilerrors.Aggregate); ok { errs := utilerrors.Flatten(agg).Errors() buf := &bytes.Buffer{} switch len(errs) { case 0: return fmt.Sprintf("%s%v\n", prefix, err) case 1: return fmt.Sprintf("%s%v\n", prefix, messageForError(errs[0])) default: fmt.Fprintln(buf, prefix) for _, err := range errs { fmt.Fprintf(buf, "* %v\n", messageForError(err)) } return buf.String() } } return fmt.Sprintf("%s%s\n", prefix, err) }
// EnsureTCPLoadBalancerDeleted is an implementation of TCPLoadBalancer.EnsureTCPLoadBalancerDeleted. func (gce *GCECloud) EnsureTCPLoadBalancerDeleted(name, region string) error { err := errors.AggregateGoroutines( func() error { return gce.deleteFirewall(name, region) }, // Even though we don't hold on to static IPs for load balancers, it's // possible that EnsureTCPLoadBalancer left one around in a failed // creation/update attempt, so make sure we clean it up here just in case. func() error { return gce.deleteStaticIP(name, region) }, func() error { // The forwarding rule must be deleted before either the target pool can, // unfortunately, so we have to do these two serially. if err := gce.deleteForwardingRule(name, region); err != nil { return err } if err := gce.deleteTargetPool(name, region); err != nil { return err } return nil }, ) if err != nil { return errors.Flatten(err) } return nil }