Add resources to a deployment stack

Completed

The deposits application continues to evolve throughout development. The team is adding resources and testing features on a daily basis. Observability is being added to the application with an existing Log Analytics workspace and a new Application Insights instance. You want to continue to manage the resources as a single atomic unit. You need to learn more about adding both existing and new resources to a deployment stack.

In this unit, you learn how to add both existing and new resources to a deployment stack as managed resources.

Note

The commands in this unit are shown to illustrate concepts. Don't run the commands yet. You'll practice what you learn here soon.

Add an existing resource

The resources that an application uses change over time. How do we update a deployment stack to include an already existing resource in Azure?

Bicep allows you to define a resource that already exists in Azure. Defining an existing resource is similar to defining a new resource with slight differences. For example, you can define an existing resource in a resource declaration using the existing keyword:

resource logAnalyticsWorkspace 'Microsoft.OperationsManagement/solutions@2015-11-01-preview' existing  = {
    name: 'log-deposits'
}

When we are adding an existing resource as a managed resource to a deployment stack, we do not need to use this existing keyword. We simply need to define the existing resource in our Bicep file, ARM JSON template, or template spec. In the end, the deployment stack manages the existing resource.

Let's consider our Bicep file from the last unit. Our file defines an app service plan, a web app, and an Azure SQL server and database. We want to add an existing Log Analytics workspace to our deployment stack. The workspace is in the same resource group where our managed resources exist.

To add the existing Log Analytics workspace, we need to add its definition to our Bicep file. Notice that we don't need to include any code that describes the workspace as an existing resource.

// 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'

@description('The name of the Log Analytics Workspace.')
var logAnalyticsWorkspaceName = 'log-deposits'

// Resource - App Service Plan
resource appServicePlan 'Microsoft.Web/serverfarms@2023-12-01' = {
  name: appServicePlanName
  location: location
  sku: {
    name: 'S1'
    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'
  }
}

// Resource - Log Analytics Workspace
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' = {
  name: logAnalyticsWorkspaceName
  location: location
  properties: {
    retentionInDays: 30
    sku: {
      name: 'PerGB2018'
    }
  }
}

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.

To update a deployment stack using Azure CLI, use the az stack group create command.

az stack group create \
    --name stack-deposits \
    --resource-group rg-depositsApplication \
    --template-file ./main.bicep \
    --action-on-unmanage detachAll \
    --deny-settings-mode none

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.

To update a deployment stack using Azure PowerShell, use the Set-AzResourceGroupDeploymentStack command.

Set-AzResourceGroupDeploymentStack `
    -Name stack-deposits `
    -ResourceGroupName rg-depositsApplication `
    -TemplateFile ./main.bicep `
    -ActionOnUnmanage DetachAll `
    -DenySettingsMode None

Add a new managed resource

The process of adding a new resource to a deployment stack is identical to adding an existing resource to the stack. We simply need to define the existing resource in our Bicep file, ARM JSON template, or template spec. In the end, the deployment stack manages the new resource.

Let's consider our Bicep file from the previous section. Our file now defines an app service plan, app service, an Azure SQL server and database, and a Log Analytics workspace. We want to add a new Application Insights instance to our deployment stack and configure the app service to use the instance. To add the new Application Insights instance, we need to add its definition to our Bicep file and update the app service to use the new instance.

// 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 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'

// Resource - App Service Plan
resource appServicePlan 'Microsoft.Web/serverfarms@2023-12-01' = {
  name: appServicePlanName
  location: location
  sku: {
    name: 'S1'
    capacity: 1
  }
}

// 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
        }     
      ]
    }    
  }
}

// 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'
  }
}

// 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
  }
}

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.

To update a deployment stack using Azure CLI, use the az stack group create command.

az stack group create \
    --name stack-deposits \
    --resource-group rg-depositsApplication \
    --template-file ./main.bicep \
    --action-on-unmanage detachAll \
    --deny-settings-mode none

Note

Azure CLI does not have a dedicated command to update a deployment stack. Use the create command to update the stack.

When performing an update on the stack, you receive a message stating that the stack already exists in the current subscription. If the value of the action on unmanage parameter changes, the warning alerts you of the new values.

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.

To update a deployment stack using Azure PowerShell, use the Set-AzResourceGroupDeploymentStack command.

Set-AzResourceGroupDeploymentStack `
    -Name stack-deposits `
    -ResourceGroupName rg-depositsApplication `
    -TemplateFile ./main.bicep `
    -ActionOnUnmanage DetachAll `
    -DenySettingsMode None

As you can see, the process of adding an existing resource or a new resource is the same.