How to set PortalFolder when publishing via arcpy.sharing?

849
2
11-16-2021 01:09 PM
tigerwoulds
Occasional Contributor III

I am using the example here to publish map image layers with associated feature layers from an EGDB to ArcGIS Enterprise. https://pro.arcgis.com/en/pro-app/2.9/arcpy/sharing/mapimagesharingdraft-class.htm#GUID-98B8320E-356...

I have set the portalFolder property in line 87 to an existing folder in my Portal but the services get placed in my root Portal Folder. How do I publish my services to the specified Portal Folder rather than the root folder?

 

import arcpy
import os
import xml.dom.minidom as DOM

def configure_featureserver_capabilities(sddraftPath, capabilities):
    """Function to configure FeatureServer properties"""
    # Read the .sddraft file
    doc = DOM.parse(sddraftPath)

    # Find all elements named TypeName
    # This is where the additional layers and capabilities are defined
    typeNames = doc.getElementsByTagName('TypeName')
    for typeName in typeNames:
        # Get the TypeName to enable
        if typeName.firstChild.data == "FeatureServer":
            extension = typeName.parentNode
            for extElement in extension.childNodes:
                if extElement.tagName == 'Info':
                    for propSet in extElement.childNodes:
                        for prop in propSet.childNodes:
                            for prop1 in prop.childNodes:
                                if prop1.tagName == "Key":
                                    if prop1.firstChild.data == 'WebCapabilities':
                                        if prop1.nextSibling.hasChildNodes():
                                            prop1.nextSibling.firstChild.data = capabilities
                                        else:
                                            txt = doc.createTextNode(capabilities)
                                            prop1.nextSibling.appendChild(txt)
    # Write to the .sddraft file
    f = open(sddraftPath, 'w')
    doc.writexml(f)
    f.close()

def configure_mapserver_capabilities(sddraftPath, capabilities):
    """Function to configure MapServer properties"""
    # Read the .sddraft file
    doc = DOM.parse(sddraftPath)

    # Find all elements named TypeName
    # This is where the additional layers and capabilities are defined
    typeNames = doc.getElementsByTagName('TypeName')
    for typeName in typeNames:
        # Get the TypeName to enable
        if typeName.firstChild.data == "MapServer":
            extension = typeName.parentNode
            for extElement in extension.childNodes:
                if extElement.tagName == 'Definition':
                    for propArray in extElement.childNodes:
                        if propArray.tagName == 'Info':
                            for propSet in propArray.childNodes:
                                for prop in propSet.childNodes:
                                    for prop1 in prop.childNodes:
                                        if prop1.tagName == "Key":
                                            if prop1.firstChild.data == 'WebCapabilities':
                                                if prop1.nextSibling.hasChildNodes():
                                                    prop1.nextSibling.firstChild.data = capabilities
                                                else:
                                                    txt = doc.createTextNode(capabilities)
                                                    prop1.nextSibling.appendChild(txt)
    # Write to the .sddraft file
    f = open(sddraftPath, 'w')
    doc.writexml(f)
    f.close()

if __name__ == "__main__":
    # Sign in to portal
    arcpy.SignInToPortal("https://www.portal.domain.com/webadaptor", "MyUserName", "MyPassword")

    # Set output file names
    outdir = r"C:\Project\Output"
    service_name = "MapImageSharingDraftExample"
    sddraft_filename = service_name + ".sddraft"
    sddraft_output_filename = os.path.join(outdir, sddraft_filename)
    sd_filename = service_name + ".sd"
    sd_output_filename = os.path.join(outdir, sd_filename)

    # Reference map to publish
    aprx = arcpy.mp.ArcGISProject(r"C:\Project\World.aprx")
    m = aprx.listMaps('World')[0]

    # Create MapImageSharingDraft and set copyDataToServer property to False to reference registered data
    server_type = "FEDERATED_SERVER"
    federated_server_url = "https://MyFederatedServer.esri.com/server"
    sddraft = m.getWebLayerSharingDraft(server_type, "MAP_IMAGE", service_name)
    sddraft.federatedServerUrl = federated_server_url
    sddraft.copyDataToServer = False
    sddraft.portalFolder = 'Test_Folder'

    # Create Service Definition Draft file
    sddraft.exportToSDDraft(sddraft_output_filename)

    """Modify the .sddraft file to include a feature layer and set map image layer and feature layer properties"""

    # Modify the .sddraft file to change map image layer properties
    # Defaults are Map,Query,Data
    # Comment out the line below if you do not want to modify map image layer properties
    configure_mapserver_capabilities(sddraft_output_filename, "Map,Data")

    # Modify the .sddraft file to include a feature layer
    # Read the file
    doc = DOM.parse(sddraft_output_filename)

    # Find all elements named TypeName
    # This is where the extensions are defined
    typeNames = doc.getElementsByTagName('TypeName')
    for typeName in typeNames:
        # Get the TypeName to enable
        if typeName.firstChild.data == "FeatureServer":
            extension = typeName.parentNode
            for extElement in extension.childNodes:
                # Include a feature layer
                if extElement.tagName == 'Enabled':
                    extElement.firstChild.data = 'true'

    # Write to new .sddraft file
    sddraft_mod_xml = service_name + '_mod_xml' + '.sddraft'
    sddraft_mod_xml_file = os.path.join(outdir, sddraft_mod_xml)
    f = open(sddraft_mod_xml_file, 'w')
    doc.writexml(f)
    f.close()

    # Modify the .sddraft file to change feature layer properties
    # Defaults are Query,Create,Update,Delete,Uploads,Editing
    # Comment out the line below if you don't want to modify feature layer properties
    configure_featureserver_capabilities(sddraft_mod_xml_file, "Create,Sync,Query")

    # Stage Service
    print("Start Staging")
    arcpy.StageService_server(sddraft_mod_xml_file, sd_output_filename)

    # Share to portal
    print("Start Uploading")
    arcpy.UploadServiceDefinition_server(sd_output_filename, federated_server_url)

    print("Finish Publishing")

 

 

 

0 Kudos
2 Replies
DonMorrison1
Occasional Contributor III

Right, I see the same behavior when I upload to ArcGIS Online as a feature layer, and work around it by moving it to the right folder after the publish (See the code below). You may have a make some tweaks if publishing to a portal or publishing a map image layer.

 

rsp = arcpy.UploadServiceDefinition_server(<sd_filename>, "HOTING_SERVER")
gis_item = gis.content.get(rsp[3])
gis_item.move(<destination_folder>) 

 

 

tigerwoulds
Occasional Contributor III

Thanks for the tip, got me going in the right direction. I added a snippet to get everything from the root folder and move it to a specified folder. Kind of a hacky solution that makes the assumption that the root folder is empty  by default, but it does the job for now. 

arcpy.UploadServiceDefinition_server(sdOutFileName, gisServer)
    myUser = gis.users.get(parameters[1].valueAsText)
    rootfolder = myUser.items()
    for item in rootfolder:
        item.move(parameters[5].valueAsText)

 

0 Kudos