77from  rest_framework .exceptions  import  ValidationError 
88
99from  ansible_base .resource_registry .models  import  Resource , service_id 
10- from  ansible_base .resource_registry .rest_client  import  ResourceRequestBody , get_resource_server_client 
10+ from  ansible_base .resource_registry .rest_client  import  ResourceAPIClient ,  ResourceRequestBody , get_resource_server_client 
1111
1212logger  =  logging .getLogger ('ansible_base.resource_registry.utils.sync_to_resource_server' )
1313
1414
15- def  sync_to_resource_server (instance , action , ansible_id = None ):
16-     """ 
17-     Use the resource server API to sync the resource across. 
15+ def  get_current_user_resource_client () ->  ResourceAPIClient :
16+     "Returns resource client for the current requesting user from CRUM" 
17+     user_ansible_id  =  None 
18+     user  =  get_current_user ()
19+     if  user :
20+         # If we have a user, try to get their ansible_id and sync as them. 
21+         # If they don't have one some how, or if we don't have a user, sync with None and 
22+         # let the resource server decide what to do. 
23+         try :
24+             user_resource  =  Resource .get_resource_for_object (user )
25+             user_ansible_id  =  user_resource .ansible_id 
26+         except  (Resource .DoesNotExist , AttributeError ):
27+             logger .error (f"User { user }   does not have a resource" )
28+             pass 
29+     else :
30+         logger .error ("No user found, syncing to resource server with jwt_user_id=None" )
1831
19-     When action is "delete", the ansible_id is required, because by the time we 
20-     get here, we've already deleted the object and its resource. So we can't 
21-     pull the ansible_id from the resource object. It's on the caller to pull 
22-     the ansible_id from the object before deleting it. 
32+     return  get_resource_server_client (
33+         settings .RESOURCE_SERVICE_PATH ,
34+         jwt_user_id = user_ansible_id ,
35+         raise_if_bad_request = True ,
36+     )
2337
24-     For all other actions, ansible_id is ignored and retrieved from the resource 
25-     object. (For create, the resource is expected to exist before calling this 
26-     function.) 
27-     """ 
2838
39+ def  should_skip_reverse_sync (instance ) ->  bool :
40+     """For a given Django model object, return True and log if reverse sync should be skipped 
41+ 
42+     This accounts for 2 cases 
43+     - environment variable set to skip sync 
44+     - instance has set flag to skip sync 
45+ 
46+     This does not account for other skip conditions, like the no_reverse_sync context manager 
47+     """ 
2948    sync_disabled  =  os .environ .get ('ANSIBLE_REVERSE_RESOURCE_SYNC' , 'true' ).lower () ==  'false' 
3049    if  sync_disabled :
3150        logger .info (f"Skipping sync of resource { instance }   because $ANSIBLE_REVERSE_RESOURCE_SYNC is 'false'" )
32-         return 
51+         return   True 
3352
3453    # This gets set in in signals.handlers.decide_to_sync_update() sometimes. 
3554    skip_sync  =  getattr (instance , '_skip_reverse_resource_sync' , False )
3655    if  skip_sync :
3756        # Avoid an infinite loop by not syncing resources that came from the resource server. 
3857        # Or avoid syncing unnecessarily, when a synced field hasn't changed. 
3958        logger .info (f"Skipping sync of resource { instance }  " )
59+         return  True 
60+ 
61+     return  False 
62+ 
63+ 
64+ def  sync_to_resource_server (instance , action , ansible_id = None ):
65+     """ 
66+     Use the resource server API to sync the resource across. 
67+ 
68+     When action is "delete", the ansible_id is required, because by the time we 
69+     get here, we've already deleted the object and its resource. So we can't 
70+     pull the ansible_id from the resource object. It's on the caller to pull 
71+     the ansible_id from the object before deleting it. 
72+ 
73+     For all other actions, ansible_id is ignored and retrieved from the resource 
74+     object. (For create, the resource is expected to exist before calling this 
75+     function.) 
76+     """ 
77+     if  should_skip_reverse_sync (instance ):
4078        return 
4179
4280    if  action  !=  "delete"  and  ansible_id  is  not   None :
@@ -55,26 +93,7 @@ def sync_to_resource_server(instance, action, ansible_id=None):
5593        logger .info (f"Skipping sync of resource { instance }   because its service_id is local" )
5694        return 
5795
58-     user_ansible_id  =  None 
59-     user  =  get_current_user ()
60-     if  user :
61-         # If we have a user, try to get their ansible_id and sync as them. 
62-         # If they don't have one some how, or if we don't have a user, sync with None and 
63-         # let the resource server decide what to do. 
64-         try :
65-             user_resource  =  Resource .get_resource_for_object (user )
66-             user_ansible_id  =  user_resource .ansible_id 
67-         except  (Resource .DoesNotExist , AttributeError ):
68-             logger .error (f"User { user }   does not have a resource" )
69-             pass 
70-     else :
71-         logger .error ("No user found, syncing to resource server with jwt_user_id=None" )
72- 
73-     client  =  get_resource_server_client (
74-         settings .RESOURCE_SERVICE_PATH ,
75-         jwt_user_id = user_ansible_id ,
76-         raise_if_bad_request = True ,
77-     )
96+     client  =  get_current_user_resource_client ()
7897
7998    if  action  !=  "delete" :
8099        ansible_id  =  resource .ansible_id 
0 commit comments