Running Azure PowerShell Workflows without Azure Automation
While developing some Workflows recently I was frustrated by something that was seemingly so simple to resolve. I’d log in to Azure and then run my parallel Workflow to perhaps start up a set of VMs in a Resource Group and get slammed with a boat load of errors.
1 |
Microsoft.PowerShell.Utility\Write-Error : Run Login-AzureRmAccount to login. |
This is the code I was running – it is specifically not designed to run in Azure Automation because I don’t want it to. Running this in Azure Automation requires a significant number of steps that I don’t want to perform so I’m not using the RunAs account. It’s a few lines of PowerShell designed to start up the VMs in a resource group quickly.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# First, log in Login-AzureRmAccount # Get the objects to work on. $VMObjects = Get-AzureRmVM -ResourceGroupName 'VMRESOURCEGROUP' # Create the Workflow Workflow PowerOn { # Retrieve the parameters. param ( [parameter(Mandatory=$true)] [psobject]$AzureRmVmObject ) # Perform a parallel execution - each is a separate job, so needs the profile every time! foreach -parallel -throttlelimit 5 ($VM in $AzureRmVmObject ) { Write-Output "[[[ STARTUP REQUESTED ]]] FOR $($VM.Name)..." # Give some information $StartRtn = Start-AzureRmVM -Name $VM.Name -ResourceGroupName $VM.ResourceGroupName # Perform the action. if ($StartRtn.Status -ne 'Succeeded') { Write-Output ("[[[$($VM.Name)]]] failed to start!") } else { Write-Output ("[[[ $($VM.Name) ]]] has been started.") } # Give some information } } # Invoke the Workflow, providing the object. PowerOn -AzureRmVmObject $VMObjects |
This would just blow up. The problem was clear enough, as a child of the parent, the parallel execution has no knowledge of my account being logged in and I just wasn’t sure how to resolve that. Many moons ago I tinkered with using Save-AzureRmProfile to save me from having to log in every time I wanted to do something in Azure but I fell out of love with the solution since the saved profile never seemed to last very long. After some Googling, I happened upon an issue report in GitHub for Azure PowerShell that seemed relevant.
The issue report was answered by Mark Cowl who advised that the child job has no knowledge of the profile and, by passing in the profile to the child job in the right place by using Select-AzureRmProfile , you could work around the problem. The lightbulb came on and I altered my script and Workflow to:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# First, log in Login-AzureRmAccount # Set the path in to which your profile will be saved $Path = '.\AzureRmProfile.json' # Save the profile - we do this every time because it does time out. Save-AzureRmProfile -Path $Path -Force # Get the objects to work on. $VMObjects = Get-AzureRmVM -ResourceGroupName 'VMRESOURCEGROUP' # Create the Workflow Workflow PowerOn { # Retrieve the parameters. The objects to work on and the profile path are mandatory param ( [parameter(Mandatory=$true)] [psobject]$AzureRmVmObject, [parameter(Mandatory=$true)] [psobject]$ProfilePath ) # Perform a parallel execution - each is a separate job, so needs the profile every time! foreach -parallel -throttlelimit 5 ($VM in $AzureRmVmObject ) { $Profile = Select-AzureRmProfile -Path $ProfilePath # Get the profile Write-Output "[[[ STARTUP REQUESTED ]]] FOR $($VM.Name)..." # Give some information $StartRtn = Start-AzureRmVM -Name $VM.Name -ResourceGroupName $VM.ResourceGroupName # Perform the action. if ($StartRtn.Status -ne 'Succeeded') { Write-Output ("[[[$($VM.Name)]]] failed to start!") } else { Write-Output ("[[[ $($VM.Name) ]]] has been started.") } # Give some information } } # Invoke the Workflow, providing the objects and the profile path. PowerOn -AzureRmVmObject $VMObjects -ProfilePath $Path |
Simple when you think about it.
You’ll notice in the foreach -parallel there is a throttlelimit set. I have my reasons for including this, yours may differ so feel free to remove the throttle altogether or alter it appropriately.
-Lewis
Glorious! Thank you for sharing your experience! I wonder who else encountered the exact same problem after learning about the awesomness of Powershell-Workflow vs Invoke-Command/Start-Process!