Azure / bicep

Bicep is a declarative language for describing and deploying Azure resources
MIT License
3.27k stars 755 forks source link

Bicep reports cycle for app service slot swapping #8712

Open Suchiman opened 2 years ago

Suchiman commented 2 years ago

Bicep version Bicep CLI version 0.11.1 (030248df55)

Describe the bug If you try to implement azure app service slot swapping via a bicep template, for example, by decompiling the example given for ARM templates https://azure.github.io/AppService/2019/10/02/Swap-slots-with-arm-templates.html then you'll get an error, saying that The expression is involved in a cycle because the site depends on the slot but the site is the parent of the slot.

Also if you remove the dependsOn so that the cycle error goes away, targetBuildVersion and buildVersion are warned as not allowed on SiteProperties

To Reproduce

param location string = resourceGroup().location
param siteName string
param buildId int

var buildVersion = '${buildId}-${deployment().name}'

resource mySite 'Microsoft.Web/sites@2018-11-01' = {
  kind: 'app'
  name: siteName
  location: location
  properties: {
    targetBuildVersion: buildVersion
  }
  dependsOn: [
    mySite_Slot
  ]
}

resource mySite_Slot 'Microsoft.Web/sites/slots@2018-11-01' = {
  parent: mySite
  kind: 'app'
  name: 'PreProd'
  location: location
  properties: {
    buildVersion: buildVersion
  }
}
alex-frankel commented 2 years ago

I'm not sure why that template has a dependency on its child resource. It is impossible to create a child resource before a parent. What happens if you remove the dependsOn property?

Edit: sorry, I missed that you tried removing that property. The warnings that show up are not related to removing dependsOn. It's just that they only show up once the other error is removed. These warnings could be false positives based on an out-of-date API specification. Have you tried deploying despite the warnings? If so, what happens?

Suchiman commented 2 years ago

@alex-frankel this code was decompiled from my existing ARM templates that is based on https://azure.github.io/AppService/2019/10/02/Swap-slots-with-arm-templates.html so they have worked for years. Both resources already exist at that point (this is part of a nested template that performs the slot swap, the parent template is responsible for creating the resources if they don't already exist). The way this works, is that you first set the buildVersion in the slot that you want to become production and in the prod slot / the main site, you then set the targetBuildVersion and app service then figures which slot has the desired buildVersion and switches that slot with the main site. That's why the child needs to be deployed (updated in fact) first. I tried using existing on the resources but that disallows all modifications to them.

alex-frankel commented 2 years ago

Oh I see. This is tricky because the app modelling is a little odd. It seems like a slot should be a separate top-level resource, not a child resource.

To make sure I understand this correctly, this deployment would fail if the website didn't already exist?

As a workaround, can you remove the parent property and instead use segmented resource name like so?

param location string = resourceGroup().location
param siteName string
param buildId int

var buildVersion = '${buildId}-${deployment().name}'

resource mySite 'Microsoft.Web/sites@2018-11-01' = {
  kind: 'app'
  name: siteName
  location: location
  properties: {
    targetBuildVersion: buildVersion
  }
  dependsOn: [
    mySite_Slot
  ]
}

resource mySite_Slot 'Microsoft.Web/sites/slots@2018-11-01' = {
  // parent: mySite
  kind: 'app'
  name: '${siteName}/PreProd'
  location: location
  properties: {
    buildVersion: buildVersion
  }
}
Suchiman commented 2 years ago

To make sure I understand this correctly, this deployment would fail if the website didn't already exist?

correct

As a workaround, can you remove the parent property and instead use segmented resource name like so?

yep that works, thanks! On another note, i realized that i can simplify the deployment by setting the buildVersion in the parent template when the slot gets created initially, then the nested template only needs to update the sites, not the slots and that solves the dependency cycles as well.

These warnings could be false positives based on an out-of-date API specification

so it seems, how to get that fixed?

alex-frankel commented 2 years ago

We will need the Web Resource Provider team to update their swagger specification. Tagging @seligj95 / @naveedaz to triage.