Skip to content

Commit

Permalink
Allow importing from Bicep templates with required parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
jeskew committed May 10, 2024
1 parent 68462f0 commit 2cab358
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 12 deletions.
49 changes: 49 additions & 0 deletions src/Bicep.Core.IntegrationTests/CompileTimeImportTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2312,4 +2312,53 @@ public void Tuple_imported_from_json_is_recompiled_to_a_valid_schema()
resultFromJson.Template.Should().NotBeNull();
resultFromJson.Template.Should().HaveJsonAtPath("definitions.t.properties.p.properties.a", expectedCompilationOfTupleA);
}

[TestMethod]
public void Bicepparam_can_import_from_bicep_template_with_required_parameters()
{
var result = CompilationHelper.CompileParams(
("parameters.bicepparam", """
using 'main.bicep'

import {exported} from 'mod.bicep'

param aParam = exported
"""),
("main.bicep", "param aParam int"),
("mod.bicep", """
param requiredParam string

@export()
var exported = 2
"""));

result.Should().NotHaveAnyDiagnostics();
result.Parameters.Should().NotBeNull();
result.Parameters.Should().HaveValueAtPath("parameters.aParam.value", 2);
}

[TestMethod]
public void Bicepparam_can_import_non_literal_variables_from_json()
{
var compiledModule = CompilationHelper.Compile("""
@export()
var exported = 2 + 2
""");
compiledModule.Template.Should().NotBeNull();

var result = CompilationHelper.CompileParams(
("parameters.bicepparam", """
using 'main.bicep'

import {exported} from 'mod.json'

param aParam = exported
"""),
("main.bicep", "param aParam int"),
("mod.json", compiledModule.Template!.ToString()));

result.Should().NotHaveAnyDiagnostics();
result.Parameters.Should().NotBeNull();
result.Parameters.Should().HaveValueAtPath("parameters.aParam.value", 4);
}
}
8 changes: 8 additions & 0 deletions src/Bicep.Core/ArmHelpers/TemplateVariablesEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
using Azure.Deployments.Expression.Engines;
using Azure.Deployments.Expression.Expressions;
using Azure.Deployments.Templates.Expressions;
using Azure.Deployments.Templates.Extensions;
using Bicep.Core.Extensions;
using Bicep.Core.Parsing;
using Microsoft.WindowsAzure.ResourceStack.Common.Extensions;
using Newtonsoft.Json.Linq;

namespace Bicep.Core.ArmHelpers;
Expand Down Expand Up @@ -38,10 +41,15 @@ internal TemplateVariablesEvaluator(Template template)
{
this.template = template;

var functionsLookup = template.GetFunctionDefinitions().ToOrdinalInsensitiveDictionary(x => x.Key, x => x.Function);

TemplateExpressionEvaluationHelper helper = new()
{
OnGetParameter = OnGetParameter,
OnGetVariable = OnGetVariable,
OnGetFunction = (functionName, _) => functionsLookup.TryGetValue(functionName)
?? throw new ArgumentException($"Function {functionName} was not found."),
ValidationContext = SchemaValidationContext.ForTemplate(template),
};
evaluationContext = helper.EvaluationContext;
}
Expand Down
18 changes: 6 additions & 12 deletions src/Bicep.Core/Emit/ParameterAssignmentEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Azure.Deployments.Templates.Engines;
using Azure.Deployments.Templates.Expressions;
using Azure.Deployments.Templates.Extensions;
using Bicep.Core.ArmHelpers;
using Bicep.Core.Diagnostics;
using Bicep.Core.Emit.CompileTimeImports;
using Bicep.Core.Intermediate;
Expand Down Expand Up @@ -50,6 +51,7 @@ private Result(JToken? value, ParameterKeyVaultReferenceExpression? keyVaultRefe
private readonly ConcurrentDictionary<WildcardImportPropertyReference, Result> wildcardImportVariableResults = new();
private readonly ConcurrentDictionary<Expression, Result> synthesizedVariableResults = new();
private readonly ConcurrentDictionary<SemanticModel, ResultWithDiagnostic<Template>> templateResults = new();
private readonly ConcurrentDictionary<Template, TemplateVariablesEvaluator> armEvaluators = new();
private readonly ImmutableDictionary<string, ParameterAssignmentSymbol> paramsByName;
private readonly ImmutableDictionary<string, VariableSymbol> variablesByName;
private readonly ImmutableDictionary<string, ImportedSymbol> importsByName;
Expand Down Expand Up @@ -189,7 +191,7 @@ private Result EvaluateImportedVariable(Template importedFrom, ImportedSymbol sy

try
{
return Result.For(importedFrom.Variables[originalSymbolName].Value);
return Result.For(armEvaluators.GetOrAdd(importedFrom, t => new(t)).GetEvaluatedVariableValue(originalSymbolName));
}
catch (Exception e)
{
Expand Down Expand Up @@ -230,7 +232,7 @@ private Result EvaluateWildcardImportPropertyAsVariable(ISemanticModel model, Te

try
{
return Result.For(importedFrom.Variables[propertyReference.PropertyName].Value);
return Result.For(armEvaluators.GetOrAdd(importedFrom, t => new(t)).GetEvaluatedVariableValue(propertyReference.PropertyName));
}
catch (Exception e)
{
Expand Down Expand Up @@ -329,6 +331,8 @@ JToken evaluateFunction(Template template, string originalFunctionName)
imported.OriginalSymbolName is { } originalSymbolName)
{
var template = GetTemplateWithCaching(imported.SourceModel).Unwrap();
var evaluator = armEvaluators.GetOrAdd(template, importedFrom => new(importedFrom));


return evaluateFunction(template, originalSymbolName);
}
Expand Down Expand Up @@ -361,16 +365,6 @@ private static ResultWithDiagnostic<Template> GetTemplate(SemanticModel model)
};
var (template, _) = new TemplateWriter(model).GetTemplate(writer);

TemplateEngine.ProcessTemplateLanguageExpressions(
managementGroupName: null,
subscriptionId: null,
resourceGroupName: null,
template: template,
apiVersion: TemplateWriter.NestedDeploymentResourceApiVersion,
inputParameters: new(),
metadata: new(),
diagnostics: TemplateDiagnosticsWriter.Create());

return new(template);
}
catch (Exception ex)
Expand Down

0 comments on commit 2cab358

Please sign in to comment.