问题
In an attempt to make life easier (in the long run), I'm trying to use properties.template, as opposed to the well documented properties.templateLink. The former has very little documentation by passing the contents of child.json template file into the parent.json template, as a template' parameter.
From the MS documentation for Microsoft.Resources/deployments:
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.
In my parent template, I am declaring the parameter childTemplates
and referencing it in 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"
}
}
}
],
I then pass the child template to New-AzureRmResourceGroupDeployment -TemplateParameterObject
to deploy the parent template:
$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
This produces the following error:
Code : InvalidTemplate
Message : The nested deployment 'linkedTemplate-VM-Net-1' failed validation: 'Required property '$schema' not found in JSON. Path 'properties.template'.'.
Target :
Details :
If I look at $JsonChildTemplate
, it gives me:
$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=}
To me, it looks like the $schema
is there.
I have also tried removing | ConvertFrom-Json
with the same error.
Above, I am showing the latest API version, but I have tried with others such as 2016-09-01, just in case there's a bug.
In my search for a solution, I found this issue on GitHub. The recomendation is to remove $schema
and contentVersion
, although this flies in the face of the error. I tried this with the following:
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}"
}...
My guess is that I have done something wrong passing child.json's contents to New-AzureRmResourceGroupDeployment
. That or it's not actually possible to do what I'm trying to do.
P.S.
get-command New-AzureRmResourceGroupDeployment
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet New-AzureRmResourceGroupDeployment 4.1.0 AzureRM.Resources
回答1:
First of all, what you are doing makes 0 sense what so ever, that being said, lets try to help you.
- Try splatting. so do
New-AzureRmResourceGroupDeployment ... @TemplateParameters
instead of what you are doing. (no idea, but somehow it works better in my experience) - If that doesn't work directly try simplifying you nested template to the bare minimum and see if it works if it does, check if your nested template is fine.
- Try creating a deployment with
-Debug
switch and see where that goes. - Try the same deployment using Azure Cli (maybe it converts json to input object in a proper way)
- Skip items 1-4 and do it the proper way. I would advice never do preprocessing\in flight generation of ARM Templates. They have enough of features already to accomplish anything if you are
smarthacky enough. I have no idea what you are trying to achieve but I can bet my life on it you don't need that monstrosity you are trying to create
small template example:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"resources": []
}
EDIT: I dug a bit more and found a solution. one way to do it would be using the json()
function of the arm template that accepts a string and converts to valid 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": {}
}
}
]
}
To deploy use something like this:
New-AzureRmResourceGroupDeployment ... -inp ((get-content path\to.json -raw) -replace '\s','')
# we minify the string so it gets properly converted to json
This is a bit of a hack, but the problem lies with how powershell converts your input to what it passes to the template, and you cannot really control that.
Another way to do that: (if you need output you can add another parameter)
{
"$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": {}
}
}
]
}
and deploying like so:
New-AzureRmResourceGroupDeployment -ResourceGroupName zzz -TemplateFile path\to.json -input-param @{...} -input-resource @(...)
ps. don't mind walter, each time he says something can't be done or is impossible it actually is possible.
来源:https://stackoverflow.com/questions/45496528/azure-nested-template-deployment-using-template-element-not-templatelink-with