你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

使用 ARM 模板测试工具包

Azure 资源管理器模板(ARM 模板)测试工具包检查模板是否使用建议的做法。 如果模板不符合建议的做法,它将返回包含建议的更改的警告列表。 通过使用测试工具包,可以了解如何避免模板开发中的常见问题。 本文介绍如何运行测试工具包以及如何添加或删除测试。 有关如何运行测试或如何运行特定测试的详细信息,请参阅测试参数

工具包是一组可从 PowerShell 或 CLI 中的命令运行的 PowerShell 脚本。 这些测试是建议,而不是要求。 你可以确定哪些测试与目标相关,并自定义要运行哪些测试。

该工具包包含四组测试:

注意

测试工具包仅适用于 ARM 模板。 若要验证 Bicep 文件,请使用 Bicep linter

培训资源

若要详细了解 ARM 模板测试工具包并获得实际操作指导,请参阅使用 ARM 模板测试工具包验证 Azure 资源

在 Windows 上安装

  1. 如果还没有 PowerShell,请在 Windows 上安装 PowerShell

  2. 下载测试工具包的最新 .zip 文件,并将其解压缩。

  3. 启动 PowerShell。

  4. 导航到在其中解压缩测试工具包的文件夹。 在该文件夹中,导航到 arm-ttk 文件夹。

  5. 如果执行策略阻止来自 Internet 的脚本,则需要取消阻止脚本文件。 请确保处于 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. 如果执行策略阻止来自 Internet 的脚本,则需要取消阻止脚本文件。 请确保处于 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. 如果执行策略阻止来自 Internet 的脚本,则需要取消阻止脚本文件。 请确保处于 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.json 或 maintemplate.json 的模板 。 它首先测试此模板,然后测试该文件夹及其子文件夹中的所有其他模板。 其他模板将作为链接模板进行测试。 如果路径包含名为 createUiDefinition.json 的文件,则它将运行与 UI 定义相关的测试。 还会针对该文件夹中的参数文件和所有 JSON 文件运行测试。

Test-AzTemplate -TemplatePath $TemplateFolder

若要测试该文件夹中的某个文件,请添加 -File 参数。 但是,该文件夹仍然必须包含名为 azuredeploy.json 或 maintemplate.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。

测试可以获取模板作为对象参数或字符串参数。 通常使用其中一种参数,但也可以同时使用两种。

需要获取模板的一部分并循环访问其属性时,请使用 object 参数。 使用 object 参数的测试采用以下格式:

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 获取参数的集合。

如果需要对整个模板执行字符串操作,请使用 string 参数。 使用 string 参数的测试采用以下格式:

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

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

例如,可以运行字符串参数的正则表达式,以查看是否使用了特定语法。

若要了解有关实施测试的更多信息,请查看该文件夹中的其他测试。

验证 Azure 市场的模板

若要将产品/服务发布到 Azure 市场,请使用测试工具包验证模板。 当模板通过验证测试后,Azure 市场会更快地批准该产品/服务。 如果未通过测试,产品/服务将认证失败。

重要

市场测试已于 2022 年 7 月增加。 如果为早期版本,请更新模块。

在环境中运行测试

安装工具包并导入模块后,运行以下 cmdlet 测试包:

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

解释结果

测试结果分两部分返回。 第一部分包括强制性测试。 这些测试的结果显示在总结部分。

重要

必须修复所有红色的结果,才能接受市场产品/服务。 建议修复返回的所有黄色结果。

文本结果为:

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 市场之前,请确保没有错误。

与 Azure Pipelines 集成

可以将测试工具包添加到 Azure Pipelines。 使用管道,可以在每次更新模板时运行测试,也可以在部署过程中运行测试。

将测试工具包添加到管道的最简单的方法是利用第三方扩展。 提供以下两个扩展:

或者,你可以执行自己的任务。 以下示例演示如何下载测试工具包。

对于发布管道:

{
  "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

后续步骤