Exercise - Create and use a module

Completed

You've been tasked with adding a content delivery network, or CDN, to your company's website for the launch of a toy wombat. However, other teams in your company have told you they don't need a CDN. In this exercise, you'll create modules for the website and the CDN, and you'll add the modules to a template.

During the process, you'll:

  • Add a module for your application.
  • Create a Bicep template that uses the module.
  • Add another module for the CDN.
  • Add the CDN module to your template, while making it optional.
  • Deploy the template to Azure.
  • Review the deployment history.

Note

This exercise is optional. If you want to complete this exercise, you'll need to create an Azure subscription before you begin. If you don't have an Azure account or you don't want to create one at this time, you can read through the instructions so you understand the information that's being presented.

This exercise uses the Bicep extension for Visual Studio Code. Be sure to install this extension in Visual Studio Code.

Note

You need to use a resource group to complete the steps in this exercise. You can use a resource group that you already created, or you can create a new resource group specifically for this exercise. If you choose to create a new resource group, that will make it easier to clean up any resources that you create as you complete the exercise. If you don't have an existing resource group or you want to create a new one specifically for this exercise, you can follow the steps in Use the Azure portal and Azure Resource Manager to manage resource groups to create a resource group by using the Azure portal, or you can follow the steps in Manage Azure resource groups by using Azure CLI to create a resource group by using the the Azure CLI.

Note

Throughout this exercise, replace myResourceGroupName in the examples with the name of an existing resource group, or the name of the resource group that you created for this exercise.

Create a blank Bicep file

  1. Open Visual Studio Code.

  2. Create a new file called main.bicep.

  3. Save the empty file so that Visual Studio Code loads the Bicep tooling.

    You can either select File > Save As or select Ctrl+S on Windows (⌘+S on macOS). Be sure to remember where you save the file. For example, you might want to create a templates folder to save it in.

Create a module for your application

  1. 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 app.bicep. Save the file.

  2. Add the following content into the app.bicep file:

    @description('The Azure region into which the resources should be deployed.')
    param location string
    
    @description('The name of the App Service app.')
    param appServiceAppName string
    
    @description('The name of the App Service plan.')
    param appServicePlanName string
    
    @description('The name of the App Service plan SKU.')
    param appServicePlanSkuName string
    
    resource appServicePlan 'Microsoft.Web/serverfarms@2024-04-01' = {
      name: appServicePlanName
      location: location
      sku: {
        name: appServicePlanSkuName
      }
    }
    
    resource appServiceApp 'Microsoft.Web/sites@2024-04-01' = {
      name: appServiceAppName
      location: location
      properties: {
        serverFarmId: appServicePlan.id
        httpsOnly: true
      }
    }
    
    @description('The default host name of the App Service app.')
    output appServiceAppHostName string = appServiceApp.properties.defaultHostName
    

    This file deploys an Azure App Service plan and an app. Notice that the module is fairly generic. It doesn't include any assumptions about the names of resources, or the App Service plan's SKU. This makes it easy to reuse the module for different deployments.

  3. Save the changes to the file.

Add the module to your Bicep template

Here, you add the app module to your Bicep template as a starting point.

  1. Open the main.bicep file.

  2. Add the following parameters and variable to the file:

    @description('The Azure region into which the resources should be deployed.')
    param location string = 'westus3'
    
    @description('The name of the App Service app.')
    param appServiceAppName string = 'toy-${uniqueString(resourceGroup().id)}'
    
    @description('The name of the App Service plan SKU.')
    param appServicePlanSkuName string = 'F1'
    
    var appServicePlanName = 'toy-product-launch-plan'
    

    Because this is the template that you intend to deploy for your toy websites, it's a little more specific. The App Service plan name is defined as a variable. The SKU parameter has a default value that makes sense for the toy launch website.

  3. Below the parameters, create a blank line. Now, type the first line of the app module definition:

    module app 'modules/app.bicep' = {
    

    As you type, notice that the Bicep extension for Visual Studio Code helps you to scaffold the module declaration. When you type the path to your module and type the equals (=) character, a pop-up menu appears with several options.

  4. Select Required properties from the pop-up menu:

    Screenshot of Visual Studio Code that shows the option to scaffold a module with its required properties.

  5. Complete the module declaration:

    module app 'modules/app.bicep' = {
      name: 'toy-launch-app'
      params: {
        appServiceAppName: appServiceAppName
        appServicePlanName: appServicePlanName
        appServicePlanSkuName: appServicePlanSkuName
        location: location
      }
    }
    
  6. At the bottom of the file, define an output:

    @description('The host name to use to access the website.')
    output websiteHostName string = app.outputs.appServiceAppHostName
    
  7. Save the changes to the file.

Create a module for the content delivery network

  1. In the modules folder, create a file called cdn.bicep. Save the file.

  2. Add the following content into the cdn.bicep file:

    @description('The host name (address) of the origin server.')
    param originHostName string
    
    @description('The name of the CDN profile.')
    param profileName string = 'cdn-${uniqueString(resourceGroup().id)}'
    
    @description('The name of the CDN endpoint')
    param endpointName string = 'endpoint-${uniqueString(resourceGroup().id)}'
    
    @description('Indicates whether the CDN endpoint requires HTTPS connections.')
    param httpsOnly bool
    
    var originName = 'my-origin'
    
    resource cdnProfile 'Microsoft.Cdn/profiles@2024-09-01' = {
      name: profileName
      location: 'global'
      sku: {
        name: 'Standard_Microsoft'
      }
    }
    
    resource endpoint 'Microsoft.Cdn/profiles/endpoints@2024-09-01' = {
      parent: cdnProfile
      name: endpointName
      location: 'global'
      properties: {
        originHostHeader: originHostName
        isHttpAllowed: !httpsOnly
        isHttpsAllowed: true
        queryStringCachingBehavior: 'IgnoreQueryString'
        contentTypesToCompress: [
          'text/plain'
          'text/html'
          'text/css'
          'application/x-javascript'
          'text/javascript'
        ]
        isCompressionEnabled: true
        origins: [
          {
            name: originName
            properties: {
              hostName: originHostName
            }
          }
        ]
      }
    }
    
    @description('The host name of the CDN endpoint.')
    output endpointHostName string = endpoint.properties.hostName
    

    This file deploys two resources: a CDN profile and a CDN endpoint.

  3. Save the changes to the file.

Add the modules to the main Bicep template

  1. Open the main.bicep file.

  2. Below the appServicePlanSkuName parameter, add the following parameter:

    @description('Indicates whether a CDN should be deployed.')
    param deployCdn bool = true
    
  3. Below the app module definition, define the cdn module:

    module cdn 'modules/cdn.bicep' = if (deployCdn) {
      name: 'toy-launch-cdn'
      params: {
        httpsOnly: true
        originHostName: app.outputs.appServiceAppHostName
      }
    }
    

    Notice that the module has a condition so that it's deployed only when the deployCdn parameter's value is set to true. Also, notice that the module's originHostName parameter is set to the value of the appServiceAppHostName output from the app module.

  4. Update the host name output so that it selects the correct host name. When a CDN is deployed, you want the host name to be that of the CDN endpoint.

    output websiteHostName string = deployCdn ? cdn.outputs.endpointHostName : app.outputs.appServiceAppHostName
    
  5. Save the changes to the file.

Verify your Bicep file

After you've completed all of the preceding changes, your main.bicep file should look like this example:

@description('The Azure region into which the resources should be deployed.')
param location string = 'westus3'

@description('The name of the App Service app.')
param appServiceAppName string = 'toy-${uniqueString(resourceGroup().id)}'

@description('The name of the App Service plan SKU.')
param appServicePlanSkuName string = 'F1'

@description('Indicates whether a CDN should be deployed.')
param deployCdn bool = true

var appServicePlanName = 'toy-product-launch-plan'

module app 'modules/app.bicep' = {
  name: 'toy-launch-app'
  params: {
    appServiceAppName: appServiceAppName
    appServicePlanName: appServicePlanName
    appServicePlanSkuName: appServicePlanSkuName
    location: location
  }
}

module cdn 'modules/cdn.bicep' = if (deployCdn) {
  name: 'toy-launch-cdn'
  params: {
    httpsOnly: true
    originHostName: app.outputs.appServiceAppHostName
  }
}

@description('The host name to use to access the website.')
output websiteHostName string = deployCdn ? cdn.outputs.endpointHostName : app.outputs.appServiceAppHostName

If it doesn't, either copy the example or adjust your template to match the example.

Deploy the Bicep template to Azure

To deploy this template to Azure, you need to sign in to your Azure account from the Visual Studio Code terminal. Be sure you've installed the Azure CLI tools.

  1. On the Terminal menu, select New Terminal. The terminal window usually opens in the lower half of your screen.

  2. If the terminal window displays bash on the right side, it means the correct shell is already open. Alternatively, if you see a bash shell icon on the right, you can select it to launch the shell.

    Screenshot of the Visual Studio Code terminal window, with the bash option shown.

    If a shell other than bash appears, select the shell dropdown arrow, and then select Git Bash.

    Screenshot of the Visual Studio Code terminal window, with the terminal shell dropdown shown and Git Bash Default selected.

  3. In the terminal, go to the directory where you saved your template. For example, if you saved your template to the templates folder, you can use this command:

    cd templates
    

Install Bicep

Run the following command to ensure you have the latest version of Bicep:

az bicep install && az bicep upgrade

Sign in to Azure by using Azure CLI

  1. In the Visual Studio Code terminal, sign in to Azure by running the following command:

    az login
    
  2. In the browser that opens, sign in to your Azure account.

    The Visual Studio Code terminal displays a list of the subscriptions associated with this account.

  3. In the list, find the subscription that you want to use for this exercise.

    If you missed the list from the sign-in, you can use the following snippet to list your subscriptions again.

    az account list --output table
    
  4. Set the default subscription for all the Azure CLI commands that you run in this session.

    az account set --subscription "Your Subscription Name or ID"
    

Deploy the template to Azure

Run the following code from the terminal in Visual Studio Code to deploy the Bicep template to Azure. This process can take a minute or two to finish, and then you'll get a successful deployment.

az deployment group create --name main --template-file main.bicep

The status Running... appears in the terminal.

To deploy this template to Azure, sign in to your Azure account from the Visual Studio Code terminal. Be sure you've installed Azure PowerShell.

  1. On the Terminal menu, select New Terminal. The terminal window usually opens in the lower half of your screen.

  2. If the terminal window displays pwsh or powershell on the right side, it means the correct shell is already open. Alternatively, if you see a PowerShell shell icon on the right, you can select it to launch the shell.

    Screenshot of the Visual Studio Code terminal window, with the pwsh option displayed in the shell dropdown list.

    If a shell other than pwsh or powershell appears, select the shell dropdown arrow, and then select PowerShell.

    Screenshot of the Visual Studio Code terminal window, with the terminal shell dropdown list shown and PowerShell selected.

  3. In the terminal, go to the directory where you saved your template. For example, if you saved your template in the templates folder, you can use this command:

    Set-Location -Path templates
    

Install the Bicep CLI

To use Bicep from Azure PowerShell, install the Bicep CLI.

Sign in to Azure by using Azure PowerShell

  1. In the Visual Studio Code terminal, sign in to Azure by running the following command:

    Connect-AzAccount
    
  2. In the browser that opens, sign in to your Azure account.

  3. Get the ID of the subscription that you want to use for this exercise by running the following command:

    Get-AzSubscription
    

    The subscription ID is the second column. Copy the second column. It looks something like aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e.

  4. Set the default subscription for all the Azure PowerShell commands that you run in this session.

    Set-AzContext -SubscriptionId {Your subscription ID}
    

Deploy the template to Azure

Deploy the template to Azure by using the following Azure PowerShell command in the terminal. This can take a minute or two to finish, and then you'll get a successful deployment.

New-AzResourceGroupDeployment -Name main -TemplateFile main.bicep

Review the deployment history

  1. Sign in to the Azure portal and make sure you're using the appropriate subscription:

    1. Select your avatar in the upper-right corner of the page.
    2. Select Switch directory. In the list, choose the appropriate directory.
  2. On the left-side panel, select Resource groups.

  3. Select myResourceGroupName.

  4. On the left menu, select Deployments under Settings.

    Screenshot of the Azure portal that shows the resource group, with the Deployments menu item highlighted.

    Three deployments are listed.

  5. Select the main deployment and expand Deployment details.

    Notice that both of the modules are listed, and that their types are displayed as Microsoft.Resources/deployments. The modules are listed twice because their outputs are also referenced within the template.

    Screenshot of the Azure portal that shows the deployment details for the main deployment.

  6. Select the toy-launch-cdn and toy-launch-app deployments and review the resources deployed in each. Notice that they correspond to the resources defined in the respective module.

Test the website

  1. Select the toy-launch-app deployment.

  2. Select Outputs.

    Screenshot of the Azure portal that shows the deployment, with the Outputs menu item highlighted.

  3. Select the copy button for the appServiceAppHostName output.

  4. On a new browser tab, try to go to the address that you copied in the previous step. The address should begin with https://.

    Screenshot of the web app's welcome page, with the address bar showing the App Service host name.

    The App Service welcome page appears, showing that you've successfully deployed the app.

  5. Go to the main deployment and select Outputs.

  6. Copy the value of the websiteHostName output. Notice that this host name is different, because it's an Azure Content Delivery Network host name.

  7. On a new browser tab, try to go to the host name that you copied in the previous step. Add https:// to the start of the address.

    CDN endpoints take a few minutes to become active. If you get a Page not found error, wait a few minutes and try pasting the link again. Also, ensure that you added https:// to the start of the URL so that you're using HTTPS.

    When the CDN endpoint is active, you'll get the same App Service welcome page. This time, it has been served through the Azure Content Delivery Network service, which helps improve the website's performance.

    Screenshot of the web app's welcome page, with the address bar showing the CDN endpoint.