Azure ARM模板如何对多个部分使用复制

时间:2019-01-10 07:30:52

标签: azure arm-template azureportal azure-template

我有一个找不到解决方案的问题,那就是当我尝试使用复制在仪表板ARM模板中动态创建多个零件时。

当我尝试在其中一个键中使用“ [copyIndex()]”时收到错误消息,从错误消息中了解到这是行不通的。但是我不确定如何解决该问题,因此任何想法都会受到赞赏。

"[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": {},
        ...

用于创建仪表板的结构如下

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

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

解决此问题的方法是删除复制功能并复制代码,但是由于我需要对它们进行硬编码,因此我很难将其与任何给定数量的“位置”一起使用。

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

enter image description here

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

更新

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

parameters.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]"
    }
  }
}

deploy.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}"
    }
  }
}

更新2

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

parameters.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]"
    }
  }
}

deploy.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]"
    }
  }
}

collector.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'))]"
    }
  }
}

transform.json

{{1}}

1 个答案:

答案 0 :(得分: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)构造它,并将其作为参数传递给tempate