Exercise - Add resources to a deployment stack

Completed

You are on sprint 3 for the new deposits application. Recently, the deposits team requested changes to some of the Azure services in use. They also requested the creation of other services needed to support the application.

In this exercise, you create a deployment stack scoped to a resource group that references a Bicep file. The file defines an app service plan, an app service, and an Azure SQL database. You then modify the SKU of the app service plan and update the deployment stack. Finally, you add an existing Log Analytics workspace and a new Application Insights instance to support monitoring of the application.

During the process, you'll:

  • Create a Bicep file that defines your initial architecture
  • Create a deployment stack scoped to a resource group using your Bicep file.
  • Modify the properties of an existing managed resource
  • Update the Bicep file to include an existing Log Analytics workspace and a new Application Insights instance
  • Update the deployment stack to deploy the managed resources
  • Validate the deployment stack's managed resources.

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

Create the Bicep file

Our first step is to create a Bicep file that defines our resources to use with the deployment stack.

  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 in Windows (⌘+S on macOS). Be sure to remember where you saved the file. For example, you might want to create a templates folder in which to save the file.

  4. Add the following Bicep code into the file. You deploy the template soon.

    // Parameters
    @description('The location for all resources.')
    param location string = 'eastus'
    
    @description('The name of the SQL database.')
    param sqlDatabaseName string = 'sqldb-${uniqueString(resourceGroup().id)}'
    
    @description('The password of the admin user.')
    param sqlServerAdminUserName string
    
    @description('The name of the admin user.')
    @secure()
    param sqlServerAdminPassword string
    
    @description('The name of the SQL server.')
    param sqlServerName string = 'sql-${uniqueString(resourceGroup().id)}'
    
    @description('The name of the web application.')
    param webApplicationName string = 'webapp-${uniqueString(resourceGroup().id)}'
    
    // Variables
    @description('The name of the app service plan.')
    var appServicePlanName = 'plan-deposits'
    
    // Resource - App Service Plan
    resource appServicePlan 'Microsoft.Web/serverfarms@2023-12-01' = {
      name: appServicePlanName
      location: location
      sku: {
        name: 'F1'
        capacity: 1
      }
    }
    
    // Resource - Web App
    resource webApplication 'Microsoft.Web/sites@2023-12-01' = {
      name: webApplicationName
      location: location
      properties: {
        serverFarmId: appServicePlan.id  
      }
    }
    
    // Resource - SQL Server
    resource sqlServer 'Microsoft.Sql/servers@2021-11-01' ={
      name: sqlServerName
      location: location
      properties: {
        administratorLogin: sqlServerAdminUserName
        administratorLoginPassword: sqlServerAdminPassword
      }
    }
    
    // Resource - SQL Database
    resource sqlServerDatabase 'Microsoft.Sql/servers/databases@2021-11-01' = {
      parent: sqlServer
      name: sqlDatabaseName
      location: location
      sku: {
        name: 'Standard'
        tier: 'Standard'
      }
    }
    

    Notice that you're using expressions that include string interpolation and the uniqueString() function to define default parameter values. Someone deploying this template can override the default parameter values by specifying the values at deployment time, but they can't override the variable values.

    Also notice that you're using a variable for the App Service plan name, but you're using parameters for the other names. Storage accounts and App Service apps need globally unique names, but App Service plan names need to be unique only within their resource group. This difference means it's not a concern to use the same App Service plan name across different deployments, as long as the deployments are all going into different resource groups.

  5. Save the changes to the file.

Create the deployment stack and deploy your resources 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 shell shown on the right side of the terminal window is bash, the correct shell is open and you can skip to the next section.

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

  3. If a shell other than bash appears, select the shell dropdown arrow, and then select Azure Cloud Shell (Bash).

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

  4. In the list of terminal shells, select bash.

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

  5. 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"
    

Create a resource group

We need to create a resource group for our deployment stack and managed resources. To create a resource group, run the following command from the terminal in Visual Studio Code.

az group create \
    --name rg-depositsApplication \
    --location eastus

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 shell shown on the right side of the terminal window is powershell or pwsh, the correct shell is open, and you can skip to the next section.

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

  3. If a shell other than powershell or pwsh 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.

  4. In the list of terminal shells, select powershell or pwsh.

    Screenshot of the Visual Studio Code terminal window, with the PowerShell terminal selected.

  5. 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 cf49fbbc-217c-4eb6-9eb5-a6a6c68295a0.

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

    Set-AzContext -SubscriptionId {Your subscription ID}
    

Create a resource group

We need to create a resource group for our deployment stack and managed resources. To create a resource group, run the following command from the terminal in Visual Studio Code.

New-AzResourceGroup `
    -Name rg-depositsApplication `
    -Location eastus

Create the deployment stack

Next, we need to create our deployment stack scoped to our recently created resource group. To create the deployment stack, run the following command from the terminal in Visual Studio Code.

  1. To create the deployment stack, run the following command from the terminal in Visual Studio Code.

    az stack group create \
        --name stack-deposits \
        --resource-group rg-depositsApplication \
        --template-file ./main.bicep \
        --action-on-unmanage detachAll \
        --deny-settings-mode none
    
  2. It prompts you to enter a value for sqlServerAdminUserName. Create a name for the SQL server administrator, followed by 'Enter.'

    A screenshot showing the Azure CLI command line prompting you to enter an SQL server administrator user name.

  3. It prompts you to enter a value for sqlServerAdminPassword. Create a complex password for the SQL server administrator, followed by 'Enter.'

    A screenshot showing the Azure CLI command line prompting you to enter an SQL server administrator password.

  4. Wait for the update operation to complete before moving on to the next task.

  1. To create the deployment stack, run the following command from the terminal in Visual Studio Code.

    New-AzResourceGroupDeploymentStack `
        -Name stack-deposits `
        -ResourceGroupName rg-depositsApplication `
        -TemplateFile ./main.bicep `
        -ActionOnUnmanage DetachAll `
        -DenySettingsMode None
    
  2. It prompts you to enter a value for sqlServerAdminUserName. Create a name for the SQL server administrator, followed by 'Enter.'

    A screenshot showing the Azure PowerShell command line prompting you to enter an SQL server administrator user name.

  3. It prompts you to enter a value for sqlServerAdminPassword. Create a complex password for the SQL server administrator, followed by 'Enter.'

    A screenshot showing the Azure PowerShell command line prompting you to enter an SQL server administrator password.

  4. Wait for the update operation to complete before moving on to the next task.

Modify the Bicep file to add the existing Log Analytics workspace and a new Application Insights instance

  1. Open the main.bicep file in Visual Studio Code.

  2. Add the highlighted code to the variables section of your file:

    // Variables
    @description('The name of the Application Insights instance.')
    var applicationInsightsName = 'appinsights-deposits'
    
    @description('The name of the app service plan.')
    var appServicePlanName = 'plan-deposits'
    
    @description('The name of the Log Analytics Workspace.')
    var logAnalyticsWorkspaceName = 'log-deposits'
    
  3. Add the following code to the bottom of the file:

    // Resource - Log Analytics Workspace
    resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' = {
      name: logAnalyticsWorkspaceName
      location: location
      properties: {
        retentionInDays: 30
        sku: {
          name: 'PerGB2018'
        }
      }
    }
    
    // Resource - Application Insights
    resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
      name: applicationInsightsName
      location: location
      kind: 'web'
      properties: {
        Application_Type: 'web'
        WorkspaceResourceId: logAnalyticsWorkspace.id
      }
    }
    
  4. Save the changes to the file.

Modify the Bicep file to modify the app service plan and app service

  1. Open the main.bicep file in Visual Studio Code.

  2. Change the sku name of the app service plan from F1 to S1:

    // Resource - App Service Plan
    resource appServicePlan 'Microsoft.Web/serverfarms@2023-12-01' = {
      name: appServicePlanName
      location: location
      sku: {
        name: 'S1'
        capacity: 1
      }
    }
    
  3. Add the highlighted code to wire in the Application Insights instance:

    // Resource - Web App
    resource webApplication 'Microsoft.Web/sites@2023-12-01' = {
      name: webApplicationName
      location: location
      properties: {
        serverFarmId: appServicePlan.id
        siteConfig: {
          appSettings: [
            {
              name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
              value: applicationInsights.properties.InstrumentationKey
            }     
          ]
        }    
      }
    }
    
  4. Save the changes to the file.

Update the deployment stack

With the Bicep file modified, we want to update the deployment stack so that the changes made to the resources in the Bicep file are implemented.

  1. To update the deployment stack, run the following command from the terminal in Visual Studio Code.

    az stack group create \
        --name stack-deposits \
        --resource-group rg-depositsApplication \
        --template-file ./main.bicep \
        --action-on-unmanage detachAll \
        --deny-settings-mode none
    
  2. You receive a message stating that the stack already exists in the current subscription. If the value of the action on unmanage parameter changed, the warning alerts you of the new values. Press y, followed by 'Enter`.

    A screenshot showing the Azure CLI command line warning that the deployment stack already exists.

  3. It prompts you to enter a value for sqlServerAdminUserName. Create a name for the SQL server administrator, followed by 'Enter.'

    A screenshot showing the Azure CLI command line prompting you to enter an SQL server administrator user name.

  4. It prompts you to enter a value for sqlServerAdminPassword. Create a complex password for the SQL server administrator, followed by 'Enter.'

    A screenshot showing the Azure CLI command line prompting you to enter an SQL server administrator password.

  5. Wait for the update operation to complete before moving on to the next task.

With the Bicep file modified, we want to update the deployment stack so that the changes made to the app service plan are implemented.

  1. To update the deployment stack, run the following command from the terminal in Visual Studio Code.

    Set-AzResourceGroupDeploymentStack `
        -Name stack-deposits `
        -ResourceGroupName rg-depositsApplication `
        -TemplateFile ./main.bicep `
        -ActionOnUnmanage DetachAll `
        -DenySettingsMode none
    
  2. It prompts you to enter a value for sqlServerAdminUserName. Create a name for the SQL server administrator, followed by 'Enter.'

    A screenshot showing the Azure PowerShell command line prompting you to enter an SQL server administrator user name.

  3. It prompts you to enter a value for sqlServerAdminPassword. Create a complex password for the SQL server administrator, followed by 'Enter.'

    A screenshot showing the Azure PowerShell command line prompting you to enter an SQL server administrator password.

  4. Wait for the update operation to complete before moving on to the next task.

Verify the update to the deployment stack and the managed resources

With the update complete, we want to validate that the app service plan's sku is updated and that the deployment stack is managing the existing Log Analytics workspace and the new Application Insights instance.

  1. To view the configuration of the app service plan, run the following command from the terminal in Visual Studio Code.

    az appservice plan show \
        --name plan-deposits
        --resource-group rg-depositsApplication
    
  2. Take notice of the sku section of the output. The app service plan is now on the S1 sku. It should be similar to the following output:

    "sku": {
        "capacity": 1,
        "family": "S",
        "name": "S1",
        "size": "S1",
        "tier": "Standard"
    },
    
  3. To view the configuration of the deployment stack, run the following command from the terminal in Visual Studio Code.

    az stack group show \
        --resource-group rg-depositsApplication \
        --name stack-deposits
    
  4. Take notice of the resources section of the output. We now see the existing Log Analytics workspace and the new Application Insights instance listed as managed resources. The result should appear similar to the following output:

    "resources": [
      {
        "denyStatus": "none",
        "id": "/subscriptions/./resourceGroups/rg-depositsApplication/././servers/sql-brpdm7iotbwjm",
        "resourceGroup": "rg-depositsApplication",
        "status": "managed"
      },
      {
        "denyStatus": "none",
        "id": "/subscriptions/./resourceGroups/rg-depositsApplication/././servers/sql-brpdm7iotbwjm/databases/sqldb-brpdm7iotbwjm",
        "resourceGroup": "rg-depositsApplication",
        "status": "managed"
      },
      {
        "denyStatus": "none",
        "id": "/subscriptions/./resourceGroups/rg-depositsApplication/././serverfarms/plan-deposits",
        "resourceGroup": "rg-depositsApplication",
        "status": "managed"
      },
      {
        "denyStatus": "none",
        "id": "/subscriptions/./resourceGroups/rg-depositsApplication/././sites/webapp-brpdm7iotbwjm",
        "resourceGroup": "rg-depositsApplication",
        "status": "managed"
      },
      {
        "denyStatus": "none",
        "id": "/subscriptions/./resourceGroups/rg-depositsApplication/././components/appinsights-deposits",
        "resourceGroup": "rg-depositsApplication",
        "status": "managed"
      },
      {
        "denyStatus": "none",
        "id": "/subscriptions/./resourceGroups/rg-depositsApplication/././workspaces/log-deposits",
        "resourceGroup": "rg-depositsApplication",
        "status": "managed"
      }
    ],
    
  1. To view the configuration of the app service plan, run the following command from the terminal in Visual Studio Code.

    $plan = Get-AzAppServicePlan `
        -ResourceGroupName rg-depositsApplication `
        -Name plan-deposits
    $sku = $plan.Sku
    $sku
    
  2. Take notice of the output. The app service plan is now on the S1 sku. It should be similar to the following:

    Name         : S1
    Tier         : Standard
    Size         : S1
    Family       : S
    Capacity     : 1
    
  3. To view the configuration of the deployment stack, run the following command from the terminal in Visual Studio Code.

    Get-AzResourceGroupDeploymentStack `
        -ResourceGroupName rg-depositsApplication `
        -Name stack-deposits
    
  4. Take notice of the resources section of the output. We now see the existing Log Analytics workspace and the new Application Insights instance listed as managed resources. The result should appear similar to the following output:

    Resources                     : /subscriptions/./resourceGroups/rg-depositsApplication/././servers/                        sql-brpdm7iotbwjm
                                    /subscriptions/./resourceGroups/rg-depositsApplication/././servers/sql-brpdm7iotbwjm/databases/sqldb-brpdm7iotbwjm
                                    /subscriptions/./resourceGroups/rg-depositsApplication/././serverfarms/plan-deposits
                                    /subscriptions/./resourceGroups/rg-depositsApplication/././sites/webapp-brpdm7iotbwjm
                                    /subscriptions/./resourceGroups/rg-depositsApplication/././components/appinsights-deposits
                                    /subscriptions/./resourceGroups/rg-depositsApplication/././workspaces/log-deposits