使用模板规范时 ARM 模板中的默认值

Default Values in ARM templates when using Template Specs

不久前,我们已经为 Azure 的 ARM 部署实施了模板规范,我们通过这样做大大减少了工作量。我们要实现的下一件事是开始在模板规范中实现默认值,因此我们不必在参数文件中指定所有项目中相同的所有参数。如果我们确实想覆盖默认值,我们当然可以在参数文件中指定参数。

我们过去已经使用模板和参数文件处理过这个问题,但我无法让它与模板规范一起使用。

例如,我正在尝试部署这样的应用服务计划:

模板规范:

{
    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "appServicePlanSettings": {
            "type": "object",
            "defaultValue": {
                "isHypervContainerPlan": false
            }
        },
        "resourceNameAndTagSettings": {
            "type": "object"
        }
    },
    "variables": {
        "appServicePlanName": "[concat('o', parameters('appServicePlanSettings').nameAbbr, parameters('resourceNameAndTagSettings').environmentType, parameters('resourceNameAndTagSettings').resourceGroupNumber, parameters('resourceNameAndTagSettings').solutionNameAbbr, parameters('resourceNameAndTagSettings').locationAbbr)]"
    },
    "resources": [
        {
            "comments": "App Service Plans",
            "condition": "[parameters('appServicePlanSettings').deploy]",
            "apiVersion": "2020-09-01",
            "type": "Microsoft.Web/serverfarms",
            "name": "[variables('appServicePlanName')]",
            "location": "[resourceGroup().location]",
            "tags": {
                "_Purpose": "[parameters('appServicePlanSettings').tagValuePurpose]",
                "CostCenter": "[parameters('resourceNameAndTagSettings').tagValueCostCenter]",
                "EnvironmentType": "[parameters('resourceNameAndTagSettings').tagValueEnvironmentType]",
                "Owner": "[parameters('resourceNameAndTagSettings').tagValueOwner]"
            },
            "kind": "[parameters('appServicePlanSettings').kind]",
            "sku": {
                "name": "[parameters('appServicePlanSettings').sku]",
                "size": "[parameters('appServicePlanSettings').sku]",
                "tier": "[parameters('appServicePlanSettings').skuTier]"
            },
            "properties": {
                "hyperV": "[parameters('appServicePlanSettings').isHypervContainerPlan]",
                "perSiteScaling": "[parameters('appServicePlanSettings').perSiteScaling]",
                "reserved": "[parameters('appServicePlanSettings').isLinuxOS]"
            },
            "dependsOn": []
        }
    ],
    "outputs": {}
}

主模板:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "appServicePlanSettings": {
            "type": "array"
        },
        "dateTime": {
            "type": "string",
            "defaultValue": "[utcNow()]"
        },
        "resourceNameAndTagSettings": {
            "type": "object"
        },
        "templateSpecSettings": {
            "type": "object"
        }
    },
    "resources": [
        {
            "comments": "Apps - App Service Plans",
            "type": "Microsoft.Resources/deployments",
            "apiVersion": "2020-06-01",
            "name": "[concat('Deploy-', parameters('appServicePlanSettings')[copyIndex()].nameAbbr, parameters('resourceNameAndTagSettings').environmentType, parameters('resourceNameAndTagSettings').resourceGroupNumber, parameters('resourceNameAndTagSettings').solutionNameAbbr, parameters('resourceNameAndTagSettings').locationAbbr, '-', parameters('dateTime'))]",
            "copy": {
                "name": "appServicePlanCopy",
                "count": "[length(parameters('appServicePlanSettings'))]"
            },
            "properties": {
                "mode": "Incremental",
                "templateLink": {
                    "id": "[concat('/subscriptions/', parameters('templateSpecSettings').templateSpecSubscriptionId, '/resourceGroups/', parameters('templateSpecSettings').templateSpecResourceGroupName, '/providers/Microsoft.Resources/TemplateSpecs/', parameters('templateSpecSettings').appServicePlan.name, '/versions/', parameters('templateSpecSettings').appServicePlan.version)]"
                },
                "parameters": {
                    "appServicePlanSettings": {
                        "value": "[parameters('appServicePlanSettings')[copyIndex()]]"
                    },
                    "resourceNameAndTagSettings": {
                        "value": "[parameters('resourceNameAndTagSettings')]"
                    }
                }
            },
            "dependsOn": []
        }
    ],
    "outputs": {}
}

参数文件:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "appServicePlanSettings": {
            "value": [
                {
                    "comments": "App Service Plan 1",
                    "deploy": true,
                    "nameAbbr": "Asp",
                    "isLinuxOS": false,
                    "isHypervContainerPlan": false,
                    "perSiteScaling": false,
                    "tagValuePurpose": "Test",
                    "kind": "app",
                    "sku": "P1v2",
                    "skuTier": "PremiumV2"
                }
            ]
        },
        "resourceNameAndTagSettings": {
            "value": {
                "environmentType": "dev",
                "locationAbbr": "europe",
                "resourceGroupNumber": "001",
                "solutionNameAbbr": "test",
                "tagValueCostCenter": "123",
                "tagValueEnvironmentType": "Development",
                "tagValueOwner": "me"
            }
        },
        "templateSpecSettings": {
            "value": {
                "templateSpecResourceGroupName": "XXX",
                "templateSpecSubscriptionId": "XXX",
                "appServicePlan": {
                    "name": "appServicePlanTest",
                    "version": "1.2"
                }
            }
        }
    }
}

这部署得很好。

但如果我遗漏了:

"isHypervContainerPlan": false,

在参数文件中,部署将失败并显示此消息:

Unable to process template language expressions for resource '...' at line '24' and column '9'. 'The language expression property 'isHypervContainerPlan' doesn't exist, available properties are 'comments, deploy, nameAbbr, isLinuxOS, perSiteScaling, tagValuePurpose, kind, sku, skuTier'.

如果在模板规范参数部分设置了默认值,为什么会出现此错误? 我在这里遗漏了什么或者模板规范不支持默认值?

参数的默认值仅在未提供值时使用。换句话说,您可以使用参数的默认值或提供一个值,而不是两者,也不是两者的任何组合。

您的 templateSpec 需要一个用于 appServicePlanSettings 参数的复杂对象。该对象需要具有被部署的 serverFarm 资源引用的所有属性。您为该参数提供了一个值,但您也省略了该参数的一个属性,这就是错误消息中标记的 属性。

要以另一种方式查看此操作,请将 属性 放回您的参数文件并删除另一个参数文件,您会看到类似的错误...或者您可以不提供参数``appServicePlanSettings``` 的所有值,然后将使用默认值。

我一直在使用 'defaultValue' 进行测试。 我也用这个设置测试过:

模板:

{
    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "appServicePlanSettings": {
            "type": "object",
            "defaultValue": {
                "isHypervContainerPlan": false,
                "isLinuxOS": false,
                "perSiteScaling": false
            }
        },
        "resourceNameAndTagSettings": {
            "type": "object"
        }
    },
    "variables": {
        "appServicePlanName": "[concat('o', parameters('appServicePlanSettings').nameAbbr, parameters('resourceNameAndTagSettings').environmentType, parameters('resourceNameAndTagSettings').resourceGroupNumber, parameters('resourceNameAndTagSettings').solutionNameAbbr, parameters('resourceNameAndTagSettings').locationAbbr)]"
    },
    "resources": [
        {
            "comments": "App Service Plans",
            "condition": "[parameters('appServicePlanSettings').deploy]",
            "apiVersion": "2020-09-01",
            "type": "Microsoft.Web/serverfarms",
            "name": "[variables('appServicePlanName')]",
            "location": "[resourceGroup().location]",
            "tags": {
                "_Purpose": "[parameters('appServicePlanSettings').tagValuePurpose]",
                "CostCenter": "[parameters('resourceNameAndTagSettings').tagValueCostCenter]",
                "EnvironmentType": "[parameters('resourceNameAndTagSettings').tagValueEnvironmentType]",
                "Owner": "[parameters('resourceNameAndTagSettings').tagValueOwner]"
            },
            "kind": "[parameters('appServicePlanSettings').kind]",
            "sku": {
                "name": "[parameters('appServicePlanSettings').sku]",
                "size": "[parameters('appServicePlanSettings').sku]",
                "tier": "[parameters('appServicePlanSettings').skuTier]"
            },
            "properties": {
                "hyperV": "[parameters('appServicePlanSettings').isHypervContainerPlan]",
                "perSiteScaling": "[parameters('appServicePlanSettings').perSiteScaling]",
                "reserved": "[parameters('appServicePlanSettings').isLinuxOS]"
            },
            "dependsOn": []
        }
    ],
    "outputs": {}
}

参数:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "appServicePlanSettings": {
            "value":    {
                    "comments": "App Service Plan 1",
                    "deploy": true,
                    "nameAbbr": "Asp",
                    "isLinuxOS": "",
                    "isHypervContainerPlan": "",
                    "perSiteScaling": "",
                    "tagValuePurpose": "Test",
                    "kind": "app",
                    "sku": "P1v2",
                    "skuTier": "PremiumV2"
                }
        },
        "resourceNameAndTagSettings": {
            "value": {
                "environmentType": "dev",
                "locationAbbr": "europe",
                "resourceGroupNumber": "001",
                "solutionNameAbbr": "test",
                "tagValueCostCenter": "123",
                "tagValueEnvironmentType": "Development",
                "tagValueOwner": "me"
            }
        },
        "templateSpecSettings": {
            "value": {
                "templateSpecResourceGroupName": "oGen1Weu1PrdMng001",
                "templateSpecSubscriptionId": "130176f8-513a-4869-9db3-7c46d0e25159",
                "appServicePlan": {
                    "name": "appServicePlanTest",
                    "version": "1.2"
                }
            }
        }
    }
}

当我没有在参数文件中指定“isHypervContainerPlan”时,这也不起作用,我认为我们对此进行了测试,但显然不够好...

唯一有效的是定义:

"isHypervContainerPlan": "",

在参数文件中,因此未指定值。这是不可取的,因为即使我不想覆盖默认值,仍然必须定义所有参数。

所以,最后的解决方案变成了下面(主模板不变):

模板规格:

{
    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "appServicePlanSettings": {
            "type": "object"
        },
        "resourceNameAndTagSettings": {
            "type": "object"
        }
    },
    "variables": {
        "appServicePlanName": "[concat('o', parameters('appServicePlanSettings').nameAbbr, parameters('resourceNameAndTagSettings').environmentType, parameters('resourceNameAndTagSettings').resourceGroupNumber, parameters('resourceNameAndTagSettings').solutionNameAbbr, parameters('resourceNameAndTagSettings').locationAbbr)]",
        "appServicePlanSettings": {
            "isHypervContainerPlan": false,
            "isLinuxOS": false,
            "kind": "app",
            "nameAbbr": "Asp",
            "perSiteScaling": false
        }
    },
    "resources": [
        {
            "comments": "App Service Plans",
            "condition": "[parameters('appServicePlanSettings').deploy]",
            "apiVersion": "2020-09-01",
            "type": "Microsoft.Web/serverfarms",
            "name": "[variables('appServicePlanName')]",
            "location": "[resourceGroup().location]",
            "tags": {
                "_Purpose": "[parameters('appServicePlanSettings').tagValuePurpose]",
                "CostCenter": "[parameters('resourceNameAndTagSettings').tagValueCostCenter]",
                "EnvironmentType": "[parameters('resourceNameAndTagSettings').tagValueEnvironmentType]",
                "Owner": "[parameters('resourceNameAndTagSettings').tagValueOwner]"
            },
            "kind": "[if(contains(parameters('appServicePlanSettings'), 'kind'), parameters('appServicePlanSettings').kind, variables('appServicePlanSettings').kind)]",
            "sku": {
                "name": "[parameters('appServicePlanSettings').sku]",
                "size": "[parameters('appServicePlanSettings').sku]",
                "tier": "[parameters('appServicePlanSettings').skuTier]"
            },
            "properties": {
                "hyperV": "[if(contains(parameters('appServicePlanSettings'), 'isHypervContainerPlan'), parameters('appServicePlanSettings').isHypervContainerPlan, variables('appServicePlanSettings').isHypervContainerPlan)]",
                "perSiteScaling": "[if(contains(parameters('appServicePlanSettings'), 'perSiteScaling'), parameters('appServicePlanSettings').perSiteScaling, variables('appServicePlanSettings').perSiteScaling)]",
                "reserved": "[if(contains(parameters('appServicePlanSettings'), 'isLinuxOS'), parameters('appServicePlanSettings').isLinuxOS, variables('appServicePlanSettings').isLinuxOS)]"
            },
            "dependsOn": []
        }
    ],
    "outputs": {}
}

如果我现在不在参数文件中指定这些值,将使用在变量部分配置的值:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "appServicePlanSettings": {
            "value": [
                {
                    "comments": "App Service Plan 1",
                    "deploy": true,
                    "nameAbbr": "Asp",
                    "tagValuePurpose": "Test",
                    "kind": "app",
                    "sku": "P1v2",
                    "skuTier": "PremiumV2"
                }
            ]
        },
        "resourceNameAndTagSettings": {
            "value": {
                "environmentType": "dev",
                "locationAbbr": "europe",
                "resourceGroupNumber": "001",
                "solutionNameAbbr": "test",
                "tagValueCostCenter": "123",
                "tagValueEnvironmentType": "Development",
                "tagValueOwner": "me"
            }
        },
        "templateSpecSettings": {
            "value": {
                "templateSpecResourceGroupName": "XXX",
                "templateSpecSubscriptionId": "XXX",
                "appServicePlan": {
                    "name": "appServicePlanTest",
                    "version": "1.2"
                }
            }
        }
    }
}