Uso de scripts de implementación para comprobar las propiedades de los recursos

En este artículo se describe cómo usar Bicep y un script de implementación para pausar una implementación hasta que una propiedad de recurso devuelva un valor específico. Puede usar esta técnica para asegurarse de que una implementación se realiza correctamente si los recursos implementados informan a Azure Resource Manager de que está listo, pero los recursos subyacentes no. En este caso, el recurso implementado aún no está listo para interactuar con el resto de la implementación, lo que significa que se requiere una pausa.

En este artículo se usa un escenario de Azure Virtual WAN para demostrar la técnica. Los siguientes archivos incluyen una comprobación de recursos y una implementación de pausa:

Puede adaptar los archivos para su implementación. Para ayudarle, el módulo azResourceStateCheck.bicep está parametrizado. La dependsOn propiedad se usa en orchestration.bicep para asegurarse de que la implementación del módulo vwanvhcs.bicep depende de la implementación del módulo azResourceStateCheck.bicep.

Architecture

Diagrama que muestra el Bicep y la arquitectura del script de implementación.

Descargue un archivo de Visio de esta arquitectura.

Revise y descargue los ejemplos de código en GitHub para esta arquitectura.

  1. Envíe el archivo orchestration.bicep para su implementación en Resource Manager en el ámbito de la suscripción.

    Nota

    Puede obtener este archivo de Bicep y los demás archivos que se usan para este ejemplo desde el directorio infra/samples/deployment-scripts-property-check. Aparece una organización parcial de los archivos del repositorio en el lado derecho del diagrama de arquitectura.

  2. El archivo orchestration.bicep crea un grupo de recursos en el ámbito de la suscripción.

  3. El archivo orchestration.bicep implementa el Virtual WAN y las redes virtuales conectadas.

    • orchestration.bicep implementa el módulo vwan.bicep, que implementa el Virtual WAN en el ámbito del grupo de recursos.

    • orchestration.bicep implementa el módulo vnet.bicep, que implementa las redes virtuales en el ámbito del grupo de recursos.

    Las redes virtuales de satélite y la WAN virtual se implementan en paralelo porque Bicep las considera independientes entre sí. Las dependencias determinan el orden de implementación en Bicep. Un recurso se implementa antes de cualquier recurso que dependa de él. Para obtener más información sobre las dependencias de recursos en Bicep, incluidas las dependencias explícitas e implícitas, consulte Dependencias de recursos en Bicep.

  4. El archivo orchestration.bicep implementa el módulo vwanhub.bicep, que implementa el centro de Virtual WAN en el ámbito del grupo de recursos. El centro depende implícitamente de la Virtual WAN, lo que significa que la implementación del centro solo se produce después de que se complete la implementación de Virtual WAN.

  5. El archivo orchestration.bicep implementa el módulo azResourceStateCheck.bicep, que crea una identidad administrada asignada por el usuario y asigna el rol lector de control de acceso basado en rol (RBAC) de Azure al grupo de recursos.

  6. El módulo azResourceStateCheck.bicep implementa el recurso de script de implementación.

  7. El recurso de script de implementación usa la identidad administrada asignada por el usuario para Resource Manager autenticación. A continuación, el recurso ejecuta el script de implementación de PowerShell, Invoke-AzResourceStateCheck.ps1. Para obtener más información sobre los scripts de implementación, consulte Uso de scripts de implementación en Bicep.

    El script sondea la propiedad del hub de Virtual WAN routingState para determinar si el valor es Provisioned.

    1. Si el valor de la propiedad no es Provisioned, el script se pausa por un tiempo definido por un parámetro establecido en el archivo orchestration.bicep y se pasa al módulo azResourceStateCheck.bicep. A continuación, el script vuelve a comprobar el valor de la routingState propiedad.

      El script repite el ciclo de pausa y comprobación. Un parámetro del archivo orchestration.bicep determina el número máximo de iteraciones. Si el valor de la propiedad no es Provisioned después del número máximo de iteraciones, el script genera una excepción y se cierra, lo que hace que el resto de la implementación de Bicep se detenga y produzca un error.

    2. Si el valor de la propiedad es Provisioned, el script de implementación sale con un código de éxito (0).

  8. Si el script de implementación se realiza correctamente, el archivo orchestration.bicep implementa el módulo vwanvhcs.bicep, que crea las conexiones entre las redes virtuales radiales y el centro de Virtual WAN.

    La definición del módulo vwanvhcs.bicep que se encuentra en orchestration.bicep tiene una dependsOn cláusula que hace que vwanvhcs.bicep dependa explícitamente de la finalización correcta del módulo azResourceStateCheck.bicep. Por lo tanto, las conexiones solo se crean si la routingState propiedad es Provisioned.

    El módulo vwanvhcs.bicep implementa las conexiones de concentrador de Virtual WAN secuencialmente, en lugar de en paralelo, ya que no se admite la implementación paralela para un único centro de Virtual WAN. Para establecer el tamaño del lote en 1, el módulo utiliza el decorador Bicep batchSize, @batchSize(1). Este decorador asegura que las conexiones se implementan una por una.

Detalles del escenario

Las partes clave de esta arquitectura son el módulo azResourceStateCheck.bicep, que implementa el recurso de script de implementación y el script de implementación asociado Invoke-AzResourceStateCheck.ps1, que es un archivo de PowerShell. El módulo usa el script de implementación para comprobar el valor de una propiedad de recurso. En este ejemplo, el recurso es un centro de Virtual WAN.

Puede usar dependsOn para que un módulo dependa explícitamente de otro porque este entorno se implementa desde un único archivo que usa módulos Bicep. En este ejemplo, dependsOn hace que el módulo vwanvhcs.bicep dependa del módulo azResourceStateCheck.bicep.

El siguiente extracto de orchestration.bicep muestra dependsOn en uso:

@description('The API version of the Azure Resource you need to use to check the state of a property.')
param parAzResourceApiVersion string = '2022-01-01'

@description('The property of the resource that you need to check. This is a property inside the `properties` bag of the resource that's captured from a GET call to the Resource ID.')
param parAzResourcePropertyToCheck string = 'routingState'

@description('The value of the property of the resource that you need to check.')
param parAzResourceDesiredState string = 'Provisioned'

@description('The duration that the deployment script waits between check or polling requests to check the property and its state, if it is not in its desired state. The duration defaults to `30` seconds.')
param parWaitInSecondsBetweenIterations int = 30

module modVWANHub 'modules/vwanHub.bicep' = {
  scope: rsg
  name: 'deployVWANHub'
  params: {
    region: region
    regionNamePrefix: regionNamePrefix
    defaultTags: defaultTags
    vwanHubCIDR: vwanHubCIDR
    vwanName: modVWAN.outputs.vwanName
  }
}

module modVWANHubRouterCheckerDeploymentScript 'modules/azResourceStateCheck.bicep' = {
  scope: rsg
  name: 'deployVWANHubRouterChecker'
  params: {
    parLocation: region
    parAzResourceId: modVWANHub.outputs.outVwanVHubId
    parAzResourceApiVersion: parAzResourceApiVersion
    parAzResourcePropertyToCheck: parAzResourcePropertyToCheck
    parAzResourceDesiredState: parAzResourceDesiredState
    parMaxIterations: parMaxIterations
    parWaitInSecondsBetweenIterations: parWaitInSecondsBetweenIterations
  }
}

module modVWanVhubVnetConnections 'modules/vwanVhcs.bicep' = {
  dependsOn: [
    modVWANHubRouterCheckerDeploymentScript
  ]
  scope: rsg
  name: 'deployConnectVnetsToVWANVHub'
  params: {
    vnets: vnets
    regionNamePrefix: regionNamePrefix
  }
}

La comprobación de recursos es necesaria porque las Virtual WAN hubs implementadas no están listas para su uso hasta que la propiedad /> . Virtual WAN hubs notifican una implementación correcta para Resource Manager para que el motor de implementación continúe con la implementación. Un nuevo concentrador de Virtual WAN se vuelve operativo después de que el enrutador del concentrador de Virtual WAN se aprovisione en el concentrador creado. Este proceso tarda aproximadamente 15 minutos. Este comportamiento se puede ver en la captura de pantalla siguiente de un nuevo centro de Virtual WAN. En la captura de pantalla se muestra un estado del concentrador de Succeeded, pero un estado de enrutamiento de Provisioning.

Captura de pantalla de un centro de Virtual WAN recién implementado. El estado del centro es Completado y el estado de enrutamiento es Provisionamiento.

Si intenta implementar el módulo vwanvhcs.bicep antes de que el valor sea routingState, se produce un error en la Provisioned creación de la conexión y se produce un error en la implementación general. Hasta que se configure el enrutador, los intentos de reimplementación también fallarán.

En la captura de pantalla siguiente se muestra un ejemplo del registro de scripts de implementación durante las routingState comprobaciones del hub de Virtual WAN. El registro muestra comprobaciones repetidas de la propiedad que devuelven un valor distinto de Provisioned.

Captura de pantalla que muestra cómo el script de implementación consulta la propiedad routingState en el hub de Virtual WAN.

En la captura de pantalla siguiente se muestra que el valor cambia a Provisioned.

Captura de pantalla que muestra la finalización del script de implementación cuando la propiedad routingState del centro de Virtual WAN cambia a Provisto.

Si el valor no cambia a Provisioned después del número máximo de iteraciones, el script genera una excepción que indica al Administrador de Recursos que ha fallado el recurso de script. El motor de implementación de Resource Manager produce un error y detiene la implementación porque la excepción sugiere que hay un problema con el recurso Azure que requiere solución de problemas. Para obtener más información, consulte el siguiente script de Invoke-AzResourceStateCheck.ps1.

[CmdletBinding()]
param (
  [string]
  $azResourceResourceId,

  [string]
  $apiVersion = "2022-05-01",

  [string]
  $azResourcePropertyToCheck = "provisioningState",

  [string]
  $azResourceDesiredState = "Provisioned",

  [int]
  $waitInSecondsBetweenIterations = 30,

  [int]
  $maxIterations = 30
)

$totalTimeoutCalculation = $waitInSecondsBetweenIterations * $maxIterations

$azResourcePropertyExistenceCheck = Invoke-AzRestMethod -Method GET -Path "$($azResourceResourceId)?api-version=$($apiVersion)"

if ($azResourcePropertyExistenceCheck.StatusCode -ne "200") {
  $DeploymentScriptOutputs["azResourcePropertyState"] = "Not Found"
  throw "Unable to get Azure Resource - $($azResourceResourceId). Likely it doesn't exist. Status code: $($azResourcePropertyExistenceCheck.StatusCode) Error: $($azResourcePropertyExistenceCheck.Content)"
}

$azResourcePropertyStateResult = "Unknown"
$iterationCount = 0

do {
  $azResourcePropertyStateGet = Invoke-AzRestMethod -Method GET -Path "$($azResourceResourceId)?api-version=$($apiVersion)"
  $azResourcePropertyStateJsonConverted = $azResourcePropertyStateGet.Content | ConvertFrom-Json -Depth 10
  $azResourcePropertyStateResult = $azResourcePropertyStateJsonConverted.properties.$($azResourcePropertyToCheck)

  if ($azResourcePropertyStateResult -ne $azResourceDesiredState) {
    Write-Host "Azure Resource Property ($($azResourcePropertyToCheck)) is not in $($azResourceDesiredState) state. Waiting $($waitInSecondsBetweenIterations) seconds before checking again. Iteration count: $($iterationCount)"
    Start-Sleep -Seconds $waitInSecondsBetweenIterations
    $iterationCount++
  }
} while (
  $azResourcePropertyStateResult -ne $azResourceDesiredState -and $iterationCount -ne $maxIterations
)

if ($azResourcePropertyStateResult -eq $azResourceDesiredState) {
  Write-Host "Azure Resource Property ($($azResourcePropertyToCheck)) is now in $($azResourceDesiredState) state."
  $DeploymentScriptOutputs["azResourcePropertyState"] = "$($azResourceDesiredState)"
}

if ($iterationCount -eq $maxIterations -and $azResourcePropertyStateResult -ne $azResourceDesiredState) {
  $DeploymentScriptOutputs["azResourcePropertyState"] = "Azure Resource Property ($($azResourcePropertyToCheck)) is still not in desired state of $($azResourceDesiredState). Timeout reached of $($totalTimeoutCalculation) seconds."
  throw "Azure Resource Property ($($azResourcePropertyToCheck)) is still not in $($azResourceDesiredState) state after $($totalTimeoutCalculation) seconds."
}

Colaboradores

Microsoft mantiene este artículo. Los siguientes colaboradores escribieron este artículo.

Autor principal:

  • Jack Tracey | Arquitecto sénior de soluciones en la nube

Otro colaborador:

  • Gary McMahon | Arquitecto sénior de soluciones en la nube

Para ver los perfiles no públicos de LinkedIn, inicie sesión en LinkedIn.

Pasos siguientes