Bicep for Azure Function Apps - from Manual to Automated Infrastructure
Another post on Try and Trash here introduces the Morning Wisher project that uses Azure Functions and Azure Communication Services to send daily emails with good morning wishes. That post is divided into two parts: setting up Azure resources and implementing the code.
The way Azure resources are set up is referred to as infrastructure. Setting up the infrastructure manually and describing it in English and with screenshots is ok to start with; however, a more precise way is to declare the infrastructure with code. Bicep is an example of a tool that can declare infrastructure in code.
This post shows how to set up a Bicep script to deploy infrastructure of the Morning Wisher project. The new infrastructure is kept as close to the original as possible.
The source code is available in the pull request here
Reference Templates
Development does not need to start from scratch. Bicep templates for various scenarios are available online. This section outlines a few reference template sources.
Exporting Templates from Existing Resources
The Azure Portal UI for resources and resource groups has an option to "Export template". This downloads an ARM (Azure Resource Manager) template. The template can be converted to Bicep using the Azure CLI command az bicep decompile --file template_name.json
.
This commit shows the result of templates exported from the rg-communication
and rg-morningwisher
resource groups.
The communication template is well generated, needing only a few minor edits to be ready.
The Morning Wisher template, however, is nearly useless. It includes declarations of a lot of unnecessary resources such as the function, its storage location, and the storage account services.
Exporting Templates Just Before Creating a Resource in Azure Portal
When creating resources in Azure Portal, just before clicking "Create", there is an option to "Download a template for automation". This commit shows such a template for a function app. It includes the function app, its app service plan, its storage account, and FTP and SCM settings. This template can be used as a starting point for the Morning Wisher function app.
GitHub Quickstart Templates
This GitHub repository contains a collection of community-contributed templates. Here is an example of a function app template that is most similar to the Morning Wisher requirements.
Implementation
The implementation proceeds in 4 steps.
Resource Groups
This commit sets up a template to deploy two resource groups and two currently empty modules. The template can be deployed using the Azure CLI command: az deployment sub create --template-file main.bicep --location australiaeast
The location
parameter specifies where Azure should store the deployment metadata. This location is also used for the resource groups and all resources within them.
The resources are deployed to the default subscription, which is selected when the Azure CLI does the login.
Communication Module
The first commit copy-pastes the reference template. The second cleans up resource and variable names. The third sets up auto-generation of random suffixes in service names. Finally, the fourth uses nested resource syntax to remove explicit dependencies.
The resources depend on each other as shown in the following diagram:
Function App Module
The implementation begins in the same way as with the communication module. The first commit copy-pastes the reference template, and the second adapts it. It updates the resource and variable names and removes unnecessary resources, properties, and parameters.
The third commit updates the API versions to latest. The latest versions can be determined by relying on VS Code autocomplete:
Here is the resource dependency diagram:
Application Settings
The original solution uses application settings for the communication services connection string, recipient address, and sender address. The first commit adds commented-out placeholders for these settings to be included.
As the connection string contains sensitive information, it cannot be used in template inputs or outputs. The standard way to access it is to refer to the communication services as an existing resource. This commit demonstrates how to achieve this.
The sender address can be constructed from the properties of the email domain and email sender resources. Since it does not contain sensitive information, it can be passed between modules via inputs and outputs. This commit implements this approach.
The recipient address is configurable, so it is set up as a parameter in the main template. This commit includes this implementation. When deploying with the az deployment sub create --template-file main.bicep --location australiaeast
command, the terminal will prompt for the value of this parameter.
Results
The infrastructure for the Morning Wisher project is now defined in a precise and reusable way.
Here is the full infrastructure diagram: