使用Bicep创建Azure VNet遇阻:高级子网属性及循环逻辑问题
关于Bicep忽略未提供属性的疑问
我已查阅相关资料,尝试通过JSON配置文件创建带多子网的Azure VNet,目前遇到NSG/路由表循环逻辑异常问题,已将相关代码注释。当前VNet及子网可正常创建,但想了解:若未提供路由表等属性值,Bicep是否会自动忽略这些属性?
我的Bicep代码
param vnetConfiguration object param location string = 'West Europe' resource vnet 'Microsoft.Network/virtualNetworks@2021-05-01' = { name: vnetConfiguration.Name location: location properties: { addressSpace: { addressPrefixes: [ vnetConfiguration.addressPrefix ] } subnets: [for (subnet,index) in vnetConfiguration.subnets: { name: subnet.name properties: { addressPrefix: subnet.addressPrefix // routeTable: subnet.routeTable // unique: subnet.unique // nsg: { // properties: { // securityRules: [for (rule,index) in vnetConfiguration.subnet.nsgRules: { // name: rule.name // properties: { // description: rule.description // priority: rule.priority // direction: rule.direction // access: rule.access // protocol: rule.protocol // sourcePortRange: rule.sourcePortRange // destinationPortRange: rule.destinationPortRange // sourceAddressPrefix: rule.sourceAddressPrefix // destinationAddressPrefix: rule.destinationAddressPrefix // } // } // ] // } // } serviceEndpoints: subnet.serviceEndpoints delegations: subnet.delegations } }] } } output vnetId string = vnet.id
配置文件
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { "vnetConfiguration": { "value": { "Name": "my-vnet", "addressPrefix": "11.0.0.0/16", "subnets": [ { "name": "subnet1", "addressPrefix": "11.0.1.0/27", "routeTable": "", "unique": false, "nsgRules": [ { "name": "DENY-ALL-VNET-INBOUND", "description": "Deny all Virtual Network traffic", "priority": "4000", "direction": "Inbound", "access": "Deny", "protocol": "*", "sourcePortRange": "*", "destinationPortRange": "*", "sourceAddressPrefix": "VirtualNetwork", "destinationAddressPrefix": "VirtualNetwork" } ], "serviceEndpoints":[], "delegations": [ { "name": "Microsoft.Web.serverFarms", "properties": { "serviceName": "Microsoft.Web/serverFarms" } } ] } ] } } } }
解答
Bicep不会自动忽略显式声明的属性,但可以通过条件判断实现“未提供则不包含该属性”的效果,具体说明如下:
直接赋值的问题
如果你直接写routeTable: subnet.routeTable,当配置里的routeTable是空字符串(比如你当前配置的""),Bicep会把这个空值传递给Azure API,这会导致错误——因为路由表需要是有效的资源ID引用,空字符串不合法。用条件属性实现忽略
要让Bicep在属性未提供时自动忽略,需要使用条件属性语法:当值为null时,Bicep会在生成的ARM模板中移除该属性,Azure API就会忽略它:- 对于路由表:判断值是否为空,非空则传入资源引用,否则设为
nullrouteTable: subnet.routeTable != '' ? { id: subnet.routeTable } : null - 对于布尔属性(比如
unique):如果需要在参数未定义时忽略,可先判断属性是否存在unique: contains(subnet, 'unique') ? subnet.unique : null
- 对于路由表:判断值是否为空,非空则传入资源引用,否则设为
修复NSG循环逻辑异常
你之前注释的NSG代码里有个错误:循环中应该用subnet.nsgRules而非vnetConfiguration.subnet.nsgRules(因为当前迭代的是subnet变量,不是顶层的vnetConfiguration.subnet)。修正后的NSG部分可以写成:nsg: contains(subnet, 'nsgRules') && length(subnet.nsgRules) > 0 ? { properties: { securityRules: [for rule in subnet.nsgRules: { name: rule.name properties: { description: rule.description priority: int(rule.priority) // 注意:priority需要是整数,配置里的字符串要转类型 direction: rule.direction access: rule.access protocol: rule.protocol sourcePortRange: rule.sourcePortRange destinationPortRange: rule.destinationPortRange sourceAddressPrefix: rule.sourceAddressPrefix destinationAddressPrefix: rule.destinationAddressPrefix } }] } } : null这里加上了条件判断,只有当
nsgRules存在且不为空时,才会生成NSG配置。修正后的完整Bicep代码示例
param vnetConfiguration object param location string = 'West Europe' resource vnet 'Microsoft.Network/virtualNetworks@2021-05-01' = { name: vnetConfiguration.Name location: location properties: { addressSpace: { addressPrefixes: [ vnetConfiguration.addressPrefix ] } subnets: [for subnet in vnetConfiguration.subnets: { name: subnet.name properties: { addressPrefix: subnet.addressPrefix routeTable: subnet.routeTable != '' ? { id: subnet.routeTable } : null unique: contains(subnet, 'unique') ? subnet.unique : null nsg: contains(subnet, 'nsgRules') && length(subnet.nsgRules) > 0 ? { properties: { securityRules: [for rule in subnet.nsgRules: { name: rule.name properties: { description: rule.description priority: int(rule.priority) direction: rule.direction access: rule.access protocol: rule.protocol sourcePortRange: rule.sourcePortRange destinationPortRange: rule.destinationPortRange sourceAddressPrefix: rule.sourceAddressPrefix destinationAddressPrefix: rule.destinationAddressPrefix } }] } } : null serviceEndpoints: subnet.serviceEndpoints delegations: subnet.delegations } }] } } output vnetId string = vnet.id
内容的提问来源于stack exchange,提问作者learner
相关产品推荐
相关产品推荐

