Updating Azure modules – In Azure Automation


Recently I wrote an article about Azure Alert Aggregation.  In that article I talked about the need to keep your modules up to date.   Since that time I spoke to @joDogLevy at Microsoft and he suggested that I submit a question on their forums:

https://social.msdn.microsoft.com/Forums/azure/en-US/eb95fcc1-d94f-42b1-a8d5-274d287bb2cd/updating-modules-in-azure?forum=azureautomation

He then provided the script to allow for updating modules in your Azure automation account as they become available.

I’ve since then updated the script to allow for a Subscription Name and a Credential from Azure Active directory.  Here is the script I came up with below.

param(
    [Parameter(Mandatory=$true)]
    [String] $ResourceGroupName,

    [Parameter(Mandatory=$true)]
    [String] $AutomationAccountName,

    [Parameter(Mandatory=$false)]
    [String] $AzCredential = 'MyAccount',

    [Parameter(Mandatory=$false)]
    [string] $subscriptionName = 'Azure Testing'

)

try {
 
    'Logging in to Azure...'
    $cred = Get-AutomationPSCredential -Name $AzCredential
    Add-AzureRmAccount -Credential $cred
}
catch {
    if(!$cred) {
        throw "Connection $AzCredential not found."
    }
    else {
        throw $_.Exception
    }
}
set-azurermContext -SubscriptionName $subscriptionName

$Modules = Get-AzureRmAutomationModule `
    -ResourceGroupName $ResourceGroupName `
    -AutomationAccountName $AutomationAccountName

$AzureRMProfileModule = Get-AzureRmAutomationModule `
    -ResourceGroupName $ResourceGroupName `
    -AutomationAccountName $AutomationAccountName `
    -Name 'AzureRM.Profile'

# Force AzureRM.Profile to be evaluated first since some other modules depend on it 
# being there / up to date to import successfully
$Modules = @($AzureRMProfileModule) + $Modules

foreach($Module in $Modules) {

    $Module = $Modules = Get-AzureRmAutomationModule `
        -ResourceGroupName $ResourceGroupName `
        -AutomationAccountName $AutomationAccountName `
        -Name $Module.Name
    
    $ModuleName = $Module.Name
    $ModuleVersionInAutomation = $Module.Version

    Write-Output "Checking if module '$ModuleName' is up to date in your automation account"

    $Url = "https://www.powershellgallery.com/api/v2/Search()?`$filter=IsLatestVersion&searchTerm=%27$ModuleName%27&targetFramework=%27%27&includePrerelease=false&`$skip=0&`$top=40" 
    Write-output $Url
    $SearchResult = Invoke-RestMethod -Method Get -Uri $Url -UseBasicParsing

    if(!$SearchResult) {
        Write-Error "Could not find module '$ModuleName' in PowerShell Gallery."
    }
    elseif($SearchResult.Length -and $SearchResult.Length -gt 1) {
        Write-Error "Module name '$ModuleName' returned multiple results. Please specify an exact module name."
    }
    else {
        $PackageDetails = Invoke-RestMethod -Method Get -UseBasicParsing -Uri $SearchResult.id 
        $LatestModuleVersionOnPSGallery = $PackageDetails.entry.properties.version

        if($ModuleVersionInAutomation -ne $LatestModuleVersionOnPSGallery) {
            Write-Output "Module '$ModuleName' is not up to date. Latest version on PS Gallery is '$LatestModuleVersionOnPSGallery' but this automation account has version '$ModuleVersionInAutomation'"
            Write-Output "Importing latest version of '$ModuleName' into your automation account"

            $ModuleContentUrl = "https://www.powershellgallery.com/api/v2/package/$ModuleName/$ModuleVersion"

            # Find the actual blob storage location of the module
            do {
                $ActualUrl = $ModuleContentUrl
                $ModuleContentUrl = (Invoke-WebRequest -Uri $ModuleContentUrl -MaximumRedirection 0 -UseBasicParsing -ErrorAction Ignore).Headers.Location 
            } while($ModuleContentUrl -ne $Null)

            $Module = New-AzureRmAutomationModule `
                -ResourceGroupName $ResourceGroupName `
                -AutomationAccountName $AutomationAccountName `
                -Name $ModuleName `
                -ContentLink $ActualUrl
                
            while($Module.ProvisioningState -ne 'Succeeded' -and $Module.ProvisioningState -ne 'Failed') {
                Start-Sleep -Seconds 10
            
                $Module = Get-AzureRmAutomationModule `
                    -ResourceGroupName $ResourceGroupName `
                    -AutomationAccountName $AutomationAccountName `
                    -Name $ModuleName

                Write-Output 'Polling for import completion...'
            }

            if($Module.ProvisioningState -eq 'Succeeded') {
                Write-Output "Successfully imported latest version of $ModuleName"
            }
            else {
                Write-Error "Failed to import latest version of $ModuleName"
            }   
        }
        else {
            Write-Output "Module '$ModuleName' is up to date."
        }
   }
}

I hope this helps someone ..

Until then keep scripting

Thom

2 thoughts on “Updating Azure modules – In Azure Automation

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s