Azure 嵌套模板部署:在 PowerShell 中使用模板元素(不是 templateLink)
Azure nested template deployment: Using template element (not templateLink) with PowerShell
为了让生活更轻松(在长 运行 中),我尝试使用 properties.template,而不是有据可查的 properties.templateLink.前者通过将 child.json 模板文件的内容作为模板参数传递到 parent.json 模板中,几乎没有文档。
来自 Microsoft.Resources/deployments 的 MS 文档:
The template content. You use this element when you want to pass the template syntax directly in the request rather than link to an existing template. It can be a JObject or well-formed JSON string. Use either the templateLink property or the template property, but not both.
在我的父模板中,我声明参数 childTemplates
并在 properties.template 中引用它:
"parameters": {
"childTemplates": {
"type": "object",
"metadata": {
"description": "Child template"
}
}
}
other stuff...
"resources": [
{
"name": "[concat('linkedTemplate-VM-Net-',copyIndex(1))]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2017-06-01",
"dependsOn": [],
"copy": {
"name": "interate",
"count": "[parameters('vmQty')]"
},
"properties": {
"mode": "Incremental",
"template": "[parameters('childTemplates')]",
"parameters": {
"sharedVariables": { "value": "[variables('sharedVariables')]" },
"sharedTemplate": { "value": "[variables('sharedTemplate')]" },
"artifactsLocationSasToken": { "value": "[parameters('artifactsLocationSasToken')]" },
"adminPassword": { "value": "[parameters('adminPassword')]" },
"copyIndexValue": { "value": "[copyIndex(1)]" }
},
"debugSetting": {
"detailLevel": "both"
}
}
}
],
然后我将子模板传递给 New-AzureRmResourceGroupDeployment -TemplateParameterObject
以部署父模板:
$TemplateFileLocation = "C:\Temp\templates\parent.json"
$JsonChildTemplate = Get-Content -Raw (Join-Path ($TemplateFileLocation | Split-Path -Parent) "nestedtemplates\child.json") | ConvertFrom-Json
$TemplateParameters = @{
childTemplates = $JsonChildTemplate
...Other parameters...
}
New-AzureRmResourceGroupDeployment -TemplateParameterObject $TemplateParameters
这会产生以下错误:
Code : InvalidTemplate
Message : The nested deployment 'linkedTemplate-VM-Net-1' failed validation: 'Required property '$schema' not found in JSON. Path 'properties.template'.'.
Target :
Details :
如果我查看 $JsonChildTemplate
,它会给我:
$schema : https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#
contentVersion : 1.0.0.0
parameters : @{sharedVariables=; sharedTemplate=; vhdStorageAccountName=; artifactsLocationSasToken=; adminPassword=; copyIndexValue=}
variables : @{seqNo=[padleft(add(parameters('copyIndexValue'),3),3,'0')]; nicName=[concat('NIC-',parameters('sharedVariables').role,'-', variables('seqNo'),'-01')];
subnetRef=[parameters('sharedVariables').network.subnetRef]; ipConfigName=[concat('ipconfig-', variables('seqNo'))]}
resources : {@{apiVersion=2016-03-30; type=Microsoft.Network/networkInterfaces; name=[variables('nicName')]; location=[resourceGroup().location]; tags=; dependsOn=System.Object[];
properties=}}
outputs : @{nicObject=; vmPrivateIp=; vmNameSuffix=; vmPrivateIpArray=}
对我来说,$schema
就在那里。
我也试过删除 | ConvertFrom-Json
,但出现同样的错误。
上面,我展示的是最新的 API 版本,但我已经尝试过其他版本,例如 2016-09-01,以防出现错误。
在寻找解决方案的过程中,我在 GitHub 上发现了 this 个问题。建议是删除 $schema
和 contentVersion
,尽管这会导致错误。我尝试了以下方法:
Function Get-ChildTemplate
{
$TemplateFileLocation = "C:\Temp\templates\nestedtemplates\child.json"
$json = Get-Content -Raw -Path $TemplateFileLocation | ConvertFrom-Json
$NewJson = @()
$NewJson += $json.parameters
$NewJson += $json.variables
$NewJson += $json.resources
$NewJson += $json.outputs
Return $NewJson | ConvertTo-Json
}
$JsonChildTemplate = Get-ChildTemplate
$TemplateParameters = @{
childTemplates = $JsonChildTemplate
...Other parameters...
}
$JsonChildTemplate
returns:
[
{
"sharedVariables": {
"type": "object",
"metadata": "@{description=Object of variables from master template}"
}...
我的猜测是我在将 child.json 的内容传递给 New-AzureRmResourceGroupDeployment
时做错了什么。那或者实际上不可能做我想做的事。
P.S.
get-command New-AzureRmResourceGroupDeployment
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet New-AzureRmResourceGroupDeployment 4.1.0 AzureRM.Resources
首先,您所做的一切毫无意义,话虽如此,让我们尽力帮助您。
- 尝试飞溅。所以
New-AzureRmResourceGroupDeployment ... @TemplateParameters
而不是你在做什么。 (不知道,但根据我的经验,它以某种方式工作得更好)
- 如果这直接不起作用,请尝试将您的嵌套模板简化到最低限度,看看是否可行,如果可行,请检查您的嵌套模板是否正常。
- 尝试使用
-Debug
开关创建一个部署,看看结果如何。
- 使用 Azure Cli 尝试相同的部署(也许它以正确的方式将 json 转换为输入对象)
- 跳过项目 1-4 并以正确的方式进行。我建议永远不要 preprocessing\in 飞行生成 ARM 模板。如果您足够
聪明 够hacky,它们已经具备足够的功能来完成任何事情。我不知道你想要达到什么目的,但我可以用我的生命来打赌你不需要你试图创造的怪物
小模板示例:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"resources": []
}
编辑: 我进一步研究并找到了解决方案。一种方法是使用 arm 模板的 json()
函数,该函数接受字符串并转换为有效的 json.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"inp": {
"type": "string"
}
},
"resources": [
{
"name": "NestedDeployment1",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2015-01-01",
"properties": {
"mode": "Incremental",
"template": "[json(parameters('inp'))]",
"parameters": {}
}
}
]
}
要部署使用这样的东西:
New-AzureRmResourceGroupDeployment ... -inp ((get-content path\to.json -raw) -replace '\s','')
# we minify the string so it gets properly converted to json
这有点 hack,但问题在于 powershell 如何将您的输入转换为它传递给模板的内容,而您无法真正控制它。
另一种方法:(如果您需要输出,您可以添加另一个参数)
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"input-param": {
"type": "object"
},
"input-resource": {
"type": "array"
}
},
"resources": [
{
"name": "NestedDeployment1",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2015-01-01",
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": "[parameters('input-param')]",
"resource": "[parameters('input-resource')]"
},
"parameters": {}
}
}
]
}
并像这样部署:
New-AzureRmResourceGroupDeployment -ResourceGroupName zzz -TemplateFile path\to.json -input-param @{...} -input-resource @(...)
ps。别介意沃尔特,每次他说某事无法完成或不可能时,它实际上是可能的。
为了让生活更轻松(在长 运行 中),我尝试使用 properties.template,而不是有据可查的 properties.templateLink.前者通过将 child.json 模板文件的内容作为模板参数传递到 parent.json 模板中,几乎没有文档。
来自 Microsoft.Resources/deployments 的 MS 文档:
The template content. You use this element when you want to pass the template syntax directly in the request rather than link to an existing template. It can be a JObject or well-formed JSON string. Use either the templateLink property or the template property, but not both.
在我的父模板中,我声明参数 childTemplates
并在 properties.template 中引用它:
"parameters": {
"childTemplates": {
"type": "object",
"metadata": {
"description": "Child template"
}
}
}
other stuff...
"resources": [
{
"name": "[concat('linkedTemplate-VM-Net-',copyIndex(1))]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2017-06-01",
"dependsOn": [],
"copy": {
"name": "interate",
"count": "[parameters('vmQty')]"
},
"properties": {
"mode": "Incremental",
"template": "[parameters('childTemplates')]",
"parameters": {
"sharedVariables": { "value": "[variables('sharedVariables')]" },
"sharedTemplate": { "value": "[variables('sharedTemplate')]" },
"artifactsLocationSasToken": { "value": "[parameters('artifactsLocationSasToken')]" },
"adminPassword": { "value": "[parameters('adminPassword')]" },
"copyIndexValue": { "value": "[copyIndex(1)]" }
},
"debugSetting": {
"detailLevel": "both"
}
}
}
],
然后我将子模板传递给 New-AzureRmResourceGroupDeployment -TemplateParameterObject
以部署父模板:
$TemplateFileLocation = "C:\Temp\templates\parent.json"
$JsonChildTemplate = Get-Content -Raw (Join-Path ($TemplateFileLocation | Split-Path -Parent) "nestedtemplates\child.json") | ConvertFrom-Json
$TemplateParameters = @{
childTemplates = $JsonChildTemplate
...Other parameters...
}
New-AzureRmResourceGroupDeployment -TemplateParameterObject $TemplateParameters
这会产生以下错误:
Code : InvalidTemplate
Message : The nested deployment 'linkedTemplate-VM-Net-1' failed validation: 'Required property '$schema' not found in JSON. Path 'properties.template'.'.
Target :
Details :
如果我查看 $JsonChildTemplate
,它会给我:
$schema : https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#
contentVersion : 1.0.0.0
parameters : @{sharedVariables=; sharedTemplate=; vhdStorageAccountName=; artifactsLocationSasToken=; adminPassword=; copyIndexValue=}
variables : @{seqNo=[padleft(add(parameters('copyIndexValue'),3),3,'0')]; nicName=[concat('NIC-',parameters('sharedVariables').role,'-', variables('seqNo'),'-01')];
subnetRef=[parameters('sharedVariables').network.subnetRef]; ipConfigName=[concat('ipconfig-', variables('seqNo'))]}
resources : {@{apiVersion=2016-03-30; type=Microsoft.Network/networkInterfaces; name=[variables('nicName')]; location=[resourceGroup().location]; tags=; dependsOn=System.Object[];
properties=}}
outputs : @{nicObject=; vmPrivateIp=; vmNameSuffix=; vmPrivateIpArray=}
对我来说,$schema
就在那里。
我也试过删除 | ConvertFrom-Json
,但出现同样的错误。
上面,我展示的是最新的 API 版本,但我已经尝试过其他版本,例如 2016-09-01,以防出现错误。
在寻找解决方案的过程中,我在 GitHub 上发现了 this 个问题。建议是删除 $schema
和 contentVersion
,尽管这会导致错误。我尝试了以下方法:
Function Get-ChildTemplate
{
$TemplateFileLocation = "C:\Temp\templates\nestedtemplates\child.json"
$json = Get-Content -Raw -Path $TemplateFileLocation | ConvertFrom-Json
$NewJson = @()
$NewJson += $json.parameters
$NewJson += $json.variables
$NewJson += $json.resources
$NewJson += $json.outputs
Return $NewJson | ConvertTo-Json
}
$JsonChildTemplate = Get-ChildTemplate
$TemplateParameters = @{
childTemplates = $JsonChildTemplate
...Other parameters...
}
$JsonChildTemplate
returns:
[
{
"sharedVariables": {
"type": "object",
"metadata": "@{description=Object of variables from master template}"
}...
我的猜测是我在将 child.json 的内容传递给 New-AzureRmResourceGroupDeployment
时做错了什么。那或者实际上不可能做我想做的事。
P.S.
get-command New-AzureRmResourceGroupDeployment
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet New-AzureRmResourceGroupDeployment 4.1.0 AzureRM.Resources
首先,您所做的一切毫无意义,话虽如此,让我们尽力帮助您。
- 尝试飞溅。所以
New-AzureRmResourceGroupDeployment ... @TemplateParameters
而不是你在做什么。 (不知道,但根据我的经验,它以某种方式工作得更好) - 如果这直接不起作用,请尝试将您的嵌套模板简化到最低限度,看看是否可行,如果可行,请检查您的嵌套模板是否正常。
- 尝试使用
-Debug
开关创建一个部署,看看结果如何。 - 使用 Azure Cli 尝试相同的部署(也许它以正确的方式将 json 转换为输入对象)
- 跳过项目 1-4 并以正确的方式进行。我建议永远不要 preprocessing\in 飞行生成 ARM 模板。如果您足够
聪明够hacky,它们已经具备足够的功能来完成任何事情。我不知道你想要达到什么目的,但我可以用我的生命来打赌你不需要你试图创造的怪物
小模板示例:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"resources": []
}
编辑: 我进一步研究并找到了解决方案。一种方法是使用 arm 模板的 json()
函数,该函数接受字符串并转换为有效的 json.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"inp": {
"type": "string"
}
},
"resources": [
{
"name": "NestedDeployment1",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2015-01-01",
"properties": {
"mode": "Incremental",
"template": "[json(parameters('inp'))]",
"parameters": {}
}
}
]
}
要部署使用这样的东西:
New-AzureRmResourceGroupDeployment ... -inp ((get-content path\to.json -raw) -replace '\s','')
# we minify the string so it gets properly converted to json
这有点 hack,但问题在于 powershell 如何将您的输入转换为它传递给模板的内容,而您无法真正控制它。
另一种方法:(如果您需要输出,您可以添加另一个参数)
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"input-param": {
"type": "object"
},
"input-resource": {
"type": "array"
}
},
"resources": [
{
"name": "NestedDeployment1",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2015-01-01",
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": "[parameters('input-param')]",
"resource": "[parameters('input-resource')]"
},
"parameters": {}
}
}
]
}
并像这样部署:
New-AzureRmResourceGroupDeployment -ResourceGroupName zzz -TemplateFile path\to.json -input-param @{...} -input-resource @(...)
ps。别介意沃尔特,每次他说某事无法完成或不可能时,它实际上是可能的。