@@ -2,76 +2,107 @@ package gcp
22
33import (
44 "context"
5+ "fmt"
56
6- "github.com/pkg/errors "
7+ "github.com/sirupsen/logrus "
78 "google.golang.org/api/compute/v1"
89 "google.golang.org/api/googleapi"
910
1011 "github.com/openshift/installer/pkg/types/gcp"
1112)
1213
13- func (o * ClusterUninstaller ) listAddresses (ctx context.Context ) ([]cloudResource , error ) {
14- return o .listAddressesWithFilter (ctx , "items(name,region,addressType),nextPageToken" , o .clusterIDFilter (), nil )
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
1547}
1648
1749// listAddressesWithFilter lists addresses in the project that satisfy the filter criteria.
1850// The fields parameter specifies which fields should be returned in the result, the filter string contains
1951// a filter string passed to the API to filter results. The filterFunc is a client-side filtering function
2052// that determines whether a particular result should be returned or not.
21- func (o * ClusterUninstaller ) listAddressesWithFilter (ctx context.Context , fields string , filter string , filterFunc func (* compute.Address ) bool ) ([]cloudResource , error ) {
22- o .Logger .Debugf ("Listing addresses" )
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 )
2355 ctx , cancel := context .WithTimeout (ctx , defaultTimeout )
2456 defer cancel ()
2557 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
2675 req := o .computeSvc .Addresses .List (o .ProjectID , o .Region ).Fields (googleapi .Field (fields ))
2776 if len (filter ) > 0 {
2877 req = req .Filter (filter )
2978 }
3079 err := req .Pages (ctx , func (list * compute.AddressList ) error {
31- for _ , item := range list .Items {
32- if filterFunc == nil || filterFunc != nil && filterFunc (item ) {
33- o .Logger .Debugf ("Found address: %s" , item .Name )
34- var quota []gcp.QuotaUsage
35- if item .AddressType == "INTERNAL" {
36- quota = []gcp.QuotaUsage {{
37- Metric : & gcp.Metric {
38- Service : gcp .ServiceComputeEngineAPI ,
39- Limit : "internal_addresses" ,
40- Dimensions : map [string ]string {
41- "region" : getNameFromURL ("regions" , item .Region ),
42- },
43- },
44- Amount : 1 ,
45- }}
46- }
47- result = append (result , cloudResource {
48- key : item .Name ,
49- name : item .Name ,
50- typeName : "address" ,
51- quota : quota ,
52- })
53- }
54- }
80+ result = append (result , createAddressCloudResources (filterFunc , list )... )
5581 return nil
5682 })
5783 if err != nil {
58- return nil , errors . Wrapf ( err , "failed to list addresses" )
84+ return nil , fmt . Errorf ( "failed to list regional addresses: %w" , err )
5985 }
86+
6087 return result , nil
6188}
6289
63- func (o * ClusterUninstaller ) deleteAddress (ctx context.Context , item cloudResource ) error {
90+ func (o * ClusterUninstaller ) deleteAddress (ctx context.Context , item cloudResource , scope resourceScope ) error {
6491 o .Logger .Debugf ("Deleting address %s" , item .name )
6592 ctx , cancel := context .WithTimeout (ctx , defaultTimeout )
6693 defer cancel ()
67- op , err := o .computeSvc .Addresses .Delete (o .ProjectID , o .Region , item .name ).RequestId (o .requestID (item .typeName , item .name )).Context (ctx ).Do ()
68- if err != nil && ! isNoOp (err ) {
69- o .resetRequestID (item .typeName , item .name )
70- return errors .Wrapf (err , "failed to delete address %s" , item .name )
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 ()
71101 }
102+
72103 if op != nil && op .Status == "DONE" && isErrorStatus (op .HttpErrorStatusCode ) {
73104 o .resetRequestID (item .typeName , item .name )
74- return errors .Errorf ("failed to delete address %s with error: %s" , item .name , operationErrorMessage (op ))
105+ return fmt .Errorf ("failed to delete address %s with error: %s: %w " , item .name , operationErrorMessage (op ), err )
75106 }
76107 if (err != nil && isNoOp (err )) || (op != nil && op .Status == "DONE" ) {
77108 o .resetRequestID (item .typeName , item .name )
@@ -84,19 +115,23 @@ func (o *ClusterUninstaller) deleteAddress(ctx context.Context, item cloudResour
84115// destroyAddresses removes all address resources that have a name prefixed
85116// with the cluster's infra ID.
86117func (o * ClusterUninstaller ) destroyAddresses (ctx context.Context ) error {
87- found , err := o .listAddresses (ctx )
88- if err != nil {
89- return err
90- }
91- items := o .insertPendingItems ("address" , found )
92- for _ , item := range items {
93- err := o .deleteAddress (ctx , item )
118+ for _ , scope := range []resourceScope {gcpGlobalResource , gcpRegionalResource } {
119+ found , err := o .listAddresses (ctx , scope )
94120 if err != nil {
95- o .errorTracker .suppressWarning (item .key , err , o .Logger )
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+ }
96134 }
97- }
98- if items = o .getPendingItems ("address" ); len (items ) > 0 {
99- return errors .Errorf ("%d items pending" , len (items ))
100135 }
101136 return nil
102137}
0 commit comments