Logic Apps can be created from the Azure Portal, or using Visual Studio. This works well if you want to create one Logic App at a time. However, if you want to deploy the same Logic App in multiple environments, e.g. Dev, Test, or Production, you want to do it in an automated way. Azure Resource Manager (ARM) Templates allow you to define Azure Resources, including Logic Apps, for automated deployment to multiple environments in a consistent and repeatedly way. ARM Templates can be tailored for each environment using a Parameters file.
The deployment of Logic Apps using ARM Templates and Parameters can be automated with different tools, such as, PowerShell, Azure CLI, or VSTS. In my projects, I normally use a VSTS release definition for this.
You probably have noticed that the Logic App Workflow Definition Language (the JSON code behind) has many similarities with the ARM Templates structure, including the use of expressions and functions, variables, and parameters.
ARM Template expressions and functions are written within JSON string literals wrapped with square brackets []. ARM expressions and functions can appear in different sections of the ARM template, including the resources member, which might contain Logic Apps. The value of these expressions is evaluated at deployment time. More information here.
Logic App expressions and functions are defined within the Logic App definition and might appear anywhere in a JSON string value. Logic Apps expressions and functions are evaluated at execution time. These are declared using the @ sign. More information here.
These similarities can be confusing by themselves. I’ve seen that it’s a quite common practice in ARM Templates with Logic Apps, to use ARM template expressions inside the Logic App definition. For example, using ARM parameters, ARM variables or ARM functions (like concat), within the definition of a Logic App. This might seem OK, as this is what you would normally do to tailor your deployment for any other Azure resources. However, in Logic Apps, this can be quite cumbersome. If you’ve done it, I’m almost sure that you know what I’m talking about ;).
In this post, I’ll share some practices that I use to ease the preparation of Logic Apps for Continuous Integration / Continuous Delivery (CI/CD) to multiple environments using ARM Templates, when values inside the Logic App definition have to be customised per environment. If you don’t have to change values within the Logic App definition, then you might not need to follow every step of this post.
As I mentioned above, if when preparing you Logic Apps for CI/CD with ARM Templates, you have used ARM template expressions or functions inside a Logic App definition, you most probably have realised that it’s quite troublesome. I personally don’t like to do it that way for two reasons:
So, the question is, is it possible to create ARM Templates for Logic Apps that can be parameterised for multiple environments while avoiding using ARM template expressions inside the Logic App definition? Fortunately, it is :). Below, I describe how.
For this post, I will work with a rather simple scenario: A Logic App that is triggered when a message in a Service Bus queue is received and posts the message to an https endpoint using basic auth. The endpoint url, the username and password will be different for each environment. Additionally, the Service Bus API Connection will have to be defined per environment.
This very simple workflow created using the Logic App editor is shown below:
And the code behind this workflow is as follows:
The code is very straight forward, but the endpoint, username and password are yet static. Not ideal for CI/CD!
In this section, I’ll show how you can prepare your Logic App for CI/CD to be deployed to multiple environments using ARM Templates, without having to use any ARM Template expressions or functions inside a Logic App definition.
Similarly to ARM Templates, the Logic App workflow definition language accepts parameters. We can use these Logic Apps parameters to prepare our Logic App definition for CI/CD. We need to add a Logic App parameter for every value that is to be tailored for each environment. Unfortunately, at the time of writing, adding Logic App parameters can only be done via the code view.
Using the code view, we need to:
I’ve done this using the code view of the workflow shown above. The updated workflow definition is as follows.
After this update, at this point in time, the workflow should work just as before, but now, instead of having fixed values, you are using Logic Apps parameters with default values. If you are doing it for yours, you can test it yourself :)
Once the Logic App is ready, we can get the ARM Template for CI/CD. One easy way to do it is to use the Visual Studio Tools for Logic Apps. This requires Visual Studio 2015 or 2017, the latest Azure SDK and the Cloud Explorer. You can also use the Logic App Template Creator PowerShell module. More information on how to create ARM Templates for Logic Apps here.
The Cloud Explorer will allow you to log in to your Azure Subscription and see the supported Azure resources, including Logic Apps. When you expand the Logic Apps menu, you will see all the Logic Apps available for that subscription.
Once you’ve found the Logic App you want to export, right click on it, and click on Open with Logic App Editor. This will open the Logic App Editor on Visual Studio.
In addition to allowing to edit Logic Apps on Visual Studio, the Visual Studio Logic App Tools let you to download the ARM Template that includes the Logic App. You just need to click the Download button, and you will get an almost ready-to-deploy ARM Template. This functionality exports the Logic App API Connections as well.
For this workflow, I got an ARM Template as follows:
As you can see, this ARM Template includes
The structure of the ARM Template can be seen in the picture below.
Once we have the ARM Template, we can set the Logic App parameters values with ARM expressions and functions, including ARM parameters or ARM variables. I’ve done it with my ARM Template as shown below.
Before you check the updated ARM Template, some things to note:
As you can see, now we are only using ARM Template expressions and functions outside the Logic App definition. This is much easier to read and maintain. Don’t you think?
Now that we have the ARM Template ready, we can prepare an ARM Parameters file for our deployment to each environment. Below I show an example of this.
Once we have the ARM Template and the ARM Parameter files, we can automate the deployment using our preferred tool. If you want to use VSTS, this is a good video that shows you how.
Once you have deployed the ARM Template, you will be able to see the deployed Logic App. The Logic App parameters value set section is hidden, but if you execute it, you will see how the values have been set accordingly.
You might be thinking, just as I am, that this process is not as intuitive as it should be, and is a bit time consuming. If you wish to ask the product team to improve this, you might want to vote for these user voice requests on the links below:
In this post, I’ve shown how to prepare your Logic Apps for CI/CD to multiple environments using ARM Templates in a more convenient way, i.e. without using ARM Template expressions or functions inside the Logic App definition. I believe that this approach makes the ARM Template of a Logic App much easier to read and to maintain.
This method not only avoids the need of writing complex ARM Template expressions inside a Logic App definition, but also allows you to update your Logic App in the Designer, after this has been deployed using ARM Templates, and later update the ARM Template by simply updating the Logic App definition section. That's much better, isn't it?
I hope you’ve found this post handy, and it has helped you to streamline the configuration of your CI/CD pipelines when implementing Logic Apps.
Do you have a different preferred way of preparing your Logic Apps for CI/CD? Feel free to leave your comments or questions below,
Happy clouding and automating!
P.S. And remember: “I will never use ARM Template expressions inside a Logic App definition” ;)
Cross-posted on Paco’s Blog.
Follow Paco on @pacodelacruz.