zheludov.com:/$ blog preserve-appservice-settings-during-bicep-deployment

Preserving appSettings in Azure App Service Between Bicep Module Deployments

// 2023-10-07

When deploying and updating Azure resources, ensuring no disruption to existing configurations is crucial. For Azure App Service, a common challenge arises when updating the service without altering the current appSettings. This post will walk you through a Bicep-based approach to preserve these settings amidst deployments.

The Challenge

Whenever we deploy changes to our Azure App Service, there's potential to overwrite existing appSettings—whether from a CI/CD pipeline, manual updates, or other automated deployments. Yet, preserving these settings is vital for ensuring uninterrupted service and retaining manually entered configurations.

The Solution: Bicep and PowerShell

By combining the declarative power of Bicep with some PowerShell scripting, we can fetch existing settings and merge them with new ones during deployment.

  1. PowerShell Script We start by writing a PowerShell script that fetches existing appSettings:
param (
    [string]$resourceGroupName,
    [string]$appServiceName
)

$DeploymentScriptOutputs = @{}

try {
    $config = Get-AzWebApp -ResourceGroupName $resourceGroupName -Name $appServiceName | Select-Object -ExpandProperty SiteConfig

    $appSettings = if ($config.AppSettings) {
        $config.AppSettings
    } else {
        @()
    }

    $appConfigObject = [ordered]@{}

    foreach($configValue in $appSettings){
        if(-not $appConfigObject.Contains($configValue.Name)){
            $appConfigObject.Add($configValue.Name, $configValue.Value)
        }
    }

    $DeploymentScriptOutputs['appConfiguration'] = $appConfigObject
} catch {
    $DeploymentScriptOutputs['appConfiguration'] = @{}
}
  1. Bicep Module to Execute the Script Next, create a Bicep module to execute the script:
param appServiceName string
param location string = resourceGroup().location
param userAssignedIdentityResourceId string = ''
param currentTime string = utcNow()

resource script 'Microsoft.Resources/deploymentScripts@2020-10-01' = if (!empty(userAssignedIdentityResourceId)) {
  name: 'fetchappServiceConfig'
  ...
  properties: {
    azPowerShellVersion: '7.1'
    scriptContent: loadTextContent('Get-AppServiceConfig.ps1')
    arguments: '-appServiceName ${appServiceName} -resourceGroupName ${resourceGroup().name}'
    ...
  }
}

output appConfiguration object = !empty(userAssignedIdentityResourceId) ? script.properties.outputs.appConfiguration : {}
  1. Final Bicep Module for App Service Finally, integrate the fetched configuration into your main App Service Bicep module:
param name string
...

module existingAppConfiguration 'retrieve-appservice-configuration.bicep' = {
  ...
}

var combinedAppConfiguration = intersection(existingAppConfiguration.outputs.appConfiguration, appConfiguration)

resource appService 'Microsoft.Web/sites@2022-03-01' = {
  ...
  resource appSettings 'config' = {
    name: 'appsettings'
    properties: combinedAppConfiguration
  }
}

Conclusion

By fetching existing configurations and merging them during deployments, we ensure our Azure App Service appSettings remain consistent and undisturbed. This Bicep and PowerShell-based approach is just one of many strategies to ensure smoother Azure deployments. Adjust as needed for your specific use case, and happy deploying!

Type 'blog' + Enter -- to get a list of my blog posts.
Type 'help' + Enter -- for available commands.
zheludov.com$