Bicep.psm1
Import-Module $PSScriptRoot/Authentication.psm1 <# .SYNOPSIS Confirm-AzBPBicepFile will confirm that the bicep files provided pass the checks executed by `bicep build`. .DESCRIPTION Confirm-AzBPBicepFile executes `bicep build` and returns an object that has an array field Errors. Each element of this array is an object that contains the bicep file path that had errors and a collection of System.Object.ErrorRecord that correspond to the file at that path: {Errors: [ {Path: [string], ErrorResults: [ErrorRecord[]]}, {Path: [string], ErrorResults: [ErrorRecord[]]}, ... ]} Any errors will also be output to stdout for capture by CI/CD pipelines. .PARAMETER BicepPath This is the path to the bicep file that will be confirmed. BicepPath is a mandatory parameter. The property name is optional if the path is provided as the first argument to Confirm-AzBPBicepFile. .EXAMPLE Pipe path into Confirm-AzBPBicepFile "./examples/actionGroupErrors.bicep" | Confirm-AzBPBicepFile Confirm-AzBPBicepFile: ../../../examples/actionGroupErrors.bicep: Confirm-AzBPBicepFile: /workspaces/benchpress/examples/actionGroupErrors.bicep(6,7) : Warning no-unused-params: Parameter "location" is declared but never used. [https://aka.ms/bicep/linter/no-unused-params] Confirm-AzBPBicepFile: /workspaces/benchpress/examples/actionGroupErrors.bicep(12,13) : Warning no-hardcoded-location: A resource location should not use a hard-coded string or variable value. Please use a parameter value, an expression, or the string 'global'. Found: 'westus' [https://aka.ms/bicep/linter/no-hardcoded-location] 0 Errors ----------- {@{Path=../../../examples/actionGroupErrors.bicep; ErrorResults=System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject]... .EXAMPLE Pipe multiple paths into Confirm-AzBPBicepFile "./examples/actionGroupErrors.bicep", "./examples/actionGroupErrors.bicep" | Confirm-AzBPBicepFile Confirm-AzBPBicepFile: ../../../examples/actionGroupErrors.bicep: Confirm-AzBPBicepFile: /workspaces/benchpress/examples/actionGroupErrors.bicep(6,7) : Warning no-unused-params: Parameter "location" is declared but never used. [https://aka.ms/bicep/linter/no-unused-params] Confirm-AzBPBicepFile: /workspaces/benchpress/examples/actionGroupErrors.bicep(12,13) : Warning no-hardcoded-location: A resource location should not use a hard-coded string or variable value. Please use a parameter value, an expression, or the string 'global'. Found: 'westus' [https://aka.ms/bicep/linter/no-hardcoded-location] 0 Confirm-AzBPBicepFile: ../../../examples/actionGroupErrors.bicep: Confirm-AzBPBicepFile: /workspaces/benchpress/examples/actionGroupErrors.bicep(6,7) : Warning no-unused-params: Parameter "location" is declared but never used. [https://aka.ms/bicep/linter/no-unused-params] Confirm-AzBPBicepFile: /workspaces/benchpress/examples/actionGroupErrors.bicep(12,13) : Warning no-hardcoded-location: A resource location should not use a hard-coded string or variable value. Please use a parameter value, an expression, or the string 'global'. Found: 'westus' [https://aka.ms/bicep/linter/no-hardcoded-location] 1 Errors ----------- {@{Path=../../../examples/actionGroupErrors.bicep; ErrorResults=System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject]... .EXAMPLE Provide -BicepPath Parameter Confirm-AzBPBicepFile -BicepPath ./examples/actionGroupErrors.bicep Confirm-AzBPBicepFile: ../../../examples/actionGroupErrors.bicep: Confirm-AzBPBicepFile: /workspaces/benchpress/examples/actionGroupErrors.bicep(6,7) : Warning no-unused-params: Parameter "location" is declared but never used. [https://aka.ms/bicep/linter/no-unused-params] Confirm-AzBPBicepFile: /workspaces/benchpress/examples/actionGroupErrors.bicep(12,13) : Warning no-hardcoded-location: A resource location should not use a hard-coded string or variable value. Please use a parameter value, an expression, or the string 'global'. Found: 'westus' [https://aka.ms/bicep/linter/no-hardcoded-location] 0 Errors ----------- {@{Path=../../../examples/actionGroupErrors.bicep; ErrorResults=System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject]... .EXAMPLE Path without -BicepPath Parameter Confirm-AzBPBicepFile ./examples/actionGroupErrors.bicep Confirm-AzBPBicepFile: ../../../examples/actionGroupErrors.bicep: Confirm-AzBPBicepFile: /workspaces/benchpress/examples/actionGroupErrors.bicep(6,7) : Warning no-unused-params: Parameter "location" is declared but never used. [https://aka.ms/bicep/linter/no-unused-params] Confirm-AzBPBicepFile: /workspaces/benchpress/examples/actionGroupErrors.bicep(12,13) : Warning no-hardcoded-location: A resource location should not use a hard-coded string or variable value. Please use a parameter value, an expression, or the string 'global'. Found: 'westus' [https://aka.ms/bicep/linter/no-hardcoded-location] 0 Errors ----------- {@{Path=../../../examples/actionGroupErrors.bicep; ErrorResults=System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject]... .INPUTS System.String[] .OUTPUTS System.Management.Automation.PSCustomObject[] #> function Confirm-BicepFile { [CmdletBinding()] [OutputType([System.Object[]])] param( [Parameter(Mandatory, Position=0, ValueFromPipeline)] [string[]]$BicepFilePath ) Begin{ $out = [PSCustomObject]@{ Errors = New-Object System.Collections.ArrayList } } Process { foreach ($path in $BicepFilePath) { # The --stdout parameter will send the built ARM template to stdout instead of creating a file # 2>&1 will send errors to stdout so that they can be captured by PowerShell # Both the ARM template and any output from linting will be in the array $results, with individual errors in the # array separately $results = Invoke-Command -ScriptBlock { bicep build $path --stdout 2>&1 } # .Where() returns a collection of System.Management.Automation.ErrorRecord or null if there are no errors $errorResults = $results.Where({$PSItem.GetType().Name -eq 'ErrorRecord'}) if ($errorResults.Count -gt 0) { Write-Error "${path}:" $errorResults | Write-Error $out.Errors.Add([PSCustomObject]@{Path = $path; ErrorResults = $errorResults}) } } } End { return $out } } <# .SYNOPSIS Deploys Azure resources using a bicep file. .DESCRIPTION Deploy-AzBPBicepFeature cmdlet deploys Azure resources when given a path to a bicep file. The cmdlet will transpile the bicep file to an ARM template and uses the ARM template to deploy to Azure. .PARAMETER BicepPath This is the path to the bicep file that will be used to transpile to ARM and deploy to Azure. .EXAMPLE $params = @{ name = "acrbenchpresstest1" location = "westus3" } Deploy-AzBPBicepFeature -BicepPath "./containerRegistry.bicep" -Params $params -ResourceGroupName "rg-test" .INPUTS System.String System.Collections.Hashtable .OUTPUTS None #> function Deploy-BicepFeature(){ [CmdletBinding()] param ( [Parameter(Mandatory=$true)] [string]$BicepPath, [Parameter(Mandatory=$true)] [hashtable]$Params, [Parameter(Mandatory=$false)] [string]$ResourceGroupName ) $fileName = [System.IO.Path]::GetFileNameWithoutExtension($BicepPath) $folder = Split-Path $BicepPath $armPath = Join-Path -Path $folder -ChildPath "$fileName.json" Connect-Account Write-Information "Transpiling Bicep to Arm" # 2>&1 will send errors to stdout so that they can be captured by PowerShell # Both the ARM template and any output from linting will be in the array $results, with individual errors in the # array separately $results = Invoke-Command -ScriptBlock { bicep build $BicepPath 2>&1 } # .Where() returns a collection of System.Management.Automation.ErrorRecord or null if there are no errors $errorResults = $results.Where({$PSItem.GetType().Name -eq 'ErrorRecord'}) # Only deploy if there are no errors. if ($errorResults.Count -eq 0) { $location = $Params.location $deploymentName = $Params.deploymentName if ([string]::IsNullOrEmpty($deploymentName)) { $deploymentName = "BenchPressDeployment" } Write-Information "Deploying ARM Template ($deploymentName) to $location" if ([string]::IsNullOrEmpty($ResourceGroupName)) { New-AzSubscriptionDeployment -Name "$deploymentName" -Location "$location" -TemplateFile "$armPath" -TemplateParameterObject $Params -SkipTemplateParameterPrompt } else{ New-AzResourceGroupDeployment -Name "$deploymentName" -ResourceGroupName "$ResourceGroupName" -TemplateFile "$armPath" -TemplateParameterObject $Params -SkipTemplateParameterPrompt } } Write-Information "Removing Arm template json" Remove-Item "$armPath" } <# .SYNOPSIS Deletes Azure resources. .DESCRIPTION Remove-AzBPBicepFeature cmdlet will take an Azure Resource Group name and delete that resource group and all resources contained in it. .PARAMETER ResourceGroupName Name of the Resource Group to delete .EXAMPLE Remove-AzBPBicepFeature -ResourceGroupName "rg-test" .INPUTS System.String .OUTPUTS None #> function Remove-BicepFeature(){ [CmdletBinding()] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] param ( [Parameter(Mandatory=$true)] [string]$ResourceGroupName ) Connect-Account $resourceGroup = Get-AzResourceGroup -Name $ResourceGroupName Remove-AzResourceGroup -Name $resourceGroup -Force } Export-ModuleMember -Function Confirm-BicepFile, Deploy-BicepFeature, Remove-BicepFeature |