Structuring Bicep files into modules is a great way to ensure re-usability and maintainability of your infrastructure-as-code (IAC) projects.
By breaking down complex configurations into modular, reusable module files, teams can standardize deployments, reduce code duplication, and streamline updates. Modules promote clarity by encapsulating distinct Azure resourceses, making it easier to troubleshoot, test, and adapt to changing requirements.
Let's try and do a simple example on how to structure our main.bicep file, where we not only include component modules, but also define the naming parameters, that we need to use in our modules.
// Based on microsoft best practices naming convention.
// https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming
// https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations
param location string = resourceGroup().location
@allowed([
'dev'
'test'
'uat'
'prod'
])
param env string
param ver string
Now we have defined our basic paramters, that we want to inject into the template and just made a quick comment on what naming convention we utilize here.
Let's continue with defing some paramters that we need to use for our modules.
param stgBlogName string = 'stblogstorage${env}${ver}'
param aspBlogName string = 'asp-blog-${env}-${ver}'
param funcBlogName string = 'func-blog-${env}-${ver}'
Now we have the basics in place and can start loading in our modules, I wont go into details on how to create the specific resources as I've already covered this in a previous post.
But let's get this wrapped up and implement our 3 modules and inject our required parameters and secure dependencies between modules are set.
// Based on microsoft best practices naming convention.
module stgBlog 'stg-blog.bicep' = {
name: stgBlogName
params: {
location: location
name: stgBlogName
}
}
module aspBlog 'asp-blog.bicep' = {
name: aspBlogName
params: {
location: location
name: aspBlogName
env: env
}
}
module funcBlog 'func-blog.bicep' = {
name: funcBlogName
params: {
location: location
aspId: aspBlog.outputs.aspId
name: funcBlogName
}
dependsOn: [
aspBlog
stgBlog
]
}
That's it, now you are ready to do full blown modular bicep scripts, pretty easy right? One thing to note, in the func-blog you can see we are using an output from a different module, these can defined in a specific output by utilizing the following line of code.
output aspId string = appServicePlan.id