2 ways to retrieve content of Azure Automation Runbook within another runbook

In this post, we’ll see how we can retrieve content of azure automation runbook from within another runbook. This content is loaded in memory. There could be multiple reasons why we would want to retrieve content of azure automation runbook. One of them could be to create a package that holds all the data from automation account. This package can be used to sync the data to other automation accounts.

There are 2 ways to do the same.

  1. Using the Get-Content cmdlet
  2. Using Export-AzureRmAutomationRunbook cmdlet

Using Get-Content Cmdlet

Consider, for example, the current runbook is Runbook1.ps1. The standard way is to use this cmdlet is to just pass the name of the runbook as shown below

Get-Content ./Runbook2.ps1

!!Caveat here!!

Now for the above cmdlet to execute correctly, the Runbook2 needs to be present within the sandbox environment at the current path where the current runbook (Runbook1.ps1) is running. This is NOT done by default when a runbook starts. Azure Automation DOES NOT get all the runbooks into the sandbox before running any. It only retrieves the ones that it sees are being INVOKED from the parent runbook.

Azure Automation parses the parent runbook and looks for any “invocations” in the code. Since Get-Content ./Runbook1.ps1 doesn’t look like an invocation, the runbook2 won’t be available and the cmdlet will return an error as shown below.

Get-Content : Cannot find path 'C:\Temp\pdur5g3d.hvp\runbook2.ps1' because it does not exist.

How to fix this

In order to fix the above issue, we need to find some way to trick Azure Automation into thinking that the parent runbook is going to invoke the second runbook. We can do this using the below snippet.

if ($false)
{
    ./Runbook2.ps1
}

Get-Content ./Runbook2.ps1

The line of code inside the IF block looks like a script invocation and so Azure Automation will ensure that this runbook is present in the sandbox before running the parent runbook and now the Get-Content will retrieve the automation runbook2.ps1 content successfully. The parser is not intelligent enough to understand that this code will never execute.

Using Export-AzureRmAutomationRunbook cmdlet

Another way to retrieve the content of the runbook is to first export the runbook to a local folder within the sandbox and then use Get-Content cmdlet directly to retrieve the content. The cmdlet syntax looks like this

$ScriptFolder = "C:\Scripts"

New-Item -itemtype Directory -Path $ScriptFolder -Force 

Export-AzureRmAutomationRunbook `
    -ResourceGroupName $AutomationResourceGroup `
    -AutomationAccountName $AutomationAccount `
    -Name "Runbook2" `
    -AzureRmContext $SubscriptionContext `
    -OutputFolder $ScriptFolder -Force

Get-Content -Path (Join-Path $ScriptFolder "Runbook2.ps1")

This will export the runbook into the given location and call to Get-Content will load the content in the memory.

Which one to use when?

Now, as you can see, you are using Get-Content in both the ways. However, the first method looks a little bit hackish as the IF block is never going to be entered into. So if you need to load contents of multiple runbooks, then I’d suggest using the second method instead as the code looks much cleaner and clear.

Another point to keep in mind is that all AzureRmAutomation cmdlets need to authenticate to Azure RM first which is an extra step and might not be convenient always. However, if you’re going to authenticate elsewhere for other reasons anyway, we can use the Export-AzureRmAutomationRunbook cmdlet without any concerns.

So finally, it’s up to you to decide which cmdlet to use depending on whether you’re ok to make your code look a bit hackish or not. Personally, I prefer using Export-AzureRmAutomationRunbook as it more clearer and shows exactly what we intend to do to the person looking at our code.

Hope this helps!

Leave a Reply

Your email address will not be published. Required fields are marked *