你当前正在访问 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.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 市场验证模板

若要将产品/服务发布到 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 Pipeline。 使用管道,可以在每次更新模板时运行测试,或将其作为部署过程的一部分运行。

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

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

对于发布管道:

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

后续步骤