Azure ARM 内联如果不工作

Azure ARM Inline IF not working

我正在尝试通过 .json 模板构建 Azure VNET。

我正在尝试使用内联条件语句来创建第二个子网或跳过创建第二个子网。我认为我没有正确使用 json('null'),或者这是否可能。我的理解是,如果选择 json('null'),则不会选择任何内容。

感谢任何帮助!

"apiVersion": "2016-06-01",
"type": "Microsoft.Network/virtualNetworks",
"name": "My-VNET",
"location": "[resourceGroup().location]",
"properties": {
    "addressSpace": {
        "addressPrefixes": [
            "[parameters('virtualNetworkCIDR')]"
        ]
    },
    "subnets": [{
            "name": "[parameters('firstSubnetName')]",
            "properties": {
                "addressPrefix": "10.10.1.0/24"
            }
        }, {
            "name": "[if(equals(parameters('createSecondSubnet'), 'Yes'), parameters('secondSubnetName'), json('null'))]",
            "properties": {
                "addressPrefix": "10.10.2.0/24"
            }
        }
    ]
}

通常要在模板中有条件地创建资源,可以使用"Condition" 属性: https://docs.microsoft.com/en-us/azure/architecture/building-blocks/extending-templates/conditional-deploy

如果您想创建多个单一类型的资源,您可以使用"Copy" 属性:https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple#resource-iteration

不幸的是,子网没有条件或副本 属性,因为它们是 "Virtual Network" 资源的子资源。因此,整个 VNET 需要是有条件的,您可以指定多个 VNET,并且只部署其中的一个。 VNETS 也不能具有相同的名称,因此您需要在模板中指定多个 VNETS。

例如:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
    "NumberofSubnets": {
      "type": "string",
      "allowedValues": ["1","2"],
      "metadata": {
        "description": "would you like to deploy 1 or 2 subnets?"
      }
    }
    },
    "resources": [
        {
        "type": "Microsoft.Network/virtualNetworks",
        "apiVersion": "2016-06-01",
        "name": "My-VNET1",
        "location": "[resourceGroup().location]",
        "condition": "[equals(parameters('NumberofSubnets'), 1)]",
        "properties": {
            "addressSpace": {
            "addressPrefixes": ["10.10.0.0/23"]
            },
    "subnets": [{
            "name": "Subnet1",
            "properties": {
                "addressPrefix": "10.10.0.0/24"
            }
        }
        ]
        }
        },
        {
        "type": "Microsoft.Network/virtualNetworks",
        "apiVersion": "2016-06-01",
        "name": "My-VNET2",
        "location": "[resourceGroup().location]",
        "condition": "[equals(parameters('NumberofSubnets'), 2)]",
        "properties": {
            "addressSpace": {
            "addressPrefixes": ["10.10.0.0/23"]
            },
    "subnets": [{
            "name": "Subnet1",
            "properties": {
                "addressPrefix": "10.10.0.0/24"
            }
        },
        {
            "name": "Subnet2",
            "properties": {
                "addressPrefix": "10.10.1.0/24"
            }
        }
        ]
        }
        }
    ]
}

这将解决您的问题,但如果有大量子网,您会发现模板会变得非常乏味。

最好但最复杂的方法是使用链接模板。 This Repository shows how you can create a dynamic number of subnets using linked templates

我确定您不久前设法找到了某种解决方案...但是,我有一个解决方案可以很好地解决此类问题...它不使用条件语句不过

在 PowerShell 中创建一些 hash-tables 像这样...

# Resource group Hashtables.
$rgDev = @{
    Name = "DEV-RG"
    SubscriptionId = $subNonProd
    Location = "desiredregion"
}
$rgUat = @{
    Name = "UAT-RG"
    SubscriptionId = $subNonProd
    Location = "desiredregion"
}

#Vnet Hashtables
$vnetDev = @{
    ResourceGroup = $rgDev
    VnetName = "Dev-vnet"
    CIDR = @('x.x.x.x/27')
    Subnets = @(
             @{
                Name = "Dev-Web-subnet"
                CIDR = "y.y.y.y/28"
             },
             @{
                Name = "Dev-DB-subnet"
                CIDR = "z.z.z.z/28"
             })
}
$vnetUat = @{
    ResourceGroup = $rgUat
    VnetName = "UAT-vnet"
    CIDR = @('f.f.f.f/27')
    Subnets = @(
             @{
                Name = "UAT-Web-subnet"
                CIDR = "g.g.g.g/28"
             },
             @{
                Name = "UAT-DB-subnet"
                CIDR = "h.h.h.h/28"
             })
}

接下来,我将散列表集中到一个数组中,然后遍历整个地块。我有一个小脚本可以切换我的上下文,这样我就可以在一个 bootstrap 类型脚本中部署到多个订阅。

$vnets = @($vnetDev, $vnetUat)

ForEach ($vn in $vnets) {

    $deploymentName = $vn.VnetName + "_Deployment."

    .\SwitchSubscription.ps1 -subName $vn.ResourceGroup.SubscriptionName -subId $vn.ResourceGroup.SubscriptionId

    New-AzureRmResourceGroupDeployment  -Name $deploymentName `
                                        -ResourceGroupName $vn.ResourceGroup.Name `
                                        -TemplateFile .\JSONFiles\Vnets.json `
                                        -vnet $vn

}

ARM 模板的参数部分如下所示...

    "parameters": {        
        "vnet": {
            "type": "object",
        }
    },

然后资源部分看起来像这样...

        {
            "name": "[concat(parameters('vnet').VnetName)]",
            "type": "Microsoft.Network/virtualNetworks",
            "apiVersion": "2017-10-01",
            "location": "[resourceGroup().location]",
            "tags": "[parameters('vnet').tags]",
            "properties": {
                "addressSpace": {
                    "addressPrefixes": "[parameters('vnet').CIDR]"
                },
                "copy": [
                    {
                        "name": "subnets",
                        "count": "[length(parameters('vnet').Subnets)]",
                        "input": {
                            "name": "[parameters('vnet').Subnets[copyIndex('Subnets')].Name]",
                            "properties": {
                                "addressPrefix": "[parameters('vnet').Subnets[copyIndex('Subnets')].CIDR]"
                            }
                        }
                    }
                ]
            }
        }
    ]

所以这一切所做的就是将一个对象传递给 ARM 模板,该模板可以有一个 Vnet 和一个或多个子网并创建它们。

希望这会帮助其他人,如果他们在谷歌搜索时发现这个。

干杯,

戴夫。

:)