使用 ARM 範本測試工具組

Azure Resource Manager 範本 (ARM 範本) 測試工具組會檢查您的範本是否有套用建議的做法。 當您的範本不符合建議的做法時,會傳回一份警告以及變更建議。 藉由使用測試工具組,您可以了解如何在範本開發過程中避免常見問題。 本文描述如何執行測試工具組,以及如何新增或移除測試。 如需如何執行測試或如何執行特定測試的詳細資訊,請參閱測試參數

此工具組是一組 PowerShell 指令碼,可從 PowerShell 或 CLI 中的執行命令作業。 這些測試是建議,不是要求。 您可以決定您的目標與哪些測試有關,自訂要執行的測試。

此工具組包含四組測試:

注意

測試工具組僅適用於 ARM 範本。 若要驗證 Bicep 檔案,請使用 Bicep linter

訓練資源

若要深入了解 ARM 範本測試工具組,以及實際操作指南,請參閱使用 ARM 範本測試工具組來驗證 Azure 資源

安裝在 Windows 上

  1. 如果您尚未擁有 PowerShell,請在 Windows 上安裝 PowerShell

  2. 下載測試工具組最新 .zip 檔案,然後解壓縮。

  3. 啟動 PowerShell。

  4. 瀏覽至解壓縮測試工具組所在的資料夾。 在該資料夾中,瀏覽至 arm-ttk 資料夾。

  5. 如果您的執行原則會封鎖來自網際網路的指令碼,您必須解除封鎖指令碼檔案。 請確定您正位於 arm-ttk 資料夾中。

    Get-ChildItem *.ps1, *.psd1, *.ps1xml, *.psm1 -Recurse | Unblock-File
    
  6. 匯入模組。

    Import-Module .\arm-ttk.psd1
    
  7. 若要執行測試,請使用下列執行命令:

    Test-AzTemplate -TemplatePath \path\to\template
    

安裝在 Linux 上

  1. 如果您尚未擁有 PowerShell,請在 Linux 上安裝 PowerShell

  2. 下載測試工具組最新 .zip 檔案,然後解壓縮。

  3. 啟動 PowerShell。

    pwsh
    
  4. 瀏覽至解壓縮測試工具組所在的資料夾。 在該資料夾中,瀏覽至 arm-ttk 資料夾。

  5. 如果您的執行原則會封鎖來自網際網路的指令碼,您必須解除封鎖指令碼檔案。 請確定您正位於 arm-ttk 資料夾中。

    Get-ChildItem *.ps1, *.psd1, *.ps1xml, *.psm1 -Recurse | Unblock-File
    
  6. 匯入模組。

    Import-Module ./arm-ttk.psd1
    
  7. 若要執行測試,請使用下列執行命令:

    Test-AzTemplate -TemplatePath /path/to/template
    

在 macOS 上安裝

  1. 如果您尚未擁有 PowerShell,請在 macOS 上安裝 PowerShell

  2. 安裝 coreutils

    brew install coreutils
    
  3. 下載測試工具組最新 .zip 檔案,然後解壓縮。

  4. 啟動 PowerShell。

    pwsh
    
  5. 瀏覽至解壓縮測試工具組所在的資料夾。 在該資料夾中,瀏覽至 arm-ttk 資料夾。

  6. 如果您的執行原則會封鎖來自網際網路的指令碼,您必須解除封鎖指令碼檔案。 請確定您正位於 arm-ttk 資料夾中。

    Get-ChildItem *.ps1, *.psd1, *.ps1xml, *.psm1 -Recurse | Unblock-File
    
  7. 匯入模組。

    Import-Module ./arm-ttk.psd1
    
  8. 若要執行測試,請使用下列執行命令:

    Test-AzTemplate -TemplatePath /path/to/template
    

結果格式

通過的測試會以綠色顯示,且前面加上[+]

失敗的測試會以紅色顯示,並在前面加上[-]

具有警告的測試會以黃色顯示,並在前面加上[?]

檢視測試結果。

文字結果為:

deploymentTemplate
[+] adminUsername Should Not Be A Literal (6 ms)
[+] apiVersions Should Be Recent In Reference Functions (9 ms)
[-] apiVersions Should Be Recent (6 ms)
    Api versions must be the latest or under 2 years old (730 days) - API version 2019-06-01 of
    Microsoft.Storage/storageAccounts is 760 days old
    Valid Api Versions:
    2021-04-01
    2021-02-01
    2021-01-01
    2020-08-01-preview

[+] artifacts parameter (4 ms)
[+] CommandToExecute Must Use ProtectedSettings For Secrets (9 ms)
[+] DependsOn Best Practices (5 ms)
[+] Deployment Resources Must Not Be Debug (6 ms)
[+] DeploymentTemplate Must Not Contain Hardcoded Uri (4 ms)
[?] DeploymentTemplate Schema Is Correct (6 ms)
    Template is using schema version '2015-01-01' which has been deprecated and is no longer
    maintained.

測試參數

當您提供-TemplatePath參數時,工具組會在該資料夾中尋找名為 azuredeploy.jsonmaintemplate.json 範本。 它會先測試這個範本,然後測試檔案夾及其子資料夾中所有其他範本。 其他範本會視為連結的範本進行測試。 如果您的路徑包含名為 createUiDefinition.json的檔案,則會執行與 UI 定義相關的測試。 測試也會針對參數檔案和資料夾中的所有 JSON 檔案執行。

Test-AzTemplate -TemplatePath $TemplateFolder

若要測試該資料夾中的一個檔案,請新增-File參數。 然而,資料夾仍必須有一個名為azuredeploy.jsonmaintemplate.json的主要範本。

Test-AzTemplate -TemplatePath $TemplateFolder -File cdn.json

依預設執行所有測試。 若要指定要執行的個別測試,請使用-Test參數並提供測試名稱。 如需測試名稱,請參閱 ARM 範本參數檔案createUiDefinition.json所有檔案

Test-AzTemplate -TemplatePath $TemplateFolder -Test "Resources Should Have Location"

自訂測試

您可以自訂預設測試或建立自己的測試。 如果您想要永久移除測試,請從資料夾中刪除 .test.ps1 檔案。

此工具組有四個資料夾,包含針對特定檔案類型執行的預設測試:

  • ARM 範本:\arm-ttk\testcases\deploymentTemplate
  • 參數檔案:\arm-ttk\testcases\deploymentParameters
  • createUiDefinition.json: \arm-ttk\testcases\CreateUIDefinition
  • 所有檔案:\arm-ttk\testcases\AllFiles

新增自訂測試

若要加入您自己的測試,請建立具有命名慣例:Your-Custom-Test-Name.test.ps1 的檔案。

測試可以取得範本作為物件參數或字串參數。 一般您只會使用其中一個,但您可以同時使用兩者。

當您需要取得範本的區段,逐一查看其屬性時,請使用物件參數。 使用物件參數的測試格式如下:

param(
  [Parameter(Mandatory=$true,Position=0)]
  [PSObject]
  $TemplateObject
)

# Implement test logic that evaluates parts of the template.
# Output error with: Write-Error -Message

範本物件具有下列屬性:

  • $schema
  • contentVersion
  • parameters
  • variables
  • resources
  • outputs

例如,您可以使用$TemplateObject.parameters取得參數的集合。

當您需要對整個範本執行字串操作時,請使用字串參數。 使用字串參數的測試格式如下:

param(
  [Parameter(Mandatory)]
  [string]
  $TemplateText
)

# Implement test logic that performs string operations.
# Output error with: Write-Error -Message

例如,您可以執行字串參數的規則運算式,以查看是否使用了特定語法。

若要深入了解如何實行測試,請查看該資料夾中的其他測試。

驗證 Azure Marketplace 的範本

若要將供應項目發佈至 Azure Marketplace,請使用測試工具組來驗證範本。 當範本通過驗證測試時,Azure Marketplace 將更快速核准您的供應項目。 如果範本測試失敗,供應項目將會認證失敗。

重要

Marketplace 測試已於 2022 年 7 月加入。 如果您是舊版,請更新模組。

在環境中執行測試

安裝工具組並匯入模組之後,請執行下列 Cmdlet 測試套件:

Test-AzMarketplacePackage -TemplatePath "Path to the unzipped package folder"

解讀結果

測試會以兩個區段傳回結果。 第一個區段包含必要的測試。 這些測試的結果會在摘要區段中顯示。

重要

在接受 Marketplace 供應項目之前,您必須修正任何反紅的結果。 建議修正反黃的任何結果。

文字結果為:

Validating nestedtemplates\AzDashboard.json
    [+] adminUsername Should Not Be A Literal (210 ms)
    [+] artifacts parameter (3 ms)
    [+] CommandToExecute Must Use ProtectedSettings For Secrets (201 ms)
    [+] Deployment Resources Must Not Be Debug (160 ms)
    [+] DeploymentTemplate Must Not Contain Hardcoded Url (13 ms)
    [+] Location Should Not Be Hardcoded (31 ms)
    [+] Min and Max Value Are Numbers (4 ms)
    [+] Outputs Must Not Contain Secrets (9 ms)
    [+] Password params must be secure (3 ms)
    [+] Resources Should Have Location (2 ms)
    [+] Resources Should Not Be Ambiguous (2 ms)
    [+] Secure Params In Nested Deployments (205 ms)
    [+] Secure String Parameters Cannot Have Default (3 ms)
    [+] URIs Should Be Properly Constructed (190 ms)
    [+] Variables Must Be Referenced (9 ms)
    [+] Virtual Machines Should Not Be Preview (173 ms)
    [+] VM Size Should Be A Parameter (165 ms)
Pass : 99
Fail : 3
Total: 102
Validating StartStopV2mkpl_1.0.09302021\anothertemplate.json
    [?] Parameters Must Be Referenced (86 ms)
        Unreferenced parameter: resourceGroupName
        Unreferenced parameter: location
        Unreferenced parameter: azureFunctionAppName
        Unreferenced parameter: applicationInsightsName
        Unreferenced parameter: applicationInsightsRegion

摘要區段下方的區段包含可理解為警告的錯誤失敗。 修正錯誤是選擇性,但強力建議加以修正。 失敗通常指向客戶安裝供應項目時造成失敗的常見問題。

若要修正測試,請遵循適合的測試案例:

提交供應項目

完成必要修正之後,請重新執行測試工具組。 將供應項目提交至 Azure Marketplace 之前,請確保您沒有任何失敗。

與 Azure Pipelines 整合

您可以將測試工具組新增至 Azure 管線。 透過管線,您可以在每次更新範本時執行測試,或在部署流程中執行測試。

使用協力廠商延伸模組是將測試工具組新增至管線最簡單的方式。 有下列兩種延伸模組可用:

或者您可以實行自己的工作。 下列範例顯示如何下載測試工具組。

針對發行管線:

{
  "environment": {},
  "enabled": true,
  "continueOnError": false,
  "alwaysRun": false,
  "displayName": "Download TTK",
  "timeoutInMinutes": 0,
  "condition": "succeeded()",
  "task": {
    "id": "e213ff0f-5d5c-4791-802d-52ea3e7be1f1",
    "versionSpec": "2.*",
    "definitionType": "task"
  },
  "inputs": {
    "targetType": "inline",
    "filePath": "",
    "arguments": "",
    "script": "New-Item '$(ttk.folder)' -ItemType Directory\nInvoke-WebRequest -uri '$(ttk.uri)' -OutFile \"$(ttk.folder)/$(ttk.asset.filename)\" -Verbose\nGet-ChildItem '$(ttk.folder)' -Recurse\n\nWrite-Host \"Expanding files...\"\nExpand-Archive -Path '$(ttk.folder)/*.zip' -DestinationPath '$(ttk.folder)' -Verbose\n\nWrite-Host \"Expanded files found:\"\nGet-ChildItem '$(ttk.folder)' -Recurse",
    "errorActionPreference": "stop",
    "failOnStderr": "false",
    "ignoreLASTEXITCODE": "false",
    "pwsh": "true",
    "workingDirectory": ""
  }
}

針對管線 YAML 定義:

- pwsh: |
   New-Item '$(ttk.folder)' -ItemType Directory
   Invoke-WebRequest -uri '$(ttk.uri)' -OutFile "$(ttk.folder)/$(ttk.asset.filename)" -Verbose
   Get-ChildItem '$(ttk.folder)' -Recurse
   
   Write-Host "Expanding files..."
   Expand-Archive -Path '$(ttk.folder)/*.zip' -DestinationPath '$(ttk.folder)' -Verbose
   
   Write-Host "Expanded files found:"
   Get-ChildItem '$(ttk.folder)' -Recurse
  displayName: 'Download TTK'

下一個範例會示範如何執行測試。

針對發行管線:

{
  "environment": {},
  "enabled": true,
  "continueOnError": true,
  "alwaysRun": false,
  "displayName": "Run Best Practices Tests",
  "timeoutInMinutes": 0,
  "condition": "succeeded()",
  "task": {
    "id": "e213ff0f-5d5c-4791-802d-52ea3e7be1f1",
    "versionSpec": "2.*",
    "definitionType": "task"
  },
  "inputs": {
    "targetType": "inline",
    "filePath": "",
    "arguments": "",
    "script": "Import-Module $(ttk.folder)/arm-ttk/arm-ttk.psd1 -Verbose\n$testOutput = @(Test-AzTemplate -TemplatePath \"$(sample.folder)\")\n$testOutput\n\nif ($testOutput | ? {$_.Errors }) {\n   exit 1 \n} else {\n    Write-Host \"##vso[task.setvariable variable=result.best.practice]$true\"\n    exit 0\n} \n",
    "errorActionPreference": "continue",
    "failOnStderr": "true",
    "ignoreLASTEXITCODE": "false",
    "pwsh": "true",
    "workingDirectory": ""
  }
}

針對管線 YAML 定義:

- pwsh: |
   Import-Module $(ttk.folder)/arm-ttk/arm-ttk.psd1 -Verbose
   $testOutput = @(Test-AzTemplate -TemplatePath "$(sample.folder)")
   $testOutput
   
   if ($testOutput | ? {$_.Errors }) {
      exit 1 
   } else {
       Write-Host "##vso[task.setvariable variable=result.best.practice]$true"
       exit 0
   } 
  errorActionPreference: continue
  failOnStderr: true
  displayName: 'Run Best Practices Tests'
  continueOnError: true

後續步驟