Azure / bicep

Bicep is a declarative language for describing and deploying Azure resources
MIT License
3.26k stars 753 forks source link

Optional module name in for-loop with custom scope, linter warning and compile error #13295

Open matferrari-msft opened 9 months ago

matferrari-msft commented 9 months ago

Bicep version Bicep CLI version 0.25.3 (862708594a)

Describe the bug When using optionalModuleNames and specifying the scope property on a module in a for loop without a module name, the linter yields the following warning:

Unique resource or deployment name is required when looping. The loop item variable "item" must be referenced in at least one of the value expressions of the following properties: "name", "scope"

To Reproduce

resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = {
  name: resourceGroupName
  location: location
}

module item 'modules/item.bicep' = [for i in range(0, 5): {
  scope: rg
  params: { ... }
}]

Compile Result

 Warning BCP179: Unique resource or deployment name is required when looping. The loop item variable "item" must be referenced in at least one of the value expressions of the following properties: "name", "scope"
Unhandled exception. System.ArgumentException: Expected module syntax body to contain property 'name'
   at Bicep.Core.Intermediate.ExpressionBuilder.GetModuleNameSyntax(ModuleSymbol moduleSymbol)
   at Bicep.Core.Intermediate.ExpressionBuilder.TryGetReplacementContext(ModuleSymbol module, SyntaxBase indexExpression, SyntaxBase newContext)
   at Bicep.Core.Intermediate.ExpressionBuilder.ToDependencyExpression(ResourceDependency dependency, SyntaxBase newContext)
   at Bicep.Core.Intermediate.ExpressionBuilder.<>c__DisplayClass29_0.<ConvertModule>b__2(ResourceDependency x)
   at System.Linq.Enumerable.SelectIPartitionIterator`2.LazyToArray()
   at System.Linq.Enumerable.SelectIPartitionIterator`2.ToArray()
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1)
   at System.Collections.Immutable.ImmutableArray.CreateRange[T](IEnumerable`1 items)
   at System.Collections.Immutable.ImmutableArray.ToImmutableArray[TSource](IEnumerable`1)
   at Bicep.Core.Intermediate.ExpressionBuilder.ConvertModule(ModuleDeclarationSyntax syntax)
   at Bicep.Core.Intermediate.ExpressionBuilder.ConvertWithoutLowering(SyntaxBase syntax)
   at Bicep.Core.Intermediate.ExpressionBuilder.<ConvertProgram>b__26_9(ModuleSymbol x)
   at System.Linq.Enumerable.SelectArrayIterator`2.MoveNext()
   at System.Linq.Enumerable.OfTypeIterator[TResult](IEnumerable)+MoveNext()
   at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1)
   at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1)
   at System.Collections.Immutable.ImmutableArray.CreateRange[T](IEnumerable`1 items)
   at System.Collections.Immutable.ImmutableArray.ToImmutableArray[TSource](IEnumerable`1)
   at Bicep.Core.Intermediate.ExpressionBuilder.ConvertProgram(ProgramSyntax syntax)
   at Bicep.Core.Intermediate.ExpressionBuilder.ConvertWithoutLowering(SyntaxBase syntax)
   at Bicep.Core.Intermediate.ExpressionBuilder.Convert(SyntaxBase syntax)
   at Bicep.Core.Emit.TemplateWriter.GenerateTemplateWithoutHash(PositionTrackingJsonTextWriter jsonWriter)
   at Bicep.Core.Emit.TemplateWriter.Write(SourceAwareJsonTextWriter writer)
   at Bicep.Core.Emit.TemplateWriter.<>c__DisplayClass65_0.<EmitModule>b__2()
   at Bicep.Core.Emit.PositionTrackingJsonTextWriter.WriteObjectWithPosition(IPositionable sourcePosition, Action propertiesFunc)
   at Bicep.Core.Emit.ExpressionEmitter.EmitObject(Action writePropertiesFunc, IPositionable position)
   at Bicep.Core.Emit.ExpressionEmitter.<>c__DisplayClass32_0.<EmitObjectProperty>b__0()
   at Bicep.Core.Emit.PositionTrackingJsonTextWriter.WritePropertyWithPosition(IPositionable keyPosition, String name, Action valueFunc)      
   at Bicep.Core.Emit.ExpressionEmitter.EmitProperty(String propertyName, Action writeValueFunc, IPositionable position)
   at Bicep.Core.Emit.ExpressionEmitter.EmitObjectProperty(String propertyName, Action writePropertiesFunc, IPositionable position)
   at Bicep.Core.Emit.TemplateWriter.<>c__DisplayClass65_0.<EmitModule>b__0()
   at Bicep.Core.Emit.PositionTrackingJsonTextWriter.WriteObjectWithPosition(IPositionable sourcePosition, Action propertiesFunc)
   at Bicep.Core.Emit.ExpressionEmitter.EmitObject(Action writePropertiesFunc, IPositionable position)
   at Bicep.Core.Emit.TemplateWriter.EmitModule(PositionTrackingJsonTextWriter jsonWriter, DeclaredModuleExpression module, ExpressionEmitter emitter)
   at Bicep.Core.Emit.TemplateWriter.<>c__DisplayClass61_2.<EmitResources>b__3()
   at Bicep.Core.Emit.PositionTrackingJsonTextWriter.WritePropertyWithPosition(IPositionable keyPosition, String name, Action valueFunc)      
   at Bicep.Core.Emit.ExpressionEmitter.EmitProperty(String propertyName, Action writeValueFunc, IPositionable position)
   at Bicep.Core.Emit.TemplateWriter.<>c__DisplayClass61_0.<EmitResources>b__1()
   at Bicep.Core.Emit.PositionTrackingJsonTextWriter.WriteObjectWithPosition(IPositionable sourcePosition, Action propertiesFunc)
   at Bicep.Core.Emit.ExpressionEmitter.EmitObject(Action writePropertiesFunc, IPositionable position)
   at Bicep.Core.Emit.ExpressionEmitter.<>c__DisplayClass32_0.<EmitObjectProperty>b__0()
   at Bicep.Core.Emit.PositionTrackingJsonTextWriter.WritePropertyWithPosition(IPositionable keyPosition, String name, Action valueFunc)      
   at Bicep.Core.Emit.ExpressionEmitter.EmitProperty(String propertyName, Action writeValueFunc, IPositionable position)
   at Bicep.Core.Emit.ExpressionEmitter.EmitObjectProperty(String propertyName, Action writePropertiesFunc, IPositionable position)
   at Bicep.Core.Emit.TemplateWriter.EmitResources(PositionTrackingJsonTextWriter jsonWriter, ExpressionEmitter emitter, ImmutableArray`1 resources, ImmutableArray`1 modules)
   at Bicep.Core.Emit.TemplateWriter.GenerateTemplateWithoutHash(PositionTrackingJsonTextWriter jsonWriter)
   at Bicep.Core.Emit.TemplateWriter.Write(SourceAwareJsonTextWriter writer)
   at Bicep.Core.Emit.TemplateEmitter.<>c__DisplayClass8_0.<Emit>b__0()
   at Bicep.Core.Emit.TemplateEmitter.EmitOrFail(Func`1 write)
   at Bicep.Core.Emit.TemplateEmitter.Emit(TextWriter textWriter)
   at Bicep.Core.Emit.CompilationEmitter.Template(SemanticModel model)
   at Bicep.Core.Emit.CompilationEmitter.Parameters()
   at Bicep.Cli.Services.OutputWriter.ParametersToStdout(Compilation compilation)
   at Bicep.Cli.Commands.BuildParamsCommand.RunAsync(BuildParamsArguments args)
   at Bicep.Cli.Program.RunAsync(String[] args, CancellationToken cancellationToken)
   at Bicep.Cli.Program.<>c__DisplayClass3_0.<<Main>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Bicep.Cli.Program.RunWithCancellationAsync(Func`2 runFunc)
   at Bicep.Cli.Program.Main(String[] args)
   at Bicep.Cli.Program.<Main>(String[] args)
majastrz commented 9 months ago

This is a bug with the optional module names feature. The linter doesn't take the possibility of an optional name into account.

The generated name expression of a module in a loop is dependent on the copyIndex() function, so the linter should pass in that situation.