我已经编写了一个模板和随附的运行手册。模板触发 Runbook。模板和 Runbook 工作正常,直到我尝试将对象传递给 Runbook 的参数之一。Azure 错误是:
错误
"content":
{
"status": "Failed",
"error":
{
"code": "DeploymentFailed",
"message": "At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/arm-debug for usage details.",
"details":
[
{
"code": "BadRequest",
"message": "{\r\n \"code\": \"BadRequest\",\r\n \"message\": \"{\\\"Message\\\":\\\"The request is invalid.\\\",\\\"ModelState\\\":{\\\"job.properties.parameters.MyTags\\\":[\\\"An error has occurred.\\\"]}}\"\r\n}"
}
]
}
}
我不确定 是什么意思ModelState
,但是job.properties.parameters.MyTags
指向麻烦的参数。
我确信这与数据类型有关。这可能是因为参数作为 JSON 对象传递,而 Runbook 无法理解它。我更习惯于将对象从 PowerShell 传递到模板。
运行手册 (Update-ResourceGroupTags.ps1)
对于测试,运行手册如下所示:
param
(
[string]$ResourceGroupId,
$MyTags
)
Write-Output "ResourceGroupId: $ResourceGroupId"
Write-Output "MyTags: $($MyTags | Out-String)"
Write-Output "MyTagsType: $($MyTags.GetType() | Out-String)"
没有身份验证,因为它还不是必需的,我故意不输入$MyTags
,尽管我已经尝试[object]
并使用 `[parameter(Mandatory = $true)] 以防万一有不成文/遗漏的规则。
目标
简而言之,我在模板中创建了一个复杂对象作为变量,并且我想将它作为单个对象传递给 Runbook 的参数。这些值是动态的,直到部署时才知道。必须在运行手册中指定每个参数(测试 8)打破了这一要求。
New-AzureRmResourceGroupDeployment
我使用cmdlet启动模板。
我创建了一个“复杂对象”变量:
"rolesTagObject": {
"db": "TestVm1",
"Server": "TestVm1",
"Client": "TestVm1"
}
该模板运行"type" : "jobs"
.
运行的 Runbookjobs
有一个MyTags
需要接受的参数roleTagObject
,我将其传递给jobs.properties.parameters.MyTags
:
,
"parameters": {
"MyTags": "[variable('roleTagObject')]"
}
这是行不通的。如果我将其分解为每个键(测试 8),它就可以工作。
我最初的想法是将其转换为单个字符串并使用json()
函数将其传递给运行手册,但我不知道在模板中执行此操作的方法。
模板(testRunbook.json)
我已将模板放在 GIST 中,以免再提出这个问题。 https://gist.github.com/arcotek-ltd/7c606540980a45a3a7915ccae2e0b140
模板已编写好,因此我可以将该"resources":[]
部分复制到不同的模板中。因此,为什么某些变量和参数的名称可能看起来很奇怪。正如我所说,除了这个问题之外,模板有效。
电源外壳
我使用 PowerShell 调用模板,因此:
$Ticks = (Get-Date).Ticks.ToString()
$RGID = (Get-AzureRmResourceGroup -Name "MyResourceGroup").ResourceId
$MyTags = @{"TestTag2"="TestValue2"}
$JsonTagsHash = ($MyTags | ConvertTo-Json -Depth 20 | Out-String) -replace '\s',''
$TemplateParametersObject = @{
currentDateTimeInTicks = $Ticks
runbookParameters = @{
ResourceGroupId = $RGID
#"MyTags" = $MyTags #$JsonTagsHash
}
}
New-AzureRmResourceGroupDeployment `
-Name "Test_Runbook" `
-ResourceGroupName "MyResourceGroup" `
-Mode Incremental `
-DeploymentDebugLogLevel All `
-Force `
-TemplateFile "D:temp\testRunRunbook.json" `
-Verbose `
-TemplateParameterObject $TemplateParametersObject
我尝试了以下测试:
测试 1
取消注释$TemplateParametersObject.runbookParameters.MyTags
:
$MyTags = @{"TestTag1"="TestValue1"}
$TemplateParametersObject = @{
currentDateTimeInTicks = $Ticks
runbookParameters = @{
ResourceGroupId = $RGID
MyTags = $MyTags
}
}
结果失败- 请参阅上面的错误。
测试 2
替换$MyTags
为$JsonTagsHash
:
$MyTags = @{"TestTag2"="TestValue2"}
$JsonTagsHash = ($MyTags | ConvertTo-Json -Depth 20 | Out-String) -replace '\s',''
$TemplateParametersObject = @{
currentDateTimeInTicks = $Ticks
runbookParameters = @{
ResourceGroupId = $RGID
MyTags = $JsonTagsHash
}
}
结果:PASS按预期工作。将参数传递给 Runbook。
测试 2 有效,但我需要能够将参数传递给运行时在模板内生成的运行手册。换句话说,我不能使用 PowerShell。在模板内部job.properties.parameters
(要点中的第 103 行)
测试 3
为了证明它是MyTags
导致问题的原因,请将其完全取出:
"parameters": {
"ResourceGroupId": "[parameters('runbookParameters').ResourceGroupId]"
}
结果:没有错误,但是,myTags
没有通过(显然)。
测试 4
创建一个变量对象并将其传递给参数:
"variables" : {
"rolesTagObject": {
"db": "TestVm1",
"Server": "TestVm1",
"Client": "TestVm1"
}
}
回到job.properties.parameters
:
"parameters": {
"ResourceGroupId": "[parameters('runbookParameters').ResourceGroupId]",
"MyTags": "[variables('rolesTagObject')]"
}
结果失败- 请参阅上面的错误。
测试 5
直接试试:
"parameters": {
"ResourceGroupId": "[parameters('runbookParameters').ResourceGroupId]",
"MyTags": {
"testTag5" : "testValue5"
}
}
结果失败- 请参阅上面的错误。
测试 6
使用json()
模板功能。并不是说我希望它能够工作,因为它需要一个字符串。
"parameters": {
"ResourceGroupId": "[parameters('runbookParameters').ResourceGroupId]",
"MyTags": "[json(variables('rolesTagObject'))]"
}
结果失败。正如预测的那样:
'The template language function 'json' expects an argument of type 'string'. The provided value is of type 'Object'.
测试 7
尝试使用我的 MS 提供的json()
模板功能示例:
"parameters": {
"ResourceGroupId": "[parameters('runbookParameters').ResourceGroupId]",
"MyTags": "[json('{\"a\": \"b\"}')]"
}
结果失败- 请参阅上面的错误。有趣的!但为什么?有效的 PowerShell 测试表明它需要是一个 JSON 对象。这不是什么json()
吗?
测试 8
将对象分解为单个键/值:
"parameters": {
"db": "[variables('rolesTagObject').db]",
"server": "[variables('rolesTagObject').server]",
"client": "[variables('rolesTagObject').client]"
}
我还必须将 Runbook 中的参数从 1 更改为 3。
结果传递- 但能够传递对象的想法是它可以有任意数量的键/值对。这样,不仅变量和参数必须进行硬编码,运行手册也是如此。不是很灵活。
我没主意了。请问有什么建议吗?