-
Notifications
You must be signed in to change notification settings - Fork 771
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
Proposal - Better validation for conditional resources/modules #3750
Comments
I definitely think Option 3 is important regardless of whether we choose Option 1 or Option 2. This assumes we've fixed any greedy conditional evaluation problems in the runtime. FWIW, I like Option 1 even though it is more verbose, mostly because it is not that much more verbose than Opt.2 and it doesn't introduce any new syntax. Overall, this will be a great improvement! |
I just hit this issue myself trying to make a set of modules to conditionally add vnet to resources. Does solution 1 simply prompt the IDE to tell me to fix the issue? If the fix for the issue is "almost" always, And that would still allow me to customize it if that is not my desired result and I could do something like Applying either of the first 2 solutions is leaving me adding boiler plate code to a lot of places. Even populating "outputs.*" as empty by default would achieve this goal. |
Yeah, essentially. It's a bit better than the present-day situation as you don't actually have to submit a validation/deployment to ARM to figure out the issue, but still pretty verbose.
I'm all for shorter syntax, but IMO a problem with picking default behavior without raising any errors/warnings is that it'll come as a surprise to some people who don't expect an empty string to be the default - especially when used in places other than
+1 - I wanted to lay out some 'cheaper' solutions to discuss pros/cons, but I would personally want solution 3. |
Ultimately I'd go also all the way with no 3, but do no 2 ASAP, as copying conditionals is a pain in you-know-where :) Additionally, similar to C# we could introduce null-forgiving operator to suppress potential null-usage errors if developer is positive, that this will not cause runtime error (i.e. if the condition is not exactly this same as for resource, but logically does this same). The Additionally, in bicepconfig.json we could define if we want to treat nullable usages as warnings or errors. |
When we implement this, let's make sure that #4886 is covered. |
Looking at the linked #1631 - one additional scenario is that the reference() may not be on an output, it may be on a property, or a param (module). Different use case but the fix should be the same - i.e. we don't know what the correct answer is, so we have to ask the developer for help (throw, squiggly, etc). |
howdy, Subscribing because I ran into this, I think! I had a ternary for conditional property defintion and lost lint on both expressions that was there when it was non-conditional. resource dataFactory 'Microsoft.DataFactory/factories@2018-06-01' = {
name: dataFactoryName
location: location
identity: {
type: 'SystemAssigned'
}
properties: {
repoConfiguration: (shouldIncludeGitRepositoryConfiguration) ? {
type: repositoryConifigurationType
projectName: azureDevOpsProjectName
accountName: azureDevOpsAccountName
collaborationBranch: collaborationBranch
repositoryName: repositoryName
rootFolder: dataFactoryGitRootFolder
} : null
}
} |
Subscribing because I've also run into this issue |
Just having solution 1 would already be a great help. It quickly becomes hard to spot any missing unchecked conditional references when working on bicep files with lots of conditionals. Getting an error during development would save us from having a broken deployment because we missed it during our tests. It isn't always feasible to test the deployment with all combinations of conditionals. What is the current progress on this proposal? |
It feels like we're in a better place to light this up now that we've added both |
I think we could tackle this with some slight modifications to code generation: One small note on option 1: I don't think |
Proposal - Better validation for conditional resources/modules
Problem statement
Dealing with conditional resources/modules today can be error prone as you must remember to propagate conditions correctly, and the type system will not alert you to this being done incorrectly - leading to deploy-time errors.
In the following sample, there are no Bicep errors although the output statement may be invalid if
someCond
is false and the resource does not exist.To fix this, the output statement needs to be changed to the following, to propagate the conditional check:
I've mentioned this idea on a few other issues, but thought it would be a good idea to write it up formally for tracking.
Potential Solutions
Note - these solutions all build on-top of each other - 3 depends on 1 & 2, and 2 depends on 1.
1. Treat conditional references as
resource | null
In the first example, if
resWithCond
has typeresource | null
, accessingproperties
directly will raise an error, so the user will be forced to handle the null-ness and write something like the following:There are still problems with this approach - it is a little verbose, and Bicep needs to validate that the condition in the ternary is exactly the same as the condition on the resource.
2. Introduce 'null-conditional' operator
.?
This builds upon the previous solution, but also adds a new operator which removes the need to propate the
someCond
condition - so the type error would be fixable with:In the generated JSON output, Bicep would generate a ternary
if()
statement, bringing the condition for the nullable reference forward:[if(<someCond>, <resWithCond reference statement>, '')]
This is essentially syntactic sugar for 1., but means that lengthy conditions don't need to be copy-pasted.
3. Going deeper with conditional flow analysis
Again, this builds on 1. & 2., giving Bicep the ability to skip null-checks if the condition has already been checked:
Other Notes
someCond && otherCond
- our flow analysis will need to understand that a nullable reference gated onsomeCond
can be used safely, and inside a block which checkssomeCond || otherCond
it cannot be.var combinedCond = someCond && otherCond
The text was updated successfully, but these errors were encountered: