Until recently I had not used the runCommands
property in Bicep. I had used the Azure Custom Script Extension for that. But now that I have used it and I am using it more and more, I wanted to share a small tip on how to use parameters in the runCommands
property.
In this blog post, I will show you how to use parameters in the runCommands
property in Bicep.
Prerequisites
If you want to follow along with this blog post, you’ll need the following:
- Azure Subscription
- Azure CLI
- Bicep CLI
- Visual Studio Code
Creating the resources
First we need to create some resources.
We will create
- a virtual network
- a subnet
- a public IP address
- a network interface
- and a virtual machine.
We will use the following Bicep script to create the resources:
param location string = 'eastus'
param vmName string = 'myVM'
param adminUsername string = 'adminUser'
param adminPassword string = 'P@ssw0rd1234'
resource vnet 'Microsoft.Network/virtualNetworks@2024-05-01' = {
name: 'myVNet'
location: location
properties: {
addressSpace: {
addressPrefixes: [
'10.0.0.0/16'
]
}
}
}
resource subnet 'Microsoft.Network/virtualNetworks/subnets@2024-05-01' = {
name: 'mySubnet'
parent: vnet
properties: {
addressPrefix: '10.0.0.0/24'
}
}
resource publicIP 'Microsoft.Network/publicIPAddresses@2024-05-01' = {
name: 'myPublicIP'
location: location
properties: {
publicIPAllocationMethod: 'Dynamic'
}
}
resource nic 'Microsoft.Network/networkInterfaces@2024-05-01' = {
name: 'myNIC'
location: location
properties: {
ipConfigurations: [
{
name: 'myIPConfig'
properties: {
subnet: {
id: subnet.id
}
publicIPAddress: {
id: publicIP.id
}
}
}
]
}
}
resource vm 'Microsoft.Compute/virtualMachines@2024-07-01' = {
name: vmName
location: location
properties: {
hardwareProfile: {
vmSize: 'Standard_DS2_v2'
}
osProfile: {
computerName: vmName
adminUsername: adminUsername
adminPassword: adminPassword
}
storageProfile: {
imageReference: {
publisher: 'MicrosoftWindowsServer'
offer: 'WindowsServer'
sku: '2019-Datacenter'
version: 'latest'
}
osDisk: {
createOption: 'FromImage'
managedDisk: {
storageAccountType: 'Standard_LRS'
}
}
}
networkProfile: {
networkInterfaces: [
{
id: nic.id
}
]
}
}
}
Save the script to a file (i.e ‘create-resources.bicep’) and deploy it with the following command:
az deployment group create --resource-group <resource-group> --template-file .\resources\create-resources.bicep
Using the runCommands
property
To demonstrate the runCommands property, we will add the following code to the Bicep file:
param location string = 'eastus'
param vmName string = 'myVM'
resource vm 'Microsoft.Compute/virtualMachines@2024-07-01' = {
name: vmName
location: location
}
resource runCommands 'Microsoft.Compute/virtualMachines/runCommands@2024-07-01' = {
name: '${vm.name}-runCommands'
location: location
parent: vm
properties: {
source: {
script: '''
if(-not (Test-Path -Path "C:\Temp")) {
New-Item -Path "C:\Temp" -ItemType Directory
}
Write-Output "Lorem ipsum dolor sit amet, consectetur adipiscing elit." | Out-File -FilePath C:\Temp\lorem.txt
'''
}
timeoutInSeconds: 900
}
}
Save the script to a file (i.e ‘create-file1.bicep’) and deploy it with the following command:
az deployment group create --resource-group <resource-group> --template-file .\resources\create-file1.bicep
We should end up with this:
This file deploys a Windows and write some static text to a file. The command is hardcoded in the Bicep file.
But what if we want to use parameters in the runCommands
property?
Using parameters in the runCommands
property
To use parameters in the runCommands
property, we need to create a parameter and use that parameter in the runCommands
property. The parameter will be a string and will contain the command we want to run.
The Bicep file will look like this:
param location string = 'eastus'
param vmName string = 'myVM'
param textValue string = 'Hello, World!'
param filePathLocation string = 'C:\\Temp\\output.txt'
resource vm 'Microsoft.Compute/virtualMachines@2024-07-01' = {
name: vmName
location: location
}
resource runCommands 'Microsoft.Compute/virtualMachines/runCommands@2024-07-01' = {
name: '${vm.name}-runCommands'
location: location
parent: vm
properties: {
parameters: [
{
name: 'FilePath'
value: filePathLocation
}
{
name: 'Text'
value: textValue
}
]
source: {
script: '''
param (
[string]$FilePath,
[string]$Text
)
if(-not (Test-Path -Path "$(Split-Path -Path $FilePath -Parent)")) {
New-Item -Path "$(Split-Path -Path $FilePath -Parent)" -ItemType Directory
}
Write-Output $Text | Out-File -FilePath $FilePath
'''
}
timeoutInSeconds: 900
}
}
We added two parameters to the Bicep file. The textValue
parameter is a string and contains the text we want to write to the file. The filePathValue
parameter is also a string and contains the path to the file we want to write to.
We also added the parameters
property to the runCommands
property. This property contains an array of parameters. Each parameter has a name
and a value
. The name
is the name of the parameter in the script and the value
is the value of the parameter.
We also changed the script
property to use the parameters. We added a param
block to the script and used the parameters in the script.
Save the script to a file (i.e ‘create-file2.bicep’) and deploy it with the following command:
az deployment group create --resource-group <resource-group> --template-file .\resources\create-file2.bicep
We should end up with this:
In this case we did not give the az command the parameters. We could have done that with the following command:
az deployment group create --resource-group <resource-group> --template-file .\resources\create-file2.bicep --parameters textValue='How cool to use parameters like this!' filePathLocation='C:\\Temp\\output2.txt'
In this example the result should look like this:
Conclusion
In this blog post, I showed you how to use parameters in the runCommands
property in Bicep. By using parameters, you can make your Bicep files more flexible and reusable. You can use parameters to pass values to the runCommands
property and use those values in the script.
I hope this blog post was helpful to you. If you have any questions or comments, please leave them below. I would love to hear from you.