Bird
Raised Fist0
Azurecloud~7 mins

Bicep syntax and modules in Azure - Commands & Configuration

Choose your learning style10 modes available
Introduction
Bicep helps you write Azure infrastructure code simply. It solves the problem of complex JSON templates by using easier syntax. Modules let you reuse parts of your code to keep things neat and organized.
When you want to create Azure resources like storage or virtual machines with simple code.
When you need to reuse the same resource setup in different projects or environments.
When you want to split a big infrastructure setup into smaller, manageable pieces.
When you want to avoid writing long and hard-to-read JSON ARM templates.
When you want to share common infrastructure code with your team.
Config File - main.bicep
main.bicep
param location string = 'eastus'

module storageModule './storage.bicep' = {
  name: 'storageDeployment'
  params: {
    storageName: 'examplestorage123'
    location: location
  }
}

output storageAccountId string = storageModule.outputs.storageAccountId

This is the main Bicep file that deploys a storage account using a module.

param location: sets the Azure region.

module storageModule: calls the storage.bicep file, passing parameters.

output storageAccountId: exports the storage account ID from the module.

Commands
This command deploys the Bicep template to the Azure resource group named example-rg. It creates the resources defined in main.bicep and its modules.
Terminal
az deployment group create --resource-group example-rg --template-file main.bicep
Expected OutputExpected
{ "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-rg/providers/Microsoft.Resources/deployments/main", "name": "main", "properties": { "provisioningState": "Succeeded", "outputs": { "storageAccountId": { "type": "String", "value": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-rg/providers/Microsoft.Storage/storageAccounts/examplestorage123" } } } }
→
--resource-group - Specifies the Azure resource group to deploy to.
→
--template-file - Specifies the Bicep file to deploy.
This command checks that the storage account was created successfully by showing its details.
Terminal
az storage account show --name examplestorage123 --resource-group example-rg
Expected OutputExpected
{ "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-rg/providers/Microsoft.Storage/storageAccounts/examplestorage123", "location": "eastus", "name": "examplestorage123", "resourceGroup": "example-rg", "sku": { "name": "Standard_LRS" }, "kind": "StorageV2", "statusOfPrimary": "available" }
→
--name - Specifies the storage account name.
→
--resource-group - Specifies the resource group where the storage account exists.
Key Concept

If you remember nothing else from this pattern, remember: Bicep modules let you reuse and organize Azure infrastructure code by calling separate files with parameters.

Common Mistakes
Using incorrect file paths for modules in the main Bicep file.
The deployment fails because Bicep cannot find the module file to include.
Ensure the module path is correct relative to the main Bicep file, like './storage.bicep'.
Not passing required parameters to the module.
The module deployment fails due to missing inputs needed to create resources.
Always provide all parameters defined in the module when calling it.
Trying to deploy Bicep files without using the Azure CLI or without compiling.
Azure does not understand Bicep files directly without deployment commands or compilation.
Use 'az deployment group create' with the Bicep file or compile it to ARM JSON before deploying.
Summary
Write reusable infrastructure code in Bicep modules to keep templates clean.
Deploy Bicep files with Azure CLI using 'az deployment group create'.
Verify resource creation with Azure CLI commands like 'az storage account show'.

Practice

(1/5)
1. What is the main purpose of a module in Bicep?
easy
A. To reuse and organize infrastructure code by calling other Bicep files
B. To define variables inside a Bicep file
C. To store output values only
D. To create a new Azure subscription

Solution

  1. Step 1: Understand what a module does

    A module in Bicep is a way to include and reuse other Bicep files, helping organize code.
  2. Step 2: Compare options to the definition

    Only To reuse and organize infrastructure code by calling other Bicep files correctly describes modules as reusable code blocks. Variables and outputs are different concepts, and creating subscriptions is unrelated.
  3. Final Answer:

    To reuse and organize infrastructure code by calling other Bicep files -> Option A
  4. Quick Check:

    Module = reusable code block [OK]
Hint: Modules call other files to reuse code easily [OK]
Common Mistakes:
  • Confusing modules with variables
  • Thinking modules only store outputs
  • Believing modules create Azure subscriptions
2. Which of the following is the correct syntax to declare a module in Bicep?
easy
A. module myModule = 'module.bicep' {}
B. module myModule 'module.bicep' = {}
C. module 'myModule' = module.bicep {}
D. module 'myModule' 'module.bicep' {}

Solution

  1. Step 1: Recall module declaration syntax

    The correct syntax is: module <name> '<path>' = {}.
  2. Step 2: Match options to syntax

    module myModule 'module.bicep' = {} matches the correct syntax exactly. Other options have misplaced quotes or assignment operators.
  3. Final Answer:

    module myModule 'module.bicep' = {} -> Option B
  4. Quick Check:

    module name 'file' = {} [OK]
Hint: Use: module name 'file.bicep' = {} [OK]
Common Mistakes:
  • Putting quotes around the module name
  • Using = before the file path
  • Omitting the equals sign
3. Given this Bicep code snippet, what will be the output value of moduleOutput?
module storageModule 'storage.bicep' = {
  name: 'storage1'
}

output moduleOutput string = storageModule.outputs.storageAccountName
medium
A. An error because outputs cannot be accessed from modules
B. The module file path 'storage.bicep'
C. The name of the storage account defined inside storage.bicep
D. The string 'storage1'

Solution

  1. Step 1: Understand module outputs

    Modules can expose outputs which can be accessed using moduleName.outputs.outputName.
  2. Step 2: Analyze the code snippet

    The output moduleOutput gets the value of storageAccountName from the module's outputs, which is the storage account name defined inside storage.bicep.
  3. Final Answer:

    The name of the storage account defined inside storage.bicep -> Option C
  4. Quick Check:

    module.outputs = module data access [OK]
Hint: Access module outputs with moduleName.outputs.outputName [OK]
Common Mistakes:
  • Thinking outputs can't be accessed from modules
  • Confusing module name with file path
  • Assuming output is the module instance name
4. Identify the error in this Bicep module usage:
module webAppModule 'webapp.bicep' = {
  name: 'webApp1'
  params: {
    location: 'eastus'
  }
}
medium
A. Incorrect keyword 'params' should be 'parameters'
B. Module name cannot contain numbers
C. Module file path must be absolute
D. Missing equals sign after 'name'

Solution

  1. Step 1: Check parameter passing syntax in modules

    In Bicep, module parameters can be passed directly as properties (e.g., location: 'eastus') or nested under parameters: { ... }. params is not a valid keyword.
  2. Step 2: Identify the error

    The code uses invalid params:, which should be parameters: for nested parameters.
  3. Final Answer:

    Incorrect keyword 'params' should be 'parameters' -> Option A
  4. Quick Check:

    parameters: { } for nested params [OK]
Hint: Use 'parameters:' not 'params' for nested params [OK]
Common Mistakes:
  • Using 'params' instead of 'parameters'
  • Thinking module names cannot contain numbers
  • Believing file paths must be absolute
5. You want to create a reusable Bicep module for a virtual network that accepts a parameter for the address prefix and outputs the subnet ID. How should you define the module's parameter and output to follow best practices?
hard
A. Declare the address prefix as an output and subnet ID as a parameter
B. Use a variable for address prefix and no output since subnet ID is internal
C. Hardcode the address prefix and output the subnet name instead of ID
D. Declare a param addressPrefix string and an output subnetId string in the module file

Solution

  1. Step 1: Define parameters for input values

    Best practice is to declare inputs as parameters so the module is flexible. Here, param addressPrefix string allows passing different address prefixes.
  2. Step 2: Define outputs for important results

    Outputs share useful info back to the caller. The subnet ID is important to output as output subnetId string.
  3. Final Answer:

    Declare a param addressPrefix string and an output subnetId string in the module file -> Option D
  4. Quick Check:

    Parameters input, outputs share results [OK]
Hint: Use param for inputs, output for results [OK]
Common Mistakes:
  • Using variables instead of parameters for inputs
  • Not outputting needed resource IDs
  • Mixing parameters and outputs roles
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard