Inhalt

Azure Automation - Erweiterte Parameterverarbeitung

Beim Arbeiten mit Azure Automation kommt man schnell an den Punkt, dass ein Runbook ein zweites Runbook starten soll. Dabei möchte man meistens auch noch den einen oder anderen Parameter übergeben. Das ist alles kein Problem und schnell und einfach realisiert.

Interessant wird es jedoch wenn komplexere Objekte wie Arrays oder Hashtables übermittelt werden sollen.

Runbook mit Parametern starten

#region Connect to Azure with certificate
try {
    # Get the connection "AzureRunAsConnection "
    $servicePrincipalConnection = Get-AutomationConnection -Name "AzureRunAsConnection"
    Write-Output "Logging in to Azure..."
    Add-AzureRmAccount `
        -ServicePrincipal `
        -TenantId $servicePrincipalConnection.TenantId `
        -ApplicationId $servicePrincipalConnection.ApplicationId `
        -CertificateThumbprint   $servicePrincipalConnection.CertificateThumbprint | Out-Null
    # Switch Azure subscription
    Write-Output "Switch to Azure SubscriptionId $($servicePrincipalConnection.SubscriptionId)"
    Select-AzureRmSubscription -SubscriptionId $servicePrincipalConnection.SubscriptionId | Out-Null
} catch {
    if (!$servicePrincipalConnection) {
        throw "Connection $connectionName not found."
    } else {
        throw $_.Exception
    }
}
#endregion

#region Start new runbook
$AzureAutomationRunbook = "SuperFunRunbook"
$HybridWorker = "HybridWorkerGroup"

# Set parameters
$AzureRunbookParameter = @{
    "ParameterString" = "Blue Jeans"
    "ParameterArray" = @("BLUE","BLACK")
}
# Start runbook
Get-AzureRmAutomationAccount | Start-AzureRmAutomationRunbook -Parameters $AzureRunbookParameter -Name $AzureAutomationRunbook -RunOn $HybridWorker
#endregion

Im ersten Abschnitt liest das Skript über eine Activity die Informationen der Connection “AzureRunAsConnection” aus. Mittels dieser Informationen und dem, auf dem Hybrid Worker installierten, Zertifikat wird eine Verbindung zu Azure hergestellt und in die korrekte Subscription gewechselt.

Anschließend werden die notwendigen Variablen gesetzt. Dabei werden die Werte in der Hastable “AzureRunbookParameter” anhand Ihres Keynames auf die Parameter des zu startenden Runbooks verknüpft.

Ein Parameter, unterschiedliche Objekttypen

Im nächsten Schritt ruft das Runbook “Test-StartRunbook.ps1” ein weiteres Runbook “Test-ObjectConversion.ps1” auf. Dabei werden jeweils drei unterschiedliche Objekttypen (String, JSON und Array) als Parameter übergeben. Das zweite Runbook gibt nur den Typ des übergebenen Parameters aus.

param( [Parameter(Mandatory = $true)]$Parameter ) $Parameter.GetType()

String

/azure-automation-erweiterte-parameterverarbeitung/images/AzureAutomation_Output_String.png

JSON

/azure-automation-erweiterte-parameterverarbeitung/images/AzureAutomation_Output_JSON.png

Array

/azure-automation-erweiterte-parameterverarbeitung/images/AzureAutomation_Output_Array.png

Durch den unterschiedlichen Objekttyp ist eine einheitliche Weiterverarbeitung des Parameters nicht möglich. Das klingt im ersten Moment nach keinem großen Problem, man kann beim Aufruf über die AzureRM Cmdlets ja immer den korrekten Objekttypen nutzen.

Interessant wird es jedoch, wenn dieses Runbook über das Azure Portal gestartet wird und der Zielobjekttyp ein Array ist.

Dazu hier die Input Parameter für das Array Objekt direkt aus dem Azure Portal./azure-automation-erweiterte-parameterverarbeitung/images/AzureAutomation_Input_Array-1.png

Start per Azure Portal

Startet man nun das Runbook mit exakt den Werten, die man aus dem Input Parameters Pane kopiert hat…

/azure-automation-erweiterte-parameterverarbeitung/images/AzureAutomation_Input_Array_Manual.png

…werden diese vom Azure Portal in einen String konvertiert…

/azure-automation-erweiterte-parameterverarbeitung/images/AzureAutomation_Input_Array_Manual_Converted.png

… und kommen auch nicht als Array Objekt im Runbook an.

/azure-automation-erweiterte-parameterverarbeitung/images/AzureAutomation_Output_ArrayConverted.png

Somit ist ein manueller Start dieses Runbooks, z.B. für Debuggingzwecke, aus dem Azure Portal nicht mehr möglich.

Es gibt jedoch einen Workaround.

Konvertierung der Variablen

Die zwei Skripte am Ende des Artikels bilden exakt das Verhalten ab, dass ich oben beschrieben habe. Jedoch mit einer Erweiterung.

Sollte ein String Objekt übermittelt werden, wird dieses in ein Array Objekt konvertiert.

Dabei ist zu beachten, das multiple Werte als JSON übermittelt werden, einzelne jedoch nur als String. Daher wird im Skript erst versucht ein JSON in ein Array umzuwandeln, sollte das nicht funktionieren wird im Catch Block der String in ein Array umgewandelt.

Somit erhält man immer ein Array Objekt und kann das Runbook aus dem Azure Portal und einem Skript starten ohne sich weitere Gedanken um den Objekttyp zu machen.

Das Ergebnis aus dem vorherigen Beispiel sieht aus wie folgt.

/azure-automation-erweiterte-parameterverarbeitung/images/AzureAutomation_Output_JSONtoArray.png

Test-ObjectConversion.ps1

param(
    [Parameter(Mandatory = $true)]$Parameter
)
$Parameter.GetType()

if ($Parameter -is [array]) {
    Write-Output "It's an array. No conversion necessary."
} else {
    try {
        $Parameter = $Parameter | ConvertFrom-Json
        Write-Output "Converted from JSON to array"
    } catch {
        $Parameter = @($Parameter)
        Write-Output "Converted from String to array"
    }
}

$Parameter.GetType()

$Parameter

Test-StartRunbook.ps1

#region Connect to Azure with certificate
try {
    # Get the connection "AzureRunAsConnection "
    $servicePrincipalConnection = Get-AutomationConnection -Name "AzureRunAsConnection"
    Write-Output "Logging in to Azure..."
    Add-AzureRmAccount `
        -ServicePrincipal `
        -TenantId $servicePrincipalConnection.TenantId `
        -ApplicationId $servicePrincipalConnection.ApplicationId `
        -CertificateThumbprint   $servicePrincipalConnection.CertificateThumbprint | Out-Null
    # Switch Azure subscription
    Write-Output "Switch to Azure SubscriptionId $($servicePrincipalConnection.SubscriptionId)"
    Select-AzureRmSubscription -SubscriptionId $servicePrincipalConnection.SubscriptionId | Out-Null
} catch {
    if (!$servicePrincipalConnection) {
        throw "Connection $connectionName not found."
    } else {
        throw $_.Exception
    }
}
#endregion

$AzureAutomationRunbook = "Test-ObjectConversion"
$HybridWorker = "HybridWorkerGroup"

# Start runbook and parameter is an array
$AzureRunbookParameter = @{
    "Parameter" = "String"
}
Get-AzureRmAutomationAccount | Start-AzureRmAutomationRunbook -Parameters $AzureRunbookParameter -Name $AzureAutomationRunbook -RunOn $HybridWorker

# Start runbook and parameter is an array
$AzureRunbookParameter = @{
    "Parameter" = @("Blue","Jeans")
}
Get-AzureRmAutomationAccount | Start-AzureRmAutomationRunbook -Parameters $AzureRunbookParameter -Name $AzureAutomationRunbook -RunOn $HybridWorker

# Start runbook and parameter is an JSON
$AzureRunbookParameter = @{
    "Parameter" = ( @("Blue","Jeans") | ConvertTo-Json )
}
Get-AzureRmAutomationAccount | Start-AzureRmAutomationRunbook -Parameters $AzureRunbookParameter -Name $AzureAutomationRunbook -RunOn $HybridWorker