github.com/openshift/installer@v1.4.17/pkg/destroy/gcp/address.go (about) 1 package gcp 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/sirupsen/logrus" 8 "google.golang.org/api/compute/v1" 9 "google.golang.org/api/googleapi" 10 11 "github.com/openshift/installer/pkg/types/gcp" 12 ) 13 14 func (o *ClusterUninstaller) listAddresses(ctx context.Context, scope resourceScope) ([]cloudResource, error) { 15 return o.listAddressesWithFilter(ctx, "items(name,region,addressType),nextPageToken", o.clusterIDFilter(), nil, scope) 16 } 17 18 func createAddressCloudResources(filterFunc func(address *compute.Address) bool, list *compute.AddressList) []cloudResource { 19 result := []cloudResource{} 20 21 for _, item := range list.Items { 22 if filterFunc == nil || filterFunc(item) { 23 logrus.Debugf("Found address: %s", item.Name) 24 var quota []gcp.QuotaUsage 25 if item.AddressType == "INTERNAL" { 26 quota = []gcp.QuotaUsage{{ 27 Metric: &gcp.Metric{ 28 Service: gcp.ServiceComputeEngineAPI, 29 Limit: "internal_addresses", 30 Dimensions: map[string]string{ 31 "region": getNameFromURL("regions", item.Region), 32 }, 33 }, 34 Amount: 1, 35 }} 36 } 37 result = append(result, cloudResource{ 38 key: item.Name, 39 name: item.Name, 40 typeName: "address", 41 quota: quota, 42 }) 43 } 44 } 45 46 return result 47 } 48 49 // listAddressesWithFilter lists addresses in the project that satisfy the filter criteria. 50 // The fields parameter specifies which fields should be returned in the result, the filter string contains 51 // a filter string passed to the API to filter results. The filterFunc is a client-side filtering function 52 // that determines whether a particular result should be returned or not. 53 func (o *ClusterUninstaller) listAddressesWithFilter(ctx context.Context, fields string, filter string, filterFunc func(*compute.Address) bool, scope resourceScope) ([]cloudResource, error) { 54 o.Logger.Debugf("Listing %s addresses", scope) 55 ctx, cancel := context.WithTimeout(ctx, defaultTimeout) 56 defer cancel() 57 result := []cloudResource{} 58 59 if scope == gcpGlobalResource { 60 req := o.computeSvc.GlobalAddresses.List(o.ProjectID).Fields(googleapi.Field(fields)) 61 if len(filter) > 0 { 62 req = req.Filter(filter) 63 } 64 err := req.Pages(ctx, func(list *compute.AddressList) error { 65 result = append(result, createAddressCloudResources(filterFunc, list)...) 66 return nil 67 }) 68 if err != nil { 69 return nil, fmt.Errorf("failed to list global addresses: %w", err) 70 } 71 return result, nil 72 } 73 74 // Regional addresses 75 req := o.computeSvc.Addresses.List(o.ProjectID, o.Region).Fields(googleapi.Field(fields)) 76 if len(filter) > 0 { 77 req = req.Filter(filter) 78 } 79 err := req.Pages(ctx, func(list *compute.AddressList) error { 80 result = append(result, createAddressCloudResources(filterFunc, list)...) 81 return nil 82 }) 83 if err != nil { 84 return nil, fmt.Errorf("failed to list regional addresses: %w", err) 85 } 86 87 return result, nil 88 } 89 90 func (o *ClusterUninstaller) deleteAddress(ctx context.Context, item cloudResource, scope resourceScope) error { 91 o.Logger.Debugf("Deleting address %s", item.name) 92 ctx, cancel := context.WithTimeout(ctx, defaultTimeout) 93 defer cancel() 94 95 var op *compute.Operation 96 var err error 97 if scope == gcpGlobalResource { 98 op, err = o.computeSvc.GlobalAddresses.Delete(o.ProjectID, item.name).RequestId(o.requestID(item.typeName, item.name)).Context(ctx).Do() 99 } else { 100 op, err = o.computeSvc.Addresses.Delete(o.ProjectID, o.Region, item.name).RequestId(o.requestID(item.typeName, item.name)).Context(ctx).Do() 101 } 102 103 if op != nil && op.Status == "DONE" && isErrorStatus(op.HttpErrorStatusCode) { 104 o.resetRequestID(item.typeName, item.name) 105 return fmt.Errorf("failed to delete address %s with error: %s: %w", item.name, operationErrorMessage(op), err) 106 } 107 if (err != nil && isNoOp(err)) || (op != nil && op.Status == "DONE") { 108 o.resetRequestID(item.typeName, item.name) 109 o.deletePendingItems(item.typeName, []cloudResource{item}) 110 o.Logger.Infof("Deleted address %s", item.name) 111 } 112 return nil 113 } 114 115 // destroyAddresses removes all address resources that have a name prefixed 116 // with the cluster's infra ID. 117 func (o *ClusterUninstaller) destroyAddresses(ctx context.Context) error { 118 for _, scope := range []resourceScope{gcpGlobalResource, gcpRegionalResource} { 119 found, err := o.listAddresses(ctx, scope) 120 if err != nil { 121 return fmt.Errorf("failed to list %s addresses: %w", scope, err) 122 } 123 items := o.insertPendingItems("address", found) 124 for _, item := range items { 125 err := o.deleteAddress(ctx, item, scope) 126 if err != nil { 127 o.errorTracker.suppressWarning(item.key, err, o.Logger) 128 } 129 } 130 for _, item := range o.getPendingItems("address") { 131 if err := o.deleteAddress(ctx, item, scope); err != nil { 132 return fmt.Errorf("error deleting pending address %s: %w", item.name, err) 133 } 134 } 135 } 136 return nil 137 }