Issue with bicep template for subnet

65 views Asked by At

I have an existing vnet and route table in RG1. All other resources are going in RG2.

I am creating a subnet bicep which will be called as a module and it has to be associated with vnet and route table.

subnet bicep

//parameters
//variables

resource vnetRef 'Microsoft.Network/virtualNetworks@2023-09-01' = {
  name: vnetId
}

resource subnet 'Microsoft.Network/virtualNetworks/subnets@2023-09-01' = {
  name: subnetName
  parent: vnetRef
  properties: {
    addressPrefix: subnetPrefix
    routeTable: {
      id: routeTableId
    }          
  }
}

output subnetId string = subnet.id

main bicep

resource vnet 'Microsoft.Network/virtualNetworks@2023-09-01' existing = {
  name: '${appAcronym}-${subscriptionName}-vnet'
  scope: resourceGroup(sharedScopeRG)
}

resource routeTable 'Microsoft.Network/routeTables@2023-09-01' existing = {
  name: routeTableName
  scope: resourceGroup(sharedScopeRG)
}

module subnetModule '../AnotherRepo/subnet.bicep' = {
  name: 'subnetModule'
  scope: resourceGroup(rgName)
  params: {
    name: subnetName
    subnetPrefix: subnetAddressSpace
    vnetId: vnet.id
    routeTableId: routeTable.id
    //other params for subnet bicep
  }
}

It fails with The template resource '/subscriptions/subid/resourceGroups/RG1/providers/Microsoft.Network/virtualNetworks/myVnet' for type 'Microsoft.Network/virtualNetworks' at line '1' and column '1739' has incorrect segment lengths. A nested resource type must have identical number of segments as its resource name. A root resource type must have segment length one greater than its resource name. Please see https://aka.ms/arm-syntax-resources for usage details.'.

I then passed vnet.name instead of vnet.id when calling subnet bicep and then get the following error: Resource 'myVnet' was disallowed by policy. Error Type: PolicyViolation, Policy Definition Name : Allowed locations, Policy Assignment Name : .

Which means it is trying to create vnet when the subnet module is being called. I have tried multiple ways of referring them but none are working out.

3

There are 3 answers

2
Thomas On BEST ANSWER

First thing, you should deploy the subnets inside the vnet resource. Otherwise if you rerun the vnet module, the existing subnets not defined in the vnet module will be destroy (see related post).

in your subnet module, you need to use the existing keyword to reference the existing vnet:

// subnet.bicep
param vnetName string
param subnetName string
param subnetPrefix string
param routeTableId string

resource vnetRef 'Microsoft.Network/virtualNetworks@2023-09-01' existing = {
  name: vnetName
}

resource subnet 'Microsoft.Network/virtualNetworks/subnets@2023-09-01' = {
  parent: vnetRef
  name: subnetName  
  properties: {
    addressPrefix: subnetPrefix
    routeTable: {
      id: routeTableId
    }   
  }
}

output subnetId string = subnet.id

When invoking the subnet module from your main file, the scope of the module has to be the scope of the vnet resource group:

param appAcronym string
param subscriptionName string
param sharedScopeRG string
param routeTableName string
param subnetName string
param subnetAddressSpace string

resource vnet 'Microsoft.Network/virtualNetworks@2023-09-01' existing = {
  name: '${appAcronym}-${subscriptionName}-vnet'
  scope: resourceGroup(sharedScopeRG)
}

resource routeTable 'Microsoft.Network/routeTables@2023-09-01' existing = {
  name: routeTableName
  scope: resourceGroup(sharedScopeRG)
}

module subnetModule 'subnet.bicep' = {
  name: 'subnetModule'
  scope: resourceGroup(sharedScopeRG) // scope should be the scope of the vnet resource group
  params: {
    subnetName: subnetName
    vnetName: vnet.name
    subnetPrefix: subnetAddressSpace
    routeTableId: routeTable.id
  }
}
0
Lucky On
resource vnet 'Microsoft.Network/virtualNetworks@2023-09-01' existing = {
  name: '${appAcronym}-${subscriptionName}-vnet'
  scope: resourceGroup(myRG)
}

module subnetModule '/subnet.bicep' = {
  name: '${prefixRName}-snetModule'
  scope: resourceGroup(myRG)
  params: {
    name: 
    subnetPrefix: 
    vnetName: vnet.name
  }
}
param name string
param vnetName string

var subnetName = '${vnetName}/${name}'

resource subnet 'Microsoft.Network/virtualNetworks/subnets@2023-09-01' = {
  name: subnetName
  properties: {
    addressPrefix: //param for address            
  }
}

output subnetId string = subnet.id

2
wenbo On

If you did not wanted to refer the vnet again in subnet bicep, you can do as follow

subnet.bicep

param vnetName string

resource subnet 'Microsoft.Network/virtualNetworks/subnets@2023-09-01' = {
  name: '${vnetName}/wbsubnet1'
  properties: {
    addressPrefix: '10.0.1.0/24'
  }
}

main.bicep

resource vnet 'Microsoft.Network/virtualNetworks@2023-09-01' existing = {
  name: 'wbvnet1'
}

module subnetModule 'subnet.bicep' = {
  name: 'wbsubnettest'
  params: {
    vnetName: 'wb-vNet'
  }
}

when deploying child resources outside, typically two ways

  • using parent keywords, you do in this way. docs
  • using full resource name. such as my sample code. docs

In order to only focus on subnet issues, I ignored routeTable resources here.