Recently, I posted an example of using an Azure Resource Manger template to create multiple virtual networks (Vnets) in multiple subscriptions.
Quoting from that post:
Today, most cloud architects have adopted wholesale the DevOps shibboleth that declarative languages (e.g. JSON or YAML) are “better” for deploying cloud assets than procedural languages (e.g. PowerShell or bash). I may be alone on this, but I don’t agree. Consider the complexity it takes in a declarative language like JSON to do something simple like loop through an array of to-be-created virtual networks versus a foreach loop in PowerShell. The benefits of declarative approaches, which boil down to idempotency, pale next to the functionality, clarity and maintainability of scripting languages.
Calling myself out means that I need to offer a PowerShell script which does the same thing as the ARM template, only better. That example is below. Note that this script uses the exact same parameter JSON file as input as does the ARM template (see the input parameters in the other post). So, it’s a fair apples-to-apples comparison.
Do you agree with me that the PowerShell script is better by virtue of being easier to understand and maintain? Comments alone should tip the balance in favor of PowerShell, IMHO.
<#? .SYNOPSIS? Creates reference architecture Vnets in multiple subscriptions? ? .DESCRIPTION? Using a JSON parameter file in the ARM template parameter format, create Visiant Reference Architecture Vnets.? ? .PARAMETER parameterFile? Name of JSON-formatted parameter file containing information about Vnets to be created? ? .NOTES? Alex Neihaus 2018-07-16? (c) 2018 Air11 Technology LLC -- licensed under the Apache OpenSource 2.0 license, https://opensource.org/licenses/Apache-2.0? Licensed under the Apache License, Version 2.0 (the "License");? you may not use this file except in compliance with the License.? You may obtain a copy of the License at? http://www.apache.org/licenses/LICENSE-2.0? ? Unless required by applicable law or agreed to in writing, software? distributed under the License is distributed on an "AS IS" BASIS,? WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.? See the License for the specific language governing permissions and? limitations under the License.? ? Author's blog: https://yobyot.com?#>?param?(? [Parameter(Mandatory = $true,? Position = 1)]? [string]$parameterFile?)?Import-Module AzureRM.profile?Import-Module AzureRM.Network?Import-Module AzureRM.Compute??if (!(Test-Path $parameterFile)) {? Write-Host "Parameter file does not exist"? Exit 404 # file not found?}??$ArmParameters = Get-Content -Path $parameterFile | Select-Object $_.parameters.parameterarray.value | ConvertFrom-Json # Get raw ARM template parameters which come in as PowerShell object several "levels" above where we want to be?$ParameterArray = $ArmParameters.parameters.ParameterArray.value # Get a nice, clean PowerShell array to work with as input??foreach ($vnet in $ParameterArray) {? # $vnet contains ? # VnetName: Text name of Vnet to be created? # ResourceGroupName: Text name of the containing resource group? # SubscriptionId: Text GUID of containing subscription for the new Vnet. CONTEXT'S USER _MUST_ HAVE ACCOUNT ADMIN ON THIS SUBSCRIPTION? # VnetAddressSpace: String in CIDR format of Vnet address space? # Subnets: Array of hashtables containing? # name: String name of subnet? # addressPrefix: String containing subnet CIDR of VnetAddressSpace? Set-AzureRmContext -Subscription $vnet.SubscriptionId? if (!(Get-AzureRmVirtualNetwork -Name $vnet.VnetName -ResourceGroupName $vnet.ResourceGroupName -ErrorAction SilentlyContinue)) {? # Vnet doesn't exist yet, let's create it? # First, create an array of objects of type Microsoft.Azure.Commands.Network.Models.PSSubnet ? $sarray = @()? foreach ($subnet in $vnet.Subnets) {? $s = New-Object -TypeName Microsoft.Azure.Commands.Network.Models.PSSubnet? $s.Name = $subnet.name # Name of subnet to be displayed in the portal? $s.AddressPrefix = $subnet.addressPrefix # Subnet address in CIDR format? $sarray += $s # Add the new subnet to the object array? }? New-AzureRmVirtualNetwork -Name $vnet.VnetName `? -ResourceGroupName $vnet.ResourceGroupName `? -Location $vnet.Region `? -AddressPrefix $vnet.VnetAddressSpace `? -Subnet $sarray? }? else {? Write-Host "$($vnet.VnetName) exists"? }?}??
Leave a Reply