Inline existing resources with runtime names#17904
Conversation
…RuntimeMemeberAccess checks
|
Test this change out locally with the following install scripts (Action run 17300505244) VSCode
Azure CLI
|
Dotnet Test Results 90 files - 45 90 suites - 45 38m 21s ⏱️ - 21m 16s Results for commit 98ce2fa. ± Comparison against base commit 934ac5c. This pull request removes 1923 and adds 663 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
# Conflicts: # src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs
There was a problem hiding this comment.
Pull Request Overview
This PR implements "inlining" of existing Azure resources whose names use runtime values. When an existing resource has runtime-dependent identifiers, no "existing": true resource declaration is emitted in the compiled ARM template, and property references are resolved directly using functions like resourceId() and reference() instead of resourceInfo().
- Extends the
InlineDependencyVisitorto identify existing resources that require inlining due to runtime names - Modifies resource type resolution to handle inlined existing resources differently
- Updates property access validation to allow access to
idandnameproperties of inlined resources - Adds new diagnostic checks to prevent explicit dependencies on or from inlined resources
Reviewed Changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/Bicep.Core/TypeSystem/Providers/ResourceTypeResolver.cs | Updates resource type resolution logic to handle inlined existing resources with topological sorting |
| src/Bicep.Core/TypeSystem/NestedRuntimeMemberAccessValidator.cs | Expands validation to include resource id property for inlined resources |
| src/Bicep.Core/TypeSystem/DeployTimeConstantViolationVisitor.cs | Updates property accessibility checks for Azure resources |
| src/Bicep.Core/Semantics/SemanticModel.cs | Adds lazy initialization for symbols to inline and scope data |
| src/Bicep.Core/Intermediate/ExpressionBuilder.cs | Filters out inlined existing resources from emitted resources |
| src/Bicep.Core/Emit/ScopeHelper.cs | Updates scope data access to use semantic model |
| src/Bicep.Core/Emit/InlineDependencyVisitor.cs | Extends visitor to handle existing resource inlining with dependency analysis |
| src/Bicep.Core/Emit/ExpressionConverter.cs | Conditionally disables resourceInfo codegen for inlined resources |
| src/Bicep.Core/Emit/EmitterContext.cs | Removes moved functionality to semantic model |
| src/Bicep.Core/Emit/EmitLimitationInfo.cs | Removes scope data fields moved to semantic model |
| src/Bicep.Core/Emit/EmitLimitationCalculator.cs | Adds validation for explicit dependencies on inlined resources |
| src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs | Adds new diagnostic messages for inlined resource dependency violations |
Comments suppressed due to low confidence (4)
src/Bicep.Core/Emit/InlineDependencyVisitor.cs:102
- The variable name 'predecssor' is misspelled. It should be 'predecessor'.
visitor.Visit(variable);
src/Bicep.Core/Emit/InlineDependencyVisitor.cs:104
- The variable name 'predecssor' is misspelled. It should be 'predecessor'.
if (!visitor.shouldInlineCache.TryGetValue(variableSymbol, out var shouldInline) || shouldInline != Decision.Inline)
src/Bicep.Core/Emit/InlineDependencyVisitor.cs:98
- The variable name 'predecssor' is misspelled. It should be 'predecessor'.
return false;
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
# Conflicts: # src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs
Resolves #10731
Description
This PR causes
existingAZ resources whose names use runtime values to be "inlined" -- no"existing": trueresource declaration will be emitted in the compiled template, and references to the resource ID, name, type, or API version will not use theresourceInfo()function. Resources with an inlined ancestor or scope are themselves inlined.Example Usage
This PR doesn't introduce any new behavior but instead makes sure that certain templates that deploy successfully with a non-symbolic name compilation target continue to deploy successfully when compiled to language version 2.0.
For example, given the following template:
A non-symbolic name compilation will produce:
{ ... "resources": [], "outputs": { "sa1_id": { "type": "string", "value": "[resourceId('Microsoft.Storage/storageAccounts', uniqueString('foo'))]" }, "sa2_id": { "type": "string", "value": "[resourceId('Microsoft.Storage/storageAccounts', uniqueString('foo', reference(resourceId('Microsoft.Storage/storageAccounts', uniqueString('foo')), '2022-09-01').accessTier))]" } } }whereas a symbolic name compilation will produce:
{ ... "languageVersion": "2.0", "resources": { "sa1": { "existing": true, "type": "Microsoft.Storage/storageAccounts", "apiVersion": "2022-09-01", "name": "[uniqueString('foo')]" }, "sa2": { "existing": true, "type": "Microsoft.Storage/storageAccounts", "apiVersion": "2022-09-01", "name": "[uniqueString('foo', reference('sa1').accessTier)]", // <-- causes a deployment validation failure because 'reference' function is used in a resource name "dependsOn": [ "sa1" ] } }, "outputs": { "sa1_id": { "type": "string", "value": "[resourceInfo('sa1').id]" }, "sa2_id": { "type": "string", "value": "[resourceInfo('sa2').id]" } } }The above template will not raise any compilation errors but will fail to deploy with a validation error.
With this PR, the symbolic name compilation would instead produce the following:
{ ... "languageVersion": "2.0", "resources": { "sa1": { "existing": true, "type": "Microsoft.Storage/storageAccounts", "apiVersion": "2022-09-01", "name": "[uniqueString('foo')]" } }, "outputs": { "sa1_id": { "type": "string", "value": "[resourceInfo('sa1').id]" }, "sa2_id": { "type": "string", "value": "[resourceId('Microsoft.Storage/storageAccounts', uniqueString('foo', reference('sa1').accessTier))]" } } }This template will deploy without issue since
sa2isn't in the compiled JSON. This mirrors the "inlining" process we do with variables that contain runtime expressions since Bicep allows those but ARM does not. Only ARM existing resources can be inlined, as extensibility resources don't have resource IDs.One user-observable behavioral difference introduced by this PR is that an error-level diagnostic will be raised if any resource or module has an explicit dependency on an inlined existing resource or if an inlined existing resource has any explicit dependencies. (See the tests added in d62fd90 for an example of what is now blocked.) I wouldn't consider this to be a backwards-incompatible change because while Bicep didn't raise any errors about these scenarios, the compiled templates would fail to deploy.
Microsoft Reviewers: Open in CodeFlow