Bird
Raised Fist0
Azurecloud~10 mins

Bicep syntax and modules in Azure - Step-by-Step Execution

Choose your learning style10 modes available
Process Flow - Bicep syntax and modules
Start Bicep file
↓
Define parameters
↓
Define variables
↓
Use modules to call other Bicep files
↓
Define resources
↓
Output values
↓
Deploy Bicep template
This flow shows how a Bicep file is structured: starting with parameters and variables, then calling modules, defining resources, and finally outputs before deployment.
Execution Sample
Azure
param location string = 'eastus'
module storageModule './storage.bicep' = {
  name: 'storageDeploy'
  params: {
    location: location
  }
}
output storageId string = storageModule.outputs.storageAccountId
This Bicep code defines a location parameter, calls a storage module passing the location, and outputs the storage account ID from the module.
Process Table
StepActionEvaluationResult
1Read parameter 'location'Default 'eastus'location = 'eastus'
2Call module './storage.bicep'Pass param location='eastus'Module deployment started
3Module './storage.bicep' deploys storage accountUses location='eastus'Storage account created
4Module outputs 'storageAccountId'Captured as storageModule.outputs.storageAccountIdValue available
5Define output 'storageId'Assign storageModule.outputs.storageAccountIdOutput ready
6Bicep deployment completesAll resources and outputs definedDeployment successful
💡 Deployment ends after all resources and outputs are processed successfully.
Status Tracker
VariableStartAfter Module CallFinal
location'eastus''eastus''eastus'
storageModule.outputs.storageAccountIdundefinedassigned after module deployassigned after module deploy
storageIdundefinedundefinedstorageModule.outputs.storageAccountId
Key Moments - 2 Insights
Why do we pass parameters to modules instead of hardcoding values?
Passing parameters allows modules to be reusable and flexible. As shown in step 2 of the execution_table, the location parameter is passed to the module, so it can deploy resources in different locations without changing the module code.
How do outputs from modules become available in the main Bicep file?
Outputs from modules are accessed via the module's outputs property. In step 4, the storageAccountId output from the module is captured and then assigned to the main output in step 5.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the value of 'location' after step 1?
A'westus'
B'eastus'
Cundefined
D'centralus'
💡 Hint
Check the 'Evaluation' column in step 1 where 'location' is set to 'eastus'.
At which step does the module './storage.bicep' complete creating the storage account?
AStep 3
BStep 2
CStep 4
DStep 5
💡 Hint
Look at the 'Action' and 'Result' columns in step 3 describing module deployment.
If the parameter 'location' was changed to 'westus', which step's evaluation would change?
AStep 5 only
BStep 1 only
CStep 2 and Step 3
DNo steps would change
💡 Hint
Refer to steps 2 and 3 where the location parameter is passed and used in the module deployment.
Concept Snapshot
Bicep files start with parameters and variables.
Modules are called with 'module' keyword and accept parameters.
Modules deploy resources and return outputs.
Outputs from modules are accessed via 'moduleName.outputs'.
This structure enables reusable, clean infrastructure code.
Full Transcript
This lesson shows how Bicep syntax organizes infrastructure as code. First, parameters like 'location' are defined with default values. Then, modules are called using the 'module' keyword, passing parameters to them. The module deploys resources, such as a storage account, using the passed parameters. After deployment, the module outputs values like the storage account ID. These outputs are accessed in the main Bicep file through the module's outputs property and can be assigned to outputs for use after deployment. This approach helps keep code modular and reusable. The execution table traces each step from reading parameters, calling modules, deploying resources, capturing outputs, and completing deployment. Variables like 'location' and module outputs change state as deployment progresses. Key moments clarify why parameters are passed to modules and how outputs are accessed. The quiz tests understanding of variable values, deployment steps, and parameter effects. The snapshot summarizes the core syntax and behavior of Bicep modules.

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