自从不久前的 Bicep 更新以来,我收到变量 vnetArray 的错误,该变量返回所有 vnet 及其各自的子网和子网 ID 的列表。我认为解决方案很简单,但我似乎找不到解决方案。
我在 mainSpoke.bicep 变量 vnetArray 中的 virtualNetworkModule[i].outputs.vnetName 和 virtualNetworkModule[i].outputs.subnetIDArray 中遇到的错误:“此表达式正在变量“vnetArray”的 for-body 中使用,需要可以在部署开始时计算的值。virtualNetworkModule 的属性“outputs”无法在开始时计算。virtualNetworkModule 可以在开始时计算的属性包括“name”.bicep(BCP182)”
mainSpoke.bicep
@description('REQUIRED: Array containing virtualNetwork parameters')
param virtualNetwork array
// This variable returns a list of all the vnets and their respective subnets and subnetIDs.
var vnetArray = [for i in range(0, length(virtualNetwork)): { name: virtualNetworkModule[i].outputs.vnetName, value: virtualNetworkModule[i].outputs.subnetIDArray }]
module virtualMachineDeploymentModule '../../Modules/Compute/virtualMachineDeployment/virtualMachineDeploy.bicep' = [for vmConfiguration in virtualMachines: {
name: 'virtualmachinedeployment-${vmConfiguration.name}'
dependsOn: [ availabilitySetModule ]
params: {
vmConfiguration: vmConfiguration
vnets: vnetArray
keyvaultName: keyvaultName
availabilitySetId: (availabilitySet.availabilitySetName == '' ? '' : availabilitySetModule.outputs.id)
}
}]
// Deploy Network resources
module virtualNetworkModule '../../Modules/Network/virtualNetwork/virtualNetwork.bicep' = [for vnet in virtualNetwork: {
name: 'virtualnetworkdeploy-${vnet.name}'
params: {
virtualNetworkName: '${customerName}-${vnet.name}'
location: vnet.location
subnets: vnet.subnets
networkSecurityGroupId: networkSecurityGroupModule.outputs.networkSecurityGroupId
addressPrefixes: vnet.addressPrefixes
diagnosticStorageAccountId: storageAccountModule[0].outputs.staccId
logAnalyticsWorkspaceId: logAnalyticsModule[0].outputs.logAnalyticsId
}
}]
mainSpoke.parameters.jsonc
"{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"customerName": {
"value": ""
},
"virtualNetwork": {
"value": [
{
"name": "VNET1",
"location": "westeurope",
"addressPrefixes": [
"10.0.0.0/16"
],
"subnets": [
{
"name": "subnet1",
"addressPrefix": "10.0.1.0/24",
"delegationsName": "",
"delegationsServiceName": ""
},
{
"name": "subnet2",
"addressPrefix": "10.0.2.0/24",
"delegationsName": "",
"delegationsServiceName": ""
}
]
},
{
"name": "VNET2",
"location": "westeurope",
"addressPrefixes": [
"10.1.0.0/16"
],
"subnets": [
{
"name": "subnet1",
"addressPrefix": "10.1.1.0/24",
"delegationsName": "",
"delegationsServiceName": ""
},
{
"name": "subnet2",
"addressPrefix": "10.1.2.0/24",
"delegationsName": "",
"delegationsServiceName": ""
}
]
}
]
}}
虚拟网络.bicep
@description('REQUIRED: The name of the virtual network resource.')
param virtualNetworkName string
@description('REQUIRED: A list of subnets in a Virtual Network.')
param subnets array
@description('REQUIRED: The reference to the NetworkSecurityGroup resource.')
param networkSecurityGroupId string
@description('REQUIRED: A list of address blocks reserved for this virtual network in CIDR notation.')
param addressPrefixes array
@description('Array that consists of objects with 2 values being routeTableName & routeTableId')
param routeTablesNameAndId array = []
// If routeTableNameAndId is empty, then a random object is created. This object will never be used, but it couldn't be empty because Bicep Linter gives an error
var routeTablesObject = empty(routeTablesNameAndId) ? { q: 'randomValueBecauseItNeedsToBeNotEmpty' } : toObject(routeTablesNameAndId, i => i.name, i => i.id)
resource VNET 'Microsoft.Network/virtualNetworks@2021-02-01' = {
name: toUpper(virtualNetworkName)
location: location
properties: {
addressSpace: {
addressPrefixes: addressPrefixes
}
subnets: [for subnet in subnets: {
name: subnet.name
properties: {
addressPrefix: subnet.addressPrefix
routeTable: empty(routeTablesNameAndId) ? null : (subnet.routeTableName == '' ? null : {
id: routeTablesObject[subnet.routeTableName]
})
networkSecurityGroup: networkSecurityGroupId == '' ? null : {
id: networkSecurityGroupId
}
delegations: subnet.delegationsName != '' ? [
{
name: subnet.delegationsName
properties: {
serviceName: subnet.delegationsServiceName
}
}
] : null
serviceEndpoints: [
{ service: 'Microsoft.KeyVault' }
]
}
}]
}
}
output vnetId string = VNET.id
output vnetName string = VNET.name
output subnetIDArray array = [for (subnet, i) in subnets: {
name: VNET.properties.subnets[i].name
resourceId: VNET.properties.subnets[i].id
}]
我可以确认 2 个虚拟网络已成功创建并具有相应的子网,我只是似乎无法映射返回所有 vnet 及其各自子网和子网 ID 列表的变量。 Var vnetArray 将在 virtualMachineDeploymentModule 中用于以下用途:
// This variable is used to create an object of the vnets and subnets lists.
var vnetObject = toObject(vnets, i => i.name, i => toObject(i.value, j => j.name, j => j.resourceId))
有点难看,但你可以将 vnet 创建包装到它自己的模块中:
// file virtualNetworkWrapper.bicep
param customerName string
param virtualNetwork array
// Deploy Network resources
module virtualNetworkModule 'virtualNetwork.bicep' = [for vnet in virtualNetwork: {
name: 'virtualnetworkdeploy-${vnet.name}'
params: {
virtualNetworkName: '${customerName}-${vnet.name}'
location: vnet.location
subnets: vnet.subnets
networkSecurityGroupId: networkSecurityGroupModule.outputs.networkSecurityGroupId
addressPrefixes: vnet.addressPrefixes
}
}]
output vnetArray array = [for i in range(0, length(virtualNetwork)): { name: virtualNetworkModule[i].outputs.vnetName, value: virtualNetworkModule[i].outputs.subnetIDArray }]
然后从你的主目录看起来像这样:
// file mainSpoke.bicep
param customerName string
param virtualNetwork array
module virtualNetworkModule '../../Modules/Network/virtualNetwork/virtualNetworkWrapper.bicep' = {
name: 'allvirtualnetworkdeploy-${customerName}'
params: {
customerName: customerName
virtualNetwork: virtualNetwork
}
}
var vnetArray = virtualNetworkModule.outputs.vnetArray
...