¿Qué son los scripts de implementación?

Completado

En esta unidad, aprenderá cómo el recurso deploymentScripts puede ampliar las plantillas de Azure Resource Manager (ARM).

Las plantillas de ARM son fantásticas. Puede usarlas para declarar el estado deseado de la infraestructura en la nube y dejar que las API y los servicios puedan averiguar cómo llegar allí. Pero en ocasiones tendrá que realizar acciones que están fuera de lo que Azure Resource Manager proporciona.

¿Qué son los scripts de implementación?

Los recursos deploymentScripts son scripts de PowerShell o Bash que se ejecutan en un contenedor de Docker como parte de la implementación de la plantilla. Las imágenes de contenedor predeterminadas tienen la CLI de Azure o Azure PowerShell disponibles. Estos scripts se ejecutan durante el procesamiento de la plantilla de ARM, por lo que puede agregar un comportamiento personalizado al proceso de implementación.

Los scripts de implementación usan una identidad administrada para autenticarse en Azure. Una identidad administrada es una entidad de servicio cuya credencial y ciclo de vida administra la plataforma Azure. Esta identidad es lo que los comandos de Azure PowerShell o la CLI de Azure usarán para actuar en el entorno. Como tiene que asignar la identidad, puede controlar el ámbito de lo que puede afectar a un recurso deploymentScripts.

El recurso deploymentScripts genera la salida que pueden usar otros recursos de la implementación. Después, puede buscar información de un sistema externo o proporcionar datos en función del estado actual del entorno para afectar al resto de la implementación.

Cómo funcionan los scripts de implementación

Un recurso deploymentScripts toma un script proporcionado por el usuario (ya sea desde la plantilla o mediante el URI) y posiblemente algunos scripts complementarios, y los ejecuta en una instancia de contenedor de Azure. A esa instancia de contenedor se le asigna la identidad administrada que proporcione. Los scripts y su salida se almacenan en un recurso compartido de archivos para una cuenta de almacenamiento de Azure.

Cuando se ejecuta la implementación de plantilla, comprueba si hay un recurso deploymentScripts existente en el grupo de recursos de destino. Si es así, compara las propiedades. Si todo coincide, no ocurre nada nuevo. Si el recurso no existe o se ha cambiado, Azure Resource Manager crea una instancia de contenedor y ejecuta los scripts de implementación dentro de ella. Cualquier salida definida se volverá a pasar a Azure Resource Manager para su uso más adelante en la implementación.

Estructura del script de implementación

Para agregar un comportamiento personalizado a una plantilla de ARM, comience con el recurso deploymentScripts. Como mínimo, debe proporcionar detalles comunes como los siguientes:

  • Un valor name para el recurso deploymentScripts.
  • Los valores type y apiVersion.
  • La ubicación (valor location) donde se crearán los recursos complementarios.
  • Objeto properties vacío. Lo hará en breve.

Se necesitan dos valores específicos de deploymentScripts:

  • kind: tipo de script que se ejecutará (AzurePowerShell o AzureCLI).

    {
      "type": "Microsoft.Resources/deploymentScripts",
      "apiVersion": "2020-10-01",
      "name": "myFirstDeploymentScript",
      "location": "[resourceGroup().location]",
      "kind": "AzurePowerShell",
      "identity": {
        "type": "UserAssigned",
        "userAssignedIdentities": {
          "/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourcegroups/deploymenttest/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myscriptingid": {}
        }
      }
    }
    
    resource myFirstDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = {
      name: 'myFirstDeploymentScript'
      location: resourceGroup().location
      kind: 'AzurePowerShell'
      identity: {
        type: 'UserAssigned'
        userAssignedIdentities: {
          '/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourcegroups/deploymenttest/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myscriptingid': {}
        }
      }
    }
    
  • identity: la identidad administrada que usará la instancia de contenedor. Puede crear la identidad administrada con antelación y especificarla como en el ejemplo siguiente, o bien puede crearla en la plantilla y hacer referencia a ella (que es lo que hará en el ejercicio siguiente).

    {
      "type": "Microsoft.Resources/deploymentScripts",
      "apiVersion": "2020-10-01",
      "name": "myFirstDeploymentScript",
      "location": "[resourceGroup().location]",
      "kind": "AzurePowerShell",
      "identity": {
        "type": "UserAssigned",
        "userAssignedIdentities": {
          "/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourcegroups/deploymenttest/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myscriptingid": {}
        }
      }
    }
    
    resource myFirstDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = {
      name: 'myFirstDeploymentScript'
      location: resourceGroup().location
      kind: 'AzurePowerShell'
      identity: {
        type: 'UserAssigned'
        userAssignedIdentities: {
          '/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourcegroups/deploymenttest/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myscriptingid': {}
        }
      }
    }
    

Después de establecer esos elementos, puede pasar a la sección properties del recurso deploymentScripts. La parte principal de esto es scriptContent, que especifica el script real que se va a ejecutar:

"properties": {
  "scriptContent": "
      $output = 'Hello Learner!'
      Write-Output $output
      $DeploymentScriptOutputs = @{}
      $DeploymentScriptOutputs['text'] = $output
  ",
}
properties: {
  scriptContent: '''
    $output = 'Hello Learner!'
    Write-Output $output
    $DeploymentScriptOutputs = @{}
    $DeploymentScriptOutputs['text'] = $output
  '''
}

Observe que scriptContent usa una cadena de varias líneas. En Bicep, puede especificar una cadena de varias líneas mediante tres comillas juntas (''') antes y después de la cadena.

Es habitual que un script de implementación devuelva las salidas a la implementación. Por ejemplo, si usa un script para buscar información de una API, podría devolver la información a la implementación como salida. Otros recursos de la implementación podrían usar la información en sus propias definiciones.

Para un script de PowerShell, las salidas se devuelven mediante la creación de una variable denominada $DeploymentScriptOutputs, que debe ser una tabla hash. El script de ejemplo inicializa la tabla hash y, después, crea una salida denominada text, que toma su valor de la variable local $output:

$output = 'Hello Learner!'
Write-Output $output
$DeploymentScriptOutputs = @{}
$DeploymentScriptOutputs['text'] = $output
$output = 'Hello Learner!'
Write-Output $output
$DeploymentScriptOutputs = @{}
$DeploymentScriptOutputs['text'] = $output

Sugerencia

También puede escribir scripts de implementación en Bash. Para crear salidas a partir de un script de Bash, debe crear un archivo JSON en una ubicación especificada por la variable de entorno AZ_SCRIPTS_OUTPUT_PATH.

Dentro de la sección properties, también se definen las distintas opciones que deploymentScripts puede tomar. En este módulo, el proceso será sencillo y solo se agregará lo suficiente para que se ejecute el script. Como mínimo, debe proporcionar la versión de Azure PowerShell o la CLI de Azure que se va a usar, un script para ejecutar y un intervalo de retención.

El intervalo de retención es cuánto tiempo se deben conservar los resultados si se quieren conservar los recursos. De forma predeterminada, los resultados se quitan después de ejecutar el script.

"properties": {
  "azPowerShellVersion": "3.0",
  "scriptContent": "
      $output = 'Hello Learner!'
      Write-Output $output
      $DeploymentScriptOutputs = @{}
      $DeploymentScriptOutputs['text'] = $output
  ",
  "retentionInterval": "P1D"
}
properties: {
  azPowerShellVersion: '3.0'
  scriptContent: '''
    $output = 'Hello Learner!'
    Write-Output $output
    $DeploymentScriptOutputs = @{}
    $DeploymentScriptOutputs['text'] = $output
  '''
  retentionInterval: 'P1D'
}

La plantilla completa tendría un aspecto parecido al siguiente:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.1",
  "apiProfile": "",
  "parameters": {},
  "variables": {},
  "functions": [],
  "resources": [
    {
      "type": "Microsoft.Resources/deploymentScripts",
      "apiVersion": "2020-10-01",
      "name": "myFirstDeploymentScript",
      "location": "[resourceGroup().location]",
      "kind": "AzurePowerShell",
      "identity": {
        "type": "UserAssigned",
        "userAssignedIdentities": {
          "/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourcegroups/deploymenttest/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myscriptingid": {}
        }
      },
      "properties": {
        "azPowerShellVersion": "3.0",
        "scriptContent": "
            $output = 'Hello Learner!'
            Write-Output $output
            $DeploymentScriptOutputs = @{}
            $DeploymentScriptOutputs['text'] = $output
        ",
        "retentionInterval": "P1D"
      }
    }
  ],
  "outputs": {
    "scriptResult": {
      "type": "string",
      "value": "[reference('myFirstDeploymentScript').outputs.text]"
    }
  }
}
resource myFirstDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = {
  name: 'myFirstDeploymentScript'
  location: resourceGroup().location
  kind: 'AzurePowerShell'
  identity: {
    type: 'UserAssigned'
    userAssignedIdentities: {
      '/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourcegroups/deploymenttest/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myscriptingid': {}
    }
  }
  properties: {
    azPowerShellVersion: '3.0'
    scriptContent: '''
      $output = 'Hello Learner!'
      Write-Output $output
      $DeploymentScriptOutputs = @{}
      $DeploymentScriptOutputs['text'] = $output
    '''
    retentionInterval: 'P1D'
  }
}

output scriptResult string = myFirstDeploymentScript.properties.outputs.text

Inclusión de archivos de script

La inserción de scripts en plantillas puede ser complicada y difícil de leer, comprender y de cambiar. Bicep usa la función loadTextContent() para insertar un archivo de texto externo en la implementación. Cuando Bicep transcribe la plantilla en JSON, inserta el archivo externo en la plantilla que emite.

Imagine que tiene un archivo de PowerShell denominado myscript.ps1 en la misma carpeta que la plantilla de Bicep. Puede indicarle a Bicep que inserte el archivo de la siguiente forma:

properties: {
  azPowerShellVersion: '3.0'
  scriptContent: loadTextContent('myscript.ps1')
  retentionInterval: 'P1D'
}

Puede encontrar todas las propiedades del recurso deploymentScripts en la documentación de referencia de las plantillas de ARM.