Azure Logic Apps – Simple, easy method to deploy a Logic App (for basic ones) using Azure PowerShell / Azure Bicep

Welcome!

This post is very juicy, very interesting, and hopefully very valuable to coders that are in need for a solution on how to deploy a Logic App. When I mean ‘deploy’, I essentially mean the ability to deploy a Logic App that is currently on a ‘Dev’ subscription/resource group, onto a ‘Prod’ subscription/resource group.

Admittingly, this article is very direct and doesn’t provide a lot of background, so you may want to learn more about ‘Azure PowerShell’ and ‘Azure Bicep’ in addition to simply reading over the code I have placed below.

For this article though, I’m going to go ahead and show the code first and then explain what it does afterwards. NOTE: Be aware that you do need to create ‘Parameters’ for your Logic App within Azure Portal if you plan on setting those to your ‘Prod’ Logic App

NOTE: The below code applies to a ‘Consumption’ Logic App. A ‘Standard’ Logic App is probably similar, but there will probably be differences between what’s written below and what you will actually need for your code

So thus, without further ado, the code for deploying a Logic App (using PowerShell and Azure Bicep is)

DeployMyLogicApp.ps1


<# NOTE: Before running this script, you must first run a 'Connect-AzAccount'  cmd in PowerShell #>

$LogicAppDevName = 'logic-mylogicapp-dev-001'
$ResourceGroupDevName = 'rg-mydevresourcegroup-001'

$LogicAppProdName = 'logic-mylogicapp-prod-001'
$ResourceGroupProdName = 'rg-myprodresourcegroup-001'

Set-AzContext -SubscriptionId 'my-prod-subscription-id'

$LogicAppProd = Get-AzLogicApp -Name $LogicAppProdName -ResourceGroupName $ResourceGroupProdName -ErrorAction SilentlyContinue

if ($LogicAppProd -eq $null) {
	# NOTE: You don't have to use the Location "Central US"; Use the location that you want to use
	New-AzTenantDeployment -Location "Central US" -TemplateFile ./initialDeployMyLogicApp_Main.bicep
}
else {
	
	Set-AzContext -SubscriptionId 'my-dev-subscription-id'
	
	$LogicAppDev = Get-AzLogicApp -Name $LogicAppProdName -ResourceGroupName $ResourceGroupProdName -ErrorAction SilentlyContinue
	
	Set-AzContext -SubscriptionId 'my-prod-subscription-id'
	
	Set-AzLogicApp -Name $LogicAppProdName -ResourceGroupName $ResourceGroupProdName -Definition $LogicAppDev.Definition -Force
}

$LogicAppProd = Get-AzLogicApp -Name $LogicAppProdName -ResourceGroupName $ResourceGroupProdName -ErrorAction SilentlyContinue

$LogicAppProd.Definition.parameters.DeploymentEnvironment.defaultValue = 'PROD' # NOTE This parameter does not have a functional purpose; its more of a 'tag'
$LogicAppProd.Definition.parameters.MyParameter1.defaultValue = 'MyParameter1Value'
$LogicAppProd.Definition.parameters.MyParameter2.defaultValue = 'MyParameter2Value'
# ...etc, for all parameters...

Set-AzLogicApp -Name $LogicAppProdName -ResourceGroupName $ResourceGroupProdName -Definition $LogicAppProd.Definition -Force

<# API Connections #>

# Remember to set the API Connections for your deployed (ie Production) Logic App after your first deploy.  This can be done within the Azure Portal, and only needs to be done after the first deploy

 

initialDeployMyLogicApp_Main.bicep



targetScope = 'tenant'

module getLogicAppDevModule 'initialDeployMyLogicApp_Part1.bicep' = {
	name: 'initialDeployMyLogicAppPart1'
	scope: resourceGroup('my-dev-subscription-id','rg-mydevresourcegroup-001')
}

module createLogicAppProdModule 'initialDeployMyLogicApp_Part2.bicep' = {
	name: 'initialDeployMyLogicAppPart2'
	scope: resourceGroup('my-prod-subscription-id','rg-myprodresourcegroup-001')
	params: {
		logicAppProperties: getLogicAppDevModule.outputs.logicAppProperties
	}
}

 

initialDeployMyLogicApp_Part1.bicep




resource logicAppDev 'Microsoft.Logic/workflows@2019-05-01' existing = {
	name: 'logic-mylogicapp-dev-001'
}

output logicAppProperties object = logicAppDev.properties


 

initialDeployMyLogicApp_Part2.bicep




param logicAppProperties object

resource logicAppProd 'Microsoft.Logic/workflows@2019-05-01' = {
	name: 'logic-mylogicapp-prod-001'
	location: resourceGroup(().location
	properties: logicAppProperties
}

 

Okay, that’s a pretty good chunk of code to digest, so I’ll explain it a little bit below.

DeployMyLogicApp.ps1

After setting all the constants at the top for LogicAppName/ResourceGroup name, the script will first set the subscription to Prod (Set-AzContext -SubscriptionId ‘my-prod-subscription-id’) and once we have that context, the script will now load the Prod Logic App ($LogicAppProd = Get-AzLogicApp -Name $LogicAppProdName -ResourceGroupName $ResourceGroupProdName -ErrorAction SilentlyContinue). Once it attempts to load it (and store in a variable), we then do a check on that variable (if ($LogicAppProd -eq $null)) to see if it is null.

If it is, then it indicates that the Logic App has never been deployed before and that we must deploy it for the first time. We will proceed with doing that (New-AzTenantDeployment -Location “Central US” -TemplateFile ./initialDeployMyLogicApp_Main.bicep). This will then run the Azure Bicep templates and create our Logic App (see sections below).

If is is not null, then it indicates that our Logic App has been deployed before, and thus we only need to update the existing Logic App. The following lines accomplish this (Set-AzContext -SubscriptionId ‘my-dev-subscription-id’

$LogicAppDev = Get-AzLogicApp -Name $LogicAppProdName -ResourceGroupName $ResourceGroupProdName -ErrorAction SilentlyContinue

Set-AzContext -SubscriptionId ‘my-prod-subscription-id’

Set-AzLogicApp -Name $LogicAppProdName -ResourceGroupName $ResourceGroupProdName -Definition $LogicAppDev.Definition -Force). This section of code fetches the Logic App that is currently in ‘Dev’, and then sets its ‘Definition’ to that of the ‘Prod’ Logic App.

After we have done the above, we now continue to the following section:

$LogicAppProd = Get-AzLogicApp -Name $LogicAppProdName -ResourceGroupName $ResourceGroupProdName -ErrorAction SilentlyContinue

$LogicAppProd.Definition.parameters.DeploymentEnvironment.defaultValue = ‘PROD’ # NOTE This parameter does not have a functional purpose; its more of a ‘tag’
$LogicAppProd.Definition.parameters.MyParameter1.defaultValue = ‘MyParameter1Value’
$LogicAppProd.Definition.parameters.MyParameter2.defaultValue = ‘MyParameter2Value’
# …etc, for all parameters…

Set-AzLogicApp -Name $LogicAppProdName -ResourceGroupName $ResourceGroupProdName -Definition $LogicAppProd.Definition -Force

These lines of code are for setting any ‘PROD’ parameters that you would like to setup for your ‘PROD’ Logic App. To do this, you must first create these Parameters in Azure Portal (go to “Logic app designer” > “Parameters”….and then create your Parameters here). Once you have these Parameters created, you can then set them once you deploy to ‘PROD’ with the values that you write into your code, like shown above.

This now finishes the DeployMyLogicApp.ps1 script

initialDeployMyLogicApp_Main.bicep

First off, note that we are doing a targetScope = ‘tenant’ deployment. This means our templates are being run at the ‘tenant’ level, so you have to make sure that a) the current tenant is the one you want to be using, and b) the tenant has access to all of Prod Subscription/Prod Resource Group/Dev Subscription/Dev Resource Group. If you need more information about this, google ‘Azure Bicep tenant scope’.

As for the actual working code itself, the Main template calls two sub-templates (or ‘modules’ I should say). The first one fetches the ‘Dev’ Logic App, and the second one takes the ‘Dev’ Logic App properties (or really, the definition of the Dev Logic App) as an input parameter and creates the ‘Prod’ Logic App, setting the properties of the ‘Prod’ Logic App to that of the ‘Dev’ Logic App.

And that concludes the initialDeployMyLogicApp_Main.bicep template

initialDeployMyLogicApp_Part1.bicep

Fairly simple and straight forward – fetches the existing ‘Dev’ Logic App, and outputs its properties

initialDeployMyLogicApp_Part2.bicep

Also fairly simple – takes the ‘logicAppProperties’ as an input parameter (this is the properties of the ‘Dev’ Logic App that is passed in, from the initialDeployMyLogicApp_Main.bicep template) and creates a new Logic App, in our Prod subscription/resource group (see the ‘scope’ property in the module call in the initialDeployMyLogicApp_Main.bicep template). This new Logic App is also defined with the properties of the ‘Dev’ Logic App > this will essentially give the ‘Prod’ Logic App the same code as the ‘Dev’ Logic App.

That concludes the coding part.

Now, one last key note I should make – these scripts above will ‘not’ work if you have a fairly complex Logic App (ie the above scripts are not able to deploy a Logic App that depends on/contains an Azure Function in it). If you are trying to do this, it is a ‘LOT’ harder! But it is doable – I will hopefully get around to making a post of it later. I will leave you with this though > you can do it if you manually deploy the prod Azure Function (which you only have to do for the initial deploy) and then in your script utilize the azcopy copy “sourceUrlForStorageOfTheSourcFuncApp” “destUrlForStorageOfDestFuncApp” –recursive and this will update the Prod Azure Function App with the definition of your Dev Azure Function App ‘Function’ call (one individual function anyways). Hopefully that will put you in the right direction 🙂

And that concludes this tutorial! Very useful for anyone trying to deploy Logic Apps with scripts/bicep templates 🙂 Hope this works out well for you during your coding travels!

Cheers,

Jeff

Azure Logic Apps – The ‘try/catch’ equivalent in Logic Apps

Hi there 🙂

For many programmers, the concept of a try/catch block is very familiar – you have a section of code that executes (the ‘try’ block), and if within that section an ‘exception’ occurs, the ‘catch’ block will then execute.

Fortunately, Logic Apps does have an exact equivalent for this 🙂 I will place it below.

(FYI – I did steal part of what’s below from another post I just made, but it applies to this post as well so I’m borrowing it 🙂 )

To implement a try/catch equivalent in Logic Apps, you can do the following

1) Add a ‘Scope’ block
2) Now that a ‘Scope’ block is in place, whenever an ‘exception’, or more specifically, an action or block ‘fails’ within the Scope block, you can handle that ‘exception’ (or ‘fail’) by adding another step after the ‘Scope’ block. You can now click on the ellipses located to the right of the title of the newly added block, and select the ‘Configure run after’ option, choose the ‘has failed’ option, and now, this newly added block will run whenever the ‘Scope’ block fails.
3) Note that you can also add another action after the ‘Scope’ block and you can set the ‘Configure run after’ to ‘has succeeded’, and then this block will execute when the ‘Scope’ block does not throw an exception (ie does not fail)

And there you have it! A Scope block, a block that runs after the Scope ‘has failed’, and thus basically the same building blocks that a try/catch block would do 🙂

Hope this helps!

Jeff

Azure Logic Apps – How to ‘throw an exception’ in Logic Apps

Hello again 🙂

While I was working away on a Logic App, I came across a situation where I wanted to essentially ‘throw an exception’, and was wondering what the equivalent option in Logic Apps is.

There are two ways you can ‘throw an exception’ in Logic Apps:

1) You can use a ‘Terminate’ action, assuming you want to end your Logic App completely (it will halt execution of the Logic App, and immediately cause the Logic App to ‘Fail’)

or

2) If you do not want to terminate the Logic App entirely, you can

a) Add a ‘Scope’ block
b) Simulate an ‘exception’ by adding a block inside the ‘Scope’ block that intentionally fails (ie add a ‘Parse JSON’ action where the ‘Content’ does not match the with ‘Schema’ defined, and thus causes the action to fail due to the ‘Content’ not being able to parse properly)
c) You can then handle the ‘exception’ accordingly by using the ‘Configure run after’ option > Add another step after the ‘Scope’ block, and click on the ellipses located to the right of the title of the newly added block, and select the ‘Configure run after’ option. Then select the ‘has failed’ option. Now, the block you have just created will run whenever the ‘Scope’ block fails.

Both of these options allow for a decent way to add exception handling to your Logic App 🙂

Hope this helps! Also, feel free to add comments to this post if needed.

Cheers,

Jeff

Azure Logic Apps – how to use a ‘local’ variable in a loop (‘For each’, ‘Until’) with parallel execution

Hi there,

While working with Azure Logic Apps, I was faced with a difficult challenging of coming up with a ‘local’ variable (actually, it was just a loop counter really) for a ‘For each’ loop.

I immediately went to using an ‘Initialize Variable’, setting the value to zero, and in my ‘For each’ loop simply do an ‘Increment Variable’ to increment it on each iteration.

What I didn’t realize at first – it was incremented by each running loop! Loops run in parallel in Logic Apps (at least by default – you can go to ‘Settings’ within the For Each block itself and set the ‘degree of parellism’ to 1, and this will also solve the problem besides the solution I’m writing), and because they run in parallel, each iteration increments the same Variable! I sort of imagined that each iteration would have its own local variable, but this is not the case.

So….unless you do the solution of setting the ‘degree of parellism’ to 1, you will need to do something to handle this. In my case, it was okay to set the ‘degree of parellism’ to 1 (the app I wrote was just doing routine maintenance, so it didn’t matter that it took an extra 5 min), but I did think of a possible solution on how you could handle the parallel case:

It’s a little bit heavy, because you will need either a) an Azure SQL DB, or b) Azure Storage, but a possible solution is:

– Create a temp table in an Azure SQL DB that will store the local variable for each iteration (where, the ‘primary key’ to your table could either be an ID you have handy, or maybe you can inject a ‘row index’ value into the item your iterating over beforehand ie before your ‘for each’ loop)

or

– Create temp files in the Azure storage, with each file associated with each iteration of your loop, and this file could store the local variable

Admittingly, neither solution is really that pretty or elegant, but I’m pretty certain it would work. It’s also dependant on having either an Azure SQL DB or a Azure storage. If neither of these is available, you might be able to use to some other ‘storage’ medium to accomplish the same goal (if its available).

Also, although not as powerful as the solution above, you may want to consider using the code function iterationIndexes(‘loopName’) as a loop counter if that’s all you need. I think it only works for ‘Until’ loops though, not for ‘For each’ loops. Feel free to google it to learn more.

Well, not the prettiest solution, but hopefully a ‘solution’ nonetheless 🙂 Hopefully this tip will help you.

Cheers!

Jeff

Azure Logic Apps – commit Logic App to Git (or any other) repo

SOLUTION FOR COMMITTING A LOGIC APP TO A (GIT) REPO:

In my recent travels as a programmer, I have been tasked with creating a Logic App for the company I work for, and one of the things I was asked was to be able to ‘commit’ the Logic App to a Git repo.

The answer didn’t come to me immediately, and I did do some research on the web to try and find a solution, but once I read an article about ‘blob storage’ and ‘json’ files…..I then remembered that a Logic App is essentially defined completely as a JSON file! Thus, I then came to this solution for committing a Logic App to Git repo:

1) Log into Azure Portal
2) Select the Logic app code view option on the left nav bar
3) Copy/Paste all the code you see in the UI into a JSON file (and save this file on your local)
4) Commit the file to Git 🙂

And that’s about it! Hopefully this tip will help you in your coding travels.

Cheers,

Jeff