1+ import boto3
12import re
23import requests
34import time
45
56from constants import API_TOKEN
67from constants import API_URL
78from constants import LOCKS_PATH
9+ from constants import OBJECTS_URL
810from constants import PROCESS_ID
911from constants import RUNNER_ID
1012from errors import Timeout
1113from events import trigger
1214from filelock import FileLock
1315from requests .adapters import HTTPAdapter
1416from requests .packages .urllib3 .util .retry import Retry
17+ from resources import ObjectsUser
1518from urllib .parse import urlparse
1619
1720
@@ -81,11 +84,13 @@ def __init__(self, scope, zone=None, read_only=False):
8184 agent_suffix = ''
8285
8386 self .api_url = API_URL
87+ self .objects_url = OBJECTS_URL
8488 self .headers ['Authorization' ] = f'Bearer { API_TOKEN } '
8589 self .headers ['User-Agent' ] = f'Acceptance Tests{ agent_suffix } '
8690 self .hooks = {'response' : self .on_response }
8791 self .scope = scope
8892 self .read_only = read_only
93+ self .zone = zone
8994
9095 # 8 Retries @ 2.5 backoff_factor = 10.6 minutes
9196 retry_strategy = RetryStrategy (
@@ -99,6 +104,10 @@ def __init__(self, scope, zone=None, read_only=False):
99104
100105 self .mount ("https://" , adapter )
101106
107+ # This is None, when running "invoke cleanup"
108+ if self .zone :
109+ self .objects_endpoint = self .objects_endpoint_for (self .zone )
110+
102111 def post (self , url , data = None , json = None , add_tags = True , ** kwargs ):
103112 assert not data , "Please only use json, not data"
104113
@@ -107,6 +116,7 @@ def post(self, url, data=None, json=None, add_tags=True, **kwargs):
107116 'runner' : RUNNER_ID ,
108117 'process' : PROCESS_ID ,
109118 'scope' : self .scope ,
119+ 'zone' : self .zone ,
110120 }
111121
112122 return super ().post (url , data = data , json = json , ** kwargs )
@@ -156,6 +166,7 @@ def resources(path):
156166 yield from resources ('/networks' )
157167 yield from resources ('/server-groups' )
158168 yield from resources ('/custom-images' )
169+ yield from resources ('/objects-users' )
159170
160171 def cleanup (self , limit_to_scope = True , limit_to_process = True ):
161172 """ Deletes resources created by this API object. """
@@ -179,6 +190,9 @@ def cleanup(self, limit_to_scope=True, limit_to_process=True):
179190 if exceptions :
180191 raise ExceptionGroup ("Failures during cleanup." , exceptions )
181192
193+ def objects_endpoint_for (self , zone ):
194+ return self .objects_url .format (region = zone .rstrip ('0123456789' ))
195+
182196
183197def delete_handler (path ):
184198 """ Registers the decorated function as delete handler for the given
@@ -244,3 +258,25 @@ def delete_volume_snapshots(api, url):
244258 f'Snapshot failed to delete within 60 seconds. Status '
245259 f'is still "{ snapshot .json ()["status" ]} ".'
246260 )
261+
262+
263+ @delete_handler (path = '/v1/objects-users/.+' )
264+ def delete_objects_users (api , url ):
265+ """ Before deleting an objects user, we have to delete owned buckets. """
266+
267+ user = ObjectsUser .from_href (None , api , url , name = "" )
268+ user .wait_for_access ()
269+
270+ session = boto3 .Session (
271+ aws_access_key_id = user .keys [0 ]['access_key' ],
272+ aws_secret_access_key = user .keys [0 ]['secret_key' ],
273+ )
274+
275+ objects_endpoint = api .objects_endpoint_for (zone = user .tags ['zone' ])
276+ s3 = session .resource ('s3' , endpoint_url = objects_endpoint )
277+
278+ for bucket in s3 .buckets .all ():
279+ bucket .objects .all ().delete ()
280+ bucket .delete ()
281+
282+ api .request ("DELETE" , url )
0 commit comments