-
Notifications
You must be signed in to change notification settings - Fork 726
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
Support for functions #447
Comments
We definitely want to support user-defined functions. We think they should translate into ARM Template functions so there is parity in the IL, but user-defined functions have a lot of limitations in ARM templates, so we would need to improve that side as well. |
Can't Bicep just inline the functions in the compiled JSON? ARM could take a while to make the necessary changes. And functions bring a LOT of value. |
Referencing #2 |
Technically, yes. However I'd be worried that the repetition of inlining more complex logic would lead to the generated JSON templates getting unexpectedly large and reaching service-side size limitations much faster. There's also the fact that fixing limitations in the ARM JSON benefits non-Bicep users and Bicep users alike, so it would be optimal to prioritize fixes there. @alex-frankel it would be helpful to have a list of the relevant limitations documented, do you know if we've got anything available? |
The Bicep compiler/lang service can produce an error if this happens.
True, but the ARM function spec is currently very limited. And my guess is that Bicep's update cadence will be far greater, as it doesn't have much of back-compat to worry about. When it's available in ARM, then it could be optimized. Perhaps Bicep could introduce a new concept - macros, that will only run during compilation, as opposed to functions that will be compiled into ARM functions. |
I think if we support user-defined functions (UDF) we'd like to improve the current limitations of ARM Template UDFs and then expose those in bicep, otherwise the complexity gets added to the bicep compiler which is hard to manage. Limitations are here |
Just getting into bicep and kind of surprised this is not available yet, as feature parity was announced for 0.3 😞 |
We'll document this as a known limitation. Out of curiosity, what are you using user-defined functions for today? Would it be possible to accomplish similar functionality with variables and/or modules? |
@alex-frankel One of the main purpose we use those is to share some basic common logic we want to avoid duplicating in the templates, especially around formatting strings with |
I'd be curious how far you could get with the "hack" of using a module in the meantime. Definitely not elegant, but you could ensure you are not rewriting the same code in multiple places. function.bicep: param inputValue
var standardSuffix
var newInputValue = '${inputValue}${standardSuffix}'
var makeLowercase = toLower(newInputValue)
output calculatedResourceName string = makeLowerCase main.bicep: module functionHack 'function.bicep' = {
name: 'functionHackDeploy'
params: {
inputValue: 'foobar'
}
}
var outputFromFunciton = functionHack.outputs.calculatedResourceName Note this will not work well for resource naming since resource names must be known at compile time. Consuming the output of a module prevents that from happening. |
For the general purpose of avoiding duplicating some really complex logic, it could... But from the point of view of simplifying the code and keep it DRY, not really, especially for such a simple task as formatting a connection string. Module can only be declared as a "root" resource, not as a sub-resource, right? Also module is going to create its own deployment in the deployment history. So definitively something I would use only for complex cases. |
use case:
|
Additional use case. We generate our resource-names based on a specific pattern including uniqueString. However since you're not allowed to set the name of a resource based on a module output we have to put those resources in another module which breaks the reading flow and the complexity increases a notch. We would love to use a function like in this official example. Aka. Generate a resource name based on a set of rules. |
@alex-frankel Would love to simplyfy something like this using a custome function:
|
I would be satisfied when I can reuse bicep user functions across different bicep files. |
FYI, once #7083 has been released, you should be able to do something like: var containers = map([checkpointContainer, snapshotsContainer, captureContainer],
c => 'https://${substring(c.name, 0, indexOf(c.name, '/'))}.blob.${environment().suffixes.storage}/${substring(c.name, lastIndexOf(c.name, '/') + 1)}')
output AZURE_METERING_INFRA_CHECKPOINTS_CONTAINER string = containers[0]
output AZURE_METERING_INFRA_SNAPSHOTS_CONTAINER string = containers[1]
output AZURE_METERING_INFRA_CAPTURE_CONTAINER string = containers[2] |
Is the team still looking into this? |
@SimonWahlin were you still interested in working on this? |
I am, just havent found the time. |
Here is the proposal I wrote: #9239 |
Very excited for this. Thank you very much for working on this! It is something I've been looking forward to for a very long time. |
See https://github.com/Azure/bicep/blob/ant/exp/func/src/Bicep.Core.Samples/Files/Functions_LF/main.bicep for a syntax example. Notes/limitations: * UDFs in JSON require declaring the return type, so I've modified the spec to require the user to declare the return type. * User-defined types in UDF params & outputs are unsupported. * UDFs are currently quite limited - they can't call UDFs, or access outer scoped variables. * This is currently behind an experimental feature flag ("userDefinedFunctions") Closes #447 Closes #9239 ###### Microsoft Reviewers: [Open in CodeFlow](https://portal.fabricbot.ms/api/codeflow?pullrequest=https://github.com/Azure/bicep/pull/10465)
Is your feature request related to a problem? Please describe.
In ARM Templates we have the notion of functions. Will that be supported in Bicep. I think where it can be useful in Bicep is that you can define the function once and you can use it across multiple Bicep files. Other thing is that it might simplify some complex code. Of course the function define in Bicep does not necessary need to become function in ARM Template. It could be you just convert the code of the function directly to where it is used. The function could also simplify the way they are written compared to ARM where you have to define namespace and members and your logic is output.
The text was updated successfully, but these errors were encountered: