7

main.bicep


resource appService 'Microsoft.Web/sites@2020-06-01' = {
  name: webSiteName
  location: location
  properties: {
    serverFarmId: appServicePlan.id
    siteConfig: {
      linuxFxVersion: linuxFxVersion

      appSettings: [
        {
          name: 'ContainerName'
          value: 'FancyContainer'
        }
        {
          name: 'FancyUrl'
          value: 'fancy.api.com'
        }
      ]
    }
  }
}

The infrastructure release process is run successfully, and the app settings are set correctly, after that I run the node application build and release where the Azure DevOps release pipeline adds some application-related config to app settings. (API keys, API URLs, for example) and everything works great.

But if I have to rerelease infrastructure, for example, I expand my environment with a storage account, the app settings which the application release set are lost.

Is there a workaround to keep app settings which not defined in Bicep template?

Thomas
  • 24,234
  • 6
  • 81
  • 125
asdpsd
  • 218
  • 2
  • 10
  • Not really. Any changes made outside of the BiCep file will be reset if they don't exist in the main. How I have done this in the past by using AzDo is to query the appSettings prior to the IaC deployment and then passing these back to the app after deployment. – JacksWastedLife Jul 11 '22 at 20:37

1 Answers1

18

From this article: Merge App Settings With Bicep.

  1. Don't include appSettings inside the siteConfig while deploying.
  2. Create a module to create/update appsettings that will merge the existing settings with new settings.

appsettings.bicep file:

param webAppName string
param appSettings object
param currentAppSettings object

resource webApp 'Microsoft.Web/sites@2022-03-01' existing = {
  name: webAppName
}

resource siteconfig 'Microsoft.Web/sites/config@2022-03-01' = {
  parent: webApp
  name: 'appsettings'
  properties: union(currentAppSettings, appSettings)
}

main.bicep:

param webAppName string
...

// Create the webapp without appsettings
resource webApp 'Microsoft.Web/sites@2022-03-01' = {
  name: webAppName
  ...
  properties:{    
    ... 
    siteConfig: {
      // Dont include the appSettings
    }
  }
}

// Create-Update the webapp app settings.
module appSettings 'appsettings.bicep' = {
  name: '${webAppName}-appsettings'
  params: {
    webAppName: webApp.name
    // Get the current appsettings
    currentAppSettings: list(resourceId('Microsoft.Web/sites/config', webApp.name, 'appsettings'), '2022-03-01').properties
    appSettings: {
      Foo: 'Bar'
    }
  }
}
Thomas
  • 24,234
  • 6
  • 81
  • 125
  • If I have the webApp resource in its own module and call the webApp and appSettings modules from main.bicep then I get an error on the list function: "This expression is being used in an argument of the function "list", which requires a value that can be calculated at the start of the deployment." – Oliver Nilsen Jul 19 '22 at 11:36
  • @OliverNilsen you're getting the webapp name / id as an output of the webapp module ? – Thomas Jul 19 '22 at 12:34
  • Yes exactly. So the main.bicep deploys the module which defines the webApp resource. Then right after that I deploy the appSettings module and provide webAppName: webApp.outputs.name as input param. It seems like the function list() can only be used inside the webApp resource module and not in the main.bicep. – Oliver Nilsen Jul 19 '22 at 16:22
  • you could always having the main invoking the webapp module and the webapp module invoking the appsettings module ? From my answer, my main become your webapp module. – Thomas Jul 19 '22 at 20:02
  • that is a nice idea. I haven't thought of that one. – Oliver Nilsen Jul 20 '22 at 07:09
  • Currently, it's a limitation in what bicep is able to comprehend at "compile-time". When a resource is created in a module, it's outputs are considered "run-time" properties that we can't calculate upfront. – Oliver Nilsen Sep 13 '22 at 10:16
  • Does this work on first deployment? In other words, will it cause an error if there are no existing function app settings to list because the resource doesn't exist? – DaveF Feb 15 '23 at 12:54
  • It should work. I did try while posting the answer and it was working – Thomas Feb 16 '23 at 18:41