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