Select to view content in your preferred language

Automation for publishing CRFs in a Storage Account

391
10
Jump to solution
2 weeks ago
Jeff-Reinhart
Frequent Contributor

I am attempting to automate the workflow for publishing a CRF stored in an Azure Storage Account as a referenced Imagery Layer. We have close to 100 CRFs to publish as part of our cloud migration. So far, I have gathered that the general workflow would be to create a service definition and then use the ArcGIS Python API to publish that service definition.

I cannot even get past creating the service definition.

When I run:

crf_path = r'c:\myacsfile.acs\folder_name\mycrf.crf'
sharing_draft = arcpy.sharing.CreateSharingDraft('FEDERATED_SERVER', 'IMAGE_SERVICE', 'service_name', crf_path)

 The return is None. The likely culprit is that CreateSharingDraft does not like the value passed for the draft_value (crf_path). I copied the CRF path from Pro | Catalog | Project | Cloud Stores using r-click > Copy Path. I have successfully tested publishing the CRF via the UI. There does not seem to be any reason the path is wrong.

I tried arcpy.Exists(crf_path), and that is returning True.

Am I missing something or is this not supported?

 

0 Kudos
1 Solution

Accepted Solutions
TonyAlmeida
MVP Regular Contributor

Try using, arcpy.management.CreateImageSDDraft  is currently the more reliable choice, even though it's the "older" tool.

import arcpy

aprx = arcpy.mp.ArcGISProject("CURRENT")

sddraft = r"C:\temp\service.sddraft"
sd = r"C:\temp\service.sd"

# This is the key tool (not CreateSharingDraft)
arcpy.management.CreateImageSDDraft(
    in_raster=crf_path,
    out_sddraft=sddraft,
    service_name="service_name",
    server_type="FEDERATED_SERVER",
    connection_file_path=r"C:\path\to\server.ags",
    copy_data_to_server=False
)

arcpy.server.StageService(sddraft, sd)
arcpy.server.UploadServiceDefinition(sd, r"C:\path\to\server.ags")

 

Esri tends to document each service type in its own section rather than having one universal publish endpoint. Feature/tiled services use the Sharing API’s /publish. Imagery services use Image Server / Raster Analysis tools and dedicated create/publish operations.

For your bulk cloud migration of CRFs as referenced web imagery layers, the most reliable automated paths are:

  • arcpy.management.CreateImageSDDraft + StageService + UploadServiceDefinition)
  • Or switching to arcgis Python API calls that leverage the registered Azure cloud store directly.

View solution in original post

10 Replies
TonyAlmeida
MVP Regular Contributor

I believe ArcPy cannot directly publish a cloud-hosted CRF via .acs path, you have to go through a map or use REST/API instead.

 

After registering try:

crf_path = r'/vsiaz/<container-name>/path/to/your.crf'
0 Kudos
Jeff-Reinhart
Frequent Contributor

What do you mean by "after registering"? Are you referring to the data store? If so, that is already registered. I would not have been able to publish via the UI otherwise.

0 Kudos
TonyAlmeida
MVP Regular Contributor

CreateSharingDraft needs a map or layer object, not a file path string. 

ok try:

# Add your CRF to a map using the .acs connection (for client access)
aprx = arcpy.mp.ArcGISProject("CURRENT")
map_obj = aprx.listMaps()[0]
crf_layer = map_obj.addDataFromPath(r'c:\myacsfile.acs\folder_name\mycrf.crf')

# Now pass the layer object, not the file path string
sharing_draft = arcpy.sharing.CreateSharingDraft(
    'FEDERATED_SERVER', 
    'IMAGE_SERVICE', 
    'service_name', 
    crf_layer  # Pass the layer object, not a string path
)

 

Use a Cloud-Native VSI Path,

This is a direct path to the raster, bypassing the .acs connection file:

crf_path = r'/vsiaz/your-container-name/path/to/your.crf

0 Kudos
Jeff-Reinhart
Frequent Contributor

Thanks for the reply. I tried that. The CRF adds to the map as expected. Unfortunately, the return from 

arcpy.sharing.CreateSharingDraft() is still None.
0 Kudos
Jeff-Reinhart
Frequent Contributor

And I should note that according to:

https://pro.arcgis.com/en/pro-app/latest/arcpy/sharing/createsharingdraft.htm

a path to a raster dataset should be valid for a draft_value param...

"For a map service, this is a Map object. For a geoprocessing service or a web tool, this is one or more geoprocessing results. For an image service or web imagery layer, this is the path of a raster or mosaic dataset."

Also of note, I tried passing the path string within a list.

0 Kudos
TonyAlmeida
MVP Regular Contributor

If I am reading it correctly. Passing a .acs path directly are not supported.

ArcPy sharing API expects real dataset path,  can not resolve cloud store connections (.acs).

So you have to use r"D:\rasters\image.crf" or r"Database Connections\conn.sde\mosaic_dataset"

 

0 Kudos
Jeff-Reinhart
Frequent Contributor

In regard to using the REST API... this doc:

https://developers.arcgis.com/rest/users-groups-and-items/publish-item/

States:

"Publishers can create feature services as well as tiled map services."

From my experience, assumption based on omission is how to read Esri documentation. With "imagery layers" not included in this description, I am lead to believe publishing them via the REST API is not supported.

0 Kudos
TonyAlmeida
MVP Regular Contributor

Try using, arcpy.management.CreateImageSDDraft  is currently the more reliable choice, even though it's the "older" tool.

import arcpy

aprx = arcpy.mp.ArcGISProject("CURRENT")

sddraft = r"C:\temp\service.sddraft"
sd = r"C:\temp\service.sd"

# This is the key tool (not CreateSharingDraft)
arcpy.management.CreateImageSDDraft(
    in_raster=crf_path,
    out_sddraft=sddraft,
    service_name="service_name",
    server_type="FEDERATED_SERVER",
    connection_file_path=r"C:\path\to\server.ags",
    copy_data_to_server=False
)

arcpy.server.StageService(sddraft, sd)
arcpy.server.UploadServiceDefinition(sd, r"C:\path\to\server.ags")

 

Esri tends to document each service type in its own section rather than having one universal publish endpoint. Feature/tiled services use the Sharing API’s /publish. Imagery services use Image Server / Raster Analysis tools and dedicated create/publish operations.

For your bulk cloud migration of CRFs as referenced web imagery layers, the most reliable automated paths are:

  • arcpy.management.CreateImageSDDraft + StageService + UploadServiceDefinition)
  • Or switching to arcgis Python API calls that leverage the registered Azure cloud store directly.
Jeff-Reinhart
Frequent Contributor

Needed a few tweaks, but this worked. Thank you. Running from 3.6.2.

The function arcpy.management.CreateImageSDDraft had to be called as arcpy.CreateImageSDDraft.

The in_raster param for CreateImageSDDraft had to be updated to raster_or_mosaic_layer.

For arcpy.server.UploadServiceDefinition, the in_server param needed to be the Enterprise URL string, not the AGS server connection file. I think this varies depending on what type of server you are publishing to.