-
Notifications
You must be signed in to change notification settings - Fork 734
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Block nested deployment resources with inner scoped evaluation and sy…
…mbolic references to outer scope (#11884) Resolves #11846 This PR updates EmitLimitationCalculator to emit an error when a resource of type `Microsoft.Resources/deployments` uses inner scoped expression evaluation but refers to symbols defined in the outer scope from within the `template` property. This PR may be a **breaking change** for some templates, as the added check may catch scenarios that would not result in a runtime deployment failure, e.g., when a template has a symbol with the same name and type defined in both contexts: ```bicep var fizz = 'buzz' resource nested 'Microsoft.Resources/deployments@2020-10-01' = { name: 'name' properties: { mode: 'Incremental' expressionEvaluationOptions: { scope: 'inner' } template: { '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' contentVersion: '1.0.0.0' variables: { fizz: 'pop' } resources: [ { apiVersion: '2022-09-01' type: 'Microsoft.Resources/tags' name: 'default' properties: { tags: { tag1: fizz // <-- Not an error, but surprise! Its value is 'pop', not 'buzz' } } } ] } } } ``` In that case, the user *may* be using a Bicep symbolic reference to save a few characters, but what the template will do (dereference the inner-scoped symbol) does not line up with the communicated intent of the syntax (i.e., to dereference the outer-scoped symbol), so I chose to flag that as an error, too, as this usage would almost certainly represent a *logical* error even if the compiled nested deployment would not raise a runtime error. ###### Microsoft Reviewers: [Open in CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/Azure/bicep/pull/11884)
- Loading branch information
Showing
13 changed files
with
297 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
...Bicep.Core/Analyzers/Linter/Rules/NoSymbolicReferencesInInnerScopedDeploymentResources.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using Bicep.Core.CodeAction; | ||
using Bicep.Core.Diagnostics; | ||
using Bicep.Core.Navigation; | ||
using Bicep.Core.Parsing; | ||
using Bicep.Core.Semantics; | ||
using Bicep.Core.Syntax; | ||
using Bicep.Core.TypeSystem; | ||
using Bicep.Core.TypeSystem.Az; | ||
using Bicep.Core.Workspaces; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Linq; | ||
|
||
namespace Bicep.Core.Analyzers.Linter.Rules | ||
{ | ||
public sealed class NoSymbolicReferencesInInnerScopedDeploymentResources : LinterRuleBase | ||
{ | ||
public new const string Code = "nested-deployment-template-scoping"; | ||
|
||
public NoSymbolicReferencesInInnerScopedDeploymentResources() : base( | ||
code: Code, | ||
description: CoreResources.NoSymbolicReferencesInInnerScopedDeploymentResourcesDescription, | ||
docUri: new Uri($"https://aka.ms/bicep/linter/{Code}"), | ||
diagnosticLevel: DiagnosticLevel.Error) | ||
{ | ||
} | ||
|
||
public override string FormatMessage(params object[] values) | ||
=> string.Format(CoreResources.NoSymbolicReferencesInInnerScopedDeploymentResourcesMessageFormat, values); | ||
|
||
public override IEnumerable<IDiagnostic> AnalyzeInternal(SemanticModel model, DiagnosticLevel diagnosticLevel) | ||
{ | ||
var innerScopedEvaluationIsDefault = model.EmitterSettings.EnableSymbolicNames; | ||
var topLevelSymbols = model.Root.Declarations.ToHashSet(); | ||
|
||
foreach (var resource in model.DeclaredResources.Where(r => r.IsAzResource)) | ||
{ | ||
if (!LanguageConstants.ResourceTypeComparer.Equals(resource.TypeReference.FormatType(), AzResourceTypeProvider.ResourceTypeDeployments) || | ||
resource.Symbol.DeclaringResource.TryGetBody()?.TryGetPropertyByName("properties", StringComparison.OrdinalIgnoreCase)?.Value is not ObjectSyntax propertiesObject || | ||
propertiesObject.TryGetPropertyByName("template", StringComparison.OrdinalIgnoreCase)?.Value is not SyntaxBase nestedTemplate) | ||
{ | ||
continue; | ||
} | ||
|
||
bool explicitInnerScope = (propertiesObject.TryGetPropertyByName("expressionEvaluationOptions", StringComparison.OrdinalIgnoreCase)?.Value as ObjectSyntax) | ||
?.TryGetPropertyByName("scope", StringComparison.OrdinalIgnoreCase)?.Value is SyntaxBase explicitScope && | ||
model.GetTypeInfo(explicitScope) is StringLiteralType folded && | ||
folded.RawStringValue.Equals("inner", StringComparison.OrdinalIgnoreCase); | ||
|
||
if (explicitInnerScope || innerScopedEvaluationIsDefault) | ||
{ | ||
foreach (var (symbolReferenced, references) in SymbolicReferenceCollector.CollectSymbolsReferenced(model.Binder, nestedTemplate)) | ||
{ | ||
if (!topLevelSymbols.Contains(symbolReferenced)) | ||
{ | ||
continue; | ||
} | ||
|
||
foreach (var reference in references) | ||
{ | ||
yield return CreateDiagnosticForSpan(diagnosticLevel, reference.Span, symbolReferenced.Name); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.