@@ -35,7 +35,7 @@ def delete_instance(self, instance_id, region):
35
35
36
36
37
37
class InstanceMock :
38
- def __init__ (self , provider , state = None , ttl = None , first_seen = None ):
38
+ def __init__ (self , provider , state = None , ttl = None , first_seen = None , last_seen = None , deleting_since = None , ignore = False ):
39
39
self .state = state if state is not None else None
40
40
self .instance_id = fake .uuid4 ()
41
41
self .region = None
@@ -46,6 +46,7 @@ def __init__(self, provider, state=None, ttl=None, first_seen=None):
46
46
self .first_seen = first_seen if first_seen else datetime .now (tz = timezone .utc )
47
47
self .last_seen = self .first_seen # For all_time_fields()
48
48
self .age = timedelta (seconds = 0 ) # Placeholder
49
+ self .ignore = ignore
49
50
50
51
def save (self , update_fields = None ):
51
52
self .save_called = True
@@ -221,39 +222,53 @@ def test_reset_stale_deleting(monkeypatch):
221
222
'state' : StateChoice .DELETING ,
222
223
'deleting_since' : now - timedelta (hours = 3 ), # 3 hours ago
223
224
'should_reset' : True ,
224
- 'desc' : "Stale (3h > 2h)"
225
+ 'desc' : "Stale (3h > 2h)" ,
226
+ 'pcw_ignore' : False
225
227
},
226
228
# Case 2: Not Stale (1h < 2h)
227
229
{
228
230
'instance_id' : "test-instance-not-stale" ,
229
231
'state' : StateChoice .DELETING ,
230
232
'deleting_since' : now - timedelta (hours = 1 ), # 1 hour ago
231
233
'should_reset' : False ,
232
- 'desc' : "Not Stale (1h < 2h)"
234
+ 'desc' : "Not Stale (1h < 2h)" ,
235
+ 'pcw_ignore' : False
233
236
},
234
237
# Case 3: Non-Deleting (ACTIVE)
235
238
{
236
239
'instance_id' : "test-instance-active" ,
237
240
'state' : StateChoice .ACTIVE ,
238
241
'deleting_since' : now - timedelta (hours = 3 ), # Shouldn’t matter
239
242
'should_reset' : False ,
240
- 'desc' : "Non-Deleting (ACTIVE)"
243
+ 'desc' : "Non-Deleting (ACTIVE)" ,
244
+ 'pcw_ignore' : False
241
245
},
242
246
# Case 4: Edge (2h = 2h)
243
247
{
244
248
'instance_id' : "test-instance-edge" ,
245
249
'state' : StateChoice .DELETING ,
246
250
'deleting_since' : now - timedelta (hours = 2 ), # Exactly 2 hours ago
247
251
'should_reset' : True ,
248
- 'desc' : "Edge (2h = 2h)"
252
+ 'desc' : "Edge (2h = 2h)" ,
253
+ 'pcw_ignore' : False
249
254
},
250
255
# Case 5: Edge (1h 59m < 2h)
251
256
{
252
257
'instance_id' : "test-instance-edge-2" ,
253
258
'state' : StateChoice .DELETING ,
254
259
'deleting_since' : now - timedelta (hours = 1 ) - timedelta (minutes = 59 ), # Exactly 2 hours ago
255
260
'should_reset' : False ,
256
- 'desc' : "Edge (1h 59m < 2h)"
261
+ 'desc' : "Edge (1h 59m < 2h)" ,
262
+ 'pcw_ignore' : False
263
+ },
264
+ # Case 6: Stale (3h > 2h) but pcw_ignore tag is True
265
+ {
266
+ 'instance_id' : "test-instance-stale-but-pcw-ignore" ,
267
+ 'state' : StateChoice .DELETING ,
268
+ 'deleting_since' : now - timedelta (hours = 3 ), # 3 hours ago
269
+ 'should_reset' : False ,
270
+ 'desc' : "Stale (3h > 2h)" ,
271
+ 'pcw_ignore' : True
257
272
},
258
273
]
259
274
@@ -279,11 +294,22 @@ def test_reset_stale_deleting(monkeypatch):
279
294
active = case ['state' ] == StateChoice .ACTIVE
280
295
)
281
296
instance .save ()
297
+ tags = {'openqa_ttl' : str (default_ttl )}
298
+ if case ['pcw_ignore' ]:
299
+ tags [Instance .TAG_IGNORE ] = "True"
300
+
282
301
CspInfo .objects .create (
283
302
instance = instance ,
284
- tags = json .dumps ({ 'openqa_ttl' : str ( default_ttl )} ),
303
+ tags = json .dumps (tags ),
285
304
type = "test_type"
286
305
)
306
+
307
+ # required so that ignore is recomputed
308
+ instance .set_alive ()
309
+
310
+ # required to save the ignore field
311
+ instance .save ()
312
+
287
313
instances .append (instance )
288
314
289
315
# Run the function
@@ -302,6 +328,8 @@ def test_reset_stale_deleting(monkeypatch):
302
328
print (f"deleting_since: { instance .deleting_since } " )
303
329
print (f"time_in_deleting: { time_in_deleting } s" )
304
330
print (f"threshold: { threshold } s" )
331
+ print (f"pcw_ignore expected: { case ['pcw_ignore' ]} , actual: { instance .ignore } " )
332
+ print (f"should_reset: { case ['should_reset' ]} " )
305
333
306
334
if case ['should_reset' ]:
307
335
assert instance .state == StateChoice .ACTIVE , f"State should reset to ACTIVE for { case ['desc' ]} "
@@ -348,6 +376,24 @@ def test_delete_instances_azure(monkeypatch):
348
376
assert instance .save_called
349
377
assert instance .state == StateChoice .DELETING
350
378
379
+ instance_with_state = InstanceMock (ProviderChoice .AZURE , StateChoice .ACTIVE )
380
+
381
+ delete_instance (instance_with_state )
382
+
383
+ assert instance_with_state .save_called
384
+ assert instance_with_state .state == StateChoice .DELETING
385
+
386
+
387
+ def test_delete_instances_azure_pcw_ignore (monkeypatch ):
388
+ monkeypatch .setattr (Azure , '__new__' , lambda cls , namespace : AzureMock ())
389
+
390
+ instance = InstanceMock (ProviderChoice .AZURE , StateChoice .ACTIVE , None , None , None , None , True )
391
+
392
+ delete_instance (instance )
393
+
394
+ assert not instance .save_called
395
+ assert instance .state == StateChoice .ACTIVE
396
+
351
397
352
398
def test_delete_instances_ec2 (monkeypatch ):
353
399
monkeypatch .setattr (EC2 , '__new__' , lambda cls , namespace : EC2Mock ())
@@ -359,6 +405,24 @@ def test_delete_instances_ec2(monkeypatch):
359
405
assert instance .save_called
360
406
assert instance .state == StateChoice .DELETING
361
407
408
+ instance_with_state = InstanceMock (ProviderChoice .EC2 , StateChoice .ACTIVE )
409
+
410
+ delete_instance (instance_with_state )
411
+
412
+ assert instance_with_state .save_called
413
+ assert instance_with_state .state == StateChoice .DELETING
414
+
415
+
416
+ def test_delete_instances_ec2_pcw_ignore (monkeypatch ):
417
+ monkeypatch .setattr (EC2 , '__new__' , lambda cls , namespace : EC2Mock ())
418
+
419
+ instance = InstanceMock (ProviderChoice .EC2 , StateChoice .ACTIVE , None , None , None , None , True )
420
+
421
+ delete_instance (instance )
422
+
423
+ assert not instance .save_called
424
+ assert instance .state == StateChoice .ACTIVE
425
+
362
426
363
427
def test_delete_instances_gce (monkeypatch ):
364
428
monkeypatch .setattr (GCE , '__new__' , lambda cls , namespace : GCEMock ())
@@ -369,3 +433,21 @@ def test_delete_instances_gce(monkeypatch):
369
433
370
434
assert instance .save_called
371
435
assert instance .state == StateChoice .DELETING
436
+
437
+ instance_with_state = InstanceMock (ProviderChoice .GCE , StateChoice .ACTIVE )
438
+
439
+ delete_instance (instance_with_state )
440
+
441
+ assert instance_with_state .save_called
442
+ assert instance_with_state .state == StateChoice .DELETING
443
+
444
+
445
+ def test_delete_instances_gce_pcw_ignore (monkeypatch ):
446
+ monkeypatch .setattr (GCE , '__new__' , lambda cls , namespace : GCEMock ())
447
+
448
+ instance = InstanceMock (ProviderChoice .GCE , StateChoice .ACTIVE , None , None , None , None , True )
449
+
450
+ delete_instance (instance )
451
+
452
+ assert not instance .save_called
453
+ assert instance .state == StateChoice .ACTIVE
0 commit comments