【问题标题】:Azure ARM template how to use copy for multiple partsAzure ARM 模板如何将副本用于多个部分
【发布时间】:2019-01-10 07:30:51
【问题描述】:

我有一个找不到解决方案的问题,我尝试使用副本在我的仪表板 ARM 模板中动态创建多个部分。

当我尝试在其中一个键中使用“[copyIndex()]”时出现错误,正如我从错误消息中了解到的那样,这将不起作用。但我不确定如何解决这个问题,所以任何想法都将不胜感激。

"copy": [
  {
    "name": "servers",
    "count": "[length(parameters('locationKeys'))]",
    "input": {
      "[copyIndex('servers')]": {
        "position": {
          "x": "[mul(copyIndex('servers'), 4)]",
          "y": 1,
          "colSpan": 2,
          "rowSpan": 1
        }
      }
    }
  }
]

正如您在上面的示例中看到的,这就是失败的原因

"[copyIndex('servers')]": {

我得到了这个错误

Error: Code=InvalidTemplate; Message=Deployment template validation failed: 
'Can not add Newtonsoft.Json.Linq.JValue to Newtonsoft.Json.Linq.JObject.'.

创建仪表板的结构如下所示

"properties": {
  "lenses": {
    "0": {
      "order": 0,
      "parts": {
        "0": {},
        "1": {},
        ...

我在“parts”键下有复制功能。

解决这个问题的方法是删除复制功能并复制代码,但是我很难让它与任何给定数量的“位置”一起工作,因为我需要对它们进行硬编码。

基本上这就是我最终想要得到的。

有没有其他好的解决方案来解决这个问题?

更新

这是我从管道中的 Azure DevOps 任务中引用的两个模板。请注意,我现在需要执行 parameters('locationKeys')[0] 并复制所有块,而不是使用 parameters('locationKeys')[copyIndex()] 进行复制。

parameters.json

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "locationNames": {
      "value": "#{locationNames}"
    }
  }
}

部署.json

{
  "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "appName": {
      "type": "string",
      "defaultValue" : "myApp"
    },
    "locationNames": {
      "type": "array"
    }
  },
  "variables": {
    "dashboardName": "[concat(parameters('appName'), '-dashboard')]"
  },
  "resources": [
    {
      "name": "[variables('dashboardName')]",
      "type": "Microsoft.Portal/dashboards",
      "apiVersion": "2015-08-01-preview",
      "location": "westeurope",
      "tags": {
        "hidden-title": "24/7 Operations"
      },
      "properties": {
        "lenses": {
          "0": {
            "order": 0,
            "parts": {
              "0": {
                "position": {
                  "x": 0,
                  "y": 0,
                  "colSpan": 4,
                  "rowSpan": 1
                },
                "metadata": {
                  "inputs": [],
                  "type": "Extension/HubsExtension/PartType/MarkdownPart",
                  "settings": {
                    "content": {
                      "settings": {
                        "content": "[concat('# ', parameters('locationNames')[0])]",
                        "title": "",
                        "subtitle": ""
                      }
                    }
                  }
                }
              },
              "1": {
                "position": {
                  "x": 4,
                  "y": 0,
                  "colSpan": 4,
                  "rowSpan": 1
                },
                "metadata": {
                  "inputs": [],
                  "type": "Extension/HubsExtension/PartType/MarkdownPart",
                  "settings": {
                    "content": {
                      "settings": {
                        "content": "[concat('# ', parameters('locationNames')[1])]",
                        "title": "",
                        "subtitle": ""
                      }
                    }
                  }
                }
              },
              "2": {
                "position": {
                  "x": 8,
                  "y": 0,
                  "colSpan": 4,
                  "rowSpan": 1
                },
                "metadata": {
                  "inputs": [],
                  "type": "Extension/HubsExtension/PartType/MarkdownPart",
                  "settings": {
                    "content": {
                      "settings": {
                        "content": "[concat('# ', parameters('locationNames')[2])]",
                        "title": "",
                        "subtitle": ""
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "dependsOn": []
    }
  ],
  "outputs": {
    "resourceGroupId": {
      "type": "string",
      "value": "[resourceGroup().id]"
    }
  }
}

更新 2

这是使用对象而不是数组的工作示例。我通过将 collector.json 和 transform.json 上传到 http://myjson.com 并在运行部署时将它们作为属性包含在本地使用 PowerShell 进行了验证。

parameters.json

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "azureEnvironment": {
      "value": "#{azureEnvironment}"
    },
    "locationKeys": {
      "value": "#{locationKeys}"
    },
    "locationNames": {
      "value": "#{locationNames}"
    },
    "transformTemplateLink": {
      "value": "#{transform}"
    },
    "collectorTemplateLink": {
      "value": "#{collector}"
    }
  }
}

部署.json

{
  "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "appName": {
      "type": "string",
      "defaultValue": "myApp"
    },
    "azureEnvironment": {
      "type": "string"
    },
    "locationKeys": {
      "type": "array"
    },
    "locationNames": {
      "type": "array"
    },
    "transformTemplateLink": {
      "type": "string",
      "defaultValue": "[uri(deployment().properties.templateLink.uri, 'transform.json')]"
    },
    "collectorTemplateLink": {
      "type": "string",
      "defaultValue": "[uri(deployment().properties.templateLink.uri, 'collector.json')]"
    }
  },
  "resources": [
    {
      "apiVersion": "2015-01-01",
      "name": "collector",
      "type": "Microsoft.Resources/deployments",
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri": "[parameters('collectorTemplateLink')]",
          "contentVersion": "1.0.0.0"
        },
        "parameters": {
          "transformTemplateUri": {
            "value": "[parameters('transformTemplateLink')]"
          },
          "locationNames": {
            "value": "[parameters('locationNames')]"
          }
        }
      }
    },
    {
      "name": "[concat(parameters('appName'), '-dash-', parameters('azureEnvironment'))]",
      "type": "Microsoft.Portal/dashboards",
      "apiVersion": "2015-08-01-preview",
      "location": "westeurope",
      "tags": {
        "hidden-title": "[concat('24/7 Operations - (', parameters('azureEnvironment'), ')')]"
      },
      "properties": {
        "lenses": {
          "0": {
            "order": 0,
            "parts": "[reference('collector').outputs.result.value]"
          }
        }
      },
      "dependsOn": [
        "collector"
      ]
    }
  ],
  "outputs": {
    "resourceGroupId": {
      "type": "string",
      "value": "[resourceGroup().id]"
    }
  }
}

collector.json

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "transformTemplateUri": {
      "type": "string"
    },
    "locationNames": {
      "type": "array"
    }
  },
  "variables": {
    "count": "[length(parameters('locationNames'))]"
  },
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2015-01-01",
      "name": "loop-0",
      "properties": {
        "mode": "Incremental",
        "parameters": {},
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {},
          "variables": {},
          "resources": [],
          "outputs": {
            "collection": {
              "type": "object",
              "value": {}
            }
          }
        }
      }
    },
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2015-01-01",
      "name": "[concat('loop-', copyIndex(1))]",
      "copy": {
        "name": "iterator",
        "count": "[variables('count')]",
        "mode": "serial"
      },
      "dependsOn": [
        "[concat('loop-', copyIndex())]"
      ],
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri": "[parameters('transformTemplateUri')]"
        },
        "parameters": {
          "state": {
            "value": "[reference(concat('loop-', copyIndex())).outputs.collection.value]"
          },
          "index": {
            "value": "[copyIndex()]"
          },
          "locationNames": {
            "value": "[parameters('locationNames')]"
          }
        }
      }
    }
  ],
  "outputs": {
    "result": {
      "type": "object",
      "value": "[reference(concat('loop-', variables('count'))).outputs.collection.value]"
    }
  }
}

transform.json

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "state": {
      "type": "object",
      "defaultValue": {}
    },
    "index": {
      "type": "int"
    },
    "locationNames": {
      "type": "array"
    }
  },
  "variables": {
    "instance": {
      "[string(parameters('index'))]": {
        "position": {
          "x": "[mul(parameters('index'), 4)]",
          "y": 0,
          "colSpan": 4,
          "rowSpan": 1
        },
        "metadata": {
          "inputs": [],
          "type": "Extension/HubsExtension/PartType/MarkdownPart",
          "settings": {
            "content": {
              "settings": {
                "content": "[concat('# ', parameters('locationNames')[parameters('index')])]",
                "title": "",
                "subtitle": ""
              }
            }
          }
        }
      }
    }
  },
  "resources": [],
  "outputs": {
    "collection": {
      "type": "object",
      "value": "[union(parameters('state'), variables('instance'))]"
    }
  }
}

【问题讨论】:

    标签: azure arm-template azureportal azure-template


    【解决方案1】:

    如果您只是在变量部分尝试相同(但经过简化)的方法,您会收到此错误:

    变量名不能是表达式。

    我认为这同样适用于任何地方,您不能使用表达式来计算属性名称,只能使用值。话虽如此,如果你想创建一个循环,你需要使用嵌套部署作为迭代器。您将在内部传递所需的部分\根据输入将它们组装到那里并创建一个结果数组:

    {
        "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
        "contentVersion": "1.0.0.0",
        "parameters": {},
        "variables": {
            "locations": [
                "eastus",
                "westeurope"
            ],
            "eastus": {
                "red": 1
            },
            "westeurope": {
                "blue": 2
            },
            "empty": []
        },
        "resources": [
            {
                "apiVersion": "2017-05-10",
                "name": "[concat('iterator-', copyIndex(1))]",
                "type": "Microsoft.Resources/deployments",
                "copy": {
                    "name": "someName",
                    "count": "[length(variables('locations'))]"
                },
                "properties": {
                    "mode": "Incremental",
                    "templateLink": {
                        "uri": "https://paste.ee/r/t5ca9/0"
                    },
                    "parameters": {
                        "source": {
                            "value": "[variables(variables('locations')[copyIndex()])]"
                        },
                        "state": {
                            "value": "[if(equals(copyIndex(), 0), variables('empty'), reference(concat('iterator-', copyIndex())).outputs.collection.value)]"
                        }
                    }
                }
            }
        ],
        "outputs": {
            "results": {
                "type": "array",
                "value": "[reference(concat('iterator-', string(length(variables('locations'))))).outputs.collection.value]"
            }
        } }
    

    你的迭代器看起来像这样:

    {
        "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
        "contentVersion": "1.0.0.0",
        "parameters": {
            "source": {
                "type": "object"
            },
            "state": {
                "type": "array",
                "defaultValue": []
            }
        },
        "resources": [],
        "outputs": {
            "collection": {
                "type": "array",
                "value": "[concat(array(parameters('source')), parameters('state'))]"
            }
        }
    }
    

    ps。该链接是临时的(1 个月),但您可以在任何地方上传迭代器模板,只需硬编码,它不包含任何秘密\不包含数据。 pps。更简单的方法 - 在模板(powershell\python\whatever)之外构建它并在模板内作为参数传递

    【讨论】:

    • 好的,谢谢,我会看看我是否可以让它为我正在尝试做的事情工作。
    • 这是我很长一段时间以来一直用来创建数组的方法,所以它会起作用,只需在你的脑海中概念化它;)
    • 我必须承认我在理解如何将它们组合在一起时遇到了一些困难,尤其是在我在上面的问题中向您展示的情况下。唯一的动态值是位置数组 ["location 1", "location 2", "location 3"]。从那里我想得到一个带有一些值的对象,其中 copyIndex() 作为每个条目的键。据我了解,所有这些都进入了deploymentTemplate,所以对于我的简单示例,我应该只管理一个文件,对吗?你有更完整的例子我可以看看吗?
    • 是的,它是您需要使用的嵌套模板(第三个 json sn-p)的链接。嵌套模板必须上传到某个地方。告诉我你是否需要更完整的例子?今天有时间我会回复你的
    • 这有点难以掌握,但您只需这样做:"parts" : "[reference(result_goes_here)"].so 您构造所需的数组,然后将其插入您需要的地方。你的例子看起来不错
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多