@@ -9,21 +9,24 @@ import (
99 awsv2 "github.com/aws/aws-sdk-go-v2/aws"
1010 "github.com/aws/aws-sdk-go-v2/aws/arn"
1111 configv2 "github.com/aws/aws-sdk-go-v2/config"
12+ "github.com/aws/aws-sdk-go-v2/credentials/stscreds"
1213 ec2v2 "github.com/aws/aws-sdk-go-v2/service/ec2"
1314 "github.com/aws/aws-sdk-go-v2/service/efs"
1415 elb "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing"
1516 elbv2 "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2"
1617 iamv2 "github.com/aws/aws-sdk-go-v2/service/iam"
18+ "github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi"
19+ tagtypes "github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi/types"
1720 "github.com/aws/aws-sdk-go-v2/service/route53"
1821 route53types "github.com/aws/aws-sdk-go-v2/service/route53/types"
1922 "github.com/aws/aws-sdk-go-v2/service/s3"
2023 s3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
24+ "github.com/aws/aws-sdk-go-v2/service/sts"
2125 "github.com/aws/aws-sdk-go/aws"
2226 "github.com/aws/aws-sdk-go/aws/awserr"
2327 "github.com/aws/aws-sdk-go/aws/endpoints"
2428 "github.com/aws/aws-sdk-go/aws/request"
2529 "github.com/aws/aws-sdk-go/aws/session"
26- "github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
2730 "github.com/aws/aws-sdk-go/service/s3/s3manager"
2831 "github.com/pkg/errors"
2932 "github.com/sirupsen/logrus"
@@ -34,6 +37,7 @@ import (
3437 awssession "github.com/openshift/installer/pkg/asset/installconfig/aws"
3538 "github.com/openshift/installer/pkg/destroy/providers"
3639 "github.com/openshift/installer/pkg/types"
40+ awstypes "github.com/openshift/installer/pkg/types/aws"
3741 "github.com/openshift/installer/pkg/version"
3842)
3943
@@ -67,6 +71,7 @@ type ClusterUninstaller struct {
6771 ClusterID string
6872 ClusterDomain string
6973 HostedZoneRole string
74+ endpoints []awstypes.ServiceEndpoint
7075
7176 // Session is the AWS session to be used for deletion. If nil, a
7277 // new session will be created based on the usual credential
@@ -175,6 +180,7 @@ func New(logger logrus.FieldLogger, metadata *types.ClusterMetadata) (providers.
175180 ClusterDomain : metadata .AWS .ClusterDomain ,
176181 Session : session ,
177182 HostedZoneRole : metadata .AWS .HostedZoneRole ,
183+ endpoints : metadata .AWS .ServiceEndpoints ,
178184 EC2Client : ec2Client ,
179185 IAMClient : iamClient ,
180186 ELBClient : elbclient ,
@@ -198,6 +204,25 @@ func (o *ClusterUninstaller) Run() (*types.ClusterQuota, error) {
198204 return nil , err
199205}
200206
207+ func createResourceTaggingClientWithConfig (cfg awsv2.Config , region string , endpoints []awstypes.ServiceEndpoint ) * resourcegroupstaggingapi.Client {
208+ return resourcegroupstaggingapi .NewFromConfig (cfg , func (options * resourcegroupstaggingapi.Options ) {
209+ options .Region = region
210+ for _ , endpoint := range endpoints {
211+ if strings .EqualFold (endpoint .Name , "resourcegroupstaggingapi" ) {
212+ options .BaseEndpoint = awsv2 .String (endpoint .URL )
213+ }
214+ }
215+ })
216+ }
217+
218+ func createResourceTaggingClient (region string , endpoints []awstypes.ServiceEndpoint ) (* resourcegroupstaggingapi.Client , error ) {
219+ cfg , err := awssession .GetConfigWithOptions (context .Background (), configv2 .WithRegion (region ))
220+ if err != nil {
221+ return nil , fmt .Errorf ("failed to create AWS config for resource tagging client: %w" , err )
222+ }
223+ return createResourceTaggingClientWithConfig (cfg , region , endpoints ), nil
224+ }
225+
201226// RunWithContext runs the uninstall process with a context.
202227// The first return is the list of ARNs for resources that could not be destroyed.
203228func (o * ClusterUninstaller ) RunWithContext (ctx context.Context ) ([]string , error ) {
@@ -219,16 +244,31 @@ func (o *ClusterUninstaller) RunWithContext(ctx context.Context) ([]string, erro
219244 Fn : request .MakeAddToUserAgentHandler ("OpenShift/4.x Destroyer" , version .Raw ),
220245 })
221246
222- tagClients := []* resourcegroupstaggingapi.ResourceGroupsTaggingAPI {
223- resourcegroupstaggingapi .New (awsSession ),
247+ baseTaggingClient , err := createResourceTaggingClient (o .Region , o .endpoints )
248+ if err != nil {
249+ return nil , err
224250 }
251+ tagClients := []* resourcegroupstaggingapi.Client {baseTaggingClient }
225252
226253 if o .HostedZoneRole != "" {
227- cfg := awssession .GetR53ClientCfg (awsSession , o .HostedZoneRole )
254+ cfg , err := awssession .GetConfigWithOptions (ctx , configv2 .WithRegion (endpointUSEast1 ))
255+ if err != nil {
256+ return nil , fmt .Errorf ("failed to create AWS config for resource tagging client: %w" , err )
257+ }
258+ stsSvc , err := awssession .NewSTSClient (ctx , awssession.EndpointOptions {
259+ Region : endpointUSEast1 ,
260+ Endpoints : o .endpoints ,
261+ }, sts .WithAPIOptions (middleware .AddUserAgentKeyValue ("OpenShift/4.x Destroyer" , version .Raw )))
262+ if err != nil {
263+ return nil , fmt .Errorf ("failed to create STS client: %w" , err )
264+ }
265+
266+ creds := stscreds .NewAssumeRoleProvider (stsSvc , o .HostedZoneRole )
267+ cfg .Credentials = awsv2 .NewCredentialsCache (creds )
228268 // This client is specifically for finding route53 zones,
229269 // so it needs to use the global us-east-1 region.
230- cfg . Region = aws . String ( endpoints . UsEast1RegionID )
231- tagClients = append (tagClients , resourcegroupstaggingapi . New ( awsSession , cfg ))
270+
271+ tagClients = append (tagClients , createResourceTaggingClientWithConfig ( cfg , endpointUSEast1 , o . endpoints ))
232272 }
233273
234274 switch o .Region {
@@ -238,13 +278,19 @@ func (o *ClusterUninstaller) RunWithContext(ctx context.Context) ([]string, erro
238278 break
239279 case endpoints .UsGovEast1RegionID , endpoints .UsGovWest1RegionID :
240280 if o .Region != endpoints .UsGovWest1RegionID {
241- tagClients = append (tagClients ,
242- resourcegroupstaggingapi .New (awsSession , aws .NewConfig ().WithRegion (endpoints .UsGovWest1RegionID )))
281+ tagClient , err := createResourceTaggingClient (endpoints .UsGovWest1RegionID , o .endpoints )
282+ if err != nil {
283+ return nil , fmt .Errorf ("failed to create resource tagging client for usgov-west-1: %w" , err )
284+ }
285+ tagClients = append (tagClients , tagClient )
243286 }
244287 default :
245288 if o .Region != endpoints .UsEast1RegionID {
246- tagClients = append (tagClients ,
247- resourcegroupstaggingapi .New (awsSession , aws .NewConfig ().WithRegion (endpoints .UsEast1RegionID )))
289+ tagClient , err := createResourceTaggingClientWithConfig (endpoints .UsEast1RegionID , o .endpoints )
290+ if err != nil {
291+ return nil , fmt .Errorf ("failed to create resource tagging client for default us-east-1: %w" , err )
292+ }
293+ tagClients = append (tagClients , tagClient )
248294 }
249295 }
250296
@@ -275,7 +321,7 @@ func (o *ClusterUninstaller) RunWithContext(ctx context.Context) ([]string, erro
275321 // Terminate EC2 instances. The instances need to be terminated first so that we can ensure that there is nothing
276322 // running on the cluster creating new resources while we are attempting to delete resources, which could leak
277323 // the new resources.
278- err = o .DeleteEC2Instances (ctx , awsSession , resourcesToDelete , deleted , tracker )
324+ err = o .DeleteEC2Instances (ctx , resourcesToDelete , deleted , tracker )
279325 if err != nil {
280326 return resourcesToDelete .UnsortedList (), err
281327 }
@@ -284,7 +330,7 @@ func (o *ClusterUninstaller) RunWithContext(ctx context.Context) ([]string, erro
284330 err = wait .PollImmediateUntil (
285331 time .Second * 10 ,
286332 func () (done bool , err error ) {
287- newlyDeleted , loopError := o .DeleteResources (ctx , awsSession , resourcesToDelete .UnsortedList (), tracker )
333+ newlyDeleted , loopError := o .DeleteResources (ctx , resourcesToDelete .UnsortedList (), tracker )
288334 // Delete from the resources-to-delete set so that the current state of the resources to delete can be
289335 // returned if the context is completed.
290336 resourcesToDelete = resourcesToDelete .Difference (newlyDeleted )
@@ -314,7 +360,7 @@ func (o *ClusterUninstaller) RunWithContext(ctx context.Context) ([]string, erro
314360 return resourcesToDelete .UnsortedList (), err
315361 }
316362
317- err = o .removeSharedTags (ctx , awsSession , tagClients , tracker )
363+ err = o .removeSharedTags (ctx , tagClients , tracker )
318364 if err != nil {
319365 return nil , err
320366 }
@@ -333,7 +379,7 @@ func (o *ClusterUninstaller) findUntaggableResources(ctx context.Context, delete
333379 profile := fmt .Sprintf ("%s-%s-profile" , o .ClusterID , profileType )
334380 response , err := o .IAMClient .GetInstanceProfile (ctx , & iamv2.GetInstanceProfileInput {InstanceProfileName : & profile })
335381 if err != nil {
336- if strings .Contains (HandleErrorCode (err ), "NoSuchEntity" ) {
382+ if strings .Contains (handleErrorCode (err ), "NoSuchEntity" ) {
337383 continue
338384 }
339385 return resources , fmt .Errorf ("failed to get IAM instance profile: %w" , err )
@@ -352,11 +398,11 @@ func (o *ClusterUninstaller) findUntaggableResources(ctx context.Context, delete
352398// deleted - the resources that have already been deleted. Any resources specified in this set will be ignored.
353399func (o * ClusterUninstaller ) findResourcesToDelete (
354400 ctx context.Context ,
355- tagClients []* resourcegroupstaggingapi.ResourceGroupsTaggingAPI ,
401+ tagClients []* resourcegroupstaggingapi.Client ,
356402 iamRoleSearch * IamRoleSearch ,
357403 iamUserSearch * IamUserSearch ,
358404 deleted sets.Set [string ],
359- ) (sets.Set [string ], []* resourcegroupstaggingapi.ResourceGroupsTaggingAPI , error ) {
405+ ) (sets.Set [string ], []* resourcegroupstaggingapi.Client , error ) {
360406 var errs []error
361407 resources , tagClients , err := FindTaggedResourcesToDelete (ctx , o .Logger , tagClients , o .Filters , iamRoleSearch , iamUserSearch , deleted )
362408 if err != nil {
@@ -380,14 +426,14 @@ func (o *ClusterUninstaller) findResourcesToDelete(
380426func FindTaggedResourcesToDelete (
381427 ctx context.Context ,
382428 logger logrus.FieldLogger ,
383- tagClients []* resourcegroupstaggingapi.ResourceGroupsTaggingAPI ,
429+ tagClients []* resourcegroupstaggingapi.Client ,
384430 filters []Filter ,
385431 iamRoleSearch * IamRoleSearch ,
386432 iamUserSearch * IamUserSearch ,
387433 deleted sets.Set [string ],
388- ) (sets.Set [string ], []* resourcegroupstaggingapi.ResourceGroupsTaggingAPI , error ) {
434+ ) (sets.Set [string ], []* resourcegroupstaggingapi.Client , error ) {
389435 resources := sets .New [string ]()
390- var tagClientsWithResources []* resourcegroupstaggingapi.ResourceGroupsTaggingAPI
436+ var tagClientsWithResources []* resourcegroupstaggingapi.Client
391437 var errs []error
392438
393439 // Find resources by tag
@@ -402,7 +448,7 @@ func FindTaggedResourcesToDelete(
402448 if len (resourcesInTagClient ) > 0 || err != nil {
403449 tagClientsWithResources = append (tagClientsWithResources , tagClient )
404450 } else {
405- logger .Debugf ("no deletions from %s, removing client" , * tagClient .Config .Region )
451+ logger .Debugf ("no deletions from %s, removing client" , tagClient .Options () .Region )
406452 }
407453 }
408454
@@ -434,39 +480,37 @@ func FindTaggedResourcesToDelete(
434480func findResourcesByTag (
435481 ctx context.Context ,
436482 logger logrus.FieldLogger ,
437- tagClient * resourcegroupstaggingapi.ResourceGroupsTaggingAPI ,
483+ tagClient * resourcegroupstaggingapi.Client ,
438484 filters []Filter ,
439485 deleted sets.Set [string ],
440486) (sets.Set [string ], error ) {
441487 resources := sets .New [string ]()
442488 for _ , filter := range filters {
443- logger .Debugf ("search for matching resources by tag in %s matching %#+v" , * tagClient .Config .Region , filter )
444- tagFilters := make ([]* resourcegroupstaggingapi .TagFilter , 0 , len (filter ))
489+ logger .Debugf ("search for matching resources by tag in %s matching %#+v" , tagClient .Options () .Region , filter )
490+ tagFilters := make ([]tagtypes .TagFilter , 0 , len (filter ))
445491 for key , value := range filter {
446- tagFilters = append (tagFilters , & resourcegroupstaggingapi .TagFilter {
492+ tagFilters = append (tagFilters , tagtypes .TagFilter {
447493 Key : aws .String (key ),
448- Values : []* string {aws . String ( value ) },
494+ Values : []string {value },
449495 })
450496 }
451- err := tagClient .GetResourcesPagesWithContext (
452- ctx ,
453- & resourcegroupstaggingapi.GetResourcesInput {TagFilters : tagFilters },
454- func (results * resourcegroupstaggingapi.GetResourcesOutput , lastPage bool ) bool {
455- for _ , resource := range results .ResourceTagMappingList {
456- arnString := * resource .ResourceARN
457- if ! deleted .Has (arnString ) {
458- resources .Insert (arnString )
459- }
497+
498+ paginator := resourcegroupstaggingapi .NewGetResourcesPaginator (tagClient , & resourcegroupstaggingapi.GetResourcesInput {TagFilters : tagFilters })
499+ for paginator .HasMorePages () {
500+ page , err := paginator .NextPage (ctx )
501+ if err != nil {
502+ return resources , fmt .Errorf ("failed to fetch resources by tag: %w" , err )
503+ }
504+
505+ for _ , resource := range page .ResourceTagMappingList {
506+ arnString := * resource .ResourceARN
507+ if ! deleted .Has (arnString ) {
508+ resources .Insert (arnString )
460509 }
461- return ! lastPage
462- },
463- )
464- if err != nil {
465- err = errors .Wrap (err , "get tagged resources" )
466- logger .Info (err )
467- return resources , err
510+ }
468511 }
469512 }
513+
470514 return resources , nil
471515}
472516
@@ -475,7 +519,7 @@ func findResourcesByTag(
475519// resources - the resources to be deleted.
476520//
477521// The first return is the ARNs of the resources that were successfully deleted.
478- func (o * ClusterUninstaller ) DeleteResources (ctx context.Context , awsSession * session. Session , resources []string , tracker * ErrorTracker ) (sets.Set [string ], error ) {
522+ func (o * ClusterUninstaller ) DeleteResources (ctx context.Context , resources []string , tracker * ErrorTracker ) (sets.Set [string ], error ) {
479523 deleted := sets .New [string ]()
480524 for _ , arnString := range resources {
481525 l := o .Logger .WithField ("arn" , arnString )
@@ -638,7 +682,7 @@ func deleteRoute53(ctx context.Context, client *route53.Client, arn arn.ARN, log
638682 if err != nil {
639683 // In some cases AWS may return the zone in the list of tagged resources despite the fact
640684 // it no longer exists.
641- if strings .Contains (HandleErrorCode (err ), "NoSuchHostedZone" ) {
685+ if strings .Contains (handleErrorCode (err ), "NoSuchHostedZone" ) {
642686 return nil
643687 }
644688 return err
@@ -850,7 +894,7 @@ func deleteFileSystem(ctx context.Context, client *efs.Client, fsid string, logg
850894
851895 _ , err = client .DeleteFileSystem (ctx , & efs.DeleteFileSystemInput {FileSystemId : aws .String (fsid )})
852896 if err != nil {
853- if strings .Contains (HandleErrorCode (err ), "FileSystemNotFound" ) {
897+ if strings .Contains (handleErrorCode (err ), "FileSystemNotFound" ) {
854898 return nil
855899 }
856900 return err
@@ -909,7 +953,7 @@ func deleteAccessPoint(ctx context.Context, client *efs.Client, id string, logge
909953 logger = logger .WithField ("AccessPoint ID" , id )
910954 _ , err := client .DeleteAccessPoint (ctx , & efs.DeleteAccessPointInput {AccessPointId : aws .String (id )})
911955 if err != nil {
912- if strings .Contains (HandleErrorCode (err ), "AccessPointNotFound" ) {
956+ if strings .Contains (handleErrorCode (err ), "AccessPointNotFound" ) {
913957 return nil
914958 }
915959 return err
@@ -923,7 +967,7 @@ func deleteMountTarget(ctx context.Context, client *efs.Client, id string, logge
923967 logger = logger .WithField ("Mount Target ID" , id )
924968 _ , err := client .DeleteMountTarget (ctx , & efs.DeleteMountTargetInput {MountTargetId : aws .String (id )})
925969 if err != nil {
926- if strings .Contains (HandleErrorCode (err ), "MountTargetNotFound" ) {
970+ if strings .Contains (handleErrorCode (err ), "MountTargetNotFound" ) {
927971 return nil
928972 }
929973 return err
0 commit comments