Skip to content

Commit

Permalink
Support deploying Azure resources described with the Bicep language
Browse files Browse the repository at this point in the history
  • Loading branch information
BethanyZhou committed Feb 3, 2021
1 parent 2eddc95 commit f5a7b63
Show file tree
Hide file tree
Showing 12 changed files with 5,208 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -203,16 +203,21 @@ public object GetDynamicParameters()
this.ResolvePath(TemplateFile),
TemplateParameterObject,
this.ResolvePath(TemplateParameterFile),
staticParameterNames);
staticParameterNames,
out templateFile,
this.ExecuteScript<Object>);
}
else
{
dynamicParameters = TemplateUtility.GetTemplateParametersFromFile(
this.ResolvePath(TemplateFile),
TemplateParameterObject,
TemplateParameterUri,
staticParameterNames);
staticParameterNames,
out templateFile,
this.ExecuteScript<Object>);
}
TemplateFile = templateFile;
}
else if (!string.IsNullOrEmpty(TemplateUri) &&
!TemplateUri.Equals(templateUri, StringComparison.OrdinalIgnoreCase))
Expand All @@ -224,16 +229,21 @@ public object GetDynamicParameters()
TemplateUri,
TemplateParameterObject,
this.ResolvePath(TemplateParameterFile),
staticParameterNames);
staticParameterNames,
out templateUri,
this.ExecuteScript<Object>);
}
else
{
dynamicParameters = TemplateUtility.GetTemplateParametersFromFile(
TemplateUri,
TemplateParameterObject,
TemplateParameterUri,
staticParameterNames);
staticParameterNames,
out templateUri,
this.ExecuteScript<Object>);
}
TemplateUri = templateUri;
}
else if (!string.IsNullOrEmpty(TemplateSpecId) &&
!TemplateSpecId.Equals(templateSpecId, StringComparison.OrdinalIgnoreCase))
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/Resources/ResourceManager/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -494,4 +494,7 @@ You can help us improve the accuracy of the result by opening an issue here: htt
<data name="InvalidChangeType" xml:space="preserve">
<value>Unrecognized resource change {0}: {1}. Specify one ore more values in the following list and try again: {2}.</value>
</data>
<data name="NoBicepInstalled" xml:space="preserve">
<value>Bicep has not been installed on this machine. Please visit https://github.com/Azure/bicep/releases and install Bicep.</value>
</data>
</root>
63 changes: 63 additions & 0 deletions src/Resources/ResourceManager/Utilities/BicepUtility.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@

using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
using Microsoft.Azure.Commands.Common.Exceptions;
using Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation;
using Microsoft.WindowsAzure.Commands.Utilities.Common;

using System;
using System.Collections.Generic;
using System.IO;
using System.Management.Automation;

namespace Microsoft.Azure.Commands.ResourceManager.Cmdlets.Utilities
{
public static class BicepUtility
{
public static bool IsBicepExecutable = false;

public static bool IsBicepFile(string templateFilePath)
{
return ".bicep".Equals(Path.GetExtension(templateFilePath)?.ToLower());
}

public delegate List<T> ScriptExecutor<T>(string script);

public static bool CheckBicepExecutable(ScriptExecutor<Object> executeScript)
{
try
{
executeScript("get-command bicep");
}
catch
{
IsBicepExecutable = false;
return IsBicepExecutable;
}
IsBicepExecutable = true;
return IsBicepExecutable;
}

public static string BuildFile(ScriptExecutor<Object> executeScript, string bicepTemplateFilePath)
{
if (!IsBicepExecutable && !CheckBicepExecutable(executeScript))
{
throw new AzPSApplicationException(Properties.Resources.NoBicepInstalled);
}

executeScript($"bicep build {bicepTemplateFilePath}");

string jsonTemplateFilePath = Path.Combine(Path.GetDirectoryName(bicepTemplateFilePath),
Path.GetFileNameWithoutExtension(bicepTemplateFilePath) + ".json");

return jsonTemplateFilePath;
}

public static string BuildFileContent(ScriptExecutor<Object> executeScript, string templateContent, out string jsonTemplateFilePath)
{
string tempFilePath = Path.GetTempFileName();
FileUtilities.DataStore.WriteFile(tempFilePath, templateContent);
jsonTemplateFilePath = BuildFile(executeScript, tempFilePath);
return FileUtilities.DataStore.ReadFileAsText(jsonTemplateFilePath);
}
}
}
8 changes: 7 additions & 1 deletion src/Resources/ResourceManager/Utilities/TemplateUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ public static class TemplateUtility
/// <param name="templateParameterFilePath">Path to the template parameter file if present</param>
/// <param name="staticParameters">The existing PowerShell cmdlet parameters</param>
/// <returns>The template parameters</returns>
public static RuntimeDefinedParameterDictionary GetTemplateParametersFromFile(string templateFilePath, Hashtable templateParameterObject, string templateParameterFilePath, string[] staticParameters)
public static RuntimeDefinedParameterDictionary GetTemplateParametersFromFile(string templateFilePath, Hashtable templateParameterObject, string templateParameterFilePath, string[] staticParameters, out string jsonTemplateFilePath, BicepUtility.ScriptExecutor<Object> executeScript = null)
{
string templateContent = null;
jsonTemplateFilePath = templateFilePath;

if (templateFilePath != null)
{
Expand All @@ -53,6 +54,11 @@ public static RuntimeDefinedParameterDictionary GetTemplateParametersFromFile(st
{
templateContent = FileUtilities.DataStore.ReadFileAsText(templateFilePath);
}

if (BicepUtility.IsBicepFile(templateFilePath))
{
templateContent = BicepUtility.BuildFileContent(executeScript, templateContent, out jsonTemplateFilePath);
}
}

RuntimeDefinedParameterDictionary dynamicParameters = ParseTemplateAndExtractParameters(templateContent, templateParameterObject, templateParameterFilePath, staticParameters);
Expand Down
2 changes: 2 additions & 0 deletions src/Resources/Resources.Test/Resources.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@

<ItemGroup>
<None Update="Resources\*.json" CopyToOutputDirectory="PreserveNewest" />
<None Update="Resources\*.bicep" CopyToOutputDirectory="PreserveNewest" />
<None Update="*.json" CopyToOutputDirectory="PreserveNewest" />
<None Update="*.bicep" CopyToOutputDirectory="PreserveNewest" />
<None Update="ScenarioTests\*.pfx" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

Expand Down
14 changes: 14 additions & 0 deletions src/Resources/Resources.Test/ScenarioTests/DeploymentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,5 +155,19 @@ public void TestNewDeploymentWithQueryString()
{
TestRunner.RunTestScript("Test-NewDeploymentWithQueryString");
}

[Fact]
[Trait(Category.AcceptanceType, Category.CheckIn)]
public void TestNewDeploymentFromBicepFile()
{
TestRunner.RunTestScript("Test-NewDeploymentFromBicepFile");
}

[Fact]
[Trait(Category.AcceptanceType, Category.CheckIn)]
public void TestTestDeploymentFromBicepFile()
{
TestRunner.RunTestScript("Test-TestDeploymentFromBicepFile");
}
}
}
67 changes: 66 additions & 1 deletion src/Resources/Resources.Test/ScenarioTests/DeploymentTests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -662,12 +662,77 @@ function Test-NewDeploymentWithQueryString

# Assert
Assert-AreEqual Succeeded $deployment.ProvisioningState

}

finally
{
# Cleanup
Clean-ResourceGroup $rgname
}
}

<#
.SYNOPSIS
Tests deployment via Bicep file.
#>
function Test-NewDeploymentFromBicepFile
{
# Setup
$rgname = Get-ResourceGroupName
$rname = Get-ResourceName
$rglocation = "West US 2"
$expectedTags = @{"key1"="value1"; "key2"="value2";}

try
{
# Test
New-AzResourceGroup -Name $rgname -Location $rglocation

$deployment = New-AzResourceGroupDeployment -Name $rname -ResourceGroupName $rgname -TemplateFile sampleDeploymentBicepFile.bicep -Tag $expectedTags

# Assert
Assert-AreEqual Succeeded $deployment.ProvisioningState
Assert-True { AreHashtableEqual $expectedTags $deployment.Tags }

$subId = (Get-AzContext).Subscription.SubscriptionId
$deploymentId = "/subscriptions/$subId/resourcegroups/$rgname/providers/Microsoft.Resources/deployments/$rname"
$getById = Get-AzResourceGroupDeployment -Id $deploymentId
Assert-AreEqual $getById.DeploymentName $deployment.DeploymentName

[hashtable]$actualTags = $getById.Tags
Assert-True { AreHashtableEqual $expectedTags $getById.Tags }
}
finally
{
# Cleanup
Clean-ResourceGroup $rgname
}
}

<#
.SYNOPSIS
Tests deployment template via bicep file.
#>
function Test-TestDeploymentFromBicepFile
{
# Setup
$rgname = Get-ResourceGroupName
$rname = Get-ResourceName
$location = "West US 2"

# Test
try
{
New-AzResourceGroup -Name $rgname -Location $location

$list = Test-AzResourceGroupDeployment -ResourceGroupName $rgname -TemplateFile sampleDeploymentBicepFile.bicep

# Assert
Assert-AreEqual 0 @($list).Count
}
finally
{
# Cleanup
Clean-ResourceGroup $rgname
}
}
Loading

0 comments on commit f5a7b63

Please sign in to comment.