我如何使用 ARM 'outputs' values 另一个发布任务?

How do I use ARM 'outputs' values another release task?

我有一个 ARM 模板,其中包含和输出如下部分:

"outputs": {
    "sqlServerFqdn": {
        "type": "string",
        "value": "[reference(concat('Microsoft.Sql/servers/', variables('sqlserverName'))).fullyQualifiedDomainName]"
    },
    "primaryConnectionString": {
        "type": "string",
        "value": "[concat('Data Source=tcp:', reference(concat('Microsoft.Sql/servers/', variables('sqlserverName'))).fullyQualifiedDomainName, ',1433;Initial Catalog=', variables('databaseName'), ';User Id=', parameters('administratorLogin'), '@', variables('sqlserverName'), ';Password=', parameters('administratorLoginPassword'), ';')]"
    },
    "envResourceGroup": {
        "type": "string",
        "value": "[parameters('hostingPlanName')]"
    }
}

我有一个使用该模板的 Azure 资源组部署任务。然后我想在下一个任务中使用变量 $(sqlServerFqdn) 进行配置。该变量似乎不只是填充,我找不到任何地方告诉我如何在发布时使用 'outputs' 值。

在此 ARM 模板运行后,我需要做什么来填充变量以用于配置任务?一个例子是 powershell 脚本任务或另一个 ARM 模板的参数。

VSTS 允许在 powershell 脚本中设置变量,您可以在其他任务中使用这些变量。

语法是

Write-Host "##vso[task.setvariable variable=myvariable;]myvalue"

您可以有一个内联 Powershell 脚本,它可以设置需要的变量以在尚未执行时使用 tasks.You 可以像 $(myvariable) 一样访问它。

您可能需要 system.debug 变量到 true 才能使用它。

阅读更多详情here

您只需为 "Azure Resource Group Deployment" 任务添加一个输出变量名称,如下所示:

然后在"PowerShell on Target Machines"任务中使用变量:

"PowerShell on Target Machines" 任务将使用 "Azure Resource Group Deployment" 任务中配置的资源:

Output variables:

Create/update action of the Azure Resource Group task now produces an output variable during execution. The output variable can be used to refer to the resource group object in the subsequent tasks. For example "PowerShell on Target Machine" task can now refer to resource group output variable as '$(variableName)' so that it can execute the powershell script on the resource group VM targets.

Limitation: Output variable produced during execution will have details about VM hostname(s) and (public) ports, if any. Credentials to connect to the VM host(s) are to be provided explicitly in the subsequent tasks.

请参阅此 link 了解更多详情:Azure Resource Group Deployment Task

A​​zure 资源组部署的 Visual Studio 团队服务任务的 UI 上显示的输出值似乎仅适用于 Eddie 的回答中描述的场景,即 VM。事实上,如果您的部署不包括 VM,您将收到类似以下内容的错误:

No VMs found in resource group: 'MY-RESOURCE-GROUP-NAME'. Could not register environment in the output variable: 'myVariableName'.

对于非 VM 示例,我创建了一个在 RG 部署之后运行的 powershell 脚本。例如,此脚本采用资源组 $resourceGroupName 的输入变量和您需要的输出变量的名称 $rgDeploymentOutputParameterName。您可以自定义并使用类似的东西:

#get the most recent deployment for the resource group
$lastRgDeployment = Get-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName |
    Sort Timestamp -Descending |
        Select -First 1        

if(!$lastRgDeployment)
{
    throw "Resource Group Deployment could not be found for '$resourceGroupName'."
}

$deploymentOutputParameters = $lastRgDeployment.Outputs

if(!$deploymentOutputParameters)
{
    throw "No output parameters could be found for the last deployment of '$resourceGroupName'."
}

$outputParameter = $deploymentOutputParameters.Item($rgDeploymentOutputParameterName)

if(!$outputParameter)
{
    throw "No output parameter could be found with the name of '$rgDeploymentOutputParameterName'."
}

$outputParameterValue  = $outputParameter.Value

# From here, use $outputParameterValue, for example:
Write-Host "##vso[task.setvariable variable=$rgDeploymentOutputParameterName;]$outputParameterValue"

捕捉这个答案,因为我在搜索解决方案时总是以这个问题结束。

There is a marketplace task 这使得 ARM 模板输出参数在管道的更下方可用。但在某些情况下,您无权为您的订阅购买市场商品,因此以下 PowerShell 将执行相同的操作。要使用它,您可以在 ARM 模板资源组部署步骤之后立即将其添加为 powershell 脚本步骤。它将查看最后一次部署并将输出变量拉入管道变量。

param(
 [string]  $resourceGroupName
)

$lastDeployment = Get-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName | Sort Timestamp -Descending | Select -First 1 

if(!$lastDeployment) {
    throw "Deployment could not be found for Resource Group '$resourceGroupName'."
}

if(!$lastDeployment.Outputs) {
    throw "No output parameters could be found for the last deployment of Resource Group '$resourceGroupName'."
}

foreach ($key in $lastDeployment.Outputs.Keys){
    $type = $lastDeployment.Outputs.Item($key).Type
    $value = $lastDeployment.Outputs.Item($key).Value

    if ($type -eq "SecureString") {
        Write-Host "##vso[task.setvariable variable=$key;issecret=true]$value" 
    }
    else {
        Write-Host "##vso[task.setvariable variable=$key;]$value" 
    }
}

请注意,环境变量在此脚本的上下文中不可用,但在后续任务中可用。

VSTS Azure 资源组部署 任务有 outputs section now (since January 2018)。因此,您可以在 Azure 资源组部署 任务的 部署输出 中将变量名称设置为,例如 ResourceGroupDeploymentOutputs 并添加 PowerShell Script 任务,包含以下内联脚本:

# Make outputs from resource group deployment available to subsequent tasks

$outputs = ConvertFrom-Json $($env:ResourceGroupDeploymentOutputs)
foreach ($output in $outputs.PSObject.Properties) {
  Write-Host "##vso[task.setvariable variable=RGDO_$($output.Name)]$($output.Value.value)"
}

在后续任务中,您可以使用模板变量。因此,例如,如果您的模板中有 sqlServerFqdn 变量,它将在 PowerShell 脚本 任务完成后作为 $(RGDO_sqlServerFqdn) 可用。

首先定义 Azure 资源部署任务,在此上下文中 Deployment outputs

在下一步中,您将创建一个 PowerShell 任务,它将上面定义的 Deployment outputs 作为输入参数

PowerShell 脚本如下所示,并为 ARM 模板中定义的每个输出分配一个单独的 VSTS 环境变量,其名称与 ARM 模板输出部分中定义的名称相同。然后可以在后续任务中使用这些变量。

param (
    [Parameter(Mandatory=$true)]
    [string]
    $armOutputString
)

Write-Host $armOutputString
$armOutputObj = $armOutputString | convertfrom-json
Write-Host $armOutputObj

$armOutputObj.PSObject.Properties | ForEach-Object {
    $type = ($_.value.type).ToLower()
    $key = $_.name
    $value = $_.value.value

    if ($type -eq "securestring") {
        Write-Host "##vso[task.setvariable variable=$key;issecret=true]$value"
        Write-Host "Create VSTS variable with key '$key' and value '$value' of type '$type'!"
    } elseif ($type -eq "string") {
        Write-Host "##vso[task.setvariable variable=$key]$value"
        Write-Host "Create VSTS variable with key '$key' and value '$value' of type '$type'!"
    } else {
        Throw "Type '$type' not supported!"
    }
}

在后续任务中,您可以通过 '$(varName)' 将它们作为参数传递来访问环境变量(这也适用于 SecureString)或例如通过 $env:varName 在 PowerShell 脚本中(这不适用于 SecureString

2020 年 11 月,在本次提交后 - https://github.com/microsoft/azure-pipelines-tasks/commit/1173324604c3f61ce52cdcc999f6d4d7ea9ab8f9,变量可以直接用于管道中的后续任务(不需要 powershell 脚本!!)

这是步骤的样子 -

  1. 在 ARM 模板部署任务中,为高级下拉列表下的部署输出部分提供任何引用名称。在我的例子中,我给出了 armOutputVariable.

    See image for visual description

  2. 现在要在后续的任务中使用sqlServerFqdn,直接这样使用即可$(armOutputVariable.sqlServerFqdn.value)

例如,假设我想用它来覆盖部署后的测试任务中的一个参数,这样我就可以按以下方式使用它 - Example image

总结一下 ARM 中的所有输出可以直接以这种方式在进一步的步骤中使用(确保您在 ARM 模板部署步骤中分配了一个引用名称)-

$(armOutputVariable.sqlServerFqdn.value)
$(armOutputVariable.sqlServerFqdn.type)
$(armOutputVariable.primaryConnectionString.value)
$(armOutputVariable.primaryConnectionString.type)
$(armOutputVariable.envResourceGroup.value)
$(armOutputVariable.envResourceGroup.type)