Automatizar operaciones de conciliación y publicación para datos versionados en rama habilitados para la sincronización

Disponible con una licencia Standard o Advanced.

Los administradores de versiones pueden utilizar scripts de Python para automatizar una conciliación programada de versiones de réplica después de que los trabajadores móviles hayan sincronizado las ediciones realizadas en los datos incluidos en el versionado en rama.

Este flujo de trabajo es aplicable a la administración de versiones de réplica que se crearon utilizando una capa de entidades web (servicio de entidades) con sincronización habilitada y datos versionados en rama.

Más información sobre cómo trabajar con mapas sin conexión con datos versionados en rama

Nota:

Este flujo de trabajo es específico del versionado en rama. El versionado tradicional requiere diferentes tareas de administración. Si utiliza el versionado tradicional, también puede automatizar las operaciones de conciliación y publicación mediante Python.

Escenario aplicable

El ejemplo de Python de la siguiente sección utiliza el servicio de entidades API REST de ArcGIS y las funciones de ArcPy para conciliar y publicar versiones de réplica con la aplicación de reglas de atributos de validación. A continuación se describe cuándo se utilizaría la muestra de código y qué hace el script de muestra.

Nota:

Este script representa un ejemplo de flujo de trabajo con una configuración de datos específica. Es posible que sus flujos de trabajo no sigan este modelo de datos exacto, pero los conceptos y la lógica de script pueden seguir utilizándose para personalizar un script automatizado para su organización. Por ejemplo, es posible que no pueda utilizar reglas de validación, pero puede modificar el script para eliminar la evaluación de las reglas de validación. Además, en algunos casos, cuando se utilizan reglas de validación, puede ser conveniente conciliar, ejecutar la validación y publicar cada versión individualmente antes de ejecutar la operación de evaluación para asegurarse de que la validación incluya las ediciones realizadas por todos los demás editores.

Requisito previo:

En este ejemplo, la configuración de datos es la siguiente:

  • La capa de entidades web debe tener habilitada la sincronización, contener datos versionados en rama y haber sido publicada con la opción Crear una versión para cada mapa descargado seleccionada, para lo que se requiere ArcGIS Enterprise 10.8.1 o posterior.
  • Las réplicas se crearon cuando un mapa con una capa de entidades web se dejó sin conexión.
  • Las credenciales proporcionadas para el usuario del portal en el script deben ser para un miembro con el rol de administrador del portal predeterminado o un rol personalizado que tenga concedido el privilegio de administración de versiones.
  • En este ejemplo, los datos también tienen reglas de atributos de validación aplicadas y la capacidad del servidor de validación habilitada. Este no es un requisito para trabajar con versiones de réplica, sino que proporciona una forma de asegurar la integridad de los datos.

A continuación mostramos un resumen de los pasos que su script deberá ejecutar tras asegurarse de que se cumplen los requisitos:

  1. Obtenga una lista de versiones de réplica para el servicio de entidades (capa de entidades web) utilizando el recurso replicas en API REST de ArcGIS.
  2. Utilice el recurso versionsInfos en API REST de ArcGIS para obtener las propiedades de la versión.

    Con estas propiedades, cree un filtro para obtener solo las versiones en las que la fecha de evaluación sea nula o la fecha modificada sea mayor que la fecha de la última evaluación (lo que significa que las ediciones se han realizado desde la última evaluación). Incorpore los nombres de las versiones que satisfacen el filtro para la lista listOfVersionsToValidate que se evaluará.

  3. Para cada versión de la lista de evaluación, utilice la operación evaluate en API REST de ArcGIS para evaluar las reglas de atributos de validación en el servicio.

    Si la evaluación resulta satisfactoria sin que se devuelvan errores, la versión de réplica está preparada para conciliar y publicar. Si la evaluación resulta satisfactoria aunque se devuelven errores, no publique las ediciones; genere un mensaje para que los errores puedan inspeccionarse y solucionarse manualmente.

  4. Para versiones que se evaluaron satisfactoriamente sin errores, ejecute la herramienta Conciliar versiones con la opción de publicar ediciones.
  5. Ejecute la herramienta Conciliar versiones con la opción para conciliar únicamente (no publicar) todas las versiones de réplica.

Ejemplo de código

El siguiente ejemplo de código de Python completa las operaciones indicadas anteriormente. Este script incluye una opción para generar un archivo de registro que capture la salida de cada operación completada y pueda visualizarse después de que se complete el script.

# Import modules
import arcpy, traceback, urllib, json, urllib.request, urllib.parse, os, urllib.error, datetime

# Overwrite the reconcile log output each time the script is run
arcpy.env.overwriteOutput = True

# Script parameters
serviceName = "MyServiceName"
baseURL = "https://MyServer.MyDomain.com"
portalAdmin = "MyAdminUser"
portalAdminPwd = "MyAdmin.Password"
logFileScript = "C:/Logs/validateRecPostScriptLog.txt"
logfileOutputRecPost = 'C:/Logs/reconcile_log.txt' 

# Choose to output a log file for the script
outputScriptReport = True

# Define functions
def openURL(url, params=None):
    """This function used to open a URL and returns the json response"""
    try:
        request_params = {'f':'pjson'}
        if params:
            request_params.update(params)
        encodedParams = urllib.parse.urlencode(request_params)
        request = urllib.request.urlopen(url, encodedParams.encode('UTF-8'))
        response = request.read()
        json_response = json.loads(response)
        return json_response
    except:
        print (traceback.format_exc())

def versionInfo(versionOwner=""):
    """This function queries the versions owned by the versionOwner.
    It returns a list of dictionaries."""
    vmsUrlinfo = "{}/server/rest/services/{}/VersionManagementServer/versionInfos?&ownerFilter={}&includeHidden=&f=json&token={}".format(baseURL, serviceName, versionOwner, token)
    response = openURL(vmsUrlinfo)
    if response['success'] == True:
        versionsDict = response['versions']
        return versionsDict
    else:
        return("Unable to get version info")

def evaluateUrl(validationUrl, validate_params):
    """This function runs evaluate on the validation server
    It returns the json response."""
    evalJsonResp = openURL(validationUrl, validate_params)
    if evalJsonResp['success'] == False:
        return [False, evalJsonResp]
    else:
        return [True, evalJsonResp]

def generateMessage(msg, print_statement=True):
    """This function generates messages as the script runs. If print_statement
    is set to True, print to the screen. If outputScriptReport is set to true,
    write the message to the logfile"""
    if outputScriptReport == True:
        with open(logFileScript, 'a') as log_file:
            log_file.write(msg + "\n")
    if print_statement == True:
        print(msg)

def recPostVersions(versionList, post):
    """This function runs the Reconcile Versions GP tool to reconcile
    and optionally post to the feature service"""
    if post == True:
        postVersion = "POST"
    elif post == False:
        postVersion = "NO_POST"
    # Reconcile and post the replica versions 
    # This tool is set to abort if there are conflicts and detects conflicts by object
    arcpy.management.ReconcileVersions(featureService,
                                        'ALL_VERSIONS',
                                        'sde.DEFAULT',
                                         versionList,
                                        'NO_LOCK_ACQUIRED',
                                        'ABORT_CONFLICTS',
                                        'BY_OBJECT',
                                        'FAVOR_EDIT_VERSION',
                                        postVersion,
                                        'KEEP_VERSION',
                                        logfileOutputRecPost)
    generateMessage(arcpy.GetMessages()+"\n")
    
# Start execution
generateMessage('Starting Validation/Reconcile/Post Automation Script... {:%Y-%b-%d %H:%M:%S}\n'.format(datetime.datetime.now()))

# Sign in to ArcGIS Enterprise    
signIntoPortal = arcpy.SignInToPortal(baseURL+"/portal", portalAdmin, portalAdminPwd)
generateMessage("Signed into ArcGIS Enterprise {} as user {}".format(baseURL+"/portal", portalAdmin))

# Get the token returned by the SignIntoPortal arcpy function to use for making REST requests
token = signIntoPortal['token']

# Build the feature service URL
featureService = "{}/server/rest/services/{}/FeatureServer".format(baseURL, serviceName)

# Get a list of the replica versions from the REST endpoint
listOfRepVersions = []
replicaVersionsURL = featureService + "/replicas?returnVersion=true&f=pjson"
repVersionsJson = openURL(replicaVersionsURL, signIntoPortal)
for repVersion in repVersionsJson:
    versionName = repVersion['replicaVersion']
    listOfRepVersions.append(versionName)
    
# Create an empty list to append version names to validate
listOfVersionsToValidate = []

# Iterate through each version returned by the versionInfo() function to find 
# the versions that need to be validated that are also in the listOfRepVersions list
for version in versionInfo():
    print("")    
    # Parse the version info response, which is a python dictionary/json
    # If the version name is sde.DEFAULT, pass since we do not want to evaluate the default version
    if version['versionName'] == "sde.DEFAULT":
        pass
    # If the modifiedDate property is null, pass
    elif version['modifiedDate'] == "None":
        pass
    # If the evaluation date is null, append the version name to the list to listOfVersions to be evaluated
    elif version['evaluationDate'] == None:
        if version['versionName'] in listOfRepVersions:
            listOfVersionsToValidate.append(version['versionName'])
    # If the evaluation date is not null, but it has been modifed since the last evaluation, add it to the list to be validated
    elif version['evaluationDate'] != None and version['modifiedDate'] > version['evaluationDate']:
        if version['versionName'] in listOfRepVersions:
            listOfVersionsToValidate.append(version['versionName'])
    # If none of these conditions are met
    else:
        generateMessage("Version {} will not be validated.".format(version['versionName']))
            
# Validate versions
generateMessage('The following versions will be validated: {}\n'.format(listOfVersionsToValidate))

# Create lists to contain versions where the validation passed or failed
failEval = []
passEval = []

# For each version in the list of versions, build the json request needed to validate
for i in listOfVersionsToValidate:
    validate_params = { "gdbVersion": i,
             "sessionId": "",
             "evaluationArea": "",
             "changesInVersion": "true",
             "selection": "",
             "evaluationType": '["validationRules"]',
             "returnEdits": "true",
             "async": "false",
             "f": "pjson",
             "token": token
    }
    # Build the REST URL used to validate the service
    validationUrl = baseURL + "/server/rest/services/"+ serviceName +"/ValidationServer/evaluate"
    
    # Call the evalVersion() function to validate the version
    evalVersion = evaluateUrl(validationUrl, validate_params)
    
    # If the evaluate failed, append to the failEval list
    if evalVersion[0] == False:
        generateMessage("Evalution of version {} failed".format(i))
        generateMessage(str(evalVersion[1]))
        failEval.append(i)
        
    # If the evaluate passed, check to see if errors were returned    
    elif evalVersion[0] == True:
        # If errors are returned, only reconcile this version
        if evalVersion[1]['errorsIdentified'] != 0:
            generateMessage("{} Errors were identified in version {}.\nThe version will be reconciled but will not be posted.\n".format((str(evalVersion[1]['errorsIdentified'])),i))
            generateMessage(str(evalVersion[1]), False)
        # If errors were not found this version can be posted
        else:
            generateMessage("Evaluation of version {} passed with no errors identified.\nThis version will be reconciled and posted.\n".format(i))
            generateMessage(str(evalVersion[1]))
            passEval.append(i)

# The versions that passed validation should be reconciled/posted
generateMessage('\nThe following versions passed validation and will be reconciled and posted: {}\n'.format(passEval))

# Run recPostVersions on the list of versions that passed evaluation with the option to post
recPostVersions(passEval, True)

# Open the reconcile log file and append the results to our report
with open(logfileOutputRecPost, 'r') as openRecLog:
    generateMessage(openRecLog.read(), False)
    
# Run recPostVersions with the option to reconcile all replica versions, no post
recPostVersions(listOfRepVersions, False)

# Open the reconcile log file and append the results to our report
with open(logfileOutputRecPost, 'r') as openRecLog:
    generateMessage(openRecLog.read(), False)

# Script execution complete
generateMessage('Validate, Reconcile, & Post Script Complete.')

Temas relacionados