Azure / bicep

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

The template function 'reference' is not expected at this location. #1917

Closed ecuaryan closed 3 years ago

ecuaryan commented 3 years ago

Bicep version Bicep CLI version 0.3.1

Describe the bug I receive the error "The template function 'reference' is not expected at this location." when expecting it to not error out. See below for more details.

To Reproduce Run the following commands using the files defined below:

bicep build root-template.bicep
az deployment group create --name test1 --resource-group <your-resouce-group-name> --template-file ".\root-template.json"

Comment/uncomment the code towards the bottom of the root-template.bicep file to use the code that will work vs the code that doesn't but is expected to.

// root-template.bicep

resource applicationInsights 'Microsoft.Insights/components@2018-05-01-preview' = {
  name: 'someAppInsightsName'
  location: 'East Us'
  kind: 'web'
  properties: {
    Application_Type: 'web'
  }
}

resource appServicePlan 'Microsoft.Web/serverfarms@2018-02-01' = {
    name: 'someName'
    location: 'East Us'
    kind: 'functionapp'
    sku: {
      name: 'Y1'
      size: 'Y1'
      family: 'Y'
      capacity: 0
      tier: 'Dynamic'
    }
    properties: {
      perSiteScaling: false
      maximumElasticWorkerCount: 1
      isSpot: false
      reserved: false
      isXenon: false
      hyperV: false
      targetWorkerCount: 0
      targetWorkerSizeId: 0
    }
}

var mainAppSettings = [
  {
    name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
    value: reference(resourceId('Microsoft.Insights/components', applicationInsights.name), '2018-05-01-preview').instrumentationKey
  }
  {
    name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
    value: 'InstrumentationKey=${reference(resourceId('Microsoft.Insights/components', applicationInsights.name), '2018-05-01-preview').instrumentationKey}'
  }
]

var functionAppNames = [
  'someFunctionAppName'
]

// this next block works

module functionApps './bicep-templates/function-app.template.bicep' = [for i in range(0, length(functionAppNames)): {
  name: functionAppNames[i]
  params:{
    name: functionAppNames[i]
    location: 'East Us'
    serverFarmId: appServicePlan.id
    appSettings: mainAppSettings
  }
  dependsOn:[
    appServicePlan
    applicationInsights
  ]
}]

// vs this next block doesn't work (comment out the above block when uncommenting out the below block)

// var functionOptions = [
//   {
//     name: functionAppNames[0]
//     settings: mainAppSettings
//   }
// ]

// module functionApps './bicep-templates/function-app.template.bicep' = [for functionOption in functionOptions: {
//   name: functionOption.name
//   params:{
//     name: functionOption.name
//     location: 'East Us'
//     serverFarmId: appServicePlan.id
//     appSettings: functionOption.settings
//   }
//     dependsOn:[
//       appServicePlan
//       applicationInsights
//     ]
// }]
//function-app.template.bicep

param name string
param location string
param serverFarmId string
param appSettings array

resource functionApp 'Microsoft.Web/sites@2018-11-01' = {
  name: name
  location: location
  kind: 'functionapp'
  properties: {
    enabled: true
    serverFarmId: serverFarmId
    reserved: false
    isXenon: false
    hyperV: false
    scmSiteAlsoStopped: false
    clientAffinityEnabled: true
    clientCertEnabled: false
    hostNamesDisabled: false
    containerSize: 1536
    dailyMemoryTimeQuota: 0
    httpsOnly: false
    redundancyMode: 'None'
    siteConfig: {
      appSettings: appSettings
    }
  }
}

output id string = functionApp.id
output name string = functionApp.name
//root-template.parameters.baseline.json

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0"
}

Additional context The main thing to look at is the mainAppSettings and how it is being used. Tried to boil this down to the basics to easily reproduce. Let me know if a loom or anything else would be helpful.

ecuaryan commented 3 years ago

Hi,

Thanks for the response.

If i follow your link I see this: [image: image.png]

I understand if in the ARM output it is doing that, but wouldn't that be a bug considering ^^?

Thanks, Ryan Willmore

On Thu, Mar 18, 2021 at 2:46 AM Steve Webster @.***> wrote:

You can't use the reference function in ARM variable declarations

See here https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-variables?tabs=json#define-variable for an explanation

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Azure/bicep/issues/1917#issuecomment-801742363, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACHPZDPNY5ZSQNRGN2QLYH3TEG4UVANCNFSM4ZLNU3FQ .

alex-frankel commented 3 years ago

You are getting the error because the array functionOptions that you are using for the loop is using the reference() function which is not allowed. We happen to be missing it in our type system because you are using the reference() function directly, which we do not recommend. You can (and should) change your mainAppSetings var to the following and then we will catch the error:

var mainAppSettings = [
  {
    name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
    value: applicationInsights.properties.InstrumentationKey
  }
  {
    name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
    value: 'InstrumentationKey=${applicationInsights.properties.InstrumentationKey}'
  }
]

This then correctly catches the error: image

Is there an alternative you can use for the loop array that does not depend on a runtime property?

ecuaryan commented 3 years ago

Thanks for the response. Here's how I was able to get things working before I opened this issue: image

image

I was hoping to not have to maintain relationships between resources via ordering in their own arrays by grouping the related resources/values together in an array of wrapper objects and then iterating over that array. Seems as though I'll have to stick with the former though.

Thanks again!

alex-frankel commented 3 years ago

Closing and tracking with #1988