* Initial commit with all but one unit test functioning correctly.
Confirm-Resource.Tests.ps1 is failing due to "Unable to find type [ResourceType]", which makes no sense, since Get-ResourceByType uses the same enum, but the unit tests pass without issue.

* Merged examples into grouped folders.
Removed modules from the psd1.

* Added a build script that can be used both during development and to build the final .psm1 for publishing to PS Gallery.

* Minor code cleanup.

* Updating CI/CD workflows.

* Updated the installation and contributing docs.

* Moved pr-psgallery.yml workflow into ci.yml. Now that there is a "build" process for the module this should happen in the CI pipeline and not the PR pipeline.

* Fixing working directory for unit tests.

* Swapped out relative paths for the PS Gallery module name in the examples, because the relative path will no longer work without building the module.

* Moved the ci-publish-docs-branch.yml into the ci.yml. It made sense logically once I tried rewriting it after the refactor.

* Fixing broken reference in the 'ci_cd_workflows.md' file.

* Minor update to 'ci_cd_workflows.md'

* I honestly couldn't figure out why `ResourceType` was not able to be found. I tried every which way of `using`/`Import`ing/dot sourcing that can be imagined. I think that this is a fundamental issue with PowerShell. The more I researched the more I found about enums and classes not being available from nested modules. I'm not sure why the classes work and enums do not though.

* Fixing broken unit test's reference to `ResourceType.psm1`.
This commit is contained in:
marclerwick 2023-02-28 16:32:31 -08:00 коммит произвёл GitHub
Родитель 343858e022
Коммит b47a0205dd
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
109 изменённых файлов: 2415 добавлений и 2215 удалений

2
.github/workflows/cd-create-version-tag.yml поставляемый
Просмотреть файл

@ -19,7 +19,7 @@ jobs:
# This will create a version tag with a leading "v" followed by the ModuleVersion value inside the quotes
# e.g., "v0.1" for ModuleVersion = "0.1"
run: |
cd ./BenchPress/Helpers/BenchPress.Azure
cd ./Modules/BenchPress.Azure
version=v$(sed -n 's/ModuleVersion = "\([^"]*\)"/\1/p' ./BenchPress.Azure.psd1 \
| sed -n 's/\s*//p')
git tag "$version"

2
.github/workflows/cd-github-release.yml поставляемый
Просмотреть файл

@ -16,7 +16,7 @@ jobs:
uses: ncipollo/release-action@v1
with:
artifactErrorsFailBuild: true
artifacts: "./BenchPress/Helpers/Azure/*"
artifacts: "./BenchPress/Generators/**,./Modules/**"
generateReleaseNotes: true
makeLatest: true
prerelease: true

10
.github/workflows/cd-psgallery.yml поставляемый
Просмотреть файл

@ -9,10 +9,14 @@ jobs:
name: Publish to the PowerShell Gallery
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Checkout repository and submodules
- name: Download module artifacts
uses: actions/download-artifact@v3
with:
name: benchpress-gallery-module
path: ./bin
- name: Publish BenchPress to Gallery
env:
NUGET_KEY: ${{ secrets.NUGET_KEY }}
shell: pwsh
run: |
Publish-Module -Path ./BenchPress/Helpers/Azure -NugetAPIKey $env:NUGET_KEY -Verbose
Publish-Module -Path ./bin -NugetAPIKey $env:NUGET_KEY -Verbose

6
.github/workflows/ci-module-versioning.yml поставляемый
Просмотреть файл

@ -5,7 +5,7 @@ on: # yamllint disable-line rule:truthy
push:
branches: [main]
paths:
- "./BenchPress/Helpers/BenchPress.Azure/*"
- "./Modules/BenchPress.Azure/*"
jobs:
get-tags:
@ -39,9 +39,9 @@ jobs:
- name: Update manifest file
run: |
sed -i 's/ModuleVersion = "[^"]*"/ModuleVersion = "${{ needs.get-tags.outputs.Version }}"/' \
./BenchPress/Helpers/BenchPress.Azure/BenchPress.Azure.psd1
./Modules/BenchPress.Azure/BenchPress.Azure.psd1
- name: Commit changes
run: |
git add ./BenchPress/Helpers/BenchPress.Azure/BenchPress.Azure.psd1
git add ./Modules/BenchPress.Azure/BenchPress.Azure.psd1
git commit -m "version: updating version"
git push origin version

40
.github/workflows/ci-publish-docs-branch.yml поставляемый
Просмотреть файл

@ -1,40 +0,0 @@
---
name: "Publish Docs branch"
on: # yamllint disable-line rule:truthy
push:
branches: [main]
paths:
- "./BenchPress/Helpers/BenchPress.Azure/*.psm1"
jobs:
publish-docs-branch:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Platyps
shell: pwsh
run: |
Install-Module -Name platyPS -Scope CurrentUser -Force
Import-Module platyPS
- name: Create and checkout new docs branch
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git checkout -b docs
- name: Generate docs
shell: pwsh
run: |
Import-Module ./BenchPress/Helpers/BenchPress.Azure/BenchPress.Azure.psd1
New-MarkdownHelp -Module BenchPress.Azure -OutputFolder ./docs
- name: If there are changes push the branch
run: |
if [ "$(git ls-files --deleted --modified --others --exclude-standard -- ./docs | wc -l)" -gt 0 ]
then
git add docs
git commit -m "docs: updating generated documentation"
git push origin docs
fi

84
.github/workflows/ci.yml поставляемый
Просмотреть файл

@ -16,3 +16,87 @@ jobs:
- name: Build Benchpress Solution
working-directory: BenchPress
run: dotnet build
build-modules:
name: Build the PS Gallery Modules
runs-on: ubuntu-latest
steps:
- name: Checkout repository and submodules
uses: actions/checkout@v3
- name: Build Module Files
shell: pwsh
run: |
./build.ps1 -InLine
- name: Archive Module artifacts
uses: actions/upload-artifact@v3
with:
name: benchpress-gallery-module
path: |
./bin/BenchPress.Azure.psd1
./bin/BenchPress.Azure.psm1
local-psgallery:
name: Publish and import from/to local PSGallery
needs: build-modules
runs-on: ubuntu-latest
steps:
- name: Create the local PSGallery folder
shell: pwsh
run: |
$path = New-Item -Path ./packages -ItemType Directory
Register-PSRepository -Name LocalFeedPSRepo -SourceLocation $path.ToString() `
-PublishLocation $path.ToString() -InstallationPolicy Trusted
- name: Download module artifacts
uses: actions/download-artifact@v3
with:
name: benchpress-gallery-module
path: ./bin
- name: Publish AzBP Module locally
shell: pwsh
run: |
Publish-Module -Path ./bin -Repository LocalFeedPSRepo -Verbose
- name: Install AzBP Module from the repository
shell: pwsh
run: |
Install-Module BenchPress.Azure
- name: Verify module exposes cmdlets (smoke test)
shell: pwsh
run: |
if ($(Get-Module -Name BenchPress.Azure -ListAvailable).ExportedCommands.Count -eq 0)
{
throw "No commands are available in the BenchPress.Azure Module."
}
build-docs-branch:
name: Build Generated Docs
needs: build-modules
runs-on: ubuntu-latest
steps:
- name: Download module artifacts
uses: actions/download-artifact@v3
with:
name: benchpress-gallery-module
path: ./bin
- name: Install Platyps
shell: pwsh
run: |
Install-Module -Name platyPS -Scope CurrentUser -Force
Import-Module platyPS
- name: Create and checkout new docs branch
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git checkout -b docs
- name: Generate docs
shell: pwsh
run: |
Import-Module ./bin/BenchPress.Azure.psd1
New-MarkdownHelp -Module BenchPress.Azure -OutputFolder ./docs
- name: If there are changes push the branch
run: |
if [ "$(git ls-files --deleted --modified --others --exclude-standard -- ./docs | wc -l)" -gt 0 ]
then
git add docs
git commit -m "docs: updating generated documentation"
git push origin docs
fi

1
.github/workflows/pr-dotnet.yml поставляемый
Просмотреть файл

@ -6,7 +6,6 @@ on: # yamllint disable-line rule:truthy
paths:
- ".github/workflows/pr-dotnet.yml"
- "BenchPress/**"
- "!BenchPress/Helpers/**"
jobs:
run-unit-tests:

2
.github/workflows/pr-powershell.yml поставляемый
Просмотреть файл

@ -27,7 +27,7 @@ jobs:
Install-Module Pester -ErrorAction Stop
- name: Run PowerShell Unit Tests
shell: pwsh
working-directory: BenchPress
working-directory: ./Modules/BenchPress.Azure
run: |
Invoke-Pester -OutputFile ps-test-results.xml -OutputFormat NUnitXml
- name: Archive PowerShell Test Results

38
.github/workflows/pr-psgallery.yml поставляемый
Просмотреть файл

@ -1,38 +0,0 @@
---
name: pr-powershell
on: # yamllint disable-line rule:truthy
pull_request:
branches: [main]
paths:
- ".github/workflows/pr-psgallery.yml"
- "**.psd1"
- "**.psm1"
- "**.ps1"
jobs:
local-psgallery:
name: Publish and import from/to local PSGallery
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Create the local PSGallery folder
shell: pwsh
run: |
$path = New-Item -Path ./packages -ItemType Directory
Register-PSRepository -Name LocalFeedPSRepo -SourceLocation $path.ToString() `
-PublishLocation $path.ToString() -InstallationPolicy Trusted
- name: Publish AzBP Module
shell: pwsh
run: |
Publish-Module -Path ./BenchPress/Helpers/BenchPress.Azure -Repository LocalFeedPSRepo -Verbose
- name: Install AzBP Module from the repository
shell: pwsh
run: |
Install-Module BenchPress.Azure
- name: Verify module exposes cmdlets (smoke test)
shell: pwsh
run: |
if ($(Get-Module -Name BenchPress.Azure -ListAvailable).ExportedCommands.Count -eq 0)
{
throw "No commands are available in the BenchPress.Azure Module."
}

Просмотреть файл

@ -1,33 +0,0 @@
using module ./public/classes/ConfirmResult.psm1
BeforeAll {
Import-Module $PSScriptRoot/ActionGroup.psm1
Import-Module $PSScriptRoot/Authentication.psm1
Import-Module Az
}
Describe "Confirm-ActionGroup" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName ActionGroup Connect-Account{}
}
It "Calls Get-AzActionGroup" {
Mock -ModuleName ActionGroup Get-AzActionGroup{}
Confirm-ActionGroup -ActionGroupName "agn" -ResourceGroupName "rgn"
Should -Invoke -ModuleName ActionGroup -CommandName "Get-AzActionGroup" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock -ModuleName ActionGroup Get-AzActionGroup{ throw [Exception]::new("Exception") }
$Results = Confirm-ActionGroup -ActionGroupName "agn" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module ActionGroup
Remove-Module Authentication
Remove-Module Az
}

Просмотреть файл

@ -1,33 +0,0 @@
using module ./public/classes/ConfirmResult.psm1
BeforeAll {
Import-Module $PSScriptRoot/AksCluster.psm1
Import-Module $PSScriptRoot/Authentication.psm1
Import-Module Az
}
Describe "Get-AksCluster" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName AksCluster Connect-Account{}
}
It "Calls Get-AzAksCluster" {
Mock -ModuleName AksCluster Get-AzAksCluster{}
Confirm-AksCluster -AksName "acn" -ResourceGroupName "rgn"
Should -Invoke -ModuleName AksCluster -CommandName "Get-AzAksCluster" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock -ModuleName AksCluster Get-AzAksCluster{ throw [Exception]::new("Exception") }
$Results = Confirm-AksCluster -AksName "acn" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module AksCluster
Remove-Module Authentication
Remove-Module Az
}

Просмотреть файл

@ -1,34 +0,0 @@
using module ./public/classes/ConfirmResult.psm1
BeforeAll {
Import-Module $PSScriptRoot/AppServicePlan.psm1
Import-Module $PSScriptRoot/Authentication.psm1
Import-Module Az
}
Describe "Confirm-AppServicePlan" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName AppServicePlan Connect-Account{}
Mock -ModuleName AppServicePlan Get-AzAppServicePlan{}
}
It "Calls Get-AzAppServicePlan" {
Mock -ModuleName AppServicePlan Get-AzAppServicePlan{}
Confirm-AppServicePlan -AppServicePlanName "aspn" -ResourceGroupName "rgn"
Should -Invoke -ModuleName AppServicePlan -CommandName "Get-AzAppServicePlan" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock -ModuleName AppServicePlan Get-AzAppServicePlan{ throw [Exception]::new("Exception") }
$Results = Confirm-AppServicePlan -AppServicePlanName "aspn" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module AppServicePlan
Remove-Module Authentication
Remove-Module Az
}

Просмотреть файл

@ -1,188 +0,0 @@
using module ./public/classes/AuthenticationResult.psm1
using module ./public/classes/AuthenticationData.psm1
<#
.SYNOPSIS
Get-RequiredEnvironmentVariable is a private helper method that retrieves environment variables with the
expectation that if they are not present that an error will be logged with an immedate exit.
.DESCRIPTION
Get-RequiredEnvironmentVariable retrieves the environment variable specified by the input parameter and checks to
be sure that a value is present for that environment variable. If the value is missing or whitespace a message will
be written to Write-Error with the name of the variable in the output and exit will be called.
.PARAMETER VariableName
This is the name of the environment variable to retrieve and validate that a value is present.
.EXAMPLE
Provide -VariableName Parameter
Get-RequiredEnvironmentVariable -VariableName AZ_APPLICATION_ID
.EXAMPLE
Provide variable name without -VariableName Parameter
Get-RequiredEnvironmentVariable AZ_APPLICATION_ID
.INPUTS
System.String
.OUTPUTS
System.String
#>
function Get-RequiredEnvironmentVariable {
[OutputType([System.String])]
param (
[Parameter(Mandatory=$true, Position=0)]
[string]$VariableName
)
Begin {
$Value = [string]$null
}
Process {
$Value = [System.Environment]::GetEnvironmentVariable($VariableName)
if ([string]::IsNullOrWhiteSpace($Value)) {
Write-Error("Missing Required Environment Variable $VariableName")
exit 1
}
}
End {
return $Value
}
}
function Connect-Account {
<#
.SYNOPSIS
Connect-Account uses environment variable values to log into an Azure context. This is an internal function and
should not be used outside of the BenchPress module.
.DESCRIPTION
Connect-Account is designed to login to an Azure context using environment variables to login as a
ServicePrincipal for the PowerShell session.
The expected environment variables are:
AZ_APPLICATION_ID - The Service Principal ID
AZ_ENCRYPTED_PASSWORD - The Service Principal account password properly encrypted using ConvertTo-SecureString and
saved as an environment variable using ConvertFrom-SecureString
AZ_TENANT_ID - The Tenant ID to login to
AZ_SUBSCRIPTION_ID - The Subscription ID to login to
If the current context that is logged in to matches the Service Principal, Tenant, and Subscription this function
is a no-op.
.EXAMPLE
There is only one way to call Connect-Account:
Connect-Account
.INPUTS
None
.OUTPUTS
AuthenticationResult
#>
[OutputType([AuthenticationResult])]
[CmdletBinding()]
param ( )
Begin { }
Process {
$ApplicationId = Get-RequiredEnvironmentVariable AZ_APPLICATION_ID
$TenantId = Get-RequiredEnvironmentVariable AZ_TENANT_ID
$SubscriptionId = Get-RequiredEnvironmentVariable AZ_SUBSCRIPTION_ID
$CurrentConnection = Get-AzContext
$Results = [AuthenticationResult]::new()
# If the current context matches the subscription, tenant, and service principal, then we're already properly
# logged in.
if ($null -ne $CurrentConnection `
-and ($CurrentConnection).Account.Type -eq 'ServicePrincipal' `
-and ($CurrentConnection).Account.Id -eq $ApplicationId `
-and ($CurrentConnection).Tenant.Id -eq $TenantId `
-and ($CurrentConnection).Subscription.Id -eq $SubscriptionId) {
$Results.Success = $true
$Results.AuthenticationData = [AuthenticationData]::new(($CurrentConnection).Subscription.Id)
} else {
# The current context is not correct, create the credentials and login to the correct account
$ClientSecret = Get-RequiredEnvironmentVariable AZ_ENCRYPTED_PASSWORD | ConvertTo-SecureString
$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $ApplicationId, $ClientSecret
try {
$ConnectionParams = @{
Credential = $Credential
TenantId = $TenantId
Subscription = $SubscriptionId
}
$Connection = Connect-AzAccount -ServicePrincipal @ConnectionParams
$Results.Success = $true
$Results.AuthenticationData = [AuthenticationData]::new()
$Results.AuthenticationData.SubscriptionId = $Connection.Context.Subscription.Id
} catch {
$Exception = $_
$Results.Error = $Exception
$Results.Success = $false
}
$Results
}
}
End { }
}
<#
.SYNOPSIS
Disconnect-Account uses environment variable values to disconnect from a specific Azure context. This is an
internal function and should not be used outside of the BenchPress module.
.DESCRIPTION
Disconnect-Account is designed to automatically log out of the specific Azure context using environment variables
to identify the context to disconnect.
The expected environment variables are:
AZ_APPLICATION_ID - The Service Principal ID
AZ_TENANT_ID - The Tenant ID to login to
AZ_SUBSCRIPTION_ID - The Subscription ID to login to
If the current context does not match the Service Principal, Tenant, or Subscription then this function is a no-op
.EXAMPLE
There is only one way to call Disconnect-Account:
Disconnect-Account
.INPUTS
None
.OUTPUTS
None
#>
function Disconnect-Account {
[OutputType([System.Void])]
[CmdletBinding()]
param ( )
Begin {
$ApplicationId = Get-RequiredEnvironmentVariable AZ_APPLICATION_ID
$TenantId = Get-RequiredEnvironmentVariable AZ_TENANT_ID
# If the current context doesn't match the target subscription, tentant, and client, then the testing account is
# not logged in. Do nothing.
$CurrentConnection = Get-AzContext
}
Process {
if ($null -eq $CurrentConnection `
-or ($CurrentConnection).Account.Type -ne "ServicePrincipal" `
-or ($CurrentConnection).Account.Id -ne $ApplicationId `
-or ($CurrentConnection).Tenant.Id -ne $TenantId) {
return
}
$CurrentConnection | Disconnect-AzAccount -Scope CurrentUser
}
End { }
}
Export-ModuleMember -Function Connect-Account, Disconnect-Account

Просмотреть файл

@ -1,28 +0,0 @@
BeforeAll {
Import-Module $PSScriptRoot/AzureCli.psm1
}
Describe "Invoke-AzCli" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName AzureCli Write-Error{}
}
It "Calls Invoke-Expression" {
Mock -ModuleName AzureCli Invoke-Expression{ return 0 }
Invoke-AzCli -Command "command"
Should -Invoke -ModuleName AzureCli -CommandName "Invoke-Expression" -Times 1
Should -Not -Invoke -ModuleName AzureCli -CommandName "Write-Error"
}
It "Calls Write-Error when the error code is greater than 0" {
Mock -ModuleName AzureCli Invoke-Expression{ return 1 }
Should -InvokeVerifiable
}
}
}
AfterAll {
Remove-Module AzureCli
}

Просмотреть файл

@ -1,58 +0,0 @@
<#
.DESCRIPTION
Invoke an Azure CLI command.
.SYNOPSIS
Invoke-AzBPAzCli cmdlet invokes an Azure CLI command and returns the result as an object.
.EXAMPLE
PS C:\> Invoke-AzBPAzCli "account list"
.EXAMPLE
PS C:\> Invoke-AzBPAzCli "account list --query [].name"
.EXAMPLE
PS C:\> Invoke-AzBPAzCli "webapp create --name ${WEBAPP_NAME} --resource-group ${RESOURCE_GROUP_NAME} --plan ${APP_SERVICE_PLAN_NAME}"
.PARAMETER Command
The command to execute.
.NOTES
Invoke-AzBPAzCli adds the az prefix to the command.
.LINK
https://learn.microsoft.com/en-us/cli/azure/
.LINK
https://learn.microsoft.com/en-us/cli/azure/get-started-with-azure-cli
.LINK
https://learn.microsoft.com/en-us/cli/azure/reference-index?view=azure-cli-latest
.INPUTS
System.String
.OUTPUTS
System.Object
#>
function Invoke-AzCli {
[CmdletBinding()]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingInvokeExpression", "")]
param (
[Parameter(Mandatory=$true)]
[string]$Command
)
$toExecute = "az $Command"
$result = Invoke-Expression "$toExecute"
if ($LastExitCode -gt 0) {
Write-Error $result
Exit 1
}
$result | ConvertFrom-Json
}
Export-ModuleMember -Function Invoke-AzCli

Просмотреть файл

@ -1,106 +0,0 @@
BeforeAll {
Import-Module $PSScriptRoot/Authentication.psm1
Import-Module $PSScriptRoot/Bicep.psm1
}
Describe "Confirm-BicepFile" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName Bicep Invoke-Command{}
Mock -ModuleName Bicep Write-Error{}
}
It "Calls Invoke-Command when path provided as first parameter without parameter name" {
Confirm-BicepFile "./nothing.bicep"
Should -Invoke -ModuleName Bicep -CommandName "Invoke-Command" -Times 1
}
It "Calls Invoke-Command with path provided as the -BicepFilePath" {
Confirm-BicepFile -BicepFilePath "./nothing.bicep"
Should -Invoke -ModuleName Bicep -CommandName "Invoke-Command" -Times 1
}
It "Calls Invoke-Command with path piped to cmdlet" {
"./nothing.bicep" | Confirm-BicepFile
Should -Invoke -ModuleName Bicep -CommandName "Invoke-Command" -Times 1
}
It "Calls Invoke-Command multiple times with an array of paths provided as first parameter without parameter name" {
Confirm-BicepFile "./nothing.bicep","./stillnothing.bicep"
Should -Invoke -ModuleName Bicep -CommandName "Invoke-Command" -Times 2
}
It "Calls Invoke-Command multiple times with an array of paths provided as -BicepFilePath" {
Confirm-BicepFile -BicepFilePath "./nothing.bicep","./stillnothing.bicep"
Should -Invoke -ModuleName Bicep -CommandName "Invoke-Command" -Times 2
}
It "Calls Invoke-Command multiple times with an array of paths piped to cmdlet" {
"./nothing.bicep","./stillnothing.bicep" | Confirm-BicepFile
Should -Invoke -ModuleName Bicep -CommandName "Invoke-Command" -Times 2
}
It "Calls Write-Error when the results have an error" {
$mockError = New-MockObject -Type 'System.Management.Automation.ErrorRecord'
Mock -ModuleName Bicep Invoke-Command{ $results = [System.Collections.ArrayList]::new()
$results.Add($mockError)
return $results }
Confirm-BicepFile "./nothing.bicep"
Should -Invoke -ModuleName Bicep -CommandName "Write-Error" -Times 2
}
}
}
Describe "Deploy-BicepFeature" {
Context "unit-test" -Tag "Unit" {
BeforeEach {
Mock -ModuleName Bicep Connect-Account{}
Mock -ModuleName Bicep New-AzResourceGroupDeployment
Mock -ModuleName Bicep Remove-Item
}
It "Should call New-AzResourceGroupDeployment when there are no errors." {
Mock -ModuleName Bicep Invoke-Command{}
Deploy-BicepFeature -BicepPath "./path" -Params @{} -ResourceGroupName "rgn"
Should -Invoke -ModuleName Bicep -CommandName "New-AzResourceGroupDeployment" -Times 1
}
It "Should not call New-AzResourceGroupDeployment when there are errors." {
$mockError = New-MockObject -Type 'System.Management.Automation.ErrorRecord'
Mock -ModuleName Bicep Invoke-Command{ $results = [System.Collections.ArrayList]::new()
$results.Add($mockError)
return $results }
Deploy-BicepFeature -BicepPath "./path" -Params @{} -ResourceGroupName "rgn"
Should -Not -Invoke -ModuleName Bicep -CommandName "New-AzResourceGroupDeployment"
}
}
}
Describe "Remove-BicepFeature" {
Context "unit-test" -Tag "Unit" {
BeforeEach {
Mock -ModuleName Bicep Connect-Account{}
Mock -ModuleName Bicep Get-AzResourceGroup { "Resource" }
Mock -ModuleName Bicep Remove-AzResourceGroup {}
}
It "Calls Get-AzResourceGroup with the passed in ResourceGroupName" {
$resourceGroupName = "rgn"
Remove-BicepFeature -ResourceGroupName $resourceGroupName
Should -Invoke -ModuleName Bicep -CommandName "Get-AzResourceGroup" `
-ParameterFilter { $name -eq $resourceGroupName } -Times 1
}
It "Calls Remove-AzResourceGroup with the returned resource group name" {
$resourceGroupName = "rgn"
Remove-BicepFeature -ResourceGroupName $resourceGroupName
Should -Invoke -ModuleName Bicep -CommandName "Remove-AzResourceGroup" `
-ParameterFilter { $name -eq $resourceGroupName } -Times 1
}
}
}
AfterAll {
Remove-Module Authentication
Remove-Module Bicep
}

Просмотреть файл

@ -1,231 +0,0 @@
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

Просмотреть файл

@ -1,198 +0,0 @@
using module ./Common.psm1
using module ./public/classes/ConfirmResult.psm1
BeforeAll {
Import-Module $PSScriptRoot/AppServicePlan.psm1
Import-Module $PSScriptRoot/Authentication.psm1
Import-Module $PSScriptRoot/Common.psm1
Import-Module $PSScriptRoot/ResourceGroup.psm1
Import-Module $PSScriptRoot/SqlDatabase.psm1
Import-Module $PSScriptRoot/SqlServer.psm1
Import-Module $PSScriptRoot/VirtualMachine.psm1
Import-Module $PSScriptRoot/WebApp.psm1
}
Describe "Get-ResourceByType" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName Common Confirm-ResourceGroup{}
Mock -ModuleName Common Confirm-AppServicePlan{}
Mock -ModuleName Common Confirm-SqlDatabase{}
Mock -ModuleName Common Confirm-SqlServer{}
Mock -ModuleName Common Confirm-VirtualMachine{}
Mock -ModuleName Common Confirm-WebApp{}
}
It "Calls <expected> when [ResourceType]::<resourceType> is used" -TestCases @(
@{ ResourceType = [ResourceType]::ResourceGroup; Expected = "Confirm-ResourceGroup"}
@{ ResourceType = [ResourceType]::AppServicePlan; Expected = "Confirm-AppServicePlan"}
@{ ResourceType = [ResourceType]::SqlDatabase; Expected = "Confirm-SqlDatabase"}
@{ ResourceType = [ResourceType]::SqlServer; Expected = "Confirm-SqlServer"}
@{ ResourceType = [ResourceType]::VirtualMachine; Expected = "Confirm-VirtualMachine"}
@{ ResourceType = [ResourceType]::WebApp; Expected = "Confirm-WebApp"}
) {
Get-ResourceByType -ResourceName resource -ResourceGroupName group -ResourceType $ResourceType -ServerName server
Should -Invoke -ModuleName Common -CommandName $Expected -Times 1
}
}
}
Describe "Get-Resource" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName Common Connect-Account{}
Mock -ModuleName Common Get-AzResource{}
}
It "Calls Get-AzResource without -ResourceGroupName parameter when not provided." {
Get-Resource -ResourceName "rn"
Should -Invoke -ModuleName Common -CommandName Get-AzResource -ParameterFilter { $name -eq "rn"; $resourceGroupName -eq $null }
}
It "Calls Get-AzResource with -ResourceGroupName parameter when provided." {
Get-Resource -ResourceName "rn" -ResourceGroupName "rgn"
Should -Invoke -ModuleName Common -CommandName Get-AzResource -ParameterFilter { $name -eq "rn"; $resourceGroupName -eq "rgn" }
}
}
}
Describe "Confirm-Resource" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName Common Format-NotExistError{}
Mock -ModuleName Common Format-ErrorRecord{}
Mock -ModuleName Common Format-IncorrectValueError{}
Mock -ModuleName Common Format-PropertyDoesNotExistError{}
$script:ConfirmResult = [ConfirmResult]::new(
@{
TestKey = "TestValue"
TestArray = @(@{AnotherKey = "AnotherValue"})
}, $null)
}
It "Calls Get-ResourceByType; returns true when Get-ResourceByType returns a Success ConfirmResult." {
Mock -ModuleName Common Get-ResourceByType{ $ConfirmResult } -Verifiable
$result = Confirm-Resource -ResourceType "ResourceGroup" -ResourceName "mockResourceName"
Should -InvokeVerifiable
Should -Invoke -ModuleName Common -CommandName "Format-NotExistError" -Times 0
Should -Invoke -ModuleName Common -CommandName "Format-IncorrectValueError" -Times 0
$result.Success | Should -Be $true
}
It "Calls Get-ResourceByType; returns true when property matches value." {
Mock -ModuleName Common Get-ResourceByType{ $ConfirmResult } -Verifiable
$result = Confirm-Resource -ResourceType "ResourceGroup" -ResourceName "mockResourceName" `
-PropertyKey "TestKey" -PropertyValue "TestValue"
Should -InvokeVerifiable
Should -Invoke -ModuleName Common -CommandName "Format-NotExistError" -Times 0
Should -Invoke -ModuleName Common -CommandName "Format-IncorrectValueError" -Times 0
$result.Success | Should -Be $true
}
It "Calls Get-ResourceByType; returns true when accessing property in array and matches value." {
Mock -ModuleName Common Get-ResourceByType{ $ConfirmResult } -Verifiable
$result = Confirm-Resource -ResourceType "ResourceGroup" -ResourceName "mockResourceName" `
-PropertyKey "TestArray[0].AnotherKey" -PropertyValue "AnotherValue"
Should -InvokeVerifiable
Should -Invoke -ModuleName Common -CommandName "Format-NotExistError" -Times 0
Should -Invoke -ModuleName Common -CommandName "Format-IncorrectValueError" -Times 0
$result.Success | Should -Be $true
}
It "Calls Get-ResourceByType and Format-Error; returns false when Get-ResourceByType returns empty object." {
Mock -ModuleName Common Get-ResourceByType{ return $null } -Verifiable
$result = Confirm-Resource -ResourceType "ResourceGroup" -ResourceName "mockResourceName"
Should -InvokeVerifiable
Should -Invoke -ModuleName Common -CommandName "Format-ErrorRecord" -Times 1
Should -Invoke -ModuleName Common -CommandName "Format-IncorrectValueError" -Times 0
$result.Success | Should -Be $false
}
It "Calls Get-ResourceByType and Format-IncorrectValueError; returns false when property does not match value." {
Mock -ModuleName Common Get-ResourceByType{ $ConfirmResult } -Verifiable
$result = Confirm-Resource -ResourceType "ResourceGroup" -ResourceName "mockResourceName" `
-PropertyKey "TestKey" -PropertyValue "WrongValue"
Should -InvokeVerifiable
Should -Invoke -ModuleName Common -CommandName "Format-NotExistError" -Times 0
Should -Invoke -ModuleName Common -CommandName "Format-IncorrectValueError" -Times 1
$result.Success | Should -Be $false
}
It "Calls Get-ResourceByType; returns false when indexing incorrectly into property array" {
Mock -ModuleName Common Get-ResourceByType{ $ConfirmResult } -Verifiable
$result = Confirm-Resource -ResourceType "ResourceGroup" -ResourceName "mockResourceName" `
-PropertyKey "WrongArray[0].AnotherKey" -PropertyValue "AnotherValue"
Should -InvokeVerifiable
$result.Success | Should -Be $false
$result.ErrorRecord | Should -Not -Be $null
}
It "Calls Get-ResourceByType and Format-PropertyDoesNotExistError; returns false when property does not exist." {
Mock -ModuleName Common Get-ResourceByType{ $ConfirmResult } -Verifiable
$result = Confirm-Resource -ResourceType "ResourceGroup" -ResourceName "mockResourceName" `
-PropertyKey "WrongKey" -PropertyValue "TestValue"
Should -InvokeVerifiable
Should -Invoke -ModuleName Common -CommandName "Format-NotExistError" -Times 0
Should -Invoke -ModuleName Common -CommandName "Format-PropertyDoesNotExistError" -Times 1
$result.Success | Should -Be $false
}
}
}
Describe "ErrorRecord Helper Methods" {
Context "unit tests" -Tag "Unit" {
It "Calls Format-ErrorRecord when Format-NotExistError is called" {
Mock -ModuleName Common Format-ErrorRecord{} -Verifiable
Format-NotExistError -Message "testMessage"
Should -InvokeVerifiable
}
It "Calls Format-ErrorRecord when Format-IncorrectValueError is called" {
Mock -ModuleName Common Format-ErrorRecord{} -Verifiable
Format-IncorrectValueError -Message "testMessage"
Should -InvokeVerifiable
}
It "Calls Format-ErrorRecord when Format-PropertyDoesNotExistError is called" {
Mock -ModuleName Common Format-ErrorRecord{} -Verifiable
Format-PropertyDoesNotExistError -PropertyKey "testKey"
Should -InvokeVerifiable
}
It "Creates ErrorRecord with correct message and ID when Format-ErrorRecord is called" {
Mock -ModuleName Common New-Object{} -Verifiable
Format-ErrorRecord -Message "testMessage" -ErrorID "testErrorID"
Should -InvokeVerifiable
}
}
}
AfterAll {
Remove-Module Common
Remove-Module ResourceGroup
Remove-Module AppServicePlan
Remove-Module Authentication
Remove-Module SqlDatabase
Remove-Module SqlServer
Remove-Module VirtualMachine
Remove-Module WebApp
}

Просмотреть файл

@ -1,409 +0,0 @@
using module ./public/classes/ConfirmResult.psm1
Import-Module $PSScriptRoot/ActionGroup.psm1
Import-Module $PSScriptRoot/AksCluster.psm1
Import-Module $PSScriptRoot/AppServicePlan.psm1
Import-Module $PSScriptRoot/Authentication.psm1
Import-Module $PSScriptRoot/ContainerRegistry.psm1
Import-Module $PSScriptRoot/KeyVault.psm1
Import-Module $PSScriptRoot/ResourceGroup.psm1
Import-Module $PSScriptRoot/SqlServer.psm1
Import-Module $PSScriptRoot/SqlDatabase.psm1
Import-Module $PSScriptRoot/VirtualMachine.psm1
Import-Module $PSScriptRoot/WebApp.psm1
enum ResourceType {
ActionGroup
AksCluster
AppServicePlan
ContainerRegistry
KeyVault
ResourceGroup
SqlDatabase
SqlServer
VirtualMachine
WebApp
}
<#
.SYNOPSIS
Gets an Azure Resource.
.DESCRIPTION
The Get-AzBPResourceByType cmdlet gets an Azure resource depending on the resource type (i.e. Action Group, Key Vault,
Container Registry, etc.).
.PARAMETER ResourceName
The name of the Resource
.PARAMETER ResourceGroupName
The name of the Resource Group
.PARAMETER ResourceType
The type of the Resource (currently support the following:
ActionGroup
AksCluster
AppServicePlan
ContainerRegistry
KeyVault
ResourceGroup
SqlDatabase
SqlServer
VirtualMachine
WebApp)
.PARAMETER ServerName
If testing an Azure SQL Database resource, the name of the server to which the database is assigned.
.EXAMPLE
Get-AzBPResourceByType -ResourceType ActionGroup -ResourceName "bpactiongroup" -ResourceGroupName "rgbenchpresstest"
.EXAMPLE
Get-AzBPResourceByType -ResourceType VirtualMachine -ResourceName "testvm" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
function Get-ResourceByType {
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
[Parameter(Mandatory = $true)]
[string]$ResourceName,
[Parameter(Mandatory = $false)]
[string]$ResourceGroupName,
[Parameter(Mandatory = $true)]
[ResourceType]$ResourceType,
[Parameter(Mandatory = $false)]
[string]$ServerName
)
switch ($ResourceType) {
ActionGroup { return Confirm-ActionGroup -ActionGroupName $ResourceName -ResourceGroupName $ResourceGroupName }
AksCluster { return Confirm-AksCluster -AKSName $ResourceName -ResourceGroupName $ResourceGroupName }
AppServicePlan { return Confirm-AppServicePlan -AppServicePlanName $ResourceName -ResourceGroupName $ResourceGroupName }
ContainerRegistry { return Confirm-ContainerRegistry -Name $ResourceName -ResourceGroupName $ResourceGroupName }
KeyVault { return Confirm-KeyVault -Name $ResourceName -ResourceGroupName $ResourceGroupName }
ResourceGroup { return Confirm-ResourceGroup -ResourceGroupName $ResourceName }
SqlDatabase { return Confirm-SqlDatabase -ServerName $ServerName -DatabaseName $ResourceName -ResourceGroupName $ResourceGroupName }
SqlServer { return Confirm-SqlServer -ServerName $ResourceName -ResourceGroupName $ResourceGroupName }
VirtualMachine { return Confirm-VirtualMachine -VirtualMachineName $ResourceName -ResourceGroupName $ResourceGroupName }
WebApp { return Confirm-WebApp -WebAppName $ResourceName -ResourceGroupName $ResourceGroupName }
default {
Write-Information "Not implemented yet"
return $null
}
}
}
<#
.SYNOPSIS
Gets one or more resources of a given name.
.DESCRIPTION
The Get-AzBPResource cmdlet gets Azure resources of a given name.
.PARAMETER ResourceName
The name of the Resources
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Get-AzBPResource -ResourceName "benchpresstest"
.EXAMPLE
Get-AzBPResource -ResourceName "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.PSResource
#>
function Get-Resource {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$ResourceName,
[Parameter(Mandatory = $false)]
[string]$ResourceGroupName
)
Connect-Account
if ([string]::IsNullOrEmpty($ResourceGroupName)) {
return Get-AzResource -Name "${ResourceName}"
}
else {
return Get-AzResource -Name "${ResourceName}" -ResourceGroupName "${ResourceGroupName}"
}
}
<#
.SYNOPSIS
Confirms whether a resource exists or properties on a resource are configured correctly.
.DESCRIPTION
The Confirm-AzBPResource cmdlet confirms whether an Azure resource exists and/or confirms whether properties
on a resource exist and are configured to the correct value. The cmdlet will return a ConfirmResult object
which contains the following properties:
- Success: True if the resource exists and/or the property is set to the expected value. Otherwise, false.
- Error: System.Management.Automation.ErrorRecord containing an ErrorRecord with a message explaining
that a resource did not exist or property was not set to the expected value.
- ResourceDetails: System.Object that contains the details of the Azure Resource that is being confirmed.
.PARAMETER ResourceName
The name of the Resource
.PARAMETER ResourceGroupName
The name of the Resource Group
.PARAMETER ResourceType
The type of the Resource (currently supports the following:
ActionGroup
AksCluster
AppServicePlan
ContainerRegistry
KeyVault
ResourceGroup
SqlDatabase
SqlServer
VirtualMachine
WebApp)
.PARAMETER ServerName
If testing an Azure SQL Database resource, the name of the server to which the database is assigned.
.PARAMETER PropertyKey
The name of the property to check on the resource
.PARAMETER PropertyValue
The expected value of the property to check
.EXAMPLE
Checking whether a resource exists (i.e. Resource Group)
Confirm-AzBPResource -ResourceType $resourceType -ResourceName $resourceGroupName
.EXAMPLE
Confirm whether a resource has a property configured correctly (i.e. Resource Group located in West US 3)
Confirm-AzBPResource -ResourceType $resourceType -ResourceName $resourceGroupName -PropertyKey "Location" `
-PropertyValue "WestUS3"
.EXAMPLE
Checking whether a nested property on a resource is configured correctly (i.e. OS of VM is Linux)
$params = @{
ResourceGroupName = "testrg";
ResourceType = "VirtualMachine";
ResourceName = "testvm";
PropertyKey = "StorageProfile.OsDisk.OsType";
PropertyValue = "Linux"
}
$result = Confirm-AzBPResource @params
.INPUTS
ResourceType
System.String
.OUTPUTS
ConfirmResult
#>
function Confirm-Resource {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[ResourceType]$ResourceType,
[Parameter(Mandatory = $true)]
[string]$ResourceName,
[Parameter(Mandatory = $false)]
[string]$ResourceGroupName,
[Parameter(Mandatory = $false)]
[string]$ServerName,
[Parameter(Mandatory = $false)]
[string]$PropertyKey,
[Parameter(Mandatory = $false)]
[string]$PropertyValue
)
$ResourceParams = @{
ResourceGroupName = $ResourceGroupName
ResourceName = $ResourceName
ResourceType = $ResourceType
ServerName = $ServerName
}
$ConfirmResult = Get-ResourceByType @ResourceParams
if ($null -eq $ConfirmResult) {
$ErrorRecord = Format-ErrorRecord -Message "ResourceType is invalid" -ErrorID "InvalidResourceType"
$ConfirmResult = [ConfirmResult]::new($ErrorRecord, $null)
}
elseif ($ConfirmResult.Success) {
if ($PropertyKey) {
$ActualValue = $ConfirmResult.ResourceDetails
# Split property path on open and close square brackets and periods. Remove empty items from array.
$Keys = ($PropertyKey -split '[\[\]\.]').Where({ $_ -ne "" })
foreach ($Key in $Keys) {
# If key is a numerical value, index into array
if ($Key -match "^\d+$") {
try {
$ActualValue = $ActualValue[$Key]
}
catch {
$ErrorRecord = $_
$ConfirmResult = [ConfirmResult]::new($ErrorRecord, $null)
break
}
}
else {
$ActualValue = $ActualValue.$Key
}
}
if ($ActualValue -ne $PropertyValue -and $ConfirmResult.Success -ne $false) {
if ($ActualValue) {
$ErrorRecord = `
Format-IncorrectValueError -ExpectedKey $PropertyKey `
-ExpectedValue $PropertyValue `
-ActualValue $ActualValue
$ConfirmResult = [ConfirmResult]::new($ErrorRecord, $null)
}
else {
$ErrorRecord = Format-PropertyDoesNotExistError -PropertyKey $PropertyKey
$ConfirmResult = [ConfirmResult]::new($ErrorRecord, $null)
}
}
}
}
$ConfirmResult
}
<#
.SYNOPSIS
Private function to create a message and ErrorRecord for when a resource does not exist.
.DESCRIPTION
Format-NotExistError is a private helper function that can be used to construct a message and ErrorRecord
for when a resource does not exist.
.PARAMETER Expected
The name of the resource that was expected to exist.
.EXAMPLE
Format-NotExistError -Expected "MyVM"
.INPUTS
System.String
.OUTPUTS
System.Management.Automation.ErrorRecord
#>
function Format-NotExistError([string]$Expected) {
$Message = "Expected $Expected to exist, but it does not exist."
return Format-ErrorRecord -Message $Message -ErrorID "BenchPressExistFail"
}
<#
.SYNOPSIS
Private function to create a message and ErrorRecord for when a resource property is not set correctly.
.DESCRIPTION
Format-IncorrectValueError is a private helper function that can be used to construct a message and ErrorRecord
for when a resource property is not set to the expected value.
.PARAMETER ExpectedKey
The resource property name that is checked
.PARAMETER ExpectedValue
The expected value of the resource property
.PARAMETER ActualValue
The actual value of the resource property
.EXAMPLE
Format-IncorrectValueError -ExpectedKey "Location" -ExpectedValue "WestUS3" -ActualValue "EastUS"
.INPUTS
System.String
.OUTPUTS
System.Management.Automation.ErrorRecord
#>
function Format-IncorrectValueError([string]$ExpectedKey, [string]$ExpectedValue, [string]$ActualValue) {
$Message = "Expected $ExpectedKey to be $ExpectedValue, but got $ActualValue"
return Format-ErrorRecord -Message $Message -ErrorID "BenchPressValueFail"
}
<#
.SYNOPSIS
Private function to create a message and ErrorRecord for when a resource property does not exist.
.DESCRIPTION
Format-PropertyDoesNotExistError is a private helper function that can be used to construct a message and ErrorRecord
for when a resource property does not exist.
.PARAMETER PropertyKey
The resource property name that is checked
.EXAMPLE
Format-PropertyDoesNotExistError -PropertyKey "Location"
.INPUTS
System.String
.OUTPUTS
System.Management.Automation.ErrorRecord
#>
function Format-PropertyDoesNotExistError([string]$PropertyKey) {
$Message = "$PropertyKey is not a property on the resource"
return Format-ErrorRecord -Message $Message -ErrorID "BenchPressPropertyFail"
}
<#
.SYNOPSIS
Private function to help construct a ErrorRecord.
.DESCRIPTION
Format-ErrorRecord is a private helper function that can be used to construct an ErrorRecord.
.PARAMETER Message
Message for the ErrorRecord
.PARAMETER ErrorID
A string that can be used to uniquily identify the ErrorRecord.
.EXAMPLE
Format-ErrorRecord -Message $incorrectValueMessage -ErrorID "BenchPressValueFail"
.INPUTS
System.String
.OUTPUTS
System.Management.Automation.ErrorRecord
#>
function Format-ErrorRecord ([string] $Message, [string]$ErrorID) {
$Exception = [Exception] $Message
$ErrorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult
$TargetObject = @{ Message = $Message }
$ErrorRecord = New-Object System.Management.Automation.ErrorRecord $Exception, $ErrorID, $ErrorCategory, $TargetObject
return $ErrorRecord
}
Export-ModuleMember -Function Get-Resource, Get-ResourceByType, Confirm-Resource, `
Format-NotExistError, Format-IncorrectValueError, Format-ErrorRecord, Format-PropertyDoesNotExistError

Просмотреть файл

@ -1,33 +0,0 @@
using module ./public/classes/ConfirmResult.psm1
BeforeAll {
Import-Module $PSScriptRoot/Authentication.psm1
Import-Module $PSScriptRoot/ContainerRegistry.psm1
Import-Module Az
}
Describe "Confirm-ContainerRegistry" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName ContainerRegistry Connect-Account{}
}
It "Calls Get-AzContainerRegistry" {
Mock -ModuleName ContainerRegistry Get-AzContainerRegistry{}
Confirm-ContainerRegistry -Name "cr" -ResourceGroupName "rgn"
Should -Invoke -ModuleName ContainerRegistry -CommandName "Get-AzContainerRegistry" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock -ModuleName ContainerRegistry Get-AzContainerRegistry{ throw [Exception]::new("Exception") }
$Results = Confirm-ContainerRegistry -Name "cr" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Authentication
Remove-Module ContainerRegistry
Remove-Module Az
}

Просмотреть файл

@ -1,93 +0,0 @@
using module ./public/classes/ConfirmResult.psm1
BeforeAll {
Import-Module $PSScriptRoot/Authentication.psm1
Import-Module $PSScriptRoot/KeyVault.psm1
Import-Module Az
}
Describe "Confirm-KeyVault" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName KeyVault Connect-Account{}
}
It "Calls Get-AzKeyVault" {
Mock -ModuleName KeyVault Get-AzKeyVault{}
Confirm-KeyVault -Name "vn" -ResourceGroupName "rgn"
Should -Invoke -ModuleName KeyVault -CommandName "Get-AzKeyVault" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock -ModuleName KeyVault Get-AzKeyVault{ throw [Exception]::new("Exception") }
$Results = Confirm-KeyVault -Name "vn" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
Describe "Confirm-KeyVaultSecret" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName KeyVault Connect-Account{}
}
It "Calls Get-AzKeyVaultSecret" {
Mock -ModuleName KeyVault Get-AzKeyVaultSecret{}
Confirm-KeyVaultSecret -Name "n" -KeyVaultName "kvn"
Should -Invoke -ModuleName KeyVault -CommandName "Get-AzKeyVaultSecret" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock -ModuleName KeyVault Get-AzKeyVaultSecret{ throw [Exception]::new("Exception") }
$Results = Confirm-KeyVaultSecret -Name "n" -KeyVaultName "kvn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
Describe "Confirm-KeyVaultKey" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName KeyVault Connect-Account{}
}
It "Calls Get-AzKeyVaultKey" {
Mock -ModuleName KeyVault Get-AzKeyVaultKey{}
Confirm-KeyVaultKey -Name "n" -KeyVaultName "kvn"
Should -Invoke -ModuleName KeyVault -CommandName "Get-AzKeyVaultKey" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock -ModuleName KeyVault Get-AzKeyVaultKey{ throw [Exception]::new("Exception") }
$Results = Confirm-KeyVaultKey -Name "n" -KeyVaultName "kvn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
Describe "Confirm-KeyVaultCertificate" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName KeyVault Connect-Account{}
}
It "Calls Get-AzKeyVaultCertificate" {
Mock -ModuleName KeyVault Get-AzKeyVaultCertificate{}
Confirm-KeyVaultCertificate -Name "n" -KeyVaultName "kvn"
Should -Invoke -ModuleName KeyVault -CommandName "Get-AzKeyVaultCertificate" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock -ModuleName KeyVault Get-AzKeyVaultCertificate{ throw [Exception]::new("Exception") }
$Results = Confirm-KeyVaultCertificate -Name "n" -KeyVaultName "kvn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Authentication
Remove-Module KeyVault
Remove-Module Az
}

Просмотреть файл

@ -1,220 +0,0 @@
using module ./public/classes/ConfirmResult.psm1
Import-Module $PSScriptRoot/Authentication.psm1
<#
.SYNOPSIS
Confirms that a Key Vault exists.
.DESCRIPTION
The Confirm-AzBPKeyVault cmdlet gets a Key Vault using the specified Key Vault and
Resource Group name.
.PARAMETER Name
The name of the Key Vault
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPKeyVault -Name "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
function Confirm-KeyVault {
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
[Parameter(Mandatory = $true)]
[string]$Name,
[Parameter(Mandatory = $true)]
[string]$ResourceGroupName
)
Begin {
$ConnectResults = Connect-Account
}
Process {
[ConfirmResult]$Results = $null
try {
$Resource = Get-AzKeyVault -ResourceGroupName $ResourceGroupName -VaultName $Name
$Results = [ConfirmResult]::new($Resource, $ConnectResults.AuthenticationData)
} catch {
$ErrorRecord = $_
$Results = [ConfirmResult]::new($ErrorRecord, $ConnectResults.AuthenticationData)
}
$Results
}
End { }
}
<#
.SYNOPSIS
Confirms that a Key Vault Secret exists.
.DESCRIPTION
The Confirm-AzBPKeyVaultSecret cmdlet gets a Key Vault Secret using the specified Key Vault and
Secret name.
.PARAMETER Name
The name of the Secret
.PARAMETER KeyVaultName
The name of the Key Vault
.EXAMPLE
Confirm-AzBPKeyVaultSecret -Name "benchpresstest" -KeyVaultName "kvbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
function Confirm-KeyVaultSecret {
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
[Parameter(Mandatory = $true)]
[string]$Name,
[Parameter(Mandatory = $true)]
[string]$KeyVaultName
)
Begin {
$ConnectResults = Connect-Account
}
Process {
[ConfirmResult]$Results = $null
try {
$Resource = Get-AzKeyVaultSecret -Name $Name -VaultName $KeyVaultName
$Results = [ConfirmResult]::new($Resource, $ConnectResults.AuthenticationData)
} catch {
$ErrorRecord = $_
$Results = [ConfirmResult]::new($ErrorRecord, $ConnectResults.AuthenticationData)
}
$Results
}
End { }
}
<#
.SYNOPSIS
Confirms that a Key Vault Key exist.
.DESCRIPTION
The Confirm-AzBPKeyVaultKey cmdlet gets a Key Vault Key using the specified Key Vault and
Key name.
.PARAMETER Name
The name of the Key
.PARAMETER KeyVaultName
The name of the Key Vault
.EXAMPLE
Confirm-AzBPKeyVaultKey -Name "benchpresstest" -KeyVaultName "kvbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
function Confirm-KeyVaultKey {
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
[Parameter(Mandatory = $true)]
[string]$Name,
[Parameter(Mandatory = $true)]
[string]$KeyVaultName
)
Begin {
$ConnectResults = Connect-Account
}
Process {
[ConfirmResult]$Results = $null
try {
$Resource = Get-AzKeyVaultKey -Name $Name -VaultName $KeyVaultName
$Results = [ConfirmResult]::new($Resource, $ConnectResults.AuthenticationData)
} catch {
$ErrorRecord = $_
$Results = [ConfirmResult]::new($ErrorRecord, $ConnectResults.AuthenticationData)
}
$Results
}
End { }
}
<#
.SYNOPSIS
Confirms that a Key Vault Certificate exists.
.DESCRIPTION
The Confirm-AzBPKeyVaultCertificate cmdlet gets a Key Vault Certificate using the specified Key Vault and
Certificate name.
.PARAMETER Name
The name of the Certificate
.PARAMETER KeyVaultName
The name of the Key Vault
.EXAMPLE
Confirm-AzBPKeyVaultCertificate -Name "benchpresstest" -KeyVaultName "kvbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
function Confirm-KeyVaultCertificate {
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
[Parameter(Mandatory = $true)]
[string]$Name,
[Parameter(Mandatory = $true)]
[string]$KeyVaultName
)
Begin {
$ConnectResults = Connect-Account
}
Process {
[ConfirmResult]$Results = $null
try {
$Resource = Get-AzKeyVaultCertificate -Name $Name -VaultName $KeyVaultName
$Results = [ConfirmResult]::new($Resource, $ConnectResults.AuthenticationData)
} catch {
$ErrorRecord = $_
$Results = [ConfirmResult]::new($ErrorRecord, $ConnectResults.AuthenticationData)
}
$Results
}
End { }
}
Export-ModuleMember -Function Confirm-KeyVault,
Confirm-KeyVaultSecret,
Confirm-KeyVaultKey,
Confirm-KeyVaultCertificate

Просмотреть файл

@ -1,33 +0,0 @@
using module ./public/classes/ConfirmResult.psm1
BeforeAll {
Import-Module $PSScriptRoot/Authentication.psm1
Import-Module $PSScriptRoot/ResourceGroup.psm1
Import-Module Az
}
Describe "Confirm-ResourceGroup" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName ResourceGroup Connect-Account{}
}
It "Calls Get-AzResourceGroup" {
Mock -ModuleName ResourceGroup Get-AzResourceGroup{}
Confirm-ResourceGroup -ResourceGroupName "rgn"
Should -Invoke -ModuleName ResourceGroup -CommandName "Get-AzResourceGroup" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock -ModuleName ResourceGroup Get-AzResourceGroup{ throw [Exception]::new("Exception") }
$Results = Confirm-ResourceGroup -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Authentication
Remove-Module ResourceGroup
Import-Module Az
}

Просмотреть файл

@ -1,33 +0,0 @@
using module ./public/classes/ConfirmResult.psm1
BeforeAll {
Import-Module $PSScriptRoot/Authentication.psm1
Import-Module $PSScriptRoot/SqlServer.psm1
Import-Module Az
}
Describe "Confirm-SqlServer" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName SqlServer Connect-Account{}
}
It "Calls Get-AzSqlServer" {
Mock -ModuleName SqlServer Get-AzSqlServer{}
Confirm-SqlServer -ServerName "sn" -ResourceGroupName "rgn"
Should -Invoke -ModuleName SqlServer -CommandName "Get-AzSqlServer" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock -ModuleName SqlServer Get-AzSqlServer{ throw [Exception]::new("Exception") }
$Results = Confirm-SqlServer -ServerName "sn" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Authentication
Remove-Module SqlServer
Remove-Module Az
}

Просмотреть файл

@ -1,33 +0,0 @@
using module ./public/classes/ConfirmResult.psm1
BeforeAll {
Import-Module $PSScriptRoot/Authentication.psm1
Import-Module $PSScriptRoot/VirtualMachine.psm1
Import-Module Az
}
Describe "Confirm-VirtualMachine" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName VirtualMachine Connect-Account{}
}
It "Calls Get-AzVM" {
Mock -ModuleName VirtualMachine Get-AzVM{}
Confirm-VirtualMachine -VirtualMachineName "vmn" -ResourceGroupName "rgn"
Should -Invoke -ModuleName VirtualMachine -CommandName "Get-AzVM" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock -ModuleName VirtualMachine Get-AzVM{ throw [Exception]::new("Exception") }
$Results = Confirm-VirtualMachine -VirtualMachineName "vmn" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Authentication
Remove-Module VirtualMachine
Remove-Module Az
}

Просмотреть файл

@ -1,32 +0,0 @@
using module ./public/classes/ConfirmResult.psm1
BeforeAll {
Import-Module $PSScriptRoot/Authentication.psm1
Import-Module $PSScriptRoot/WebApp.psm1
Import-Module Az
}
Describe "Confirm-WebApp" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName WebApp Connect-Account{}
}
It "Calls Get-AzWebApp" {
Mock -ModuleName WebApp Get-AzWebApp{}
Confirm-WebApp -WebAppName "wan" -ResourceGroupName "rgn"
Should -Invoke -ModuleName WebApp -CommandName "Get-AzWebApp" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock -ModuleName WebApp Get-AzWebApp{ throw [Exception]::new("Exception") }
$Results = Confirm-WebApp -WebAppName "wan" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Authentication
Remove-Module WebApp
}

Просмотреть файл

@ -137,6 +137,20 @@ BenchPress code and documentation:
1. If necessary address any automated Pull Request checks by making fixes on the local feature branch and pushing the
fixes when completed. Repeat this process until all PR checks have been resolved.
## Requirements for submitting functions or classes
- It is required that there is one file per class/function.
- Functions will be written to `.ps1` files.
- Classes will be written to `.psm1` files.
- The filename of a function must match the function name (e.g., `Get-Something` function must be in a file named
`Get-Something.ps1`).
- Any function that is used internally and not desired to be exposed via `Export-ModuleMember` must reside in the
`Private` folder.
- Any statements at the beginning of a file that import data from another relative file (e.g., `using module`, or dot
sourcing another file), or that execute `Import-Module` must be at the top of the file, and must be preceded by a line
with the content `# INLINE_SKIP` and followed by a line with the content `# end INLINE_SKIP`. These denote to the build
script that content which will not be built into the final inline module script.
## Thank You
Thank you for your interest and contribution to the BenchPress open-source project.

Просмотреть файл

@ -2,50 +2,38 @@
# Generated by: CSEDevOps
# Generated on: 12/1/2022
@{
RootModule = "BenchPress.Azure.psm1"
ModuleVersion = "0.1"
GUID = "3db0c6b2-7453-4972-a9de-402be1277ac9"
Author = "CSEDevOps"
CompanyName = "Microsoft"
Copyright = "(c) Microsoft. All rights reserved."
Description = "Benchpress Test Framework for Azure Deployment Scenarios"
RequiredModules = @()
NestedModules = @(
"ActionGroup.psm1",
"AksCluster.psm1",
"AppServicePlan.psm1",
"Authentication.psm1",
"AzureCli.psm1",
"Bicep.psm1",
"Common.psm1",
"ContainerRegistry.psm1",
"KeyVault.psm1",
"ResourceGroup.psm1",
"SqlDatabase.psm1",
"SqlServer.psm1",
"VirtualMachine.psm1",
"WebApp.psm1"
RequiredModules = @(
"Az"
)
NestedModules = @()
FunctionsToExport = @(
"Invoke-AzCli",
"Confirm-BicepFile",
"Deploy-BicepFeature",
"Remove-BicepFeature",
"Confirm-ActionGroup",
"Confirm-AksCluster",
"Confirm-AppServicePlan",
"Confirm-BicepFile",
"Confirm-ContainerRegistry",
"Confirm-KeyVault",
"Confirm-KeyVaultSecret",
"Confirm-KeyVaultKey",
"Confirm-KeyVaultCertificate",
"Get-ResourceByType",
"Confirm-Resource"
"Get-Resource",
"Confirm-KeyVaultKey",
"Confirm-KeyVaultSecret",
"Confirm-Resource",
"Confirm-ResourceGroup",
"Confirm-SqlDatabase",
"Confirm-SqlServer",
"Confirm-VirtualMachine",
"Confirm-WebApp"
"Confirm-WebApp",
"Deploy-BicepFeature",
"Get-Resource",
"Get-ResourceByType",
"Invoke-AzCli",
"Remove-BicepFeature"
)
PrivateData = @{
PSData = @{

Просмотреть файл

@ -1,4 +1,6 @@
# INLINE_SKIP
using module ./AuthenticationData.psm1
# end INLINE_SKIP
class AuthenticationResult {
[boolean]$Success

Просмотреть файл

@ -1,4 +1,6 @@
using module ./AuthenticationData.psm1
# INLINE_SKIP
using module ./AuthenticationData.psm1
# end INLINE_SKIP
class ConfirmResult {
[boolean]$Success

Просмотреть файл

@ -0,0 +1,88 @@
# INLINE_SKIP
using module ./../Classes/AuthenticationResult.psm1
using module ./../Classes/AuthenticationData.psm1
Import-Module Az
. $PSScriptRoot/../Private/Get-RequiredEnvironmentVariable.ps1
# end INLINE_SKIP
function Connect-Account {
<#
.SYNOPSIS
Connect-Account uses environment variable values to log into an Azure context. This is an internal function and
should not be used outside of the BenchPress module.
.DESCRIPTION
Connect-Account is designed to login to an Azure context using environment variables to login as a
ServicePrincipal for the PowerShell session.
The expected environment variables are:
AZ_APPLICATION_ID - The Service Principal ID
AZ_ENCRYPTED_PASSWORD - The Service Principal account password properly encrypted using ConvertTo-SecureString
and saved as an environment variable using ConvertFrom-SecureString
AZ_TENANT_ID - The Tenant ID to login to
AZ_SUBSCRIPTION_ID - The Subscription ID to login to
If the current context that is logged in to matches the Service Principal, Tenant, and Subscription this function
is a no-op.
.EXAMPLE
There is only one way to call Connect-Account:
Connect-Account
.INPUTS
None
.OUTPUTS
AuthenticationResult
#>
[OutputType([AuthenticationResult])]
[CmdletBinding()]
param ( )
Begin { }
Process {
$ApplicationId = Get-RequiredEnvironmentVariable AZ_APPLICATION_ID
$TenantId = Get-RequiredEnvironmentVariable AZ_TENANT_ID
$SubscriptionId = Get-RequiredEnvironmentVariable AZ_SUBSCRIPTION_ID
$CurrentConnection = Get-AzContext
$Results = [AuthenticationResult]::new()
# If the current context matches the subscription, tenant, and service principal, then we're already properly
# logged in.
if ($null -ne $CurrentConnection `
-and ($CurrentConnection).Account.Type -eq 'ServicePrincipal' `
-and ($CurrentConnection).Account.Id -eq $ApplicationId `
-and ($CurrentConnection).Tenant.Id -eq $TenantId `
-and ($CurrentConnection).Subscription.Id -eq $SubscriptionId) {
$Results.Success = $true
$Results.AuthenticationData = [AuthenticationData]::new(($CurrentConnection).Subscription.Id)
} else {
# The current context is not correct, create the credentials and login to the correct account
$ClientSecret = Get-RequiredEnvironmentVariable AZ_ENCRYPTED_PASSWORD | ConvertTo-SecureString
$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $ApplicationId, $ClientSecret
try {
$ConnectionParams = @{
Credential = $Credential
TenantId = $TenantId
Subscription = $SubscriptionId
}
$Connection = Connect-AzAccount -ServicePrincipal @ConnectionParams
$Results.Success = $true
$Results.AuthenticationData = [AuthenticationData]::new()
$Results.AuthenticationData.SubscriptionId = $Connection.Context.Subscription.Id
} catch {
$Exception = $_
$Results.Error = $Exception
$Results.Success = $false
}
$Results
}
}
End { }
}

Просмотреть файл

@ -0,0 +1,57 @@
# INLINE_SKIP
Import-Module Az
# end INLINE_SKIP
function Disconnect-Account {
<#
.SYNOPSIS
Disconnect-Account uses environment variable values to disconnect from a specific Azure context. This is an
internal function and should not be used outside of the BenchPress module.
.DESCRIPTION
Disconnect-Account is designed to automatically log out of the specific Azure context using environment variables
to identify the context to disconnect.
The expected environment variables are:
AZ_APPLICATION_ID - The Service Principal ID
AZ_TENANT_ID - The Tenant ID to login to
AZ_SUBSCRIPTION_ID - The Subscription ID to login to
If the current context does not match the Service Principal, Tenant, or Subscription then this function is a
no-op
.EXAMPLE
There is only one way to call Disconnect-Account:
Disconnect-Account
.INPUTS
None
.OUTPUTS
None
#>
[OutputType([System.Void])]
[CmdletBinding()]
param ( )
Begin {
$ApplicationId = Get-RequiredEnvironmentVariable AZ_APPLICATION_ID
$TenantId = Get-RequiredEnvironmentVariable AZ_TENANT_ID
# If the current context doesn't match the target subscription, tentant, and client, then the testing account is
# not logged in. Do nothing.
$CurrentConnection = Get-AzContext
}
Process {
if ($null -eq $CurrentConnection `
-or ($CurrentConnection).Account.Type -ne "ServicePrincipal" `
-or ($CurrentConnection).Account.Id -ne $ApplicationId `
-or ($CurrentConnection).Tenant.Id -ne $TenantId) {
return
}
$CurrentConnection | Disconnect-AzAccount -Scope CurrentUser
}
End { }
}

Просмотреть файл

@ -0,0 +1,29 @@
function Format-ErrorRecord ([string] $Message, [string]$ErrorID) {
<#
.SYNOPSIS
Private function to help construct a ErrorRecord.
.DESCRIPTION
Format-ErrorRecord is a private helper function that can be used to construct an ErrorRecord.
.PARAMETER Message
Message for the ErrorRecord
.PARAMETER ErrorID
A string that can be used to uniquily identify the ErrorRecord.
.EXAMPLE
Format-ErrorRecord -Message $incorrectValueMessage -ErrorID "BenchPressValueFail"
.INPUTS
System.String
.OUTPUTS
System.Management.Automation.ErrorRecord
#>
$Exception = [Exception] $Message
$ErrorCategory = [System.Management.Automation.ErrorCategory]::InvalidResult
$TargetObject = @{ Message = $Message }
$ErrorRecord = New-Object System.Management.Automation.ErrorRecord $Exception, $ErrorID, $ErrorCategory, $TargetObject
return $ErrorRecord
}

Просмотреть файл

@ -0,0 +1,30 @@
function Format-IncorrectValueError([string]$ExpectedKey, [string]$ExpectedValue, [string]$ActualValue) {
<#
.SYNOPSIS
Private function to create a message and ErrorRecord for when a resource property is not set correctly.
.DESCRIPTION
Format-IncorrectValueError is a private helper function that can be used to construct a message and ErrorRecord
for when a resource property is not set to the expected value.
.PARAMETER ExpectedKey
The resource property name that is checked
.PARAMETER ExpectedValue
The expected value of the resource property
.PARAMETER ActualValue
The actual value of the resource property
.EXAMPLE
Format-IncorrectValueError -ExpectedKey "Location" -ExpectedValue "WestUS3" -ActualValue "EastUS"
.INPUTS
System.String
.OUTPUTS
System.Management.Automation.ErrorRecord
#>
$Message = "Expected $ExpectedKey to be $ExpectedValue, but got $ActualValue"
return Format-ErrorRecord -Message $Message -ErrorID "BenchPressValueFail"
}

Просмотреть файл

@ -0,0 +1,24 @@
function Format-NotExistError([string]$Expected) {
<#
.SYNOPSIS
Private function to create a message and ErrorRecord for when a resource does not exist.
.DESCRIPTION
Format-NotExistError is a private helper function that can be used to construct a message and ErrorRecord
for when a resource does not exist.
.PARAMETER Expected
The name of the resource that was expected to exist.
.EXAMPLE
Format-NotExistError -Expected "MyVM"
.INPUTS
System.String
.OUTPUTS
System.Management.Automation.ErrorRecord
#>
$Message = "Expected $Expected to exist, but it does not exist."
return Format-ErrorRecord -Message $Message -ErrorID "BenchPressExistFail"
}

Просмотреть файл

@ -0,0 +1,24 @@
function Format-PropertyDoesNotExistError([string]$PropertyKey) {
<#
.SYNOPSIS
Private function to create a message and ErrorRecord for when a resource property does not exist.
.DESCRIPTION
Format-PropertyDoesNotExistError is a private helper function that can be used to construct a message and
ErrorRecord for when a resource property does not exist.
.PARAMETER PropertyKey
The resource property name that is checked
.EXAMPLE
Format-PropertyDoesNotExistError -PropertyKey "Location"
.INPUTS
System.String
.OUTPUTS
System.Management.Automation.ErrorRecord
#>
$Message = "$PropertyKey is not a property on the resource"
return Format-ErrorRecord -Message $Message -ErrorID "BenchPressPropertyFail"
}

Просмотреть файл

@ -0,0 +1,50 @@
function Get-RequiredEnvironmentVariable {
<#
.SYNOPSIS
Get-RequiredEnvironmentVariable is a private helper method that retrieves environment variables with the
expectation that if they are not present that an error will be logged with an immedate exit.
.DESCRIPTION
Get-RequiredEnvironmentVariable retrieves the environment variable specified by the input parameter and checks to
be sure that a value is present for that environment variable. If the value is missing or whitespace a message
will be written to Write-Error with the name of the variable in the output and exit will be called.
.PARAMETER VariableName
This is the name of the environment variable to retrieve and validate that a value is present.
.EXAMPLE
Provide -VariableName Parameter
Get-RequiredEnvironmentVariable -VariableName AZ_APPLICATION_ID
.EXAMPLE
Provide variable name without -VariableName Parameter
Get-RequiredEnvironmentVariable AZ_APPLICATION_ID
.INPUTS
System.String
.OUTPUTS
System.String
#>
[OutputType([System.String])]
param (
[Parameter(Mandatory=$true, Position=0)]
[string]$VariableName
)
Begin {
$Value = [string]$null
}
Process {
$Value = [System.Environment]::GetEnvironmentVariable($VariableName)
if ([string]::IsNullOrWhiteSpace($Value)) {
Write-Error("Missing Required Environment Variable $VariableName")
exit 1
}
}
End {
return $Value
}
}

Просмотреть файл

@ -1,30 +1,32 @@
using module ./public/classes/ConfirmResult.psm1
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
Import-Module $PSScriptRoot/Authentication.psm1
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
<#
.SYNOPSIS
Confirms that an Action Group exists.
.DESCRIPTION
The Confirm-AzBPActionGroup cmdlet gets an action group using the specified Action Group and Resource Group name.
.PARAMETER ActionGroupName
The name of the Azure Action Group
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPActionGroup -ActionGroupName "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
function Confirm-ActionGroup {
<#
.SYNOPSIS
Confirms that an Action Group exists.
.DESCRIPTION
The Confirm-AzBPActionGroup cmdlet gets an action group using the specified Action Group and Resource Group name.
.PARAMETER ActionGroupName
The name of the Azure Action Group
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPActionGroup -ActionGroupName "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
@ -53,5 +55,3 @@ function Confirm-ActionGroup {
}
End { }
}
Export-ModuleMember -Function Confirm-ActionGroup

Просмотреть файл

@ -1,30 +1,32 @@
using module ./public/classes/ConfirmResult.psm1
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
Import-Module $PSScriptRoot/Authentication.psm1
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
<#
.SYNOPSIS
Confirms that an AKS Cluster exists.
.DESCRIPTION
The Confirm-AzBPAksCluster cmdlet gets an AKS cluster using the specified AKS Cluster and Resource Group name.
.PARAMETER AKSName
The name of the AKS Cluster
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPAksCluster -AKSName "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
function Confirm-AksCluster {
<#
.SYNOPSIS
Confirms that an AKS Cluster exists.
.DESCRIPTION
The Confirm-AzBPAksCluster cmdlet gets an AKS cluster using the specified AKS Cluster and Resource Group name.
.PARAMETER AKSName
The name of the AKS Cluster
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPAksCluster -AKSName "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
@ -53,5 +55,3 @@ function Confirm-AksCluster {
}
End { }
}
Export-ModuleMember -Function Confirm-AksCluster

Просмотреть файл

@ -1,31 +1,33 @@
using module ./public/classes/ConfirmResult.psm1
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
Import-Module $PSScriptRoot/Authentication.psm1
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
<#
.SYNOPSIS
Confirms that an App Service Plan exists.
.DESCRIPTION
The Confirm-AzBPAppServicePlan cmdlet gets an App Service Plan using the specified App Service Plan and
Resource Group name.
.PARAMETER AppServicePlanName
The name of the App Service Plan
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPAppServicePlan -AppServicePlanName "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
function Confirm-AppServicePlan {
<#
.SYNOPSIS
Confirms that an App Service Plan exists.
.DESCRIPTION
The Confirm-AzBPAppServicePlan cmdlet gets an App Service Plan using the specified App Service Plan and
Resource Group name.
.PARAMETER AppServicePlanName
The name of the App Service Plan
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPAppServicePlan -AppServicePlanName "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
@ -54,5 +56,3 @@ function Confirm-AppServicePlan {
}
End { }
}
Export-ModuleMember -Function Confirm-AppServicePlan

Просмотреть файл

@ -0,0 +1,123 @@
# INLINE_SKIP
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
function Confirm-BicepFile {
<#
.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
ofthis 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[]
#>
[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
}
}

Просмотреть файл

@ -1,31 +1,33 @@
using module ./public/classes/ConfirmResult.psm1
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
Import-Module $PSScriptRoot/Authentication.psm1
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
<#
.SYNOPSIS
Confirms that a Container Registry exists.
.DESCRIPTION
The Confirm-AzBPContainerRegistry cmdlet gets a Container Registry using the specified Container Registry and
Resource Group name.
.PARAMETER Name
The name of the Container Registry
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPContainerRegistry -Name "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
function Confirm-ContainerRegistry {
<#
.SYNOPSIS
Confirms that a Container Registry exists.
.DESCRIPTION
The Confirm-AzBPContainerRegistry cmdlet gets a Container Registry using the specified Container Registry and
Resource Group name.
.PARAMETER Name
The name of the Container Registry
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPContainerRegistry -Name "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
@ -54,5 +56,3 @@ function Confirm-ContainerRegistry {
}
End { }
}
Export-ModuleMember -Function Confirm-ContainerRegistry

Просмотреть файл

@ -0,0 +1,58 @@
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
function Confirm-KeyVault {
<#
.SYNOPSIS
Confirms that a Key Vault exists.
.DESCRIPTION
The Confirm-AzBPKeyVault cmdlet gets a Key Vault using the specified Key Vault and
Resource Group name.
.PARAMETER Name
The name of the Key Vault
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPKeyVault -Name "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
[Parameter(Mandatory = $true)]
[string]$Name,
[Parameter(Mandatory = $true)]
[string]$ResourceGroupName
)
Begin {
$ConnectResults = Connect-Account
}
Process {
[ConfirmResult]$Results = $null
try {
$Resource = Get-AzKeyVault -ResourceGroupName $ResourceGroupName -VaultName $Name
$Results = [ConfirmResult]::new($Resource, $ConnectResults.AuthenticationData)
} catch {
$ErrorRecord = $_
$Results = [ConfirmResult]::new($ErrorRecord, $ConnectResults.AuthenticationData)
}
$Results
}
End { }
}

Просмотреть файл

@ -0,0 +1,58 @@
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
function Confirm-KeyVaultCertificate {
<#
.SYNOPSIS
Confirms that a Key Vault Certificate exists.
.DESCRIPTION
The Confirm-AzBPKeyVaultCertificate cmdlet gets a Key Vault Certificate using the specified Key Vault and
Certificate name.
.PARAMETER Name
The name of the Certificate
.PARAMETER KeyVaultName
The name of the Key Vault
.EXAMPLE
Confirm-AzBPKeyVaultCertificate -Name "benchpresstest" -KeyVaultName "kvbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
[Parameter(Mandatory = $true)]
[string]$Name,
[Parameter(Mandatory = $true)]
[string]$KeyVaultName
)
Begin {
$ConnectResults = Connect-Account
}
Process {
[ConfirmResult]$Results = $null
try {
$Resource = Get-AzKeyVaultCertificate -Name $Name -VaultName $KeyVaultName
$Results = [ConfirmResult]::new($Resource, $ConnectResults.AuthenticationData)
} catch {
$ErrorRecord = $_
$Results = [ConfirmResult]::new($ErrorRecord, $ConnectResults.AuthenticationData)
}
$Results
}
End { }
}

Просмотреть файл

@ -0,0 +1,58 @@
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
function Confirm-KeyVaultKey {
<#
.SYNOPSIS
Confirms that a Key Vault Key exist.
.DESCRIPTION
The Confirm-AzBPKeyVaultKey cmdlet gets a Key Vault Key using the specified Key Vault and
Key name.
.PARAMETER Name
The name of the Key
.PARAMETER KeyVaultName
The name of the Key Vault
.EXAMPLE
Confirm-AzBPKeyVaultKey -Name "benchpresstest" -KeyVaultName "kvbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
[Parameter(Mandatory = $true)]
[string]$Name,
[Parameter(Mandatory = $true)]
[string]$KeyVaultName
)
Begin {
$ConnectResults = Connect-Account
}
Process {
[ConfirmResult]$Results = $null
try {
$Resource = Get-AzKeyVaultKey -Name $Name -VaultName $KeyVaultName
$Results = [ConfirmResult]::new($Resource, $ConnectResults.AuthenticationData)
} catch {
$ErrorRecord = $_
$Results = [ConfirmResult]::new($ErrorRecord, $ConnectResults.AuthenticationData)
}
$Results
}
End { }
}

Просмотреть файл

@ -0,0 +1,58 @@
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
function Confirm-KeyVaultSecret {
<#
.SYNOPSIS
Confirms that a Key Vault Secret exists.
.DESCRIPTION
The Confirm-AzBPKeyVaultSecret cmdlet gets a Key Vault Secret using the specified Key Vault and
Secret name.
.PARAMETER Name
The name of the Secret
.PARAMETER KeyVaultName
The name of the Key Vault
.EXAMPLE
Confirm-AzBPKeyVaultSecret -Name "benchpresstest" -KeyVaultName "kvbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
[Parameter(Mandatory = $true)]
[string]$Name,
[Parameter(Mandatory = $true)]
[string]$KeyVaultName
)
Begin {
$ConnectResults = Connect-Account
}
Process {
[ConfirmResult]$Results = $null
try {
$Resource = Get-AzKeyVaultSecret -Name $Name -VaultName $KeyVaultName
$Results = [ConfirmResult]::new($Resource, $ConnectResults.AuthenticationData)
} catch {
$ErrorRecord = $_
$Results = [ConfirmResult]::new($ErrorRecord, $ConnectResults.AuthenticationData)
}
$Results
}
End { }
}

Просмотреть файл

@ -0,0 +1,155 @@
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
. $PSScriptRoot/Get-ResourceByType.ps1
. $PSScriptRoot/../Private/Format-ErrorRecord.ps1
. $PSScriptRoot/../Private/Format-IncorrectValueError.ps1
. $PSScriptRoot/../Private/Format-PropertyDoesNotExistError.ps1
# end INLINE_SKIP
function Confirm-Resource {
<#
.SYNOPSIS
Confirms whether a resource exists or properties on a resource are configured correctly.
.DESCRIPTION
The Confirm-AzBPResource cmdlet confirms whether an Azure resource exists and/or confirms whether properties
on a resource exist and are configured to the correct value. The cmdlet will return a ConfirmResult object
which contains the following properties:
- Success: True if the resource exists and/or the property is set to the expected value. Otherwise, false.
- Error: System.Management.Automation.ErrorRecord containing an ErrorRecord with a message explaining
that a resource did not exist or property was not set to the expected value.
- ResourceDetails: System.Object that contains the details of the Azure Resource that is being confirmed.
.PARAMETER ResourceName
The name of the Resource
.PARAMETER ResourceGroupName
The name of the Resource Group
.PARAMETER ResourceType
The type of the Resource (currently supports the following:
ActionGroup
AksCluster
AppServicePlan
ContainerRegistry
KeyVault
ResourceGroup
SqlDatabase
SqlServer
VirtualMachine
WebApp)
.PARAMETER ServerName
If testing an Azure SQL Database resource, the name of the server to which the database is assigned.
.PARAMETER PropertyKey
The name of the property to check on the resource
.PARAMETER PropertyValue
The expected value of the property to check
.EXAMPLE
Checking whether a resource exists (i.e. Resource Group)
Confirm-AzBPResource -ResourceType $resourceType -ResourceName $resourceGroupName
.EXAMPLE
Confirm whether a resource has a property configured correctly (i.e. Resource Group located in West US 3)
Confirm-AzBPResource -ResourceType $resourceType -ResourceName $resourceGroupName -PropertyKey "Location" `
-PropertyValue "WestUS3"
.EXAMPLE
Checking whether a nested property on a resource is configured correctly (i.e. OS of VM is Linux)
$params = @{
ResourceGroupName = "testrg";
ResourceType = "VirtualMachine";
ResourceName = "testvm";
PropertyKey = "StorageProfile.OsDisk.OsType";
PropertyValue = "Linux"
}
$result = Confirm-AzBPResource @params
.INPUTS
ResourceType
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[ValidateSet("ActionGroup", "AksCluster", "AppServicePlan", "ContainerRegistry", "KeyVault", "ResourceGroup",
"SqlDatabase", "SqlServer", "VirtualMachine", "WebApp")]
[string]$ResourceType,
[Parameter(Mandatory = $true)]
[string]$ResourceName,
[Parameter(Mandatory = $false)]
[string]$ResourceGroupName,
[Parameter(Mandatory = $false)]
[string]$ServerName,
[Parameter(Mandatory = $false)]
[string]$PropertyKey,
[Parameter(Mandatory = $false)]
[string]$PropertyValue
)
$ResourceParams = @{
ResourceGroupName = $ResourceGroupName
ResourceName = $ResourceName
ResourceType = $ResourceType
ServerName = $ServerName
}
$ConfirmResult = Get-ResourceByType @ResourceParams
if ($null -eq $ConfirmResult) {
$ErrorRecord = Format-ErrorRecord -Message "ResourceType is invalid" -ErrorID "InvalidResourceType"
$ConfirmResult = [ConfirmResult]::new($ErrorRecord, $null)
}
elseif ($ConfirmResult.Success) {
if ($PropertyKey) {
$ActualValue = $ConfirmResult.ResourceDetails
# Split property path on open and close square brackets and periods. Remove empty items from array.
$Keys = ($PropertyKey -split '[\[\]\.]').Where({ $_ -ne "" })
foreach ($Key in $Keys) {
# If key is a numerical value, index into array
if ($Key -match "^\d+$") {
try {
$ActualValue = $ActualValue[$Key]
}
catch {
$ErrorRecord = $_
$ConfirmResult = [ConfirmResult]::new($ErrorRecord, $null)
break
}
}
else {
$ActualValue = $ActualValue.$Key
}
}
if ($ActualValue -ne $PropertyValue -and $ConfirmResult.Success -ne $false) {
if ($ActualValue) {
$ErrorRecord = `
Format-IncorrectValueError -ExpectedKey $PropertyKey `
-ExpectedValue $PropertyValue `
-ActualValue $ActualValue
$ConfirmResult = [ConfirmResult]::new($ErrorRecord, $null)
}
else {
$ErrorRecord = Format-PropertyDoesNotExistError -PropertyKey $PropertyKey
$ConfirmResult = [ConfirmResult]::new($ErrorRecord, $null)
}
}
}
}
$ConfirmResult
}

Просмотреть файл

@ -1,28 +1,30 @@
using module ./public/classes/ConfirmResult.psm1
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
Import-Module $PSScriptRoot/Authentication.psm1
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
<#
.SYNOPSIS
Confirms that a Resource Group exists.
.DESCRIPTION
The Confirm-AzBPResourceGroup cmdlet gets a Resource Group using the specified Resource Group and
Resource Group name.
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPResourceGroup -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
function Confirm-ResourceGroup {
<#
.SYNOPSIS
Confirms that a Resource Group exists.
.DESCRIPTION
The Confirm-AzBPResourceGroup cmdlet gets a Resource Group using the specified Resource Group and
Resource Group name.
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPResourceGroup -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
@ -48,5 +50,3 @@ function Confirm-ResourceGroup {
}
End { }
}
Export-ModuleMember -Function Confirm-ResourceGroup

Просмотреть файл

@ -1,37 +1,39 @@
using module ./public/classes/ConfirmResult.psm1
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
Import-Module $PSScriptRoot/Authentication.psm1
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
<#
.SYNOPSIS
Confirms that one or more SQL Databases exist.
.DESCRIPTION
The Confirm-AzBPSqlDatabase cmdlet gets one or more SQL Databases using the specified SQL Database, SQL Server and
Resource Group name.
.PARAMETER DatabaseName
The name of the SQL Database
.PARAMETER DatabaseServer
The name of the SQL Server
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPSqlDatabase -ServerName "testserver" -ResourceGroupName "rgbenchpresstest"
.EXAMPLE
Confirm-AzBPSqlDatabase -DatabaseName "testdb" -ServerName "testserver" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
function Confirm-SqlDatabase {
<#
.SYNOPSIS
Confirms that one or more SQL Databases exist.
.DESCRIPTION
The Confirm-AzBPSqlDatabase cmdlet gets one or more SQL Databases using the specified SQL Database, SQL Server
and Resource Group name.
.PARAMETER DatabaseName
The name of the SQL Database
.PARAMETER DatabaseServer
The name of the SQL Server
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPSqlDatabase -ServerName "testserver" -ResourceGroupName "rgbenchpresstest"
.EXAMPLE
Confirm-AzBPSqlDatabase -DatabaseName "testdb" -ServerName "testserver" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
@ -65,5 +67,3 @@ function Confirm-SqlDatabase {
}
End { }
}
Export-ModuleMember -Function Confirm-SqlDatabase

Просмотреть файл

@ -1,30 +1,33 @@
using module ./public/classes/ConfirmResult.psm1
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
Import-Module $PSScriptRoot/Authentication.psm1
<#
.SYNOPSIS
Confirms that a SQL Server exists.
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
.DESCRIPTION
The Confirm-AzBPSqlServer cmdlet gets a SQL Server using the specified SQL Server and
Resource Group name.
.PARAMETER ServerName
The name of the SQL Server
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPSqlServer -ServerName "testserver" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
function Confirm-SqlServer {
<#
.SYNOPSIS
Confirms that a SQL Server exists.
.DESCRIPTION
The Confirm-AzBPSqlServer cmdlet gets a SQL Server using the specified SQL Server and
Resource Group name.
.PARAMETER ServerName
The name of the SQL Server
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPSqlServer -ServerName "testserver" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
@ -52,5 +55,3 @@ function Confirm-SqlServer {
$Results
}
}
Export-ModuleMember -Function Confirm-SqlServer

Просмотреть файл

@ -1,31 +1,33 @@
using module ./public/classes/ConfirmResult.psm1
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
Import-Module $PSScriptRoot/Authentication.psm1
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
<#
.SYNOPSIS
Confirms that a Virtual Machine exists.
.DESCRIPTION
The Confirm-AzBPVirtualMachine cmdlet gets a Virtual Machine using the specified Virtual Machine and
Resource Group name.
.PARAMETER VirtualMachineName
The name of the Virtual Machine
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPVirtualMachine -VirtualMachineName "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
function Confirm-VirtualMachine {
<#
.SYNOPSIS
Confirms that a Virtual Machine exists.
.DESCRIPTION
The Confirm-AzBPVirtualMachine cmdlet gets a Virtual Machine using the specified Virtual Machine and
Resource Group name.
.PARAMETER VirtualMachineName
The name of the Virtual Machine
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPVirtualMachine -VirtualMachineName "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
@ -53,5 +55,3 @@ function Confirm-VirtualMachine {
$Results
}
}
Export-ModuleMember -Function Confirm-VirtualMachine

Просмотреть файл

@ -1,31 +1,33 @@
using module ./public/classes/ConfirmResult.psm1
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
Import-Module $PSScriptRoot/Authentication.psm1
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
<#
.SYNOPSIS
Confirms that a Web App exists.
.DESCRIPTION
The Confirm-AzBPWebApp cmdlet gets a Web App using the specified Web App and
Resource Group name.
.PARAMETER WebAppName
The name of the Web App
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPWebApp -WebAppName "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
function Confirm-WebApp {
<#
.SYNOPSIS
Confirms that a Web App exists.
.DESCRIPTION
The Confirm-AzBPWebApp cmdlet gets a Web App using the specified Web App and
Resource Group name.
.PARAMETER WebAppName
The name of the Web App
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Confirm-AzBPWebApp -WebAppName "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
@ -53,5 +55,3 @@ function Confirm-WebApp {
$Results
}
}
Export-ModuleMember -Function Confirm-WebApp

Просмотреть файл

@ -0,0 +1,77 @@
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
# end INLINE_SKIP
function Deploy-BicepFeature(){
<#
.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
#>
[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"
}

Просмотреть файл

@ -0,0 +1,50 @@
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
function Get-Resource {
<#
.SYNOPSIS
Gets one or more resources of a given name.
.DESCRIPTION
The Get-AzBPResource cmdlet gets Azure resources of a given name.
.PARAMETER ResourceName
The name of the Resources
.PARAMETER ResourceGroupName
The name of the Resource Group
.EXAMPLE
Get-AzBPResource -ResourceName "benchpresstest"
.EXAMPLE
Get-AzBPResource -ResourceName "benchpresstest" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.PSResource
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]$ResourceName,
[Parameter(Mandatory = $false)]
[string]$ResourceGroupName
)
Connect-Account
if ([string]::IsNullOrEmpty($ResourceGroupName)) {
return Get-AzResource -Name "${ResourceName}"
}
else {
return Get-AzResource -Name "${ResourceName}" -ResourceGroupName "${ResourceGroupName}"
}
}

Просмотреть файл

@ -0,0 +1,93 @@
# INLINE_SKIP
using module ./../Classes/ConfirmResult.psm1
. $PSScriptRoot/Confirm-ActionGroup.ps1
. $PSScriptRoot/Confirm-AksCluster.ps1
. $PSScriptRoot/Confirm-AppServicePlan.ps1
. $PSScriptRoot/Confirm-ContainerRegistry.ps1
. $PSScriptRoot/Confirm-KeyVault.ps1
. $PSScriptRoot/Confirm-ResourceGroup.ps1
. $PSScriptRoot/Confirm-SqlDatabase.ps1
. $PSScriptRoot/Confirm-SqlServer.ps1
. $PSScriptRoot/Confirm-VirtualMachine.ps1
. $PSScriptRoot/Confirm-WebApp.ps1
# end INLINE_SKIP
function Get-ResourceByType {
<#
.SYNOPSIS
Gets an Azure Resource.
.DESCRIPTION
The Get-AzBPResourceByType cmdlet gets an Azure resource depending on the resource type (i.e. Action Group, Key Vault,
Container Registry, etc.).
.PARAMETER ResourceName
The name of the Resource
.PARAMETER ResourceGroupName
The name of the Resource Group
.PARAMETER ResourceType
The type of the Resource (currently support the following:
ActionGroup
AksCluster
AppServicePlan
ContainerRegistry
KeyVault
ResourceGroup
SqlDatabase
SqlServer
VirtualMachine
WebApp)
.PARAMETER ServerName
If testing an Azure SQL Database resource, the name of the server to which the database is assigned.
.EXAMPLE
Get-AzBPResourceByType -ResourceType ActionGroup -ResourceName "bpactiongroup" -ResourceGroupName "rgbenchpresstest"
.EXAMPLE
Get-AzBPResourceByType -ResourceType VirtualMachine -ResourceName "testvm" -ResourceGroupName "rgbenchpresstest"
.INPUTS
System.String
.OUTPUTS
ConfirmResult
#>
[CmdletBinding()]
[OutputType([ConfirmResult])]
param (
[Parameter(Mandatory = $true)]
[string]$ResourceName,
[Parameter(Mandatory = $false)]
[string]$ResourceGroupName,
[Parameter(Mandatory = $true)]
[ValidateSet("ActionGroup", "AksCluster", "AppServicePlan", "ContainerRegistry", "KeyVault", "ResourceGroup",
"SqlDatabase", "SqlServer", "VirtualMachine", "WebApp")]
[string]$ResourceType,
[Parameter(Mandatory = $false)]
[string]$ServerName
)
switch ($ResourceType) {
ActionGroup { return Confirm-ActionGroup -ActionGroupName $ResourceName -ResourceGroupName $ResourceGroupName }
AksCluster { return Confirm-AksCluster -AKSName $ResourceName -ResourceGroupName $ResourceGroupName }
AppServicePlan { return Confirm-AppServicePlan -AppServicePlanName $ResourceName -ResourceGroupName $ResourceGroupName }
ContainerRegistry { return Confirm-ContainerRegistry -Name $ResourceName -ResourceGroupName $ResourceGroupName }
KeyVault { return Confirm-KeyVault -Name $ResourceName -ResourceGroupName $ResourceGroupName }
ResourceGroup { return Confirm-ResourceGroup -ResourceGroupName $ResourceName }
SqlDatabase { return Confirm-SqlDatabase -ServerName $ServerName -DatabaseName $ResourceName -ResourceGroupName $ResourceGroupName }
SqlServer { return Confirm-SqlServer -ServerName $ResourceName -ResourceGroupName $ResourceGroupName }
VirtualMachine { return Confirm-VirtualMachine -VirtualMachineName $ResourceName -ResourceGroupName $ResourceGroupName }
WebApp { return Confirm-WebApp -WebAppName $ResourceName -ResourceGroupName $ResourceGroupName }
default {
Write-Information "Not implemented yet"
return $null
}
}
}

Просмотреть файл

@ -0,0 +1,55 @@
function Invoke-AzCli {
<#
.DESCRIPTION
Invoke an Azure CLI command.
.SYNOPSIS
Invoke-AzBPAzCli cmdlet invokes an Azure CLI command and returns the result as an object.
.EXAMPLE
PS C:\> Invoke-AzBPAzCli "account list"
.EXAMPLE
PS C:\> Invoke-AzBPAzCli "account list --query [].name"
.EXAMPLE
PS C:\> Invoke-AzBPAzCli "webapp create --name ${WEBAPP_NAME} --resource-group ${RESOURCE_GROUP_NAME} --plan ${APP_SERVICE_PLAN_NAME}"
.PARAMETER Command
The command to execute.
.NOTES
Invoke-AzBPAzCli adds the az prefix to the command.
.LINK
https://learn.microsoft.com/en-us/cli/azure/
.LINK
https://learn.microsoft.com/en-us/cli/azure/get-started-with-azure-cli
.LINK
https://learn.microsoft.com/en-us/cli/azure/reference-index?view=azure-cli-latest
.INPUTS
System.String
.OUTPUTS
System.Object
#>
[CmdletBinding()]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingInvokeExpression", "")]
param (
[Parameter(Mandatory=$true)]
[string]$Command
)
$toExecute = "az $Command"
$result = Invoke-Expression "$toExecute"
if ($LastExitCode -gt 0) {
Write-Error "$result"
} else {
$result | ConvertFrom-Json
}
}

Просмотреть файл

@ -0,0 +1,37 @@
# INLINE_SKIP
. $PSScriptRoot/../Private/Connect-Account.ps1
# end INLINE_SKIP
function Remove-BicepFeature(){
<#
.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
#>
[CmdletBinding()]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
param (
[Parameter(Mandatory=$true)]
[string]$ResourceGroupName
)
Connect-Account
$resourceGroup = Get-AzResourceGroup -Name $ResourceGroupName
Remove-AzResourceGroup -Name $resourceGroup -Force
}

Просмотреть файл

@ -1,8 +1,8 @@
using module ./public/classes/AuthenticationResult.psm1
using module ./public/classes/AuthenticationData.psm1
using module ./../../Classes/AuthenticationResult.psm1
using module ./../../Classes/AuthenticationData.psm1
BeforeAll {
Import-Module $PSScriptRoot/Authentication.psm1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
@ -15,40 +15,32 @@ Describe "Connect-Account" {
$EncryptedPassword = "EncryptedPassword"
Mock Get-RequiredEnvironmentVariable{ return $ApplicationId } `
-ParameterFilter { $VariableName -eq "AZ_APPLICATION_ID" } `
-ModuleName Authentication
Mock Get-RequiredEnvironmentVariable{ return $TenantId } `
-ParameterFilter { $VariableName -eq "AZ_TENANT_ID" } `
-ModuleName Authentication
-ParameterFilter { $VariableName -eq "AZ_APPLICATION_ID" }
Mock Get-RequiredEnvironmentVariable{ return $TenantId } -ParameterFilter { $VariableName -eq "AZ_TENANT_ID" }
Mock Get-RequiredEnvironmentVariable{ return $SubscriptionId } `
-ParameterFilter { $VariableName -eq "AZ_SUBSCRIPTION_ID" } `
-ModuleName Authentication
-ParameterFilter { $VariableName -eq "AZ_SUBSCRIPTION_ID" }
Mock Get-RequiredEnvironmentVariable{ return $EncryptedPassword } `
-ParameterFilter { $VariableName -eq "AZ_ENCRYPTED_PASSWORD" } `
-ModuleName Authentication
-ParameterFilter { $VariableName -eq "AZ_ENCRYPTED_PASSWORD" }
Mock New-Object{ New-MockObject -Type "System.Management.Automation.PSCredential" } `
-ModuleName Authentication `
-ParameterFilter { $TypeName -eq "System.Management.Automation.PSCredential" }
Mock ConvertTo-SecureString{} -ModuleName Authentication
Mock Connect-AzAccount{} -ModuleName Authentication
Mock ConvertTo-SecureString{}
Mock Connect-AzAccount{}
}
It "Does not invoke Connect-AzAccount when the account matches environment variables." {
Mock Get-AzContext { @{Account = @{Type = "ServicePrincipal"; Id = $ApplicationId};
Tenant = @{Id = $TenantId};
Subscription = @{Id = $SubscriptionId}}} `
-ModuleName Authentication
Subscription = @{Id = $SubscriptionId}}}
Connect-Account
Should -Invoke -ModuleName Authentication -CommandName "Connect-AzAccount" -Times 0
Should -Invoke -CommandName "Connect-AzAccount" -Times 0
}
It "Invokes Connect-AzAccount when the account type is not ServicePrincipal." {
Mock Get-AzContext { @{Account = @{Type = "User"; Id = $ApplicationId};
Tenant = @{Id = $TenantId};
Subscription = @{Id = $SubscriptionId}}} `
-ModuleName Authentication `
-Verifiable
Connect-Account
@ -60,7 +52,6 @@ Describe "Connect-Account" {
Mock Get-AzContext { @{Account = @{Type = "ServicePrincipal"; Id = "not application ID"};
Tenant = @{Id = $TenantId};
Subscription = @{Id = $SubscriptionId}}} `
-ModuleName Authentication `
-Verifiable
Connect-Account
@ -72,7 +63,6 @@ Describe "Connect-Account" {
Mock Get-AzContext { @{Account = @{Type = "ServicePrincipal"; Id = $ApplicationId};
Tenant = @{Id = "not tenant id"};
Subscription = @{Id = $SubscriptionId}}} `
-ModuleName Authentication `
-Verifiable
Connect-Account
@ -84,18 +74,15 @@ Describe "Connect-Account" {
Mock Get-AzContext { @{Account = @{Type = "ServicePrincipal"; Id = $ApplicationId};
Tenant = @{Id = $TenantId};
Subscription = @{Id = "Not subscription id"}}} `
-ModuleName Authentication `
-Verifiable
Connect-Account
Should -InvokeVerifiable
}
}
}
AfterAll {
Remove-Module Authentication
Remove-Module Az
}

Просмотреть файл

@ -0,0 +1,16 @@
BeforeAll {
. $PSScriptRoot/../../Private/Format-ErrorRecord.ps1
}
Describe "Format-ErrorRecord" {
Context "unit tests" -Tag "Unit" {
It "Creates ErrorRecord with correct message and ID when Format-ErrorRecord is called" {
Mock New-Object{} -Verifiable
Format-ErrorRecord -Message "testMessage" -ErrorID "testErrorID"
Should -InvokeVerifiable
}
}
}
AfterAll {
}

Просмотреть файл

@ -0,0 +1,17 @@
BeforeAll {
. $PSScriptRoot/../../Private/Format-ErrorRecord.ps1
. $PSScriptRoot/../../Private/Format-IncorrectValueError.ps1
}
Describe "Format-IncorrectValueError" {
Context "unit tests" -Tag "Unit" {
It "Calls Format-ErrorRecord when Format-IncorrectValueError is called" {
Mock Format-ErrorRecord{} -Verifiable
Format-IncorrectValueError -Message "testMessage"
Should -InvokeVerifiable
}
}
}
AfterAll {
}

Просмотреть файл

@ -0,0 +1,17 @@
BeforeAll {
. $PSScriptRoot/../../Private/Format-ErrorRecord.ps1
. $PSScriptRoot/../../Private/Format-NotExistError.ps1
}
Describe "Format-NotExistError" {
Context "unit tests" -Tag "Unit" {
It "Calls Format-ErrorRecord when Format-NotExistError is called" {
Mock Format-ErrorRecord{} -Verifiable
Format-NotExistError -Message "testMessage"
Should -InvokeVerifiable
}
}
}
AfterAll {
}

Просмотреть файл

@ -0,0 +1,17 @@
BeforeAll {
. $PSScriptRoot/../../Private/Format-ErrorRecord.ps1
. $PSScriptRoot/../../Private/Format-PropertyDoesNotExistError.ps1
}
Describe "Format-PropertyDoesNotExistError" {
Context "unit tests" -Tag "Unit" {
It "Calls Format-ErrorRecord when Format-PropertyDoesNotExistError is called" {
Mock Format-ErrorRecord{} -Verifiable
Format-PropertyDoesNotExistError -PropertyKey "testKey"
Should -InvokeVerifiable
}
}
}
AfterAll {
}

Просмотреть файл

@ -0,0 +1,29 @@
BeforeAll {
. $PSScriptRoot/../../Public/Confirm-ActionGroup.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
Describe "Confirm-ActionGroup" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Connect-Account{}
}
It "Calls Get-AzActionGroup" {
Mock Get-AzActionGroup{}
Confirm-ActionGroup -ActionGroupName "agn" -ResourceGroupName "rgn"
Should -Invoke -CommandName "Get-AzActionGroup" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock Get-AzActionGroup{ throw [Exception]::new("Exception") }
$Results = Confirm-ActionGroup -ActionGroupName "agn" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Az
}

Просмотреть файл

@ -0,0 +1,29 @@
BeforeAll {
. $PSScriptRoot/../../Public/Confirm-AksCluster.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
Describe "Confirm-AksCluster" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Connect-Account{}
}
It "Calls Get-AzAksCluster" {
Mock Get-AzAksCluster{}
Confirm-AksCluster -AksName "acn" -ResourceGroupName "rgn"
Should -Invoke -CommandName "Get-AzAksCluster" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock Get-AzAksCluster{ throw [Exception]::new("Exception") }
$Results = Confirm-AksCluster -AksName "acn" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Az
}

Просмотреть файл

@ -0,0 +1,30 @@
BeforeAll {
. $PSScriptRoot/../../Public/Confirm-AppServicePlan.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
Describe "Confirm-AppServicePlan" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Connect-Account{}
Mock Get-AzAppServicePlan{}
}
It "Calls Get-AzAppServicePlan" {
Mock Get-AzAppServicePlan{}
Confirm-AppServicePlan -AppServicePlanName "aspn" -ResourceGroupName "rgn"
Should -Invoke -CommandName "Get-AzAppServicePlan" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock Get-AzAppServicePlan{ throw [Exception]::new("Exception") }
$Results = Confirm-AppServicePlan -AppServicePlanName "aspn" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Az
}

Просмотреть файл

@ -0,0 +1,55 @@
BeforeAll {
. $PSScriptRoot/../../Public/Confirm-BicepFile.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
}
Describe "Confirm-BicepFile" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Invoke-Command{}
Mock Write-Error{}
}
It "Calls Invoke-Command when path provided as first parameter without parameter name" {
Confirm-BicepFile "./nothing.bicep"
Should -Invoke -CommandName "Invoke-Command" -Times 1
}
It "Calls Invoke-Command with path provided as the -BicepFilePath" {
Confirm-BicepFile -BicepFilePath "./nothing.bicep"
Should -Invoke -CommandName "Invoke-Command" -Times 1
}
It "Calls Invoke-Command with path piped to cmdlet" {
"./nothing.bicep" | Confirm-BicepFile
Should -Invoke -CommandName "Invoke-Command" -Times 1
}
It "Calls Invoke-Command multiple times with an array of paths provided as first parameter without parameter name" {
Confirm-BicepFile "./nothing.bicep","./stillnothing.bicep"
Should -Invoke -CommandName "Invoke-Command" -Times 2
}
It "Calls Invoke-Command multiple times with an array of paths provided as -BicepFilePath" {
Confirm-BicepFile -BicepFilePath "./nothing.bicep","./stillnothing.bicep"
Should -Invoke -CommandName "Invoke-Command" -Times 2
}
It "Calls Invoke-Command multiple times with an array of paths piped to cmdlet" {
"./nothing.bicep","./stillnothing.bicep" | Confirm-BicepFile
Should -Invoke -CommandName "Invoke-Command" -Times 2
}
It "Calls Write-Error when the results have an error" {
$mockError = New-MockObject -Type 'System.Management.Automation.ErrorRecord'
Mock Invoke-Command{ $results = [System.Collections.ArrayList]::new()
$results.Add($mockError)
return $results }
Confirm-BicepFile "./nothing.bicep"
Should -Invoke -CommandName "Write-Error" -Times 2
}
}
}
AfterAll {
}

Просмотреть файл

@ -0,0 +1,29 @@
BeforeAll {
. $PSScriptRoot/../../Public/Confirm-ContainerRegistry.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
Describe "Confirm-ContainerRegistry" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Connect-Account{}
}
It "Calls Get-AzContainerRegistry" {
Mock Get-AzContainerRegistry{}
Confirm-ContainerRegistry -Name "cr" -ResourceGroupName "rgn"
Should -Invoke -CommandName "Get-AzContainerRegistry" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock Get-AzContainerRegistry{ throw [Exception]::new("Exception") }
$Results = Confirm-ContainerRegistry -Name "cr" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Az
}

Просмотреть файл

@ -0,0 +1,29 @@
BeforeAll {
. $PSScriptRoot/../../Public/Confirm-KeyVault.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
Describe "Confirm-KeyVault" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Connect-Account{}
}
It "Calls Get-AzKeyVault" {
Mock Get-AzKeyVault{}
Confirm-KeyVault -Name "vn" -ResourceGroupName "rgn"
Should -Invoke -CommandName "Get-AzKeyVault" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock Get-AzKeyVault{ throw [Exception]::new("Exception") }
$Results = Confirm-KeyVault -Name "vn" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Az
}

Просмотреть файл

@ -0,0 +1,29 @@
BeforeAll {
. $PSScriptRoot/../../Public/Confirm-KeyVaultCertificate.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
Describe "Confirm-KeyVaultCertificate" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Connect-Account{}
}
It "Calls Get-AzKeyVaultCertificate" {
Mock Get-AzKeyVaultCertificate{}
Confirm-KeyVaultCertificate -Name "n" -KeyVaultName "kvn"
Should -Invoke -CommandName "Get-AzKeyVaultCertificate" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock Get-AzKeyVaultCertificate{ throw [Exception]::new("Exception") }
$Results = Confirm-KeyVaultCertificate -Name "n" -KeyVaultName "kvn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Az
}

Просмотреть файл

@ -0,0 +1,29 @@
BeforeAll {
. $PSScriptRoot/../../Public/Confirm-KeyVaultKey.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
Describe "Confirm-KeyVaultKey" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Connect-Account{}
}
It "Calls Get-AzKeyVaultKey" {
Mock Get-AzKeyVaultKey{}
Confirm-KeyVaultKey -Name "n" -KeyVaultName "kvn"
Should -Invoke -CommandName "Get-AzKeyVaultKey" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock Get-AzKeyVaultKey{ throw [Exception]::new("Exception") }
$Results = Confirm-KeyVaultKey -Name "n" -KeyVaultName "kvn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Az
}

Просмотреть файл

@ -0,0 +1,29 @@
BeforeAll {
. $PSScriptRoot/../../Public/Confirm-KeyVaultSecret.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
Describe "Confirm-KeyVaultSecret" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Connect-Account{}
}
It "Calls Get-AzKeyVaultSecret" {
Mock Get-AzKeyVaultSecret{}
Confirm-KeyVaultSecret -Name "n" -KeyVaultName "kvn"
Should -Invoke -CommandName "Get-AzKeyVaultSecret" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock Get-AzKeyVaultSecret{ throw [Exception]::new("Exception") }
$Results = Confirm-KeyVaultSecret -Name "n" -KeyVaultName "kvn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Az
}

Просмотреть файл

@ -0,0 +1,116 @@
using module ./../../Classes/ConfirmResult.psm1
BeforeAll {
. $PSScriptRoot/../../Private/Format-ErrorRecord.ps1
. $PSScriptRoot/../../Private/Format-IncorrectValueError.ps1
. $PSScriptRoot/../../Private/Format-NotExistError.ps1
. $PSScriptRoot/../../Private/Format-PropertyDoesNotExistError.ps1
. $PSScriptRoot/../../Public/Confirm-Resource.ps1
. $PSScriptRoot/../../Public/Get-ResourceByType.ps1
}
Describe "Confirm-Resource" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Format-NotExistError{}
Mock Format-ErrorRecord{}
Mock Format-IncorrectValueError{}
Mock Format-PropertyDoesNotExistError{}
$script:ConfirmResult = [ConfirmResult]::new(
@{
TestKey = "TestValue"
TestArray = @(@{AnotherKey = "AnotherValue"})
}, $null)
}
It "Calls Get-ResourceByType; returns true when Get-ResourceByType returns a Success ConfirmResult." {
Mock Get-ResourceByType{ $ConfirmResult }
$result = Confirm-Resource -ResourceType "ResourceGroup" -ResourceName "mockResourceName"
Should -InvokeVerifiable
Should -Invoke -CommandName "Format-NotExistError" -Times 0
Should -Invoke -CommandName "Format-IncorrectValueError" -Times 0
$result.Success | Should -Be $true
}
It "Calls Get-ResourceByType; returns true when property matches value." {
Mock Get-ResourceByType{ $ConfirmResult } -Verifiable
$result = Confirm-Resource -ResourceType "ResourceGroup" -ResourceName "mockResourceName" `
-PropertyKey "TestKey" -PropertyValue "TestValue"
Should -InvokeVerifiable
Should -Invoke -CommandName "Format-NotExistError" -Times 0
Should -Invoke -CommandName "Format-IncorrectValueError" -Times 0
$result.Success | Should -Be $true
}
It "Calls Get-ResourceByType; returns true when accessing property in array and matches value." {
Mock Get-ResourceByType{ $ConfirmResult } -Verifiable
$result = Confirm-Resource -ResourceType "ResourceGroup" -ResourceName "mockResourceName" `
-PropertyKey "TestArray[0].AnotherKey" -PropertyValue "AnotherValue"
Should -InvokeVerifiable
Should -Invoke -CommandName "Format-NotExistError" -Times 0
Should -Invoke -CommandName "Format-IncorrectValueError" -Times 0
$result.Success | Should -Be $true
}
It "Calls Get-ResourceByType and Format-Error; returns false when Get-ResourceByType returns empty object." {
Mock Get-ResourceByType{ return $null } -Verifiable
$result = Confirm-Resource -ResourceType "ResourceGroup" -ResourceName "mockResourceName"
Should -InvokeVerifiable
Should -Invoke -CommandName "Format-ErrorRecord" -Times 1
Should -Invoke -CommandName "Format-IncorrectValueError" -Times 0
$result.Success | Should -Be $false
}
It "Calls Get-ResourceByType and Format-IncorrectValueError; returns false when property does not match value." {
Mock Get-ResourceByType{ $ConfirmResult } -Verifiable
$result = Confirm-Resource -ResourceType "ResourceGroup" -ResourceName "mockResourceName" `
-PropertyKey "TestKey" -PropertyValue "WrongValue"
Should -InvokeVerifiable
Should -Invoke -CommandName "Format-NotExistError" -Times 0
Should -Invoke -CommandName "Format-IncorrectValueError" -Times 1
$result.Success | Should -Be $false
}
It "Calls Get-ResourceByType; returns false when indexing incorrectly into property array" {
Mock Get-ResourceByType{ $ConfirmResult } -Verifiable
$result = Confirm-Resource -ResourceType "ResourceGroup" -ResourceName "mockResourceName" `
-PropertyKey "WrongArray[0].AnotherKey" -PropertyValue "AnotherValue"
Should -InvokeVerifiable
$result.Success | Should -Be $false
$result.ErrorRecord | Should -Not -Be $null
}
It "Calls Get-ResourceByType and Format-PropertyDoesNotExistError; returns false when property does not exist." {
Mock Get-ResourceByType{ $ConfirmResult } -Verifiable
$result = Confirm-Resource -ResourceType "ResourceGroup" -ResourceName "mockResourceName" `
-PropertyKey "WrongKey" -PropertyValue "TestValue"
Should -InvokeVerifiable
Should -Invoke -CommandName "Format-NotExistError" -Times 0
Should -Invoke -CommandName "Format-PropertyDoesNotExistError" -Times 1
$result.Success | Should -Be $false
}
}
}
AfterAll {
}

Просмотреть файл

@ -0,0 +1,29 @@
BeforeAll {
. $PSScriptRoot/../../Public/Confirm-ResourceGroup.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
Describe "Confirm-ResourceGroup" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Connect-Account{}
}
It "Calls Get-AzResourceGroup" {
Mock Get-AzResourceGroup{}
Confirm-ResourceGroup -ResourceGroupName "rgn"
Should -Invoke -CommandName "Get-AzResourceGroup" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock Get-AzResourceGroup{ throw [Exception]::new("Exception") }
$Results = Confirm-ResourceGroup -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Az
}

Просмотреть файл

@ -1,33 +1,31 @@
using module ./public/classes/ConfirmResult.psm1
BeforeAll {
Import-Module $PSScriptRoot/Authentication.psm1
Import-Module $PSScriptRoot/SqlDatabase.psm1
BeforeAll {
. $PSScriptRoot/../../Public/Confirm-SqlDatabase.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
Describe "Confirm-SqlDatabase" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock -ModuleName SqlDatabase Connect-Account{}
Mock Connect-Account{}
}
It "Calls Get-AzSqlDatabase without -DatbaseName when not provided" {
Mock -ModuleName SqlDatabase Get-AzSqlDatabase{}
Mock Get-AzSqlDatabase{}
Confirm-SqlDatabase -DatabaseName "dbn" -ServerName "sn" -ResourceGroupName "rgn"
Should -Invoke -ModuleName SqlDatabase -CommandName "Get-AzSqlDatabase" -Times 1 `
Should -Invoke -CommandName "Get-AzSqlDatabase" -Times 1 `
-ParameterFilter { $databaseName -eq $null; $serverName -eq "sn"; $resourceGroupName -eq "rgn" }
}
It "Calls Get-AzSqlDatabase with -DatbaseName when provided" {
Mock -ModuleName SqlDatabase Get-AzSqlDatabase{}
Mock Get-AzSqlDatabase{}
Confirm-SqlDatabase -DatabaseName "dbn" -ServerName "sn" -ResourceGroupName "rgn"
Should -Invoke -ModuleName SqlDatabase -CommandName "Get-AzSqlDatabase" -Times 1 `
Should -Invoke -CommandName "Get-AzSqlDatabase" -Times 1 `
-ParameterFilter { $databaseName -eq "dbn"; $serverName -eq "sn"; $resourceGroupName -eq "rgn" }
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock -ModuleName SqlDatabase Get-AzSqlDatabase{ throw [Exception]::new("Exception") }
Mock Get-AzSqlDatabase{ throw [Exception]::new("Exception") }
$Results = Confirm-SqlDatabase -DatabaseName "dbn" -ServerName "sn" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
@ -35,7 +33,5 @@ Describe "Confirm-SqlDatabase" {
}
AfterAll {
Remove-Module Authentication
Remove-Module SqlDatabase
Remove-Module Az
}

Просмотреть файл

@ -0,0 +1,29 @@
BeforeAll {
. $PSScriptRoot/../../Public/Confirm-SqlServer.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
Describe "Confirm-SqlServer" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Connect-Account{}
}
It "Calls Get-AzSqlServer" {
Mock Get-AzSqlServer{}
Confirm-SqlServer -ServerName "sn" -ResourceGroupName "rgn"
Should -Invoke -CommandName "Get-AzSqlServer" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock Get-AzSqlServer{ throw [Exception]::new("Exception") }
$Results = Confirm-SqlServer -ServerName "sn" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Az
}

Просмотреть файл

@ -0,0 +1,29 @@
BeforeAll {
. $PSScriptRoot/../../Public/Confirm-VirtualMachine.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
Describe "Confirm-VirtualMachine" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Connect-Account{}
}
It "Calls Get-AzVM" {
Mock Get-AzVM{}
Confirm-VirtualMachine -VirtualMachineName "vmn" -ResourceGroupName "rgn"
Should -Invoke -CommandName "Get-AzVM" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock Get-AzVM{ throw [Exception]::new("Exception") }
$Results = Confirm-VirtualMachine -VirtualMachineName "vmn" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Az
}

Просмотреть файл

@ -0,0 +1,29 @@
BeforeAll {
. $PSScriptRoot/../../Public/Confirm-WebApp.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
Describe "Confirm-WebApp" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Connect-Account{}
}
It "Calls Get-AzWebApp" {
Mock Get-AzWebApp{}
Confirm-WebApp -WebAppName "wan" -ResourceGroupName "rgn"
Should -Invoke -CommandName "Get-AzWebApp" -Times 1
}
It "Sets the ErrorRecord when an exception is thrown" {
Mock Get-AzWebApp{ throw [Exception]::new("Exception") }
$Results = Confirm-WebApp -WebAppName "wan" -ResourceGroupName "rgn"
$Results.ErrorRecord | Should -Not -Be $null
}
}
}
AfterAll {
Remove-Module Az
}

Просмотреть файл

@ -0,0 +1,32 @@
BeforeAll {
. $PSScriptRoot/../../Public/Deploy-BicepFeature.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
}
Describe "Deploy-BicepFeature" {
Context "unit-test" -Tag "Unit" {
BeforeEach {
Mock Connect-Account{}
Mock New-AzResourceGroupDeployment
Mock Remove-Item
}
It "Should call New-AzResourceGroupDeployment when there are no errors." {
Mock Invoke-Command{}
Deploy-BicepFeature -BicepPath "./path" -Params @{} -ResourceGroupName "rgn"
Should -Invoke -CommandName "New-AzResourceGroupDeployment" -Times 1
}
It "Should not call New-AzResourceGroupDeployment when there are errors." {
$mockError = New-MockObject -Type 'System.Management.Automation.ErrorRecord'
Mock Invoke-Command{ $results = [System.Collections.ArrayList]::new()
$results.Add($mockError)
return $results }
Deploy-BicepFeature -BicepPath "./path" -Params @{} -ResourceGroupName "rgn"
Should -Not -Invoke -CommandName "New-AzResourceGroupDeployment"
}
}
}
AfterAll {
}

Просмотреть файл

@ -0,0 +1,29 @@
BeforeAll {
. $PSScriptRoot/../../Public/Get-Resource.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
Describe "Get-Resource" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Connect-Account{}
Mock Get-AzResource{}
}
It "Calls Get-AzResource without -ResourceGroupName parameter when not provided." {
Get-Resource -ResourceName "rn"
Should -Invoke -CommandName Get-AzResource -ParameterFilter { $name -eq "rn"; $resourceGroupName -eq $null }
}
It "Calls Get-AzResource with -ResourceGroupName parameter when provided." {
Get-Resource -ResourceName "rn" -ResourceGroupName "rgn"
Should -Invoke -CommandName Get-AzResource -ParameterFilter { $name -eq "rn"; $resourceGroupName -eq "rgn" }
}
}
}
AfterAll {
Remove-Module Az
}

Просмотреть файл

@ -0,0 +1,37 @@
BeforeAll {
. $PSScriptRoot/../../Public/Confirm-AppServicePlan.ps1
. $PSScriptRoot/../../Public/Confirm-ResourceGroup.ps1
. $PSScriptRoot/../../Public/Confirm-SqlDatabase.ps1
. $PSScriptRoot/../../Public/Confirm-SqlServer.ps1
. $PSScriptRoot/../../Public/Confirm-VirtualMachine.ps1
. $PSScriptRoot/../../Public/Confirm-WebApp.ps1
. $PSScriptRoot/../../Public/Get-ResourceByType.ps1
}
Describe "Get-ResourceByType" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Confirm-ResourceGroup{}
Mock Confirm-AppServicePlan{}
Mock Confirm-SqlDatabase{}
Mock Confirm-SqlServer{}
Mock Confirm-VirtualMachine{}
Mock Confirm-WebApp{}
}
It "Calls <expected> when <resourceType> is used" -TestCases @(
@{ ResourceType = "ResourceGroup"; Expected = "Confirm-ResourceGroup"}
@{ ResourceType = "AppServicePlan"; Expected = "Confirm-AppServicePlan"}
@{ ResourceType = "SqlDatabase"; Expected = "Confirm-SqlDatabase"}
@{ ResourceType = "SqlServer"; Expected = "Confirm-SqlServer"}
@{ ResourceType = "VirtualMachine"; Expected = "Confirm-VirtualMachine"}
@{ ResourceType = "WebApp"; Expected = "Confirm-WebApp"}
) {
Get-ResourceByType -ResourceName resource -ResourceGroupName group -ResourceType $ResourceType -ServerName server
Should -Invoke -CommandName $Expected -Times 1
}
}
}
AfterAll {
}

Просмотреть файл

@ -0,0 +1,35 @@
BeforeAll {
. $PSScriptRoot/../../Public/Invoke-AzCli.ps1
}
Describe "Invoke-AzCli" {
Context "unit tests" -Tag "Unit" {
BeforeEach {
Mock Write-Error{}
$Global:LASTEXITCODE = 0
}
It "Calls Invoke-Expression" {
Mock Invoke-Expression{ }
Invoke-AzCli -Command "command"
Should -Invoke -CommandName "Invoke-Expression" -Times 1
Should -Not -Invoke -CommandName "Write-Error"
}
It "Calls Write-Error when the error code is greater than 0" {
Mock Invoke-Expression{ $Global:LASTEXITCODE = 1 }
Invoke-AzCli -Command "command"
Should -InvokeVerifiable
}
AfterEach {
# Reset the $LastExitCode
$Global:LASTEXITCODE = 0
}
}
}
AfterAll {
}

Просмотреть файл

@ -0,0 +1,34 @@
BeforeAll {
. $PSScriptRoot/../../Public/Remove-BicepFeature.ps1
. $PSScriptRoot/../../Private/Connect-Account.ps1
Import-Module Az
}
Describe "Remove-BicepFeature" {
Context "unit-test" -Tag "Unit" {
BeforeEach {
Mock Connect-Account{}
Mock Get-AzResourceGroup { "Resource" }
Mock Remove-AzResourceGroup {}
}
It "Calls Get-AzResourceGroup with the passed in ResourceGroupName" {
$resourceGroupName = "rgn"
Remove-BicepFeature -ResourceGroupName $resourceGroupName
Should -Invoke -CommandName "Get-AzResourceGroup" `
-ParameterFilter { $name -eq $resourceGroupName } -Times 1
}
It "Calls Remove-AzResourceGroup with the returned resource group name" {
$resourceGroupName = "rgn"
Remove-BicepFeature -ResourceGroupName $resourceGroupName
Should -Invoke -CommandName "Remove-AzResourceGroup" `
-ParameterFilter { $name -eq $resourceGroupName } -Times 1
}
}
}
AfterAll {
Remove-Module Az
}

111
build.ps1 Normal file
Просмотреть файл

@ -0,0 +1,111 @@
#! /usr/bin/pwsh
[CmdletBinding()]
param (
[switch] $Load,
[switch] $Clean,
[switch] $Inline,
[switch] $Import
)
function Copy-Content ($Content) {
foreach ($c in $content) {
$source, $destination = $c
$null = New-Item -Force $destination -ItemType Directory
Get-ChildItem $source -File | Copy-Item -Destination $destination
}
}
$ErrorActionPreference = 'Stop'
if (-not $PSBoundParameters.ContainsKey("Inline")) {
# Force inlining by env variable, build.ps1 is used in multiple places and passing the $inline everywhere is
# difficult.
# Only read this option here. Don't write it.
$Inline = $env:BENCPRESS_BUILD_INLINE -eq "1"
} else {
# We provided Inline explicitly, write the option. This assumes that you don't use -Inline:$false in any of the
# test scripts, otherwise the test script would reset the option incorrectly.
$env:BENCHPRESS_BUILD_INLINE = [string][int][bool] $Inline
}
Get-Module BenchPress | Remove-Module
if ($Clean -and (Test-Path "$PSScriptRoot/bin")) {
Remove-Item "$PSScriptRoot/bin" -Recurse -Force
}
$null = New-Item "$PSScriptRoot/bin" -ItemType Directory -Force
$content = @(
, ("$PSScriptRoot/Modules/BenchPress.Azure/BenchPress.Azure.psd1", "$PSScriptRoot/bin/")
)
Copy-Content -Content $content
$publicClasses = @(Get-ChildItem -Path $PSScriptRoot/Modules/BenchPress.Azure/Classes -Recurse -Filter "*.psm1")
$publicFunctions = @(Get-ChildItem -Path $PSScriptRoot/Modules/BenchPress.Azure/Public -Recurse -Filter "*.ps1")
$privateFunctions = @(Get-ChildItem -Path $PSScriptRoot/Modules/BenchPress.Azure/Private -Recurse -Filter "*.ps1")
$sb = [System.Text.StringBuilder]""
if ($Inline) {
$allFiles = $publicClasses + $publicFunctions + $privateFunctions
foreach ($file in $allFiles) {
$lines = Get-Content $file
$relativePath = ($file.FullName -replace ([regex]::Escape($PSScriptRoot))).TrimStart('\').TrimStart('/')
$null = $sb.AppendLine("# file $($relativePath)")
$skipLine = $false
foreach ($line in $lines) {
# when inlining the code skip everything wrapped in # INLINE_SKIP, # end INLINE_SKIP
if (-not $skipLine -and $line -match '^.*#\s*INLINE_SKIP') {
$skipLine = $true
}
if (-not $skipLine) {
$null = $sb.AppendLine($line)
}
if ($skipLine -and $line -match '^.*#\s*end\s*INLINE_SKIP') {
$skipLine = $false
}
}
}
} else {
# "using" for class files must be the first line in the module script
foreach ($class in $publicClasses) {
$null = $sb.AppendLine("using module $($class.FullName)")
}
# Define this at the top of the module, after the using statements, to skip the code that is wrapped in this if in
# different source files.
$null = $sb.AppendLine('$BENCHPRESS_BUILD=1')
$functionFiles = $publicFunctions + $privateFunctions
foreach ($file in $functionFiles) {
$null = $sb.AppendLine(". '$($file.FullName)'")
}
}
$null = $sb.AppendLine("Export-ModuleMember $($publicFunctions.BaseName -join ',')")
$sb.ToString() | Set-Content "$PSScriptRoot/bin/BenchPress.Azure.psm1" -Encoding UTF8
if ($Load) {
$powershell = Get-Process -Id $PID | Select-Object -ExpandProperty Path
& $powershell -c "'Load: ' + (Measure-Command { Import-Module '$PSScriptRoot/bin/BenchPress.Azure.psd1' -ErrorAction Stop}).TotalMilliseconds + 'ms'"
if (0 -ne $LASTEXITCODE) {
throw "load failed!"
}
}
if ($Import) {
Import-Module "$PSScriptRoot/bin/BenchPress.Azure.psd1" -Force
}

Просмотреть файл

@ -44,20 +44,18 @@ CI/CD process. This stage consists of the following steps:
for code styling and formatting.
- [`pr-dotnet.yml`](../.github/workflows/pr-dotnet.yml) and [`pr-powershell`](../.github/workflows/pr-powershell.yml) -
Unit tests (for .NET Solution and PowerShell code) for code quality and testing.
- [`pr-psgallery.yml`](../.github/workflows/pr-powershell.yml) - PowerShell module publishing to a local "PowerShell
Gallery"
- The local "PowerShell Gallery" uses the workflow runner's local filesystem to simulate PowerShell Gallery. We then
push and pull from this filesystem using the same PowerShell cmdlets that are used to interact with PowerShell
Gallery.
### Continuous Integration
After pull requests are merged to the `main` branch, they will automatically trigger the CI stage of the CI/CD process.
This stage consists of the following steps:
- [`ci.yml`](../.github/workflows/ci.yml) - building the .NET solution.
- [`ci-publish-docs-branch.yml`](../.github/workflows/ci-publish-docs-branch.yml) - generates documentation using help
comments for PowerShell cmdlets and saves documentation to a branch named `docs`.
- [`ci.yml`](../.github/workflows/ci.yml) - builds the .NET solution and the final module file for BenchPress. It also
tests the module for deployability to a local PS Repo. Lastly, it generates documentation using help comments for
PowerShell cmdlets and saves documentation to a branch named `docs`.
- The local "PowerShell Gallery" uses the workflow runner's local filesystem to simulate PowerShell Gallery. We then
push and pull from this filesystem using the same PowerShell cmdlets that are used to interact with PowerShell
Gallery.
- [`ci-module-versioning.yml`](../.github/workflows/ci-module-versioning.yml) - calculating the version for the
PowerShell module using GitVersion and writing it to the module manifest on a branch named `version`.

Просмотреть файл

@ -102,7 +102,7 @@ Infrastructure as Code (IaC) and why our tests are failing.
```PowerShell
BeforeAll {
Import-Module "../BenchPress/Helpers/Azure/BenchPress.Azure.psd1"
Import-Module Az.InfrastructureTest
}
Describe 'Verify Container Registry' {

Просмотреть файл

@ -12,8 +12,8 @@ In order to install from the PowerShell Gallery follow these steps from a PowerS
1. Ensure that the latest version of
[PowerShellGet](https://learn.microsoft.com/en-us/powershell/scripting/gallery/installing-psget?view=powershell-7.3)
is installed.
1. Execute `Install-Module -Name BenchPress.Azure`
1. To make the module available to the current session execute `Import-Module -Name BenchPress.Azure`
1. Execute `Install-Module -Name Az.InfrastructureTest`
1. To make the module available to the current session execute `Import-Module -Name Az.InfrastructureTest`
## Install From a Local Copy of the Repository
@ -42,4 +42,13 @@ To clone the repository:
### Install the BenchPress Module from the Local File System
Once a local copy of the BenchPress repository exists, to install the BenchPress Module, from the project root path
execute `Import-Module -Name ./BenchPress/Helpers/BenchPress.Azure/BenchPress.Azure.psd1`
execute `./build.ps1 -Import`. This will create a `.psm1` file in the `bin` directory that will dot source all cmdlets
in the `Public` and `Private` folders, `Export-ModuleMember` for all `Public` cmdlets, and sets the proper `using`
statements to import classes.
To clean the `bin` folder before outputting the artifacts from `build.ps1` the `-Clean` flag can be passed.
To test the load time the `-Load` flag can be passed.
To test the build as an inline `.psm1` file pass the `-InLine` flag. This will consolidate all files in the `Classes`
, `Public`, and `Private` folders into a single file instead of dot sourcing the files.

Просмотреть файл

@ -1,5 +1,5 @@
BeforeAll {
Import-Module "../BenchPress/Helpers/BenchPress.Azure/BenchPress.Azure.psd1"
Import-Module Az-InfrastructureTest
}
Describe 'Verify Action Group Exists' {

Просмотреть файл

Просмотреть файл

@ -1,5 +1,5 @@
BeforeAll {
Import-Module "../BenchPress/Helpers/BenchPress.Azure/BenchPress.Azure.psd1"
Import-Module Az-InfrastructureTest
}
Describe 'Verify AKS Cluster Exists' {

Просмотреть файл

Просмотреть файл

@ -1,5 +1,5 @@
BeforeAll {
Import-Module "../BenchPress/Helpers/BenchPress.Azure/BenchPress.Azure.psd1"
Import-Module Az-InfrastructureTest
}
Describe 'Verify App Service Plan Exists' {

Просмотреть файл

@ -1,5 +1,5 @@
BeforeAll {
Import-Module "../BenchPress/Helpers/BenchPress.Azure/BenchPress.Azure.psd1"
Import-Module Az-InfrastructureTest
}
Describe 'Verify Resource Exists' {
@ -58,7 +58,7 @@ Describe 'Use Confirm-AzBPResource to confirm resource and/or properties exist'{
$containerRegistryName = "testcontaineregistry"
#act
$result = Confirm-AzBPResource -ResourceGroupName $resourceGroupName -ResourceType $resourceType `
$result = Confirm-AzBPResource -ResourceGroupName $resourceGroupName -ResourceType $ResourceType `
-ResourceName $containerRegistryName
#assert
@ -74,7 +74,7 @@ Describe 'Use Confirm-AzBPResource to confirm resource and/or properties exist'{
$expectedValue = "Standard"
#act
$result = Confirm-AzBPResource -ResourceGroupName $resourceGroupName -ResourceType $resourceType `
$result = Confirm-AzBPResource -ResourceGroupName $resourceGroupName -ResourceType $ResourceType `
-ResourceName $containerRegistryName -PropertyKey $property -PropertyValue $expectedValue
#assert

Просмотреть файл

@ -1,5 +1,5 @@
BeforeAll {
Import-Module "../BenchPress/Helpers/BenchPress.Azure/BenchPress.Azure.psd1"
Import-Module Az-InfrastructureTest
}
Describe 'Verify Container Registry' {

Просмотреть файл

@ -1,5 +1,5 @@
BeforeAll {
Import-Module "../BenchPress/Helpers/BenchPress.Azure/BenchPress.Azure.psd1"
Import-Module Az-InfrastructureTest
}
Describe 'Verify KeyVault Exists' {

Просмотреть файл

Просмотреть файл

@ -1,5 +1,5 @@
BeforeAll {
Import-Module "../BenchPress/Helpers/BenchPress.Azure/BenchPress.Azure.psd1"
Import-Module Az-InfrastructureTest
}
Describe 'Verify Resource Group Exists' {

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше