Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisSidebotham authored Nov 30, 2023
2 parents 27b7df8 + 09e5c03 commit f7f62f1
Show file tree
Hide file tree
Showing 7 changed files with 254 additions and 87 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/avm.res.resources.deployment-script.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ on:

env:
modulePath: "avm/res/resources/deployment-script"
workflowPath: ".github/workflows/avm.res.resources.deployment-script"
workflowPath: ".github/workflows/avm.res.resources.deployment-script.yml"

concurrency:
group: ${{ github.workflow }}
Expand Down
4 changes: 2 additions & 2 deletions avm/res/resources/deployment-script/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ module deploymentScript 'br/public:avm/res/resources/deployment-script:<version>
| [`location`](#parameter-location) | string | Location for all resources. |
| [`lock`](#parameter-lock) | object | The lock settings of the service. |
| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. |
| [`primaryScriptUri`](#parameter-primaryscripturi) | string | Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead. |
| [`primaryScriptUri`](#parameter-primaryscripturi) | string | Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent parameter instead. |
| [`retentionInterval`](#parameter-retentioninterval) | string | Interval for which the service retains the script resource after it reaches a terminal state. Resource will be deleted when this duration expires. Duration is based on ISO 8601 pattern (for example P7D means one week). |
| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. |
| [`runOnce`](#parameter-runonce) | bool | When set to false, script will run every time the template is deployed. When set to true, the script will only run once. |
Expand Down Expand Up @@ -869,7 +869,7 @@ Name of the Deployment Script.

### Parameter: `primaryScriptUri`

Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead.
Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent parameter instead.
- Required: No
- Type: string

Expand Down
2 changes: 1 addition & 1 deletion avm/res/resources/deployment-script/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ param azCliVersion string?
@description('Optional. Script body. Max length: 32000 characters. To run an external script, use primaryScriptURI instead.')
param scriptContent string?

@description('Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead.')
@description('Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent parameter instead.')
param primaryScriptUri string?

@metadata({
Expand Down
4 changes: 2 additions & 2 deletions avm/res/resources/deployment-script/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"_generator": {
"name": "bicep",
"version": "0.23.1.45101",
"templateHash": "18060507539317064739"
"templateHash": "15035964448255167860"
},
"name": "Deployment Scripts",
"description": "This module deploys Deployment Scripts.",
Expand Down Expand Up @@ -183,7 +183,7 @@
"type": "string",
"nullable": true,
"metadata": {
"description": "Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent instead."
"description": "Optional. Uri for the external script. This is the entry point for the external script. To run an internal script, use the scriptContent parameter instead."
}
},
"environmentVariables": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,25 @@ function Test-TemplateDeployment {
}

process {
$deploymentNamePrefix = Split-Path -Path (Split-Path $templateFilePath -Parent) -LeafBase
if ([String]::IsNullOrEmpty($deploymentNamePrefix)) {
$deploymentNamePrefix = 'templateDeployment-{0}' -f (Split-Path $templateFilePath -LeafBase)
}

# Convert, e.g., [C:\myFork\avm\res\kubernetes-configuration\flux-configuration\tests\e2e\defaults\main.test.bicep] to [a-r-kc-fc-defaults]
$shortPathElems = ((Split-Path $templateFilePath) -replace ('{0}[\\|\/]' -f [regex]::Escape($repoRoot))) -split '[\\|\/]' | Where-Object { $_ -notin @('tests', 'e2e') }
# Shorten all elements but the last
$reducedElem = $shortPathElems[0 .. ($shortPathElems.Count - 2)] | ForEach-Object {
$shortPathElem = $_
if ($shortPathElem -match '-') {
($shortPathElem -split '-' | ForEach-Object { $_[0] }) -join ''
} else {
$shortPathElem[0]
}
}
# Add the last back and join the elements together
$deploymentNamePrefix = ($reducedElem + @($shortPathElems[-1])) -join '-'

$DeploymentInputs = @{
TemplateFile = $templateFilePath
Verbose = $true
Expand All @@ -102,24 +121,6 @@ function Test-TemplateDeployment {

$deploymentScope = Get-ScopeOfTemplateFile -TemplateFilePath $templateFilePath -Verbose

$deploymentNamePrefix = Split-Path -Path (Split-Path $templateFilePath -Parent) -LeafBase
if ([String]::IsNullOrEmpty($deploymentNamePrefix)) {
$deploymentNamePrefix = 'templateDeployment-{0}' -f (Split-Path $templateFilePath -LeafBase)
}
if ($templateFilePath -match '.*(\\|\/)Microsoft.+') {
# If we can assume we're operating in a module structure, we can further fetch the provider namespace & resource type
$shortPathElem = (($templateFilePath -split 'Microsoft\.')[1] -replace '\\', '/') -split '/' # e.g., AppConfiguration, configurationStores, .test, common, main.test.bicep
$providerNamespace = $shortPathElem[0] # e.g., AppConfiguration
$providerNamespaceShort = ($providerNamespace -creplace '[^A-Z]').ToLower() # e.g., ac

$resourceType = $shortPathElem[1] # e.g., configurationStores
$resourceTypeShort = ('{0}{1}' -f ($resourceType.ToLower())[0], ($resourceType -creplace '[^A-Z]')).ToLower() # e.g. cs

$testFolderShort = Split-Path (Split-Path $templateFilePath -Parent) -Leaf # e.g., common

$deploymentNamePrefix = "$providerNamespaceShort-$resourceTypeShort-$testFolderShort" # e.g., ac-cs-common
}

# Generate a valid deployment name. Must match ^[-\w\._\(\)]+$
do {
$deploymentName = ('{0}-{1}' -f $deploymentNamePrefix, (Get-Date -Format 'yyyyMMddTHHMMssffffZ'))[0..63] -join ''
Expand Down
100 changes: 37 additions & 63 deletions avm/utilities/tools/Test-ModuleLocally.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Optional. A hashtable parameter that contains custom tokens to be replaced in th
$TestModuleLocallyInput = @{
TemplateFilePath = 'C:\network\route-table\main.bicep'
ModuleTestFilePath = 'C:\network\route-table\.test\parameters.json'
ModuleTestFilePath = 'C:\network\route-table\.test\common\main.test.bicep'
PesterTest = $false
DeploymentTest = $false
ValidationTest = $true
Expand All @@ -56,46 +56,26 @@ $TestModuleLocallyInput = @{
}
Test-ModuleLocally @TestModuleLocallyInput -Verbose
Run a Test-Az*Deployment using a specific parameter-template combination with the provided tokens
Run a Test-Az*Deployment using a test file with the provided tokens
.EXAMPLE
$TestModuleLocallyInput = @{
TemplateFilePath = 'C:\network\route-table\main.bicep'
ModuleTestFilePath = 'C:\network\route-table\.test\common\main.test.bicep'
PesterTest = $false
DeploymentTest = $false
ValidationTest = $true
ValidateOrDeployParameters = @{
Location = 'westeurope'
ResourceGroupName = 'validation-rg'
SubscriptionId = '00000000-0000-0000-0000-000000000000'
ManagementGroupId = '00000000-0000-0000-0000-000000000000'
RemoveDeployment = $false
}
AdditionalTokens = @{
tenantId = '00000000-0000-0000-0000-000000000000'
namePrefix = 'avm'
moduleVersion = '1.0.0'
}
PesterTest = $true
}
Test-ModuleLocally @TestModuleLocallyInput -Verbose
Run a Test-Az*Deployment using a test file with the provided tokens
Run all Pester tests for the given template file
.EXAMPLE
$TestModuleLocallyInput = @{
TemplateFilePath = 'C:\network\route-table\main.bicep'
PesterTest = $true
DeploymentTest = $false
ValidationTest = $true
ValidateOrDeployParameters = @{
Location = 'westeurope'
ResourceGroupName = 'validation-rg'
SubscriptionId = '00000000-0000-0000-0000-000000000000'
ManagementGroupId = '00000000-0000-0000-0000-000000000000'
RemoveDeployment = $false
}
AdditionalTokens = @{
tenantId = '00000000-0000-0000-0000-000000000000'
Expand All @@ -105,40 +85,33 @@ $TestModuleLocallyInput = @{
}
Test-ModuleLocally @TestModuleLocallyInput -Verbose
Run all Pester tests for a given template and a Test-Az*Deployment using each test file in the module's default test folder ('.test') in combination with the template and the provided tokens
.EXAMPLE
$TestModuleLocallyInput = @{
TemplateFilePath = 'C:\network\route-table\main.bicep'
PesterTest = $true
}
Test-ModuleLocally @TestModuleLocallyInput -Verbose
Run all Pester tests for the given template file
Run all Pester tests for the given template file including tests for the use of tokens
.EXAMPLE
$TestModuleLocallyInput = @{
TemplateFilePath = 'C:\network\route-table\main.bicep'
PesterTest = $true
ModuleTestFilePath = 'C:\network\route-table\.test\common\main.test.bicep'
PesterTest = $false
DeploymentTest = $false
WhatIfTest = $true
ValidationTest = $false
ValidateOrDeployParameters = @{
Location = 'westeurope'
ResourceGroupName = 'validation-rg'
SubscriptionId = '00000000-0000-0000-0000-000000000000'
ManagementGroupId = '00000000-0000-0000-0000-000000000000'
RemoveDeployment = $false
}
AdditionalTokens = @{
tenantId = '00000000-0000-0000-0000-000000000000'
namePrefix = 'avm'
moduleVersion = '1.0.0'
tenantId = '00000000-0000-0000-0000-000000000000'
}
}
Test-ModuleLocally @TestModuleLocallyInput -Verbose
Run all Pester tests for the given template file including tests for the use of tokens
Get What-If deployment result using a test file with the provided tokens
.NOTES
- Make sure you provide the right information in the 'ValidateOrDeployParameters' parameter for this function to work.
- Ensure you have the ability to perform the deployment operations using your account (if planning to test deploy)
- Ensure you have the ability to perform the deployment operations using your account (if planning to test deploy or performing what-if validation.)
#>
function Test-ModuleLocally {

Expand All @@ -148,7 +121,7 @@ function Test-ModuleLocally {
[string] $TemplateFilePath,

[Parameter(Mandatory = $false)]
[string] $ModuleTestFilePath = (Join-Path (Split-Path $TemplateFilePath -Parent) '.test'),
[string] $ModuleTestFilePath = (Join-Path (Split-Path $TemplateFilePath -Parent) 'tests'),

[Parameter(Mandatory = $false)]
[string] $PesterTestFilePath = 'avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1',
Expand All @@ -169,7 +142,10 @@ function Test-ModuleLocally {
[switch] $DeploymentTest,

[Parameter(Mandatory = $false)]
[switch] $ValidationTest
[switch] $ValidationTest,

[Parameter(Mandatory = $false)]
[switch] $WhatIfTest
)

begin {
Expand All @@ -183,6 +159,7 @@ function Test-ModuleLocally {
# Load Modules Validation / Deployment Scripts
. (Join-Path $utilitiesFolderPath 'pipelines' 'e2eValidation' 'resourceDeployment' 'New-TemplateDeployment.ps1')
. (Join-Path $utilitiesFolderPath 'pipelines' 'e2eValidation' 'resourceDeployment' 'Test-TemplateDeployment.ps1')
. (Join-Path $PSScriptRoot 'helper' 'Get-TemplateDeploymentWhatIf.ps1')
}
process {

Expand Down Expand Up @@ -247,21 +224,20 @@ function Test-ModuleLocally {
# Validation & Deployment tests #
#################################

if (($ValidationTest -or $DeploymentTest) -and $ValidateOrDeployParameters) {
if (($ValidationTest -or $DeploymentTest -or $WhatIfTest) -and $ValidateOrDeployParameters) {

# Invoke Token Replacement Functionality and Convert Tokens in Parameter Files
$null = Convert-TokensInFileList @tokenConfiguration

# Deployment & Validation Testing
# -------------------------------
$functionInput = @{
TemplateFilePath = $TemplateFilePath
location = $ValidateOrDeployParameters.Location
resourceGroupName = $ValidateOrDeployParameters.ResourceGroupName
subscriptionId = $ValidateOrDeployParameters.SubscriptionId
managementGroupId = $ValidateOrDeployParameters.ManagementGroupId
additionalParameters = $additionalParameters
RepoRoot = Split-Path (Split-Path (Split-Path $PSScriptRoot))
RepoRoot = $repoRootPath
Verbose = $true
}

Expand All @@ -272,12 +248,17 @@ function Test-ModuleLocally {
# Loop through test files
foreach ($moduleTestFile in $moduleTestFiles) {
Write-Verbose ('Validating module [{0}] with test file [{1}]' -f $ModuleName, (Split-Path $moduleTestFile -Leaf)) -Verbose
if ((Split-Path $moduleTestFile -Extension) -eq '.json') {
Test-TemplateDeployment @functionInput -ParameterFilePath $moduleTestFile
} else {
$functionInput['TemplateFilePath'] = $moduleTestFile
Test-TemplateDeployment @functionInput
}
Test-TemplateDeployment @functionInput -TemplateFilePath $moduleTestFile
}
}

# What-If validation for template
# -----------------
if ($WhatIfTest) {
# Loop through test files
foreach ($moduleTestFile in $moduleTestFiles) {
Write-Verbose ('Get Deployment What-If result for module [{0}] with test file [{1}]' -f $ModuleName, (Split-Path $moduleTestFile -Leaf)) -Verbose
Get-TemplateDeploymentWhatIf @functionInput -TemplateFilePath $moduleTestFile
}
}

Expand All @@ -288,15 +269,8 @@ function Test-ModuleLocally {
# Loop through test files
foreach ($moduleTestFile in $moduleTestFiles) {
Write-Verbose ('Deploy Module [{0}] with test file [{1}]' -f $ModuleName, (Split-Path $moduleTestFile -Leaf)) -Verbose
if ((Split-Path $moduleTestFile -Extension) -eq '.json') {
if ($PSCmdlet.ShouldProcess(('Module [{0}] with test file [{1}]' -f $ModuleName, (Split-Path $moduleTestFile -Leaf)), 'Deploy')) {
New-TemplateDeployment @functionInput -ParameterFilePath $moduleTestFile
}
} else {
$functionInput['TemplateFilePath'] = $moduleTestFile
if ($PSCmdlet.ShouldProcess(('Module [{0}] with test file [{1}]' -f $ModuleName, (Split-Path $moduleTestFile -Leaf)), 'Deploy')) {
New-TemplateDeployment @functionInput
}
if ($PSCmdlet.ShouldProcess(('Module [{0}] with test file [{1}]' -f $ModuleName, (Split-Path $moduleTestFile -Leaf)), 'Deploy')) {
New-TemplateDeployment @functionInput -TemplateFilePath $moduleTestFile
}
}
}
Expand Down
Loading

0 comments on commit f7f62f1

Please sign in to comment.