Exercise - Refactor your template to use modules
In this exercise, you'll update the Bicep template you previously created so it uses a module for the Azure App Service resources. Modules help to keep the intention of the main template clearer. You can reuse the App Service module in other templates if you choose to.
During the process, you'll:
- Add a new module and move the App Service resources into it.
- Reference the module from the main Bicep template.
- Add an output for the App Service app's host name, and emit it from the module and template deployments.
- Test the deployment to ensure that the template is valid.
Add a new module file
In Visual Studio Code, create a new folder called modules in the same folder where you created your main.bicep file. In the modules folder, create a file called appService.bicep. Save the file.
Add the following content into the appService.bicep file:
param location string param appServiceAppName string @allowed([ 'nonprod' 'prod' ]) param environmentType string var appServicePlanName = 'toy-product-launch-plan' var appServicePlanSkuName = (environmentType == 'prod') ? 'P2v3' : 'F1' resource appServicePlan 'Microsoft.Web/serverfarms@2023-12-01' = { name: appServicePlanName location: location sku: { name: appServicePlanSkuName } } resource appServiceApp 'Microsoft.Web/sites@2023-12-01' = { name: appServiceAppName location: location properties: { serverFarmId: appServicePlan.id httpsOnly: true } }
Notice that you've copied the parameters and variables from your main.bicep template, because the appService.bicep template needs to be self-contained.
Save the changes to the file. Notice that Visual Studio Code doesn't show you any red squiggles to indicate warnings about missing variables, missing parameters, or invalid resources.
Add a reference to the module from the parent template
Now that you have a complete module to deploy the App Service resources, you can refer to the module within the parent template. Because the module deploys the App Service resources, you can delete the associated resources and variables from the parent template.
In the main.bicep file, delete the App Service resources and the
appServicePlanName
andappServicePlanSkuName
variable definitions. Don't delete the App Service parameters, because you still need them. Also, don't delete the storage account parameters, variable, or resources.At the bottom of the main.bicep file, add the following Bicep code:
module appService 'modules/appService.bicep' = { name: 'appService' params: { location: location appServiceAppName: appServiceAppName environmentType: environmentType } }
Notice that you're specifying the parameters for your module by referencing the parameters in the parent template.
Save the changes to the file.
Add the host name as an output
Add the following Bicep code at the bottom of the appService.bicep file:
output appServiceAppHostName string = appServiceApp.properties.defaultHostName
This code declares that an output for this module, which will be named
appServiceAppHostName
, will be of typestring
. The output will take its value from thedefaultHostName
property of the App Service app.Save the changes to the file.
This output is declared within a Bicep file we'll use as a module, so it's going to be available only to the parent template. You also need to return the output to the person who deployed the template.
Open the main.bicep file and add the following code at the bottom of the file:
output appServiceAppHostName string = appService.outputs.appServiceAppHostName
Notice that this output is declared in a similar way to the output in the module. But this time, you're referencing the module's output instead of a resource property.
Save the changes to the file.
Verify your Bicep files
After you've completed all of the preceding changes, your main.bicep file should look like this example:
param location string = 'eastus'
param storageAccountName string = 'toylaunch${uniqueString(resourceGroup().id)}'
param appServiceAppName string = 'toylaunch${uniqueString(resourceGroup().id)}'
@allowed([
'nonprod'
'prod'
])
param environmentType string
var storageAccountSkuName = (environmentType == 'prod') ? 'Standard_GRS' : 'Standard_LRS'
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: storageAccountName
location: location
sku: {
name: storageAccountSkuName
}
kind: 'StorageV2'
properties: {
accessTier: 'Hot'
}
}
module appService 'modules/appService.bicep' = {
name: 'appService'
params: {
location: location
appServiceAppName: appServiceAppName
environmentType: environmentType
}
}
output appServiceAppHostName string = appService.outputs.appServiceAppHostName
Your appService.bicep file should look like this example:
param location string
param appServiceAppName string
@allowed([
'nonprod'
'prod'
])
param environmentType string
var appServicePlanName = 'toy-product-launch-plan'
var appServicePlanSkuName = (environmentType == 'prod') ? 'P2v3' : 'F1'
resource appServicePlan 'Microsoft.Web/serverfarms@2023-12-01' = {
name: appServicePlanName
location: location
sku: {
name: appServicePlanSkuName
}
}
resource appServiceApp 'Microsoft.Web/sites@2023-12-01' = {
name: appServiceAppName
location: location
properties: {
serverFarmId: appServicePlan.id
httpsOnly: true
}
}
output appServiceAppHostName string = appServiceApp.properties.defaultHostName
If either file doesn't match, copy the example or adjust your template to match the example.
Deploy the updated Bicep template
Run the following Azure CLI command in the terminal.
az deployment group create \
--template-file main.bicep \
--parameters environmentType=nonprod
Run the following Azure PowerShell command in the terminal.
New-AzResourceGroupDeployment `
-TemplateFile main.bicep `
-environmentType nonprod
Check your deployment
In your browser, go back to the Azure portal. Go to your resource group; there are now two successful deployments.
Select the 2 Succeeded link. Notice that you have a deployment called main in the list, and a new deployment called appService.
Select the deployment called main, then select Deployment details to expand the list of deployed resources.
Notice that our module deployment appears in the list.
Select the Outputs tab. Notice that there's an output called appServiceAppHostName with the host name of your App Service app. Copy the host name to your clipboard.
Open a new browser tab and paste the host name that you copied. You should see the default App Service welcome page.
Congratulations! You've successfully deployed the foundations for a great app.