in step_delete_resources.go [256:405]
func (d *DeleteResources) run(ctx context.Context, s *Step) DError {
var wg sync.WaitGroup
w := s.w
e := make(chan DError)
for _, i := range d.Instances {
wg.Add(1)
go func(i string) {
defer wg.Done()
w.LogStepInfo(s.name, "DeleteResources", "Deleting instance %q.", i)
if err := w.instances.delete(i); err != nil {
if err.etype() == resourceDNEError {
w.LogStepInfo(s.name, "DeleteResources", "WARNING: Error deleting instance %q: %v", i, err)
return
}
e <- err
}
}(i)
}
for _, i := range d.Images {
wg.Add(1)
go func(i string) {
defer wg.Done()
w.LogStepInfo(s.name, "DeleteResources", "Deleting image %q.", i)
if err := w.images.delete(i); err != nil {
if err.etype() == resourceDNEError {
w.LogStepInfo(s.name, "DeleteResources", "WARNING: Error deleting image %q: %v", i, err)
return
}
e <- err
}
}(i)
}
for _, i := range d.MachineImages {
wg.Add(1)
go func(i string) {
defer wg.Done()
w.LogStepInfo(s.name, "DeleteResources", "Deleting machine image %q.", i)
if err := w.machineImages.delete(i); err != nil {
if err.etype() == resourceDNEError {
w.LogStepInfo(s.name, "DeleteResources", "WARNING: Error deleting machine image %q: %v", i, err)
return
}
e <- err
}
}(i)
}
for _, p := range d.GCSPaths {
wg.Add(1)
go func(p string) {
defer wg.Done()
bkt, obj, err := splitGCSPath(p)
if err != nil {
e <- err
return
}
if obj == "" || strings.HasSuffix(obj, "/") {
if err := recursiveGCSDelete(ctx, s.w, bkt, obj); err != nil {
e <- err
}
return
}
if err := w.StorageClient.Bucket(bkt).Object(obj).Delete(ctx); err != nil {
if gErr, ok := err.(*googleapi.Error); ok && gErr.Code == http.StatusNotFound {
w.LogStepInfo(s.name, "DeleteResources", "WARNING: Error deleting GCS Path %q: %v", p, err)
return
}
e <- Errf("error deleting GCS path %q: %v", p, err)
}
}(p)
}
if abort, ret := waitGroup(&wg, e, w); abort {
return ret
}
// Delete disks only after instances have been deleted.
e = make(chan DError)
for _, d := range d.Disks {
wg.Add(1)
go func(d string) {
defer wg.Done()
w.LogStepInfo(s.name, "DeleteResources", "Deleting disk %q.", d)
if err := w.disks.delete(d); err != nil {
if err.etype() == resourceDNEError {
w.LogStepInfo(s.name, "DeleteResources", "WARNING: Error deleting disk %q: %v", d, err)
return
}
e <- err
}
}(d)
}
// Delete firewalls after instance have been deleted
for _, n := range d.Firewalls {
wg.Add(1)
go func(n string) {
defer wg.Done()
w.LogStepInfo(s.name, "DeleteResources", "Deleting firewall %q.", n)
if err := w.firewallRules.delete(n); err != nil {
if err.etype() == resourceDNEError {
w.LogStepInfo(s.name, "DeleteResources", "WARNING: Error deleting firewall %q: %v", n, err)
}
e <- err
}
}(n)
}
// Delete subnetworks after firewalls.
for _, sn := range d.Subnetworks {
wg.Add(1)
go func(sn string) {
defer wg.Done()
w.LogStepInfo(s.name, "DeleteResources", "Deleting subnetwork %q.", sn)
if err := w.subnetworks.delete(sn); err != nil {
if err.etype() == resourceDNEError {
w.LogStepInfo(s.name, "DeleteResources", "WARNING: Error deleting subnetwork %q: %v", sn, err)
}
e <- err
}
}(sn)
}
if abort, ret := waitGroup(&wg, e, w); abort {
return ret
}
// Delete networks after subnetworks have been deleted
for _, n := range d.Networks {
wg.Add(1)
go func(n string) {
defer wg.Done()
w.LogStepInfo(s.name, "DeleteResources", "Deleting network %q.", n)
if err := w.networks.delete(n); err != nil {
if err.etype() == resourceDNEError {
w.LogStepInfo(s.name, "DeleteResources", "WARNING: Error deleting network %q: %v", n, err)
}
e <- err
}
}(n)
}
_, ret := waitGroup(&wg, e, w)
return ret
}