Deploying Azure Resources via powershell and bicep

Posted on Wed 06 March 2024 in azure

Deploying Azure Resources via Powershell

Deploying bicep templates

For the purpose of this article, I'm going to assume you already have your bicep templates made and have them stored in a convention which allows you to parameterise the paths to find them along with hosting profiles.

Start your script with any parameters that you might need

Param(
    [Parameter(Mandatory = $True)]
    [alias("n")][string]$applicationName,

    [Parameter(Mandatory)]
    [alias("e")][string]$environment
)

Given that most modern applications will look to deploy resources to more than one environment, maybe as many as four or five for larger companies, it's generally a good idea to define these environments within a hosting profile which your script can access to deploy them a generic manner. I'd strongly advise that a hosting profile only contains non-sensitive data or data which it is simply not possible to put in keyvault or an Azure app configuration instance. For my case, I've setup my bicep templates in a folder called Provisioning which then has sub folders for each applications bicep + hosting profile (which is a json file). We can then get the hosting profile and its environment specific data like this...

    $root = Get-Location
    $applicationName = $applicationName.ToLower()
    $environment = $environment.ToLower()

    # load our environment settings from our hosting profiles
    $hostingProfiles = Get-Content "$root\Provisioning\$applicationName.json" | ConvertFrom-Json;
    $hostingProfile = $hostingProfiles.$environment

My assumption here is that your hosting profile looks something like this...

    "dev": {},
    "qa": {},
    "live": {}

And you should never trust parameters, check the environment actually exists before you go any further with something like this

    if ($null -eq $hostingProfiles.$environment) {
        Write-Host "No profile is configured for environment $environment. Profile: $hostingProfiles"
        exit 1;
    }

Once we're a bit more sure that our hosting profile probably contains what we need, we should try to authenticate with azure.

    $tenantId = $hostingProfile.tenantId
    $subscriptionId = $hostingProfile.subscriptionId
    $resourceGroup = $hostingProfile.resourceGroup
    Connect-AzAccount -Tenant $tenantId -Subscription $subscriptionId

From there we simply get our template variable referenced and call the azure powershell module to deploy.

    # run templated deployment
    $templateFile = "$root\Provisioning\$applicationName.bicep"

    $deployment = New-AzResourceGroupDeployment `
        -ResourceGroupName $resourceGroup `
        -TemplateFile $templateFile `
        -applicationName $applicationName `
        -environment $environment

If our bicep templates gives us any output, we can iterate through it and display it.

    Foreach($output in $deployment.Outputs.Keys)
        {
            $keyValue = $deployment.Outputs.$output.Value
            if ($null -eq $keyValue)
            {
                Write-Host "Output from key : $output is null - this suggests strongly that the deployment failed."
                exit 1;
            }
            Write-Host $output " : " $keyValue
        }

We can also check if anything appears to have gone wrong with the bicep template and we want to exit with a code of 1, which would generally get picked up as a failed script.