diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index ed4559b3..7e5aff3a 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -35,7 +35,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: 6.x + dotnet-version: 7.x - name: Setup NuGet uses: nuget/setup-nuget@v1 diff --git a/src/Analyzer.BicepProcessor.UnitTests/Analyzer.BicepProcessor.UnitTests.csproj b/src/Analyzer.BicepProcessor.UnitTests/Analyzer.BicepProcessor.UnitTests.csproj index d25af7db..e9eb124d 100644 --- a/src/Analyzer.BicepProcessor.UnitTests/Analyzer.BicepProcessor.UnitTests.csproj +++ b/src/Analyzer.BicepProcessor.UnitTests/Analyzer.BicepProcessor.UnitTests.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 false diff --git a/src/Analyzer.BicepProcessor/Analyzer.BicepProcessor.csproj b/src/Analyzer.BicepProcessor/Analyzer.BicepProcessor.csproj index d5b6e7d2..a7d071a0 100644 --- a/src/Analyzer.BicepProcessor/Analyzer.BicepProcessor.csproj +++ b/src/Analyzer.BicepProcessor/Analyzer.BicepProcessor.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 Microsoft.Azure.Templates.Analyzer.BicepProcessor Microsoft.Azure.Templates.Analyzer.BicepProcessor @@ -11,7 +11,7 @@ - + diff --git a/src/Analyzer.BicepProcessor/BicepTemplateProcessor.cs b/src/Analyzer.BicepProcessor/BicepTemplateProcessor.cs index bd4525a7..7b83e6d3 100644 --- a/src/Analyzer.BicepProcessor/BicepTemplateProcessor.cs +++ b/src/Analyzer.BicepProcessor/BicepTemplateProcessor.cs @@ -6,8 +6,9 @@ using System.IO.Abstractions; using System.Linq; using System.Text.RegularExpressions; +using Bicep.Core; +using Bicep.Core.Analyzers.Interfaces; using Bicep.Core.Analyzers.Linter; -using Bicep.Core.Analyzers.Linter.ApiVersions; using Bicep.Core.Configuration; using Bicep.Core.Diagnostics; using Bicep.Core.Emit; @@ -16,27 +17,47 @@ using Bicep.Core.FileSystem; using Bicep.Core.Registry; using Bicep.Core.Registry.Auth; -using Bicep.Core.Semantics; using Bicep.Core.Semantics.Namespaces; using Bicep.Core.Syntax; using Bicep.Core.Text; using Bicep.Core.TypeSystem.Az; using Bicep.Core.Workspaces; +using Microsoft.Extensions.DependencyInjection; using Microsoft.WindowsAzure.ResourceStack.Common.Extensions; +using IOFileSystem = System.IO.Abstractions.FileSystem; namespace Microsoft.Azure.Templates.Analyzer.BicepProcessor { /// /// Contains functionality to process Bicep templates. /// - public class BicepTemplateProcessor + public static class BicepTemplateProcessor { - private static readonly Regex IsModuleRegistryPathRegex = new("^br(:[\\w.]+\\/|\\/public:)", RegexOptions.CultureInvariant | RegexOptions.Compiled); + /// + /// DI Helper from Bicep.Cli.Helpers.ServiceCollectionExtensions + /// + /// + /// + public static IServiceCollection AddBicepCore(this IServiceCollection services) => services + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() // needed for below + .AddSingleton() // enable source mapping + .AddSingleton() + .AddSingleton(); - private static readonly IConfigurationManager configurationManager = new ConfigurationManager(new FileSystem()); - private static readonly IFileResolver fileResolver = new FileResolver(new FileSystem()); - private static readonly INamespaceProvider namespaceProvider = new DefaultNamespaceProvider(new AzResourceTypeLoader()); - private static readonly ITokenCredentialFactory tokenCredentialFactory = new TokenCredentialFactory(); + private static readonly Regex IsModuleRegistryPathRegex = new("^br(:[\\w.]+\\/|\\/public:)", RegexOptions.CultureInvariant | RegexOptions.Compiled); + private static BicepCompiler BicepCompiler = null; /// /// Converts Bicep template into JSON template and returns it as a string and its source map @@ -45,36 +66,17 @@ public class BicepTemplateProcessor /// The compiled template as a JSON string and its source map. public static (string, BicepMetadata) ConvertBicepToJson(string bicepPath) { - var bicepPathUri = new Uri(bicepPath); - using var stringWriter = new StringWriter(); - - var configuration = configurationManager.GetConfiguration(bicepPathUri); - - var featureProviderFactory = IFeatureProviderFactory.WithStaticFeatureProvider( - new SourceMapFeatureProvider(new FeatureProvider(configuration))); - var apiVersionProvider = new ApiVersionProvider( - featureProviderFactory.GetFeatureProvider(bicepPathUri), namespaceProvider); - var apiVersionProviderFactory = IApiVersionProviderFactory.WithStaticApiVersionProvider(apiVersionProvider); - - var moduleDispatcher = new ModuleDispatcher( - new DefaultModuleRegistryProvider( - fileResolver, - new ContainerRegistryClientFactory(tokenCredentialFactory), - new TemplateSpecRepositoryFactory(tokenCredentialFactory), - featureProviderFactory, - configurationManager), - configurationManager); - var workspace = new Workspace(); - var sourceFileGrouping = SourceFileGroupingBuilder.Build(fileResolver, moduleDispatcher, workspace, PathHelper.FilePathToFileUrl(bicepPath)); - - // Pull modules optimistically - if (moduleDispatcher.RestoreModules(moduleDispatcher.GetValidModuleReferences(sourceFileGrouping.GetModulesToRestore())).Result) + if (BicepCompiler == null) { - // Modules had to be restored - recompile - sourceFileGrouping = SourceFileGroupingBuilder.Rebuild(moduleDispatcher, workspace, sourceFileGrouping); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddBicepCore(); + + var services = serviceCollection.BuildServiceProvider(); + BicepCompiler = services.GetRequiredService(); } - var compilation = new Compilation(featureProviderFactory, namespaceProvider, sourceFileGrouping, configurationManager, apiVersionProviderFactory, new LinterAnalyzer()); + using var stringWriter = new StringWriter(); + var compilation = BicepCompiler.CreateCompilation(new Uri(bicepPath)).Result; var emitter = new TemplateEmitter(compilation.GetEntrypointSemanticModel()); var emitResult = emitter.Emit(stringWriter); @@ -87,27 +89,32 @@ public static (string, BicepMetadata) ConvertBicepToJson(string bicepPath) } string GetPathRelativeToEntryPoint(string absolutePath) => Path.GetRelativePath( - Path.GetDirectoryName(sourceFileGrouping.EntryPoint.FileUri.AbsolutePath), absolutePath); + Path.GetDirectoryName(compilation.SourceFileGrouping.EntryPoint.FileUri.AbsolutePath), absolutePath); - // Collect all needed module info from sourceFileGrouping metadata - var moduleInfo = sourceFileGrouping.UriResultByModule.Select(kvp => + // Collect all needed module info from SourceFileGrouping metadata + var moduleInfo = compilation.SourceFileGrouping.UriResultByArtifactReference.Select(sourceFileAndMetadata => { - var bicepSourceFile = kvp.Key as BicepSourceFile; + var bicepSourceFile = sourceFileAndMetadata.Key as BicepSourceFile; var pathRelativeToEntryPoint = GetPathRelativeToEntryPoint(bicepSourceFile.FileUri.AbsolutePath); - var modules = kvp.Value.Values - .Select(result => + var modules = sourceFileAndMetadata.Value + .Select(artifactRefAndUriResult => { // Do not include modules imported from public/private registries, as it is more useful for user to see line number // of the module declaration itself instead of line number in the module as the user does not control template in registry directly - if (result.Statement is not ModuleDeclarationSyntax moduleDeclaration + if (artifactRefAndUriResult.Key is not ModuleDeclarationSyntax moduleDeclaration || moduleDeclaration.Path is not StringSyntax moduleDeclarationPath || moduleDeclarationPath.SegmentValues.Any(v => IsModuleRegistryPathRegex.IsMatch(v))) { return null; } + if (!artifactRefAndUriResult.Value.IsSuccess()) + { + return null; + } + var moduleLine = TextCoordinateConverter.GetPosition(bicepSourceFile.LineStarts, moduleDeclaration.Span.Position).line; - var modulePath = new FileInfo(result.FileUri.AbsolutePath).FullName; // converts path to current platform + var modulePath = new FileInfo(artifactRefAndUriResult.Value.Unwrap().AbsolutePath).FullName; // converts path to current platform // Use relative paths for bicep to match file paths used in bicep modules and source map if (modulePath.EndsWith(".bicep")) diff --git a/src/Analyzer.BicepProcessor/SourceMapFeatureProvider.cs b/src/Analyzer.BicepProcessor/SourceMapFeatureProvider.cs index 24bcf195..b44cb761 100644 --- a/src/Analyzer.BicepProcessor/SourceMapFeatureProvider.cs +++ b/src/Analyzer.BicepProcessor/SourceMapFeatureProvider.cs @@ -1,7 +1,27 @@ -using Bicep.Core.Features; +using System; +using Azure.ResourceManager.Resources; +using Bicep.Core.Features; namespace Microsoft.Azure.Templates.Analyzer.BicepProcessor { + /// + /// Helper class that enables source mapping feature in Bicep.Core + /// + public class SourceMapFeatureProviderFactory : IFeatureProviderFactory + { + private readonly IFeatureProviderFactory factory; + + /// + public SourceMapFeatureProviderFactory(FeatureProviderFactory factory) + { + this.factory = factory; + } + + /// + public IFeatureProvider GetFeatureProvider(Uri templateUri) + => new SourceMapFeatureProvider(this.factory.GetFeatureProvider(templateUri)); + } + /// /// Helper class that enables source mapping feature in Bicep.Core /// @@ -21,9 +41,6 @@ public SourceMapFeatureProvider(IFeatureProvider features) /// public string CacheRootDirectory => features.CacheRootDirectory; - /// - public bool RegistryEnabled => features.RegistryEnabled; - /// public bool SymbolicNameCodegenEnabled => features.SymbolicNameCodegenEnabled; @@ -37,9 +54,27 @@ public SourceMapFeatureProvider(IFeatureProvider features) public bool SourceMappingEnabled => true; /// - public bool ParamsFilesEnabled => features.ParamsFilesEnabled; + public bool UserDefinedFunctionsEnabled => features.UserDefinedFunctionsEnabled; + + /// + public bool DynamicTypeLoadingEnabled => features.DynamicTypeLoadingEnabled; + + /// + public bool PrettyPrintingEnabled => features.PrettyPrintingEnabled; + + /// + public bool TestFrameworkEnabled => features.TestFrameworkEnabled; + + /// + public bool AssertsEnabled => features.AssertsEnabled; + + /// + public bool CompileTimeImportsEnabled => features.CompileTimeImportsEnabled; + + /// + public bool MicrosoftGraphPreviewEnabled => features.MicrosoftGraphPreviewEnabled; /// - public bool UserDefinedTypesEnabled => features.UserDefinedTypesEnabled; + public bool PublishSourceEnabled => features.PublishSourceEnabled; } } diff --git a/src/Analyzer.Cli.FunctionalTests/Analyzer.Cli.FunctionalTests.csproj b/src/Analyzer.Cli.FunctionalTests/Analyzer.Cli.FunctionalTests.csproj index 37633bbe..303a0f2b 100644 --- a/src/Analyzer.Cli.FunctionalTests/Analyzer.Cli.FunctionalTests.csproj +++ b/src/Analyzer.Cli.FunctionalTests/Analyzer.Cli.FunctionalTests.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 false diff --git a/src/Analyzer.Cli.NuGet/Analyzer.Cli.nuspec b/src/Analyzer.Cli.NuGet/Analyzer.Cli.nuspec index 029a5416..f16d9165 100644 --- a/src/Analyzer.Cli.NuGet/Analyzer.Cli.nuspec +++ b/src/Analyzer.Cli.NuGet/Analyzer.Cli.nuspec @@ -12,7 +12,7 @@ - + diff --git a/src/Analyzer.Cli/Analyzer.Cli.csproj b/src/Analyzer.Cli/Analyzer.Cli.csproj index 78e46ddb..2345bec0 100644 --- a/src/Analyzer.Cli/Analyzer.Cli.csproj +++ b/src/Analyzer.Cli/Analyzer.Cli.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net7.0 TemplateAnalyzer A command line interface for Microsoft.Azure.Templates.Analyzer.Core - an ARM and Bicep template scanner for security misconfigurations and best practices diff --git a/src/Analyzer.Core.BuiltInRuleTests/Analyzer.Core.BuiltInRuleTests.csproj b/src/Analyzer.Core.BuiltInRuleTests/Analyzer.Core.BuiltInRuleTests.csproj index 08058cb5..4efb61af 100644 --- a/src/Analyzer.Core.BuiltInRuleTests/Analyzer.Core.BuiltInRuleTests.csproj +++ b/src/Analyzer.Core.BuiltInRuleTests/Analyzer.Core.BuiltInRuleTests.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 false diff --git a/src/Analyzer.Core.NuGet/Analyzer.Core.nuspec b/src/Analyzer.Core.NuGet/Analyzer.Core.nuspec index e942d09d..65e160cd 100644 --- a/src/Analyzer.Core.NuGet/Analyzer.Core.nuspec +++ b/src/Analyzer.Core.NuGet/Analyzer.Core.nuspec @@ -11,16 +11,16 @@ arm bicep azure template analyzer scanner deployment security - - - - - + + + + + - - + + diff --git a/src/Analyzer.Core.UnitTests/Analyzer.Core.UnitTests.csproj b/src/Analyzer.Core.UnitTests/Analyzer.Core.UnitTests.csproj index 4f9602d9..2b5007a4 100644 --- a/src/Analyzer.Core.UnitTests/Analyzer.Core.UnitTests.csproj +++ b/src/Analyzer.Core.UnitTests/Analyzer.Core.UnitTests.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 false diff --git a/src/Analyzer.Core/Analyzer.Core.csproj b/src/Analyzer.Core/Analyzer.Core.csproj index ce623d5d..58497f4c 100644 --- a/src/Analyzer.Core/Analyzer.Core.csproj +++ b/src/Analyzer.Core/Analyzer.Core.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 Microsoft.Azure.Templates.Analyzer Microsoft.Azure.Templates.Analyzer.Core An ARM and Bicep template scanner for security misconfigurations and best practices diff --git a/src/Analyzer.Core/TemplateAnalyzer.cs b/src/Analyzer.Core/TemplateAnalyzer.cs index 7b0873ed..1fbd85e9 100644 --- a/src/Analyzer.Core/TemplateAnalyzer.cs +++ b/src/Analyzer.Core/TemplateAnalyzer.cs @@ -134,7 +134,7 @@ private IEnumerable AnalyzeAllIncludedTemplates(string populatedTem try { - templatejObject = armTemplateProcessor.ProcessTemplate(parameters); + templatejObject = armTemplateProcessor.ProcessTemplate(parameters, generateMissingParameters: parentContext.IsMainTemplate); } catch (Exception e) { diff --git a/src/Analyzer.JsonRuleEngine.FunctionalTests/Analyzer.JsonRuleEngine.FunctionalTests.csproj b/src/Analyzer.JsonRuleEngine.FunctionalTests/Analyzer.JsonRuleEngine.FunctionalTests.csproj index 9070feb8..2911c513 100644 --- a/src/Analyzer.JsonRuleEngine.FunctionalTests/Analyzer.JsonRuleEngine.FunctionalTests.csproj +++ b/src/Analyzer.JsonRuleEngine.FunctionalTests/Analyzer.JsonRuleEngine.FunctionalTests.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 false diff --git a/src/Analyzer.JsonRuleEngine.UnitTests/Analyzer.JsonRuleEngine.UnitTests.csproj b/src/Analyzer.JsonRuleEngine.UnitTests/Analyzer.JsonRuleEngine.UnitTests.csproj index c63a3c4e..75094e2e 100644 --- a/src/Analyzer.JsonRuleEngine.UnitTests/Analyzer.JsonRuleEngine.UnitTests.csproj +++ b/src/Analyzer.JsonRuleEngine.UnitTests/Analyzer.JsonRuleEngine.UnitTests.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 false diff --git a/src/Analyzer.JsonRuleEngine/Analyzer.JsonRuleEngine.csproj b/src/Analyzer.JsonRuleEngine/Analyzer.JsonRuleEngine.csproj index 6d07ba3a..ef4bf4f8 100644 --- a/src/Analyzer.JsonRuleEngine/Analyzer.JsonRuleEngine.csproj +++ b/src/Analyzer.JsonRuleEngine/Analyzer.JsonRuleEngine.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 Microsoft.Azure.Templates.Analyzer.JsonRuleEngine Microsoft.Azure.Templates.Analyzer.RuleEngines.JsonEngine diff --git a/src/Analyzer.PowerShellRuleEngine.UnitTests/Analyzer.PowerShellRuleEngine.UnitTests.csproj b/src/Analyzer.PowerShellRuleEngine.UnitTests/Analyzer.PowerShellRuleEngine.UnitTests.csproj index 72a39a57..6aae6da5 100644 --- a/src/Analyzer.PowerShellRuleEngine.UnitTests/Analyzer.PowerShellRuleEngine.UnitTests.csproj +++ b/src/Analyzer.PowerShellRuleEngine.UnitTests/Analyzer.PowerShellRuleEngine.UnitTests.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 false diff --git a/src/Analyzer.PowerShellRuleEngine/Analyzer.PowerShellRuleEngine.csproj b/src/Analyzer.PowerShellRuleEngine/Analyzer.PowerShellRuleEngine.csproj index 667d3e92..3c214f60 100644 --- a/src/Analyzer.PowerShellRuleEngine/Analyzer.PowerShellRuleEngine.csproj +++ b/src/Analyzer.PowerShellRuleEngine/Analyzer.PowerShellRuleEngine.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 Microsoft.Azure.Templates.Analyzer.PowerShellRuleEngine Microsoft.Azure.Templates.Analyzer.RuleEngines.PowerShellEngine diff --git a/src/Analyzer.Reports.UnitTests/Analyzer.Reports.UnitTests.csproj b/src/Analyzer.Reports.UnitTests/Analyzer.Reports.UnitTests.csproj index 8db08bb9..7020bc7f 100644 --- a/src/Analyzer.Reports.UnitTests/Analyzer.Reports.UnitTests.csproj +++ b/src/Analyzer.Reports.UnitTests/Analyzer.Reports.UnitTests.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 false diff --git a/src/Analyzer.Reports/Analyzer.Reports.csproj b/src/Analyzer.Reports/Analyzer.Reports.csproj index 22741166..aa549817 100644 --- a/src/Analyzer.Reports/Analyzer.Reports.csproj +++ b/src/Analyzer.Reports/Analyzer.Reports.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 Microsoft.Azure.Templates.Analyzer.Reports Microsoft.Azure.Templates.Analyzer.Reports diff --git a/src/Analyzer.TemplateProcessing.NuGet/Analyzer.TemplateProcessing.nuspec b/src/Analyzer.TemplateProcessing.NuGet/Analyzer.TemplateProcessing.nuspec index 0d5b8f96..b4e0963c 100644 --- a/src/Analyzer.TemplateProcessing.NuGet/Analyzer.TemplateProcessing.nuspec +++ b/src/Analyzer.TemplateProcessing.NuGet/Analyzer.TemplateProcessing.nuspec @@ -12,11 +12,11 @@ arm bicep azure template analyzer scanner deployment security - - - - - + + + + + @@ -24,7 +24,7 @@ - + diff --git a/src/Analyzer.TemplateProcessor.UnitTests/Analyzer.TemplateProcessor.UnitTests.csproj b/src/Analyzer.TemplateProcessor.UnitTests/Analyzer.TemplateProcessor.UnitTests.csproj index cfd9f869..3ea60d9c 100644 --- a/src/Analyzer.TemplateProcessor.UnitTests/Analyzer.TemplateProcessor.UnitTests.csproj +++ b/src/Analyzer.TemplateProcessor.UnitTests/Analyzer.TemplateProcessor.UnitTests.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 false diff --git a/src/Analyzer.TemplateProcessor.UnitTests/ArmTemplateProcessorTests.cs b/src/Analyzer.TemplateProcessor.UnitTests/ArmTemplateProcessorTests.cs index d630cbf3..8c09d55c 100644 --- a/src/Analyzer.TemplateProcessor.UnitTests/ArmTemplateProcessorTests.cs +++ b/src/Analyzer.TemplateProcessor.UnitTests/ArmTemplateProcessorTests.cs @@ -8,6 +8,7 @@ using Azure.Deployments.Core.Definitions.Schema; using Azure.Deployments.Core.Json; using Azure.Deployments.Templates.Engines; +using Azure.Deployments.Templates.Exceptions; using Microsoft.Azure.Templates.Analyzer.Utilities; using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.WindowsAzure.ResourceStack.Common.Collections; @@ -1117,6 +1118,62 @@ public void ProcessTemplate_ValidTemplateUsingManagementGroupFunction_ProcessTem Assert.AreEqual("/providers/Microsoft.Management/managementGroups/placeholderManagementGroup", template["resources"][0]["properties"]["details"]["parent"]["id"]); } + [TestMethod] + [DataRow(false)] + [DataRow(true)] + public void ProcessTemplate_ValidTemplateWithPartialParameterList_ProcessTemplateFunction(bool generateMissingParameters) + { + string parametersJson = @"{ + ""$schema"": ""https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#"", + ""contentVersion"": ""1.0.0.0"", + ""parameters"": { + ""trafficRoutingMethod"": { + ""value"": ""Priority"" + } + } + }"; + + string templateJson = @"{ + ""$schema"": ""https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#"", + ""contentVersion"": ""1.0.0.0"", + ""parameters"": { + ""trafficRoutingMethod"": { + ""type"": ""string"" + }, + ""location"": { + ""type"": ""string"" + } + }, + ""resources"": [ + { + ""type"": ""Microsoft.Network/trafficmanagerprofiles"", + ""apiVersion"": ""2018-08-01"", + ""name"": ""testTrafMan"", + ""location"": ""[parameters('location')]"", + ""properties"": { + ""trafficRoutingMethod"": ""[parameters('trafficRoutingMethod')]"" + } + } + ] + }"; + + var armTemplateProcessor = new ArmTemplateProcessor(templateJson); + + if (generateMissingParameters) + { + JToken template = armTemplateProcessor.ProcessTemplate(parametersJson, null, generateMissingParameters); + Assert.AreEqual(2, template["parameters"].Count()); + Assert.IsNotNull(template["parameters"]["trafficRoutingMethod"]); + Assert.AreEqual("Priority", template["parameters"]["trafficRoutingMethod"]["value"]); + Assert.IsNotNull(template["parameters"]["location"]); + } + else + { + Assert.ThrowsException( + () => armTemplateProcessor.ProcessTemplate(parametersJson, null, generateMissingParameters)); + } + } + private string GenerateTemplateWithOutputs(string outputValue) { return string.Format(@"{{ diff --git a/src/Analyzer.TemplateProcessor/Analyzer.TemplateProcessor.csproj b/src/Analyzer.TemplateProcessor/Analyzer.TemplateProcessor.csproj index accfdc4c..1960caaa 100644 --- a/src/Analyzer.TemplateProcessor/Analyzer.TemplateProcessor.csproj +++ b/src/Analyzer.TemplateProcessor/Analyzer.TemplateProcessor.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 Microsoft.Azure.Templates.Analyzer.TemplateProcessor Microsoft.Azure.Templates.Analyzer.TemplateProcessor diff --git a/src/Analyzer.TemplateProcessor/ArmTemplateProcessor.cs b/src/Analyzer.TemplateProcessor/ArmTemplateProcessor.cs index 96075b04..c219b73a 100644 --- a/src/Analyzer.TemplateProcessor/ArmTemplateProcessor.cs +++ b/src/Analyzer.TemplateProcessor/ArmTemplateProcessor.cs @@ -67,10 +67,11 @@ public JToken ProcessTemplate() /// Processes the ARM template with provided parameters and placeholder deployment metadata. /// /// The template parameters and their values JSON. Must follow this schema: https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json# + /// Use given parameters and generate placeholders for missing parameters /// The processed template as a JSON object. - public JToken ProcessTemplate(string parameters) + public JToken ProcessTemplate(string parameters, bool generateMissingParameters = false) { - return ProcessTemplate(parameters, null); + return ProcessTemplate(parameters, null, generateMissingParameters); } /// @@ -78,10 +79,15 @@ public JToken ProcessTemplate(string parameters) /// /// The template parameters and their values JSON. Must follow this schema: https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json# /// The deployment metadata JSON. + /// Use given parameters and generate placeholders for missing parameters /// The processed template as a JSON object. - public JToken ProcessTemplate(string parameters, string metadata) + public JToken ProcessTemplate(string parameters, string metadata, bool generateMissingParameters = false) { - InsensitiveDictionary parametersDictionary = PopulateParameters(string.IsNullOrEmpty(parameters) ? PlaceholderInputGenerator.GeneratePlaceholderParameters(armTemplate) : parameters); + string actualParams = string.IsNullOrEmpty(parameters) || generateMissingParameters + ? PlaceholderInputGenerator.GeneratePlaceholderParameters(armTemplate, parameters) + : parameters; + + InsensitiveDictionary parametersDictionary = PopulateParameters(actualParams); InsensitiveDictionary metadataDictionary = string.IsNullOrEmpty(metadata) ? PlaceholderInputGenerator.GeneratePlaceholderDeploymentMetadata() : PopulateDeploymentMetadata(metadata); var template = ParseAndValidateTemplate(parametersDictionary, metadataDictionary); @@ -543,7 +549,7 @@ internal InsensitiveDictionary PopulateParameters(string parameters) if (parametersObject["parameters"] == null) { - throw new Exception("Parameteres property is not specified in the ARM Template parameters provided. Please ensure ARM Template parameters follows the following JSON schema https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#"); + throw new Exception("Parameters property is not specified in the ARM Template parameters provided. Please ensure ARM Template parameters follows the following JSON schema https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#"); } foreach (var parameter in parametersObject.InsensitiveToken("parameters").Value()?.Properties() ?? Enumerable.Empty()) diff --git a/src/Analyzer.TemplateProcessor/PlaceholderInputGenerator.cs b/src/Analyzer.TemplateProcessor/PlaceholderInputGenerator.cs index eb68ce9c..8147b75c 100644 --- a/src/Analyzer.TemplateProcessor/PlaceholderInputGenerator.cs +++ b/src/Analyzer.TemplateProcessor/PlaceholderInputGenerator.cs @@ -18,13 +18,26 @@ internal static class PlaceholderInputGenerator /// Generates placeholder parameters when no default value is specified in the ARM Template. /// /// The ARM Template to generate parameters for JSON. + /// Parameters with defined values to use /// The Json string of the placeholder parameter values. - internal static string GeneratePlaceholderParameters(string armTemplate) + internal static string GeneratePlaceholderParameters(string armTemplate, string definedParameters = null) { JObject jsonTemplate = JObject.Parse(armTemplate); - JObject jsonParameters = new JObject(); + if (definedParameters != null) + { + JObject definedParameterJson = JObject.Parse(definedParameters); + if (definedParameterJson.InsensitiveToken("parameters") is JObject paramsObject) + { + jsonParameters = paramsObject; + } + else + { + throw new Exception("Parameters property is not specified in the ARM Template parameters provided. Please ensure ARM Template parameters follows the following JSON schema https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#"); + } + } + JToken parameters = jsonTemplate.InsensitiveToken("parameters"); if (parameters != null) { @@ -33,7 +46,7 @@ internal static string GeneratePlaceholderParameters(string armTemplate) foreach (JProperty parameter in parameters.Children()) { JToken parameterValue = parameter.Value; - if (parameterValue.InsensitiveToken("defaultValue") == null) + if (!jsonParameters.ContainsKey(parameter.Name) && parameterValue.InsensitiveToken("defaultValue") == null) { JToken allowedValues = parameterValue.InsensitiveToken("allowedValues"); if (allowedValues != null) diff --git a/src/Analyzer.Types/Analyzer.Types.csproj b/src/Analyzer.Types/Analyzer.Types.csproj index 091c40b6..a9a91367 100644 --- a/src/Analyzer.Types/Analyzer.Types.csproj +++ b/src/Analyzer.Types/Analyzer.Types.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 Microsoft.Azure.Templates.Analyzer.Types Microsoft.Azure.Templates.Analyzer.Types diff --git a/src/Analyzer.Utilities.UnitTests/Analyzer.Utilities.UnitTests.csproj b/src/Analyzer.Utilities.UnitTests/Analyzer.Utilities.UnitTests.csproj index 163ec20d..48f663ef 100644 --- a/src/Analyzer.Utilities.UnitTests/Analyzer.Utilities.UnitTests.csproj +++ b/src/Analyzer.Utilities.UnitTests/Analyzer.Utilities.UnitTests.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 false diff --git a/src/Analyzer.Utilities/Analyzer.Utilities.csproj b/src/Analyzer.Utilities/Analyzer.Utilities.csproj index af492922..13cf45ee 100644 --- a/src/Analyzer.Utilities/Analyzer.Utilities.csproj +++ b/src/Analyzer.Utilities/Analyzer.Utilities.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 Microsoft.Azure.Templates.Analyzer.Utilities Microsoft.Azure.Templates.Analyzer.Utilities