在PowerShell中使用模板元素

在PowerShell中使用模板元素

本文介绍了Azure嵌套模板部署:在PowerShell中使用模板元素(而非templateLink)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了使生活更轻松(从长远来看),我正在尝试使用properties.template,而不是有据可查的properties.templateLink.前者通过将child.json模板文件的内容作为模板的参数传递到parent.json模板中的文档很少.

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.

Microsoft.Resources/deployments :

在父模板中,我声明参数 childTemplates 并在properties.template中引用它:

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"
      }
    }
  }
],

然后我将子模板传递给 New-AzureRmResourceGroupDeployment -TemplateParameterObject 来部署父模板:

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

这会产生以下错误:

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 ,它会给我:

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=}

对我来说,看起来像是 $ schema .

To me, it looks like the $schema is there.

我也尝试过删除 |发生相同错误的ConvertFrom-Json .

以上,我正在显示最新的API版本,但是我尝试与其他应用程序一起使用,例如2016-09-01,以防万一有错误.

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.

在寻找解决方案时,我发现了在GitHub上发布.建议删除 $ schema contentVersion ,尽管这在遇到错误时仍然有效.我尝试了以下方法:

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 返回:

[
    {
        "sharedVariables":  {
                                "type":  "object",
                                "metadata":  "@{description=Object of variables from master template}"
                            }...

我的猜测是我将child.json的内容传递给 New-AzureRmResourceGroupDeployment 时做错了.那或者实际上不可能做我想做的事.

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

推荐答案

首先,您正在做的事情使0有意义,也就是说,可以帮助您.

First of all, what you are doing makes 0 sense what so ever, that being said, lets try to help you.

  1. 尝试喷溅.因此,请执行 New-AzureRmResourceGroupDeployment ... @TemplateParameters 而不是您正在执行的操作.(不知道,但是根据我的经验,它可以更好地工作)
  2. 如果这不能直接起作用,请尝试将嵌套模板简化到最低限度,然后查看它是否可以正常工作,请检查嵌套模板是否正常.
  3. 尝试使用 -Debug 开关创建部署,然后查看部署的方向.
  4. 使用Azure Cli尝试相同的部署(也许它以正确的方式将json转换为输入对象)
  5. 跳过项目1-4,并以正确的方式进行操作.我建议不要在ARM模板的生成过程中进行预处理.如果您足够聪明,它们已经具有足够的功能来完成任何事情.我不知道您要达到什么目标,但我可以打赌,您不需要试图制造的怪异
  1. Try splatting. so do New-AzureRmResourceGroupDeployment ... @TemplateParameters instead of what you are doing. (no idea, but somehow it works better in my experience)
  2. 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.
  3. Try creating a deployment with -Debug switch and see where that goes.
  4. Try the same deployment using Azure Cli (maybe it converts json to input object in a proper way)
  5. 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 hacky 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

小模板示例:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {},
    "resources": []
}

编辑:我再挖了一点,找到了解决方案.一种方法是使用arm模板的 json()函数,该函数接受一个字符串并将其转换为有效的json.

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

这有点麻烦,但是问题在于powershell如何将您的输入转换为传递给模板的内容,而您无法真正控制它.

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": {}
            }
        }
    ]
}

并像这样部署:

New-AzureRmResourceGroupDeployment -ResourceGroupName zzz -TemplateFile path\to.json -input-param @{...} -input-resource @(...)

ps.不要介意沃尔特,每次他说无法做或不可能做某事时,实际上都是可能的.

ps. don't mind walter, each time he says something can't be done or is impossible it actually is possible.

这篇关于Azure嵌套模板部署:在PowerShell中使用模板元素(而非templateLink)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 18:51