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")
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>)
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)