Adding Azure App Service Application Settings with PowerShell

6 minute read

Within Azure there is a option to change several configuration settings. When working with  Deployment Slots this means you have to click a lot within the Azure Portal and that can be a very time consuming operation.

The configuration of the Azure App Service can be automated by using PowerShell, for this first example we will start configuring Application settings.

To maintain the application settings values we start off by making a configuration file in which the key value pairs can be saved.

<?xml version="1.0" encoding="utf-8"?>
<Azure SubscriptionName="Pay-As-You-Go">
  <AppService Name="api-app" ResourceGroup="Demo-Group">
      <AppSettings>
        <AppSetting Key="Test" Value="Test"></AppSetting>
      </AppSettings>    
  </AppService>
  <AppService Name="api-app" ResourceGroup="Demo-Group" Slot="acc">
    <AppSettings>
      <AppSetting Key="Test" Value="Test"></AppSetting>
    </AppSettings>
  </AppService>
</Azure>

If you look at the configuration file you will notice that there is one API application within Azure. This API Application also has a deployment slot called “acc”.

With the use of PowerShell we can read out this configuration file and add the application settings to the right deployment slot.

$fileName = "configuration.xml";

Write-Host "Loading configuration file for Azure:" $fileName; 
$config = [xml] (Get-Content $fileName)

if ($config -eq $null) {
    Write-Host "Error loading configuration file, make sure the file exists." -ForegroundColor Red
    Exit
}
$subscription = $config.Azure.SubscriptionName

Write-Host "Login to the Azure Environment:" -ForegroundColor Green

#login to Azure
Login-AzureRmAccount

Write-Host "Setting the correct Subscription:" -ForegroundColor Green

#get the Azure Subscription
Get-AzureRmSubscription –SubscriptionName $subscription | Select-AzureRmSubscription

foreach($webApp in $config.Azure.AppService){
    
    $appService = '';
    $group = $webApp.ResourceGroup;
    $name = $webApp.Name;
    $slot = $webApp.Slot;

    if(!$slot){
        Write-Host "Applying settings for app service : " $name " in group: " $group -ForegroundColor Green
       $appService = Get-AzureRmWebApp -Name $name -ResourceGroupName $group;
    }else{
      Write-Host "Applying settings for app service : " $name " in group: " $group "in slot: " $slot -ForegroundColor Green
      $appService = Get-AzureRmWebAppSlot -Name $name -Slot $slot -ResourceGroupName $group;
    }

    $appSettings = $appService.SiteConfig.AppSettings

    #setup the current app settings
    $settings = @{}
    ForEach ($setting in $appSettings) {
        $settings[$setting.Name] = $setting.Value
    }

    #adding new settings to the app settigns
    foreach($appSetting in $webApp.AppSettings.AppSetting){
        $settings[$appSetting.Key] = $appSetting.Value;
    }

    if(!$slot){
        $app = Set-AzureRMWebApp -Name $name -ResourceGroupName $group -AppSettings $settings
    }else{
        $app = Set-AzureRMWebAppSlot -Name $name -ResourceGroupName $group -AppSettings $settings -Slot $slot
    }

    Write-Host "Application settings applied to: " $appService.Name -ForegroundColor Green
}

In the code snip-it above there are a lot of comments so I hope you understand what happens within the script. The main difference for updating the production environment in the slot is described in the following paragraph.

By using “Set-AzureRMWebApp” you can set the the properties of the production version. By using “Set-AzureRMWebAppSlot” and specifying the “Slot” parameter you update the settings of the specified slot.

Know I hear you think: What about the specific slot settings as within the picture below.

image

Until know I haven’t found a solution other then doing this in the Azure Portal or by using Azure Classic scripts.

In order to run the upcoming PowerShell a Azure subscription needs to be configured (https://www.opsgility.com/blog/windows-azure-powershell-reference-guide/getting-started-with-windows-azure-powershell/).

With the use of “Select-AzureSubscription” the default Azure subscription will be set. The subscription that will be used is configured in the configuration file.

After that the “Set-AzureWebsite” will be used to set the property “SlotStickyAppSettingNames”. This property needs to be set to a string array that contains all the key’s that need to be sticky slot settings.

Set-AzureWebsite -Name "api-app" -SlotStickyAppSettingNames @("Test") 

To support this within the configuration file we alter the app settings. Besides that you must make sure that you set this property on the default (production) slot of your app service. Otherwise you will get the following exception.

Set-AzureWebsite : <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">{"Code":"BadRequest","Message":"The names 
of the app settings and connection strings can be only set on a parent site level because they apply to all site's slots.","Exten
dedCode":"04084","MessageTemplate":"The names of the app settings and connection strings can be only set on a parent site level b
ecause they apply to all site's slots.","Parameters":[],"InnerErrors":null}</string>
At line:2 char:1
+ Set-AzureWebsite -Name "api-app" -SlotStickyAppSettingNames @("Test") -Slot "acc"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : CloseError: (:) [Set-AzureWebsite], CloudException
    + FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.Websites.SetAzureWebsiteCommand

With the extension the configuration file know looks liked the below code snip-it.

<?xml version="1.0" encoding="utf-8"?>
<Azure SubscriptionName="Pay-As-You-Go">
  <AppService Name="api-app" ResourceGroup="Demo-Group">
      <AppSettings>
        <AppSetting Key="Test" Value="Test" Slot="true"></AppSetting>
      </AppSettings>    
  </AppService>
  <AppService Name="api-app" ResourceGroup="Demo-Group" Slot="acc">
    <AppSettings>
      <AppSetting Key="Test" Value="Test"></AppSetting>
    </AppSettings>
  </AppService>
</Azure>

With the configuration file altered the classic PowerShell code and the “Set-AzureWebsite” can be added to the PowerShell script that results in the following file.

$fileName = "configuration.xml";

Write-Host "Loading configuration file for Azure:" $fileName; 
$config = [xml] (Get-Content $fileName)

if ($config -eq $null) {
    Write-Host "Error loading configuration file, make sure the file exists." -ForegroundColor Red
    Exit
}
$subscription = $config.Azure.SubscriptionName

Write-Host "Login to the Azure Environment:" -ForegroundColor Green

#login to Azure
Login-AzureRmAccount

Write-Host "Setting the correct Subscription:" -ForegroundColor Green

#get the Azure Subscription
Get-AzureRmSubscription –SubscriptionName $subscription | Select-AzureRmSubscription
Select-AzureSubscription -SubscriptionName $subscription

foreach($webApp in $config.Azure.AppService){
    
    $appService = '';
    $group = $webApp.ResourceGroup;
    $name = $webApp.Name;
    $slot = $webApp.Slot;

    if(!$slot){
        Write-Host "Applying settings for app service : " $name " in group: " $group -ForegroundColor Green
       $appService = Get-AzureRmWebApp -Name $name -ResourceGroupName $group;
       
       if(!$slot){
            if($appSetting.Slot -eq 'true' -or $appSetting.Slot -eq '1'){
                $stickyslot += $appSetting.Key;
            }
        }
       
    }else{
      Write-Host "Applying settings for app service : " $name " in group: " $group "in slot: " $slot -ForegroundColor Green
      $appService = Get-AzureRmWebAppSlot -Name $name -Slot $slot -ResourceGroupName $group;
    }

    $appSettings = $appService.SiteConfig.AppSettings

    #setup the current app settings
    $settings = @{}
    ForEach ($setting in $appSettings) {
        $settings[$setting.Name] = $setting.Value
    }

    #adding new settings to the app settigns
    foreach($appSetting in $webApp.AppSettings.AppSetting){
        $settings[$appSetting.Key] = $appSetting.Value;
    }

    if(!$slot){
        $app = Set-AzureRMWebApp -Name $name -ResourceGroupName $group -AppSettings $settings
        
        if($stickyslot.Count -lt 0){
            Write-Host "Set Sticky Slot Settings" -ForegroundColor Yellow
            Set-AzureWebsite -Name $name -SlotStickyAppSettingNames $stickyslot
        }
    }else{
        $app = Set-AzureRMWebAppSlot -Name $name -ResourceGroupName $group -AppSettings $settings -Slot $slot
    }

    Write-Host "Application settings applied to: " $appService.Name -ForegroundColor Green
}