func CleanNetworks()

in cleanerupper/cleanerupper.go [715:1036]


func CleanNetworks(clients Clients, project string, delete PolicyFunc, dryRun bool) ([]string, []error) {
	networks, err := clients.Daisy.ListNetworks(project)
	if err != nil {
		return nil, []error{fmt.Errorf("error listing networks in project %q: %v", project, err)}
	}

	firewalls, err := clients.Daisy.ListFirewallRules(project)
	if err != nil {
		return nil, []error{fmt.Errorf("error listing firewalls in project %q: %v", project, err)}
	}

	subnetworks, err := clients.Daisy.AggregatedListSubnetworks(project)
	if err != nil {
		return nil, []error{fmt.Errorf("error listing subnetworks in project %q: %v", project, err)}
	}

	regionalForwardingRules := make(map[string][]*compute.ForwardingRule)
	regionalBackendServices := make(map[string][]*compute.BackendService)
	regionalNetworkEndpointGroups := make(map[string][]*compute.NetworkEndpointGroup)
	regionalURLMaps := make(map[string][]*compute.UrlMap)
	regionalHTTPProxies := make(map[string][]*compute.TargetHttpProxy)

	var deletedMu sync.Mutex
	var deleted []string
	var errsMu sync.Mutex
	var errs []error
	var wg sync.WaitGroup
	for _, n := range networks {
		if !delete(n) {
			continue
		}

		name := path.Base(n.SelfLink)
		netpartial := fmt.Sprintf("projects/%s/global/networks/%s", project, name)

		// Delete firewall rules associated with network.
		for _, f := range firewalls {
			if f.Network != n.SelfLink {
				continue
			}
			name := path.Base(f.SelfLink)
			fwallpartial := fmt.Sprintf("projects/%s/global/firewalls/%s", project, name)
			wg.Add(1)
			go func() {
				defer wg.Done()
				if !dryRun {
					if err := clients.Daisy.DeleteFirewallRule(project, name); err != nil {
						errsMu.Lock()
						defer errsMu.Unlock()
						errs = append(errs, err)
						return
					}
				}
				deletedMu.Lock()
				defer deletedMu.Unlock()
				deleted = append(deleted, fwallpartial)
			}()
		}

		for _, sn := range subnetworks {
			if sn.Network != n.SelfLink {
				continue
			}
			// If this network is setup with auto subnetworks we need to ignore any subnetworks that are in 10.128.0.0/9.
			// https://cloud.google.com/vpc/docs/vpc#ip-ranges
			if n.AutoCreateSubnetworks == true {
				i, err := strconv.Atoi(strings.Split(sn.IpCidrRange, ".")[1])
				if err != nil {
					fmt.Printf("Error parsing network range %q: %v\n", sn.IpCidrRange, err)
				}
				if i >= 128 {
					continue
				}
			}
			// Don't delete network yet - wait until resources associated with it are
			// deleted to avoid resource in use issues.

			region := path.Base(sn.Region)
			regionFRs, ok := regionalForwardingRules[region]
			if !ok {
				var err error
				regionFRs, err = clients.Daisy.ListForwardingRules(project, region)
				if err != nil {
					errsMu.Lock()
					errs = append(errs, err)
					errsMu.Unlock()
				} else {
					regionalForwardingRules[region] = regionFRs
				}
			}

			// Delete all forwarding rules in the same region as the subnetwork.
			for _, fr := range regionFRs {
				if fr.Network != n.SelfLink {
					continue
				}
				frpartial := fmt.Sprintf("projects/%s/regions/%s/forwardingRules/%s", project, region, fr.Name)
				wg.Add(1)
				go func(frName string) {
					defer wg.Done()
					if !dryRun {
						if err := clients.Daisy.DeleteForwardingRule(project, region, frName); err != nil {
							errsMu.Lock()
							defer errsMu.Unlock()
							errs = append(errs, err)
							return
						}
					}
					deletedMu.Lock()
					defer deletedMu.Unlock()
					deleted = append(deleted, frpartial)
				}(fr.Name)
			}

			regionBSs, ok := regionalBackendServices[region]
			if !ok {
				var err error
				regionBSs, err = clients.Daisy.ListRegionBackendServices(project, region)
				if err != nil {
					errsMu.Lock()
					errs = append(errs, err)
					errsMu.Unlock()
				} else {
					regionalBackendServices[region] = regionBSs
				}
			}
			// Delete all backend services in the same region as the subnetwork.
			for _, bs := range regionBSs {
				if bs.Network != n.SelfLink {
					continue
				}
				bspartial := fmt.Sprintf("projects/%s/regions/%s/backendServices/%s", project, region, bs.Name)
				regionUMs, ok := regionalURLMaps[region]
				if !ok {
					var err error
					regionUMs, err = clients.Daisy.ListRegionURLMaps(project, region)
					if err != nil {
						errsMu.Lock()
						errs = append(errs, err)
						errsMu.Unlock()
					} else {
						regionalURLMaps[region] = regionUMs
					}
				}
				// Delete all url maps in the same region as the subnetwork.
				for _, um := range regionUMs {
					if um.DefaultService != bs.SelfLink {
						continue
					}
					umpartial := fmt.Sprintf("projects/%s/regions/%s/urlMaps/%s", project, region, um.Name)
					regionHPs, ok := regionalHTTPProxies[region]
					if !ok {
						var err error
						regionHPs, err = clients.Daisy.ListRegionTargetHTTPProxies(project, region)
						if err != nil {
							errsMu.Lock()
							errs = append(errs, err)
							errsMu.Unlock()
						} else {
							regionalHTTPProxies[region] = regionHPs
						}
					}
					// Delete all target http proxies in the same region as the subnetwork.
					for _, hp := range regionHPs {
						if hp.UrlMap != um.SelfLink {
							continue
						}
						hppartial := fmt.Sprintf("projects/%s/regions/%s/targetHttpProxies/%s", project, region, hp.Name)
						wg.Add(1)
						go func(hpName string) {
							defer wg.Done()
							if !dryRun {
								if err := clients.Daisy.DeleteRegionTargetHTTPProxy(project, region, hpName); err != nil {
									errsMu.Lock()
									defer errsMu.Unlock()
									errs = append(errs, err)
									return
								}
							}
							deletedMu.Lock()
							defer deletedMu.Unlock()
							deleted = append(deleted, hppartial)
						}(path.Base(hp.Name))
					}
					wg.Wait()
					// Wait for target http proxy deletion before URL map deletion to avoid resource
					// in use issues.
					wg.Add(1)
					go func(unName string) {
						defer wg.Done()
						if !dryRun {
							if err := clients.Daisy.DeleteRegionURLMap(project, region, unName); err != nil {
								errsMu.Lock()
								defer errsMu.Unlock()
								errs = append(errs, err)
								return
							}
						}
						deletedMu.Lock()
						defer deletedMu.Unlock()
						deleted = append(deleted, umpartial)
					}(path.Base(um.Name))
				}
				// Wait for URL Map deletion before backend service deletion to avoid resource
				// in use issues.
				wg.Wait()
				wg.Add(1)
				go func(bsName string) {
					defer wg.Done()
					if !dryRun {
						if err := clients.Daisy.DeleteRegionBackendService(project, region, bsName); err != nil {
							errsMu.Lock()
							defer errsMu.Unlock()
							errs = append(errs, err)
							return
						}
					}
					deletedMu.Lock()
					defer deletedMu.Unlock()
					deleted = append(deleted, bspartial)
				}(bs.Name)
				wg.Wait()
				// Delete all health checks in the same region as the subnetwork.
				for _, hc := range bs.HealthChecks {
					hcpartial := fmt.Sprintf("projects/%s/regions/%s/healthChecks/%s", project, region, path.Base(hc))
					wg.Add(1)
					go func(hcName string) {
						defer wg.Done()
						if !dryRun {
							if err := clients.Daisy.DeleteRegionHealthCheck(project, region, hcName); err != nil {
								errsMu.Lock()
								defer errsMu.Unlock()
								errs = append(errs, err)
								return
							}
						}
						deletedMu.Lock()
						defer deletedMu.Unlock()
						deleted = append(deleted, hcpartial)
					}(path.Base(hc))
				}
			}
			wg.Wait()

			regionalNEGs, ok := regionalNetworkEndpointGroups[region]
			if !ok {
				var err error
				regionalNEGs, err = clients.Daisy.ListRegionNetworkEndpointGroups(project, region)
				if err != nil {
					errsMu.Lock()
					errs = append(errs, err)
					errsMu.Unlock()
				} else {
					regionalNetworkEndpointGroups[region] = regionalNEGs
				}
			}
			for _, neg := range regionalNEGs {
				// Delete all NEGs in the same region as the subnetwork.
				if neg.Network != n.SelfLink {
					continue
				}
				negpartial := fmt.Sprintf("projects/%s/regions/%s/networkEndpointGroups/%s", project, region, neg.Name)
				wg.Add(1)
				go func(negName string) {
					defer wg.Done()
					if !dryRun {
						if err := clients.Daisy.DeleteRegionNetworkEndpointGroup(project, region, negName); err != nil {
							errsMu.Lock()
							defer errsMu.Unlock()
							errs = append(errs, err)
							return
						}
					}
					deletedMu.Lock()
					defer deletedMu.Unlock()
					deleted = append(deleted, negpartial)
				}(neg.Name)
			}
			// Wait for NEG deletion before subnetwork deletion to avoid resource in use
			// issues.
			wg.Wait()

			subnetpartial := fmt.Sprintf("projects/%s/regions/%s/subnetworks/%s", project, region, sn.Name)
			wg.Wait()
			wg.Add(1)
			go func(snName string) {
				defer wg.Done()
				if !dryRun {
					if err := clients.Daisy.DeleteSubnetwork(project, region, snName); err != nil {
						errsMu.Lock()
						defer errsMu.Unlock()
						errs = append(errs, err)
						return
					}
				}
				deletedMu.Lock()
				defer deletedMu.Unlock()
				deleted = append(deleted, subnetpartial)
			}(sn.Name)
		}
		// Wait for subnetwork deletion before network deletion to avoid resource
		// in use issues.
		wg.Wait()
		wg.Add(1)
		go func() {
			defer wg.Done()
			if !dryRun {
				if err := clients.Daisy.DeleteNetwork(project, name); err != nil {
					errsMu.Lock()
					defer errsMu.Unlock()
					errs = append(errs, err)
					return
				}
			}
			deletedMu.Lock()
			defer deletedMu.Unlock()
			deleted = append(deleted, netpartial)
		}()
	}
	wg.Wait()
	return deleted, errs
}