@@ -132,6 +132,16 @@ def approval_state(self) -> Optional[str]:
132
132
"""Return approval state of this ResourceClaim."""
133
133
return self .status .get ('approval' , {}).get ('state' )
134
134
135
+ @property
136
+ def auto_delete_when (self ) -> Optional [str ]:
137
+ """Return condition which triggers automatic delete if defined."""
138
+ return self .spec .get ('autoDelete' , {}).get ('when' )
139
+
140
+ @property
141
+ def auto_detach_when (self ) -> Optional [str ]:
142
+ """Return condition which triggers automatic detach if defined."""
143
+ return self .spec .get ('autoDetach' , {}).get ('when' )
144
+
135
145
@property
136
146
def claim_is_initialized (self ) -> bool :
137
147
return f"{ Poolboy .operator_domain } /resource-claim-init-timestamp" in self .annotations
@@ -181,6 +191,13 @@ def is_approved(self) -> bool:
181
191
If claim is already has a resource hadle then it is considered approved."""
182
192
return self .has_resource_handle or self .approval_state == 'approved'
183
193
194
+ @property
195
+ def is_detached (self ) -> bool :
196
+ """Return whether this ResourceClaim has been detached from its ResourceHandle."""
197
+ if not self .status :
198
+ return False
199
+ return self .status .get ('resourceHandle' , {}).get ('detached' , False )
200
+
184
201
@property
185
202
def lifespan_end_datetime (self ) -> Optional [datetime ]:
186
203
"""Return datetime object representing when this ResourceClaim will be automatically deleted.
@@ -365,6 +382,53 @@ async def bind_resource_handle(self,
365
382
366
383
return resource_handle
367
384
385
+ def check_condition (self , when_condition , resource_handle , resource_provider ):
386
+ # resource_provider may be None if there is no top-level provider.
387
+ resource_provider_vars = resource_provider .vars if resource_provider else {}
388
+ vars_ = {
389
+ ** resource_provider_vars ,
390
+ ** resource_handle .vars ,
391
+ "resource_claim" : self ,
392
+ "resource_handle" : resource_handle ,
393
+ "resource_provider" : resource_provider ,
394
+ "metadata" : self .meta ,
395
+ "spec" : self .spec ,
396
+ "status" : self .status ,
397
+ }
398
+ check_value = recursive_process_template_strings (
399
+ '{{(' + when_condition + ')|bool}}' ,
400
+ variables = vars_
401
+ )
402
+ return check_value
403
+
404
+ def check_auto_delete (self , logger , resource_handle , resource_provider ) -> bool :
405
+ if not self .auto_delete_when :
406
+ return False
407
+ try :
408
+ check_value = self .check_condition (
409
+ resource_handle = resource_handle ,
410
+ resource_provider = resource_provider ,
411
+ when_condition = self .auto_delete_when
412
+ )
413
+ return check_value
414
+ except Exception as exception :
415
+ logger .warning (f"Auto delete check failed for { self } : { exception } " )
416
+ return False
417
+
418
+ def check_auto_detach (self , logger , resource_handle , resource_provider ):
419
+ if not self .auto_detach_when :
420
+ return False
421
+ try :
422
+ check_value = self .check_condition (
423
+ resource_handle = resource_handle ,
424
+ resource_provider = resource_provider ,
425
+ when_condition = self .auto_detach_when
426
+ )
427
+ return check_value
428
+ except Exception as exception :
429
+ logger .warning (f"Auto detach check failed for { self } : { exception } " )
430
+ return False
431
+
368
432
def get_resource_state_from_status (self , resource_number ):
369
433
if not self .status \
370
434
or not 'resources' in self .status \
@@ -522,6 +586,14 @@ async def delete(self):
522
586
version = Poolboy .operator_version ,
523
587
)
524
588
589
+ async def detach (self , resource_handle ):
590
+ await self .merge_patch_status ({
591
+ "resourceHandle" : {
592
+ "detached" : True
593
+ }
594
+ })
595
+ await resource_handle .delete ()
596
+
525
597
async def get_resource_handle (self ):
526
598
return await resourcehandle .ResourceHandle .get (self .resource_handle_name )
527
599
@@ -598,6 +670,17 @@ async def manage(self, logger) -> None:
598
670
and self .lifespan_start_datetime > datetime .utcnow ():
599
671
return
600
672
673
+ if self .is_detached :
674
+ # Normally lifespan end is tracked by the ResourceHandle.
675
+ # Detached ResourceClaims have no handle.
676
+ if self .lifespan_end_datetime \
677
+ and self .lifespan_start_datetime < datetime .utcnow ():
678
+ logger .info (f"Deleting detacthed { self } at end of lifespan" )
679
+ await self .delete ()
680
+ # No further processing for detached ResourceClaim
681
+ return
682
+
683
+ resource_provider = None
601
684
if self .has_resource_provider :
602
685
if self .has_spec_resources :
603
686
raise kopf .TemporaryError (
@@ -619,7 +702,7 @@ async def manage(self, logger) -> None:
619
702
)
620
703
621
704
try :
622
- provider = await self .get_resource_provider ()
705
+ resource_provider = await self .get_resource_provider ()
623
706
except kubernetes_asyncio .client .exceptions .ApiException as e :
624
707
if e .status == 404 :
625
708
raise kopf .TemporaryError (
@@ -629,11 +712,11 @@ async def manage(self, logger) -> None:
629
712
else :
630
713
raise
631
714
632
- if provider .approval_required :
715
+ if resource_provider .approval_required :
633
716
if not 'approval' in self .status :
634
717
await self .merge_patch_status ({
635
718
"approval" : {
636
- "message" : provider .approval_pending_message ,
719
+ "message" : resource_provider .approval_pending_message ,
637
720
"state" : "pending"
638
721
}
639
722
})
@@ -683,6 +766,16 @@ async def manage(self, logger) -> None:
683
766
resource_claim_resources = resource_claim_resources ,
684
767
)
685
768
769
+ if self .check_auto_delete (logger = logger , resource_handle = resource_handle , resource_provider = resource_provider ):
770
+ logger .info (f"auto-delete of { self } triggered" )
771
+ await self .delete ()
772
+ return
773
+
774
+ if self .check_auto_detach (logger = logger , resource_handle = resource_handle , resource_provider = resource_provider ):
775
+ logger .info (f"auto-detach of { self } triggered" )
776
+ await self .detach (resource_handle = resource_handle )
777
+ return
778
+
686
779
await self .__manage_resource_handle (
687
780
logger = logger ,
688
781
resource_claim_resources = resource_claim_resources ,
0 commit comments