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 4, 2021
1 parent 2eddc95 commit 084aabd
Show file tree
Hide file tree
Showing 13 changed files with 5,218 additions and 11 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
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,8 @@ public void GetsDynamicParametersForTemplateFile()
templateFile,
null,
null,
new[] { "TestPS" });
new[] { "TestPS" },
out templateFile);

Assert.Equal(7, result.Count);

Expand Down Expand Up @@ -332,7 +333,8 @@ public void GetTemplateParametersFromObject()
templateFile,
templateParameterObject,
null,
new[] { "TestPS" });
new[] { "TestPS" },
out templateFile);

Assert.Equal(7, result.Count);

Expand Down Expand Up @@ -374,7 +376,8 @@ public void GetTemplateParametersFromFileMergesObjects()
templateFile,
null,
templateParameterFileSchema1,
new[] { "TestPS" });
new[] { "TestPS" },
out templateFile);

Assert.Equal(7, result.Count);

Expand Down Expand Up @@ -416,7 +419,8 @@ public void GetTemplateParametersFromFileWithSchema2MergesObjects()
templateFile,
null,
templateParameterFileSchema2,
new[] { "TestPS" });
new[] { "TestPS" },
out templateFile);

Assert.Equal(7, result.Count);

Expand Down Expand Up @@ -458,7 +462,8 @@ public void HandlesInvalidTemplateFiles()
invalidTemplateFile,
null,
templateParameterFileSchema1,
new[] { "TestPS" });
new[] { "TestPS" },
out templateFile);

Assert.Empty(result);
}
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 084aabd

Please sign in to comment.