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?
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.
}
Try this:
if(!(Get-AzureRmStorageAccountNameAvailability -Name $storageName))
{
New-AzureRmStorageAccount -ResourceGroupName $resourceGroupName -Name $storageName -SkuName Standard_LRS
}
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}
}
something like this ?
if(
Get-AzureStorageAccount | Where {$_.Label -match $name} | measure |select -expand count -eq 0) {
$storageAcct = New-AzureStorageAccount -StorageAccountName $Name -Location $Location
}
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
}
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
}