1
+ import logging
1
2
import tempfile
2
3
import time
3
4
import uuid
10
11
import gitlab .base
11
12
12
13
SLEEP_INTERVAL = 0.1
13
- TIMEOUT = 60 # seconds before timeout will occur
14
+ TIMEOUT = 3 * 60 # seconds before timeout will occur
14
15
15
16
16
17
@pytest .fixture (scope = "session" )
17
18
def fixture_dir (test_dir ):
18
19
return test_dir / "functional" / "fixtures"
19
20
20
21
21
- def reset_gitlab (gl ):
22
- # previously tools/reset_gitlab.py
22
+ def reset_gitlab (gl : gitlab .Gitlab ) -> None :
23
+ # Mark our resources for deletion. It takes time for them to actually be deleted
24
+ # though.
25
+ _reset_gitlab_delete_resources (gl = gl )
26
+
27
+ # Wait for all resources to be deleted
28
+ _reset_gitlab_wait_deletion_finish (gl = gl )
29
+
30
+
31
+ def _reset_gitlab_delete_resources (gl : gitlab .Gitlab ) -> None :
32
+ """Mark for deletion, resources (such as projects, groups, users) that shouldn't
33
+ exist. Once marked they will still take time to be deleted."""
23
34
for project in gl .projects .list ():
35
+ logging .info (f"Mark for deletion project: { project .name !r} " )
24
36
for deploy_token in project .deploytokens .list ():
37
+ logging .info (
38
+ f"Mark for deletion token: { deploy_token .name !r} in "
39
+ f"project: { project .name !r} "
40
+ )
25
41
deploy_token .delete ()
26
42
project .delete ()
27
43
for group in gl .groups .list ():
44
+ logging .info (f"Mark for deletion group: { group .name !r} " )
28
45
for deploy_token in group .deploytokens .list ():
46
+ logging .info (
47
+ f"Mark for deletion token: { deploy_token .name !r} in "
48
+ f"group: { group .name !r} "
49
+ )
29
50
deploy_token .delete ()
30
51
group .delete ()
31
52
for variable in gl .variables .list ():
53
+ logging .info (f"Mark for deletion variable: { variable .name !r} " )
32
54
variable .delete ()
33
55
for user in gl .users .list ():
34
56
if user .username != "root" :
57
+ logging .info (f"Mark for deletion user: { user .username !r} " )
35
58
user .delete (hard_delete = True )
36
59
60
+
61
+ def _reset_gitlab_wait_deletion_finish (gl : gitlab .Gitlab ) -> None :
62
+ """Wait for all of our resources to be deleted.
63
+
64
+ If anything exists then mark it again for deletion in case initial call to delete
65
+ didn't work, which has been seen :("""
66
+
37
67
max_iterations = int (TIMEOUT / SLEEP_INTERVAL )
38
68
39
69
# Ensure everything has been reset
40
70
start_time = time .perf_counter ()
41
71
42
72
def wait_for_maximum_list_length (
43
- rest_manager : gitlab .base .RESTManager , description : str , max_length : int = 0
73
+ rest_manager : gitlab .base .RESTManager ,
74
+ description : str ,
75
+ max_length : int = 0 ,
76
+ should_delete_func = lambda x : True ,
77
+ delete_kwargs = {},
44
78
) -> None :
45
79
"""Wait for the list() length to be no greater than expected maximum or fail
46
80
test if timeout is exceeded"""
47
- for _ in range (max_iterations ):
48
- if len (rest_manager .list ()) <= max_length :
81
+ for count in range (max_iterations ):
82
+ items = rest_manager .list ()
83
+ logging .info (
84
+ f"Iteration: { count } : items in { description } : { [x .name for x in items ]} "
85
+ )
86
+ for item in items :
87
+ if should_delete_func (item ):
88
+ logging .info (
89
+ f"Marking again for deletion { description } : { item .name !r} "
90
+ )
91
+ try :
92
+ item .delete (** delete_kwargs )
93
+ except gitlab .exceptions .GitlabDeleteError as exc :
94
+ logging .info (
95
+ f"Already marked for deletion: { item .name !r} { exc } "
96
+ )
97
+ if len (items ) <= max_length :
49
98
break
50
99
time .sleep (SLEEP_INTERVAL )
51
- assert len (rest_manager .list ()) <= max_length , (
100
+ items = rest_manager .list ()
101
+ elapsed_time = time .perf_counter () - start_time
102
+ if len (items ) > max_length :
103
+ logging .error (
104
+ f"Too many items still remaining and timeout exceeded: { elapsed_time } "
105
+ )
106
+ assert len (items ) <= max_length , (
52
107
f"Did not delete required items for { description } . "
53
- f"Elapsed_time: { time .perf_counter () - start_time } "
108
+ f"Elapsed_time: { time .perf_counter () - start_time } \n "
109
+ f"items: { [str (x ) for x in items ]!r} "
54
110
)
55
111
56
112
wait_for_maximum_list_length (rest_manager = gl .projects , description = "projects" )
57
113
wait_for_maximum_list_length (rest_manager = gl .groups , description = "groups" )
58
114
wait_for_maximum_list_length (rest_manager = gl .variables , description = "variables" )
115
+
116
+ def should_delete_user (user ):
117
+ if user .username == "root" :
118
+ return False
119
+ return True
120
+
59
121
wait_for_maximum_list_length (
60
- rest_manager = gl .users , description = "users" , max_length = 1
122
+ rest_manager = gl .users ,
123
+ description = "users" ,
124
+ max_length = 1 ,
125
+ should_delete_func = should_delete_user ,
126
+ delete_kwargs = {"hard_delete" : True },
61
127
)
62
128
63
129
@@ -144,7 +210,7 @@ def wait_for_sidekiq(gl):
144
210
"""
145
211
146
212
def _wait (timeout = 30 , step = 0.5 ):
147
- for _ in range (timeout ):
213
+ for count in range (timeout ):
148
214
time .sleep (step )
149
215
busy = False
150
216
processes = gl .sidekiq .process_metrics ()["processes" ]
@@ -153,6 +219,7 @@ def _wait(timeout=30, step=0.5):
153
219
busy = True
154
220
if not busy :
155
221
return True
222
+ logging .info (f"sidekiq busy { count } of { timeout } " )
156
223
return False
157
224
158
225
return _wait
@@ -188,8 +255,10 @@ def gitlab_config(check_is_alive, docker_ip, docker_services, temp_dir, fixture_
188
255
def gl (gitlab_config ):
189
256
"""Helper instance to make fixtures and asserts directly via the API."""
190
257
258
+ logging .info ("Create python-gitlab gitlab.Gitlab object" )
191
259
instance = gitlab .Gitlab .from_config ("local" , [gitlab_config ])
192
- reset_gitlab (instance )
260
+
261
+ reset_gitlab (gl = instance )
193
262
194
263
return instance
195
264
0 commit comments