New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
remove support for providers() function in bicep #2017
Comments
agree with Brian! good suggestion. |
Relates to #4262 |
Need to decide whether to do this or to create a rule for it (the TTK has a rule discouraging the apiVersions return member). |
I am using the providers function for another use case. I have automated my deployments (using ARM then Bicep) and encountered an issue where I wanted to deploy resources in Canada Central but some of the resources were not available in that region and so I had to fall back to another region for certain resources. I ended up configuring my deployments with a primary location and an alternate location. Once
|
@kzryzstof thanks for sharing your scenario! The motivation for us to generally discourage this pattern is because the Is hard-coding the location to either @bmoore-msft, @alex-frankel FYI. |
The values for both the
In the example above, I specify that I want to deploy the service in two places, in Canada and in Japan. In the
This setup allows me to 'easily' add another region without messing with the resources. Let's say I want to deploy the service in India as well, I just need to do this. 1st I have to define the new locations with a new
And 2nd, in the YAML, I just need to add the new
All of this works because the Now if I have to hard-code the locations at the resource level (which I assume this was what you meant), it seems to complicate things a little bit as I may have to have a structure that tells Let me know if I am mistaken (and I could be :P ) |
Please what then will be the replaced version of this statement? {
name: 'AzureWebJobsStorage'
value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};AccountKey=${listKeys(resourceId(resourceGroup().name, 'Microsoft.Storage/storageAccounts', storageAccountName), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value};EndpointSuffix=${suffix}'
} |
@olusola-adio-sweaty - here's a sample: bicep/src/Bicep.Core.Samples/user_submitted/101/function-premium-vnet-integration/main.bicep Lines 134 to 137 in 7a933cf
If you already have the storageAccount in your Bicep file, then you'll just need to replace If you don't, then you'll need to define the following at the start of your file: resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' existing = {
name: storageAccountName
} You can then use the following for the 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value};EndpointSuffix=${suffix}' |
@anthony-c-martin Thanks a lot. That worked very well. |
@kzryzstof thanks for the extra detail. Without the // picked these values at random - I haven't checked which locations are available
var componentsLocations = {
cae1: 'Canada East'
cae2: 'Canada Central'
jpe1: 'Japan West'
}
resource applicationInsightsResource 'Microsoft.Insights/components@2020-02-02' = {
name: applicationInsightsName
location: componentsLocations[deploymentId]
kind: 'web'
properties: {
Application_Type: 'web'
}
} It's definitely more verbose, but there are also some benefits as it is declarative and not dynamic; you wouldn't have to worry about the location being changed out from underneath you if a particular provider decides to support a new region. This also makes it possible to understand by looking at the file how the region selection logic is going to work. Would that be a suitable solution for you? |
@anthony-c-martin This is what I will have to do indeed... for each resources in my deployment. That makes it pretty verbose considering the number of number resources spread across several services. I just had a look at the number of resources (for fun) and I -apparently- have 152 resources. Would it be possible still to consider having something similar to |
@kzryzstof - can you expand a bit on what you're trying to do with "failing over" locations? Typically what we see is that a deployment will target a particular location and then when Also, since // if the primary location is in the list below, this map will relocate it to a region where insights are available
var insightsLocationMap = {
germanynorth: 'germanywestcentral'
southafricawest: 'southafricanorth'
westcentralus: 'westus2'
westindia: 'centralindia'
} Then the resource code is: resource applicationInsightsResource 'Microsoft.Insights/components@2020-02-02' = {
name: applicationInsightsName
location: contains(insightsLocationMap, primaryLocation) ? insightsLocationMap[primaryLocation] : alternateLocation
kind: 'web'
properties: {
Application_Type: 'web'
}
} Just a variation on @anthony-c-martin's solution that is a bit more generic based on what we usually see for resources that are not available in every region. Another "simplification" of this it putting the location map in keyVault and then it doesn't need to be added to every file. I would go this route if you map all locations, then the syntax of That said - I'm interested in the overall scenario - if you're doing this for 152 resources, you probably don't need to... most resources are available globally and when they aren't, it's unlikely that one map would work for all resource types. E.g. different resources will have different Any of that help? |
@bmoore-msft You definitely have a good argument stating that most of the resources are available everywhere. Turns out I got hit twice with App insights and SignalR at the beginning of a rather small project. So I figured it would be easier to build the concept of fail-over in my ARM pipeline (and then Bicep) (that was almost 2 years ago). It looks like it would be fairly simple to apply your suggestion that would target only few resources then. Thank you very much; I really appreciate it :) |
We're currently using this construct to dynamically retrieve the principalId that is required in various settings:
This allows one to use the same pattern for system-assigned and user-assigned identities. For example:
Not sure how to accomplish the same thing if the providers function was completely removed. |
The JSON template language has a providers() function that returns information from the /providers api at run-time. The most common (may only) use case I've seen for this is
providers().apiVersions[0]
and using that in a list*() function to supply an apiVersion for the POST. The problem this creates is that the function is not deterministic... the "first" apiVersion will change over time (which changes the shape of the response) and it also doesn't indicate "latest" which is a mistaken common understanding.
TLDR; use of the function will eventually break your code even though you didn't change anything.
The function should be deprecated in ARM, though that would be a harder breaking change. In Bicep we can prevent the problem before it starts.
If we don't allow the fn, and there are valid use cases for it, we can always add it.
The text was updated successfully, but these errors were encountered: