我写了一个模板并附带了Runbook。模板触发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传递到模板。
对于测试,Runbook看起来像:
param
(
[string]$ResourceGroupId,
$MyTags
)
Write-Output "ResourceGroupId: $ResourceGroupId"
Write-Output "MyTags: $($MyTags | Out-String)"
Write-Output "MyTagsType: $($MyTags.GetType() | Out-String)"
没有身份验证,因为它不是必需的,我故意没有输入$MyTags
,虽然我已经尝试[object]
并使用`[参数(强制= $ true)]以防万一有未写/错过了规则。
简而言之,我在模板中创建了一个复杂对象作为变量,我希望将它作为单个对象传递给Runbook的参数。这些值是动态的,直到部署时才知道。必须在Runbook中指定每个参数(测试8)才会破坏此要求。
我使用New-AzureRmResourceGroupDeployment
cmdlet启动模板。
我创建了一个“复杂对象”变量:
"rolesTagObject": {
"db": "TestVm1",
"Server": "TestVm1",
"Client": "TestVm1"
}
模板运行资源"type" : "jobs"
。
由jobs
运行的Runbook有一个参数MyTags
,需要roleTagObject
,我会传递给jobs.properties.parameters.MyTags
:
,
"parameters": {
"MyTags": "[variable('roleTagObject')]"
}
这是不起作用的。如果我把它分解成每个键(测试8)就可以了。
我最初的想法是将其转换为单个字符串并使用json()
函数将其传递给Runbook,但我不知道如何在模板中执行此操作。
我已将模板放入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
我尝试过以下测试:
取消注释$TemplateParametersObject.runbookParameters.MyTags
:
$MyTags = @{"TestTag1"="TestValue1"}
$TemplateParametersObject = @{
currentDateTimeInTicks = $Ticks
runbookParameters = @{
ResourceGroupId = $RGID
MyTags = $MyTags
}
}
结果失败 - 请参阅上面的错误。
将$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有效,但我需要能够将参数传递给在运行时在模板内生成的Runbook。换句话说,我不能使用PowerShell。在job.properties.parameters
的模板内(要点中的第103行)
要证明问题MyTags
导致问题,请完全取出:
"parameters": {
"ResourceGroupId": "[parameters('runbookParameters').ResourceGroupId]"
}
结果:没有错误,但myTags
未通过(显然)。
创建一个变量对象并将其传递给参数:
"variables" : {
"rolesTagObject": {
"db": "TestVm1",
"Server": "TestVm1",
"Client": "TestVm1"
}
}
回到job.properties.parameters
:
"parameters": {
"ResourceGroupId": "[parameters('runbookParameters').ResourceGroupId]",
"MyTags": "[variables('rolesTagObject')]"
}
结果失败 - 请参阅上面的错误。
直接尝试:
"parameters": {
"ResourceGroupId": "[parameters('runbookParameters').ResourceGroupId]",
"MyTags": {
"testTag5" : "testValue5"
}
}
结果失败 - 请参阅上面的错误。
使用json()
template function。并不是说我希望它能够工作,因为它需要一个字符串。
"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'.
尝试使用我的MS为json()
template function提供的示例:
"parameters": {
"ResourceGroupId": "[parameters('runbookParameters').ResourceGroupId]",
"MyTags": "[json('{\"a\": \"b\"}')]"
}
结果失败 - 请参阅上面的错误。有趣!但为什么?工作的PowerShell测试表明它需要是一个JSON对象。这不是json()
的作用吗?
将对象分解为单个键/值:
"parameters": {
"db": "[variables('rolesTagObject').db]",
"server": "[variables('rolesTagObject').server]",
"client": "[variables('rolesTagObject').client]"
}
我还必须将Runbook中的参数从一个更改为三个。
结果传递 - 但是能够传递对象的想法是它可以具有任意数量的键/值对。这样,不仅必须对变量和参数进行硬编码,Runbook也是如此。不是很灵活。
我没有想法。有什么建议吗?
答案 0 :(得分:0)
自动化作业参数不了解复杂对象,因此您希望将参数作为字符串传递,然后转换回Runbook中的Json。 在您的示例中,您可以在json对象$ MyTags周围加上引号,以便它以字符串形式出现。
这
$TemplateParametersObject = @{
currentDateTimeInTicks = $Ticks
runbookParameters = @{
ResourceGroupId = $RGID
"MyTags" = $MyTags
}
}
到
$TemplateParametersObject = @{
currentDateTimeInTicks = $Ticks
runbookParameters = @{
ResourceGroupId = $RGID
"MyTags" = "$MyTags"
}
}
然后在你的Runbook中你可以做到 $ MyTags = ConvertFrom-Json $ MyTags
将其恢复为可以根据需要使用的json对象。
如果要将模板中的对象转换为字符串,则只需使用字符串函数https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-string#string
评论中显示的示例:
"myParams": {
"Hello": "World",
"Location": {
"Country": "USA",
"State": "WA"
}
},
然后您只需将其转换为字符串即可传递此模板对象:
"properties": {
"runbook": {
"name": "[variables('runbookName')]"
},
"parameters": {
"ResourceGroupId": "[variables('myParams').Hello]",
"MyTags": "[String(variables('myParams'))]"
}
如果字符串功能不起作用,请告诉我。
希望这个帮助, 埃蒙