9

I'm using Powershell to automate setting up my Azure environment - to create storage account, database, website, etc.

In development, I want to provision and a tear down a lot. Very often, I want to run my provisioning script and create a azure asset if it doesn't already exist

However, I haven't found an elegant way of doing this. Some of the "Get" cmdlets throw exceptions if the item doesn't exist, and catching it is a bit of a hack:

try {
    $storageAcct = Get-AzureStorageAccount -StorageAccountName $Name
    Write-Verbose "Storage Account already exists"
} catch {
    $storageAcct = New-AzureStorageAccount -StorageAccountName $Name -Location $Location
}

What's more, with some commands, I can't catch the exception at all and I don't know why:

try {
        $cache = Get-AzureRedisCache -ResourceGroupName $resourceGroupName -Name $cacheName
} catch {
       //Even with an exception, never arrives here.
}

Is there a better way to do this?

user888734
  • 3,797
  • 5
  • 36
  • 67
  • 3
    catch will catch only terminating errors, did you set `$errorActionPreference` to `"stop"` prior to the try/catch ? – Loïc MICHEL May 06 '15 at 12:26
  • Thanks - that solves the second problem. Now I just wish I didn't have to catch errors at all to do this. – user888734 May 06 '15 at 12:31
  • The Get-AzureStorageAccount cmdlet returns an object with the details about the storage accounts for the current subscription. If the StorageAccountName parameter is specified, then only that storage account is returned. So do not use this parameter and check among the result if the storage name exists. – Loïc MICHEL May 06 '15 at 12:33

7 Answers7

4

You should use Test-AzureName for this instead of Get-AzureStorageAccount.

if (!Test-AzureName -Storage $Name)
{
   # create the storage account.
}

This will work for Cloud Services, Web Apps, and Service Bus namespaces too. For your database, you will have to resort back to your existing approach.

**

Added the following to address questions about v2 (ARM) resources:

**

For v2 resources (ARM), the story is mostly the same. For example, the DNS name for a v1 or v2 storage account will be the same, such as contoso.blob.core.windows.net. The same holds for Azure Web Apps (formerly Azure Web Sites), where you would have a DNS name such as contoso.azurewebsites.net. So, in other words, Test-AzureName would work just as well for these resources in ARM.

One notable difference is the DNS name for virtual machines. In v1, virtual machines are contained in a cloud service and get a DNS name such as contoso.cloudapp.net. For v2 virtual machines, the public DNS name is provided by the Public IP Address resource, for which the DNS name for a virtual machine in East US (for example) would be contoso.eastus.cloudapp.azure.com. To test for the availability of this DNS name, you should use the Test-AzureRmDnsAvailability cmdlet. For example,

if (Test-AzureRmDnsAvailability -DomainNameLabel "contos0" -Location "East US")
{
  # Assign DNS name to Public IP Address resource here.
}
Rick Rainey
  • 11,096
  • 4
  • 30
  • 48
  • Is there an Resource Manager equivalent ? – Mark Broadhurst Jun 13 '16 at 09:35
  • Is there any RM commands available to check resources deployed globally? Test-AzureRmDnsAvailability accepts Location as parameter. But for TrafficManager resources which are deployed globally, this command never works out... – Amruta May 25 '17 at 07:19
  • Test-AzureName doesn't work as expected. Its asking to select-AzureSubscription and select-AzureSubscription says my working subscription name and id do not exist. Finally ended up using Test-AzureRmDnsAvailability for HDInsight creation. Any idea how to check globally for checking name exists? – Joy George Kunjikkuru May 01 '18 at 22:29
  • For most of the providers, there's an API called **checkNameAvailability** that you could use to see of the name is already taken or is globally unique. I've wrapped up some of these in a PowerShell function. See https://secureinfra.blog/2019/11/07/test-azure-resource-name-availability/ – Martin Schvartzman Nov 09 '19 at 08:36
4

Try this:

if(!(Get-AzureRmStorageAccountNameAvailability -Name $storageName))
{
    New-AzureRmStorageAccount -ResourceGroupName $resourceGroupName -Name $storageName -SkuName Standard_LRS
}
Caleb Brinkman
  • 2,489
  • 3
  • 26
  • 40
user891818
  • 175
  • 1
  • 8
  • The if-check is 'reversed' as Get-AzureRmStorageAccountNameAvailability returns 'true' if the storage name is available. Apart from that the check is perfect if you are in ARM-mode. – lindstromhenrik Oct 24 '16 at 07:42
4

It is my solution with new Azure PowerShell Az module


$StorageAccountName = "Storage account name"
$ResourceGroupName = "Resource group name"

$StorageAccount = Get-AzStorageAccount -Name $StorageAccountName -ResourceGroupName $ResourceGroupName -ErrorAction SilentlyContinue

if($StorageAccount -eq $null){
    $storage =  New-AzStorageAccount -ResourceGroupName $ResourceGroupName -StorageAccountName $StorageAccountName -Location "westeurope" -SkuName Standard_LRS -Kind StorageV2
}
else{
    Write-Host "$StorageAccountName already exist"
}
2

I usually go for the following (works for pretty much any resource in Azure, just replace the "Get" module and parameters):

function Test-AzureStorageAccountExists {
     Param(
        [string]$resourceGroupName,
        [string]$storageAccountName
     )

     $SA = Get-AzureRmStorageAccount -Name $storageAccountName -ResourceGroupName $resourceGroupName -ErrorVariable notPresent -ErrorAction SilentlyContinue
     if ($notPresent) {return $false}
}
Frederik Gheysels
  • 56,135
  • 11
  • 101
  • 154
Panos_C
  • 21
  • 1
0

something like this ?

if(
 Get-AzureStorageAccount | Where {$_.Label -match $name} | measure |select -expand count -eq 0) {

    $storageAcct = New-AzureStorageAccount -StorageAccountName $Name -Location $Location
}
Loïc MICHEL
  • 24,935
  • 9
  • 74
  • 103
0

Maybe you can use the cmdlet Get-AzureRmResource. If the resource exists, it returns the information about the specified resource including the resource type; If not, it return $null. e.g.:

$MyRes=Get-AzureRmResource -ResourceName "MyResourceName" -ResourceGroupName 
"MyResourceGroupName"
if ($null == $MyRes) {
  # Not existing
}
Don Branson
  • 13,631
  • 10
  • 59
  • 101
Wynn
  • 11
  • 1
  • @Dan I have run the above (removing the if) and it doesn't fail if the resource isn't present. It just returns nothing. – mslot Dec 02 '19 at 18:13
0

I needed to check for the existing of a variable in the Azure Automation account using Get-AzureRmAutomaitonVariable before deciding if it needed to be created. user888734's solution of using a "catch" helped me get past this issue which I was blocked on for 2 days :-)

try {
    $existingVariable = Get-AzureRMAutomationVariable -ResourceGroupName $resourceGroup -AutomationAccountName $automationAccountName -Name $variable
} catch {
    New-AzureRmAutomationVariable -ResourceGroupName $resourceGroup -AutomationAccountName $automationAccountName -Name $variable -Value $value -Encrypted $False
}
Alex Rodrigues
  • 179
  • 1
  • 1
  • 6