Esri-Private-Sector-SEs / gbd-migration

Migration project to consolidate various orgs within the Commercial GBD team.
0 stars 0 forks source link

Error on Content Migration #12

Open JHendrickson4 opened 1 year ago

JHendrickson4 commented 1 year ago

ITEM_ID = "72ce7dbbfbc04b60affe0267492e7cfd"

resulted in

`--------------------------------------------------------------------------- Exception Traceback (most recent call last) /opt/conda/lib/python3.9/site-packages/arcgis/gis/init.py in _hydrate(self) 16930 try:

16931 self._refresh() 16932

/opt/conda/lib/python3.9/site-packages/arcgis/gis/init.py in _refresh(self) 16904 else:

16905 raise e 16906

/opt/conda/lib/python3.9/site-packages/arcgis/gis/init.py in _refresh(self) 16893 else:

16894 dictdata = self._con.post( 16895 self.url, params

/opt/conda/lib/python3.9/site-packages/arcgis/gis/_impl/_con/_connection.py in post(self, path, params, files, **kwargs) 1527 return resp -> 1528 return self._handle_response( 1529 resp=resp,

/opt/conda/lib/python3.9/site-packages/arcgis/gis/_impl/_con/_connection.py in _handle_response(self, resp, file_name, out_path, try_json, force_bytes, ignore_error_key) 1007 errorcode = data["error"]["code"] if "code" in data["error"] else 0 -> 1008 self._handle_json_error(data["error"], errorcode) 1009 return data

/opt/conda/lib/python3.9/site-packages/arcgis/gis/_impl/_con/_connection.py in _handle_json_error(self, error, errorcode) 1030 errormessage = errormessage + "\n(Error Code: " + str(errorcode) + ")" -> 1031 raise Exception(errormessage) 1032

Exception: User does not have permissions to access this service User does not have permissions to access this service (Error Code: 403)

During handling of the above exception, another exception occurred:

Exception Traceback (most recent call last) /tmp/ipykernel_18/3793353524.py in <cell line: 1>() ----> 1 transfer()

/tmp/ipykernel_18/3758147352.py in transfer() 220 # decide on appropriate workflow for item 221 if item_origin.type == "StoryMap": --> 222 sm_transfer(destination=destination, item=item_origin) 223 elif item_origin.type == "Dashboard": 224 dash_transfer(destination=destination, dash=item_origin, swizzle=True)

/tmp/ipykernel_18/3758147352.py in sm_transfer(destination, item) 161 webmap_mapper[webmap_to_copy.id] = webmap_destination_id 162 else: --> 163 cloned_webmaps = destination.content.clone_items([webmap_to_copy]) 164 webmap_mapper[webmap_to_copy.id] = [i for i in cloned_webmaps if i.type == 'Web Map'][0].id 165

/opt/conda/lib/python3.9/site-packages/arcgis/gis/init.py in clone_items(self, items, folder, item_extent, use_org_basemap, copy_data, copy_global_ids, search_existing_items, item_mapping, group_mapping, owner, preserve_item_id) 7887 preserve_item_id = False 7888 -> 7889 deep_cloner = clone._DeepCloner( 7890 self._gis, 7891 items,

/opt/conda/lib/python3.9/site-packages/arcgis/_impl/common/_clone.py in init(self, target, items, folder, item_extent, service_extent, use_org_basemap, copy_data, copy_global_ids, search_existing_items, item_mapping, group_mapping, owner, preserve_item_id) 106 self._temp_dir = tempfile.TemporaryDirectory() 107 # parse the config and get values --> 108 self._create_graph() 109 self._cloned_items = [] 110

/opt/conda/lib/python3.9/site-packages/arcgis/_impl/common/_clone.py in _create_graph(self) 118 user = self.target.users.me 119 # Get the definitions associated with the item --> 120 self._get_item_definitions(item) 121 122 # Test if the user has the correct privileges to create the items requested

/opt/conda/lib/python3.9/site-packages/arcgis/_impl/common/_clone.py in _get_item_definitions(self, item) 433 if feature_service: 434 item_definition.add_child( --> 435 self._get_item_definitions(feature_service) 436 ) 437 else:

/opt/conda/lib/python3.9/site-packages/arcgis/_impl/common/_clone.py in _get_item_definitions(self, item) 544 layer_source.update(layer_url_dict) 545 _sources.append(layer_source) --> 546 properties = self._get_properties( 547 layer, data, len(_sources) > 1, is_view 548 )

/opt/conda/lib/python3.9/site-packages/arcgis/_impl/common/_clone.py in _get_properties(self, layer, data, is_multi_services_view, is_view) 196 layer._token 197 or layer._con.token --> 198 and layer.manager 199 and layer.manager.properties 200 and "adminLayerInfo" in layer.manager.properties

/opt/conda/lib/python3.9/site-packages/arcgis/features/layer.py in manager(self) 229 admin_url = "%s%s%s" % (part1, add_text, part2) 230 --> 231 res = FeatureLayerManager(admin_url, self._gis) 232 return res 233

/opt/conda/lib/python3.9/site-packages/arcgis/features/managers.py in init(self, url, gis) 2793 def init(self, url, gis=None): 2794 super(FeatureLayerManager, self).init(url, gis) -> 2795 self._hydrate() 2796 2797 # ----------------------------------------------------------------------

/opt/conda/lib/python3.9/site-packages/arcgis/gis/init.py in _hydrate(self) 16952 # try as a public server 16953 self._lazy_token = None

16954 self._refresh() 16955 16956 except HTTPError as httperror:

/opt/conda/lib/python3.9/site-packages/arcgis/gis/init.py in _refresh(self) 16903 dictdata = self._con.get(self.url, params) 16904 else:

16905 raise e 16906 16907 self._lazy_properties = _mixins.PropertyMap(dictdata)

/opt/conda/lib/python3.9/site-packages/arcgis/gis/init.py in _refresh(self) 16892 ) 16893 else:

16894 dictdata = self._con.post( 16895 self.url, params 16896 ) # , token=self._lazy_token)

/opt/conda/lib/python3.9/site-packages/arcgis/gis/_impl/_con/_connection.py in post(self, path, params, files, **kwargs) 1526 if return_raw_response: 1527 return resp -> 1528 return self._handle_response( 1529 resp=resp, 1530 out_path=out_path,

/opt/conda/lib/python3.9/site-packages/arcgis/gis/_impl/_con/_connection.py in _handle_response(self, resp, file_name, out_path, try_json, force_bytes, ignore_error_key) 1006 return data 1007 errorcode = data["error"]["code"] if "code" in data["error"] else 0 -> 1008 self._handle_json_error(data["error"], errorcode) 1009 return data 1010 else:

/opt/conda/lib/python3.9/site-packages/arcgis/gis/_impl/_con/_connection.py in _handle_json_error(self, error, errorcode) 1029 1030 errormessage = errormessage + "\n(Error Code: " + str(errorcode) + ")" -> 1031 raise Exception(errormessage) 1032 1033 def post_multipart(

Exception: User does not have permissions to access this service User does not have permissions to access this service (Error Code: `403)``

rfreedBusiness commented 1 year ago

This seems to be a permissions issue, I am not sure what I can do on this side of things. Check to make sure you have admin perms etc?

JHendrickson4 commented 1 year ago

Yeah, both users are admin but it may be related to how its handling referenced content form outside the org (Living Atlas & other shared items) that's what I was hoping you could help narrow down. What layer(s) it go caught up on

rfreedBusiness commented 1 year ago

I believe that this version of the script should have print statements for each participating layer. dash_transfer() calls wc_transfer() which is the generic web content transfer protocol. Can you run this again and tell me what print statements are made below the cell? That way we can determine which item its hung up on.

I agree that its most likely something outside the org or a living atlas layer. If its outside the org, there is a parameter to get/search outside the org, it just needs to be enabled. API devs highly suggest not to do this, but we can give it a shot for science!

JHendrickson4 commented 1 year ago

Doesn't look like the print statements got executed. This is what I got back with the latest one. My guess is this is a referenced item that we don't need to 'deep copy' but just leave it as is as a referenced item.

Folder already exists.

Exception Traceback (most recent call last) /opt/conda/lib/python3.9/site-packages/arcgis/gis/init.py in _hydrate(self) 16930 try:

16931 self._refresh() 16932

/opt/conda/lib/python3.9/site-packages/arcgis/gis/init.py in _refresh(self) 16904 else:

16905 raise e 16906

/opt/conda/lib/python3.9/site-packages/arcgis/gis/init.py in _refresh(self) 16893 else:

16894 dictdata = self._con.post( 16895 self.url, params

/opt/conda/lib/python3.9/site-packages/arcgis/gis/_impl/_con/_connection.py in post(self, path, params, files, **kwargs) 1527 return resp -> 1528 return self._handle_response( 1529 resp=resp,

/opt/conda/lib/python3.9/site-packages/arcgis/gis/_impl/_con/_connection.py in _handle_response(self, resp, file_name, out_path, try_json, force_bytes, ignore_error_key) 1007 errorcode = data["error"]["code"] if "code" in data["error"] else 0 -> 1008 self._handle_json_error(data["error"], errorcode) 1009 return data

/opt/conda/lib/python3.9/site-packages/arcgis/gis/_impl/_con/_connection.py in _handle_json_error(self, error, errorcode) 1030 errormessage = errormessage + "\n(Error Code: " + str(errorcode) + ")" -> 1031 raise Exception(errormessage) 1032

Exception: User does not have permissions to access this service User does not have permissions to access this service (Error Code: 403)

During handling of the above exception, another exception occurred:

Exception Traceback (most recent call last) /tmp/ipykernel_20/3793353524.py in <cell line: 1>() ----> 1 transfer()

/tmp/ipykernel_20/3758147352.py in transfer() 220 # decide on appropriate workflow for item 221 if item_origin.type == "StoryMap": --> 222 sm_transfer(destination=destination, item=item_origin) 223 elif item_origin.type == "Dashboard": 224 dash_transfer(destination=destination, dash=item_origin, swizzle=True)

/tmp/ipykernel_20/3758147352.py in sm_transfer(destination, item) 161 webmap_mapper[webmap_to_copy.id] = webmap_destination_id 162 else: --> 163 cloned_webmaps = destination.content.clone_items([webmap_to_copy]) 164 webmap_mapper[webmap_to_copy.id] = [i for i in cloned_webmaps if i.type == 'Web Map'][0].id 165

/opt/conda/lib/python3.9/site-packages/arcgis/gis/init.py in clone_items(self, items, folder, item_extent, use_org_basemap, copy_data, copy_global_ids, search_existing_items, item_mapping, group_mapping, owner, preserve_item_id) 7887 preserve_item_id = False 7888 -> 7889 deep_cloner = clone._DeepCloner( 7890 self._gis, 7891 items,

/opt/conda/lib/python3.9/site-packages/arcgis/_impl/common/_clone.py in init(self, target, items, folder, item_extent, service_extent, use_org_basemap, copy_data, copy_global_ids, search_existing_items, item_mapping, group_mapping, owner, preserve_item_id) 106 self._temp_dir = tempfile.TemporaryDirectory() 107 # parse the config and get values --> 108 self._create_graph() 109 self._cloned_items = [] 110

/opt/conda/lib/python3.9/site-packages/arcgis/_impl/common/_clone.py in _create_graph(self) 118 user = self.target.users.me 119 # Get the definitions associated with the item --> 120 self._get_item_definitions(item) 121 122 # Test if the user has the correct privileges to create the items requested

/opt/conda/lib/python3.9/site-packages/arcgis/_impl/common/_clone.py in _get_item_definitions(self, item) 433 if feature_service: 434 item_definition.add_child( --> 435 self._get_item_definitions(feature_service) 436 ) 437 else:

/opt/conda/lib/python3.9/site-packages/arcgis/_impl/common/_clone.py in _get_item_definitions(self, item) 544 layer_source.update(layer_url_dict) 545 _sources.append(layer_source) --> 546 properties = self._get_properties( 547 layer, data, len(_sources) > 1, is_view 548 )

/opt/conda/lib/python3.9/site-packages/arcgis/_impl/common/_clone.py in _get_properties(self, layer, data, is_multi_services_view, is_view) 196 layer._token 197 or layer._con.token --> 198 and layer.manager 199 and layer.manager.properties 200 and "adminLayerInfo" in layer.manager.properties

/opt/conda/lib/python3.9/site-packages/arcgis/features/layer.py in manager(self) 229 admin_url = "%s%s%s" % (part1, add_text, part2) 230 --> 231 res = FeatureLayerManager(admin_url, self._gis) 232 return res 233

/opt/conda/lib/python3.9/site-packages/arcgis/features/managers.py in init(self, url, gis) 2793 def init(self, url, gis=None): 2794 super(FeatureLayerManager, self).init(url, gis) -> 2795 self._hydrate() 2796 2797 # ----------------------------------------------------------------------

/opt/conda/lib/python3.9/site-packages/arcgis/gis/init.py in _hydrate(self) 16952 # try as a public server 16953 self._lazy_token = None

16954 self._refresh() 16955 16956 except HTTPError as httperror:

/opt/conda/lib/python3.9/site-packages/arcgis/gis/init.py in _refresh(self) 16903 dictdata = self._con.get(self.url, params) 16904 else:

16905 raise e 16906 16907 self._lazy_properties = _mixins.PropertyMap(dictdata)

/opt/conda/lib/python3.9/site-packages/arcgis/gis/init.py in _refresh(self) 16892 ) 16893 else:

16894 dictdata = self._con.post( 16895 self.url, params 16896 ) # , token=self._lazy_token)

/opt/conda/lib/python3.9/site-packages/arcgis/gis/_impl/_con/_connection.py in post(self, path, params, files, **kwargs) 1526 if return_raw_response: 1527 return resp -> 1528 return self._handle_response( 1529 resp=resp, 1530 out_path=out_path,

/opt/conda/lib/python3.9/site-packages/arcgis/gis/_impl/_con/_connection.py in _handle_response(self, resp, file_name, out_path, try_json, force_bytes, ignore_error_key) 1006 return data 1007 errorcode = data["error"]["code"] if "code" in data["error"] else 0 -> 1008 self._handle_json_error(data["error"], errorcode) 1009 return data 1010 else:

/opt/conda/lib/python3.9/site-packages/arcgis/gis/_impl/_con/_connection.py in _handle_json_error(self, error, errorcode) 1029 1030 errormessage = errormessage + "\n(Error Code: " + str(errorcode) + ")" -> 1031 raise Exception(errormessage) 1032 1033 def post_multipart(

Exception: User does not have permissions to access this service User does not have permissions to access this service (Error Code: 403)

rfreedBusiness commented 1 year ago

Solution to this is to add org check logic for each origin item. Some pseudocode:

for item in BiggerItem:
   if item.gis != origin:
      continue
rfreedBusiness commented 1 year ago

alternative:

try:
  transfer logic
except TheExceptionRelatedToErrorCode403:
  continue
rfreedBusiness commented 1 year ago

Update 8/28:

Need to dig deeper into the item itself. However, this could be another issue unrelated to a Living Atlas layer or outside org participant.

This is the last call in the trace before the REST API becomes the handler:

cloned_webmaps = destination.content.clone_items([webmap_to_copy])

Which comes from:

webmap_to_copy = origin.content.get(wm)

This will return a None type if the item does not exist in the origin. That should not raise the 403 Exception. However, I have added the following code to handle a None type, as the web_maps set for which origin.content.get is called is simply scraping the JSON:

if webmap_to_copy == None:
            print(f"Webmap Item {wm.title} in Storymap not found in the org. Skipping...")
            continue
        else:

So that might be the source of the issue, though it is strange that the 403 Error is being thrown on a None type.

Keeping this ticket open and lets see if we can reproduce this issue with the latest push.