Change WebApp AppSetting values when creating a new Slot - powershell

When creating a new Slot for an Azure WebApp, how can I successfully change one or more of the AppSettings?
The docs for New-AzureRmWebAppSlot suggest that there is a parameter called -AppSettingsOverrides, but that does not work.
It should be noted however that the linked docs seem to incorrectly reference the New-AzureRmWebApp Cmdlet, so I can't be sure if the parameter is actually valid (although it seems to be accepted without error).
Here is the code that I am running.
New-AzureRmWebAppSlot -ResourceGroupName $resourceGroupName -Name $webAppName -Slot $slotName -AppSettingsOverrides #{"FUNCTION_APP_EDIT_MODE" = "readwrite"} -ErrorAction Stop
Has anyone else experienced this seemlying incorrect behaviour, and if so, how did you fix it?
My Azure version is 3.5.0.

You could create Slot firstly, then use Set-AzureRmWebAppSlot to change AppSetting. Following script works for me.
$myResourceGroup = "shuiapp"
$mySite = "shuicli"
$slotName = "Test1"
$webApp = Get-AzureRMWebAppSlot -ResourceGroupName $myResourceGroup -Name $mySite -Slot $slotName
$appSettingList = $webApp.SiteConfig.AppSettings
$hash = #{}
ForEach ($kvp in $appSettingList) {
$hash[$kvp.Name] = $kvp.Value
}
$hash['ExistingKey2'] = "NewValue12"
Set-AzureRMWebAppSlot -ResourceGroupName $myResourceGroup -Name $mySite -AppSettings $hash -Slot $slotName
The question will be helpful.

Credit to this dingmeng-xue on Github for pointing this out but for the benefit of everyone reading Stackoverflow, it appears that the cmdlet doesn't a) check that -SourceWebApp and -AppSettingsOverrides are set together and b) only does a null check if $SourceWebApp is defined and silently does nothing even if $AppSettingsOverrides was defined. So you might set them both and test if that solves the issue.

Related

Hashtable not being read as hashtable in Azure Automation

We have a piece of code which works perfectly in Powershell ISE, however when we use the same code in Azure automation, it clears the tags.
$rgs = Get-AzureRmResourceGroup | Where-Object {$_.ResourceGroupName -like "*$rg*"}
foreach ($rg in $rgs)
{
$vms = Get-AzureRmVm -ResourceGroupName $rg.ResourceGroupName
$vms.ForEach({
$tags = $vm.Tags
$tags['ShutdownSchedule_AllowStop'] = "$False";
Set-AzureRmResource -ResourceId $_.Id -Tag $tags -Force -Verbose
})
}
What I've managed to establish so far is that the code Set-AzureRmResource -ResourceId $_.Id -Tag $tags -Force -Verbose does not see $tags as a hastable. I've done some debugging and I can see $tags = $vm.Tags is a hashtable.
I looked around on google and I've seen a few mentions of using [system.collections.hashtable] to specify it is a hashtable, but this is where my powershell is limited. I was hoping someone could point me in the right direction.
I've tried doingResourceId $_.Id -Tag [system.collections.hashtable]$tags but that didn't work.
What we are trying to do is change a tag value from true to false. The Key is Shutdown_AllowStop and the value is currently set to True.
Thanks in advance (and really hoping this makes sense) :)
The following script works for me.
$rgs = Get-AzureRmResourceGroup | Where-Object {$_.ResourceGroupName -like *$rg*"}
foreach ($rg in $rgs)
{
$vms = Get-AzureRmVm -ResourceGroupName $rg.ResourceGroupName
foreach ($vm in $vms)
{
$tags = $vm.Tags
foreach ($tag in $tags)
{
$tag['ShutdownSchedule_AllowStop'] = "$True";
Write-Output ("Showing VM's resource ID " + $vm.ID)
Write-output ("Show VM's tag "+[System.Collections.Hashtable]::new($tag))
$hash = [System.Collections.Hashtable]::new($tag)
$hash['ShutdownSchedule_AllowStop']
Set-AzureRmResource -ResourceId $vm.ID -Tag $hash -ApiVersion "2017-12-01" -Force -Verbose
}
}
}
But you need update Azure Power Shell version in Automation Account, if you don't do this, the script does not work.
This is my test result.
I think I see the issue. It works in the ISE because you defined $vm somewhere earlier in the session. Change it to $tags = $_.Tags and this should work for you.
Edit: So I took a look and the Get-AzureRmVm cmdlet returns an object where the Tags property is a horrid type when what they want in return is a hashtable. What it returns is:
[System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]]
Or Dictionary`2 for short if you run a .GetType() on it. What you can do to get around this is to explicitly declare your type when you define it:
[hashtable]$tags = $_.Tags

Check If Azure Resource Group Exist - Azure Powershell

I'm trying to verify if ResourceGroup exist or not so i thought that following code should return true or false, but it doesn't output anything.
$RSGtest = Find-AzureRmResource | Format-List ResourceGroupName | get-unique
$RSGtest -Match "$myResourceGroupName"
Why am I not getting any output?
Update:
You should use the Get-AzResourceGroup cmdlet from the new cross-plattform AZ PowerShell Module now. :
Get-AzResourceGroup -Name $myResourceGroupName -ErrorVariable notPresent -ErrorAction SilentlyContinue
if ($notPresent)
{
# ResourceGroup doesn't exist
}
else
{
# ResourceGroup exist
}
Original Answer:
There is a Get-AzureRmResourceGroup cmdlet:
Get-AzureRmResourceGroup -Name $myResourceGroupName -ErrorVariable notPresent -ErrorAction SilentlyContinue
if ($notPresent)
{
# ResourceGroup doesn't exist
}
else
{
# ResourceGroup exist
}
try this
$ResourceGroupName = Read-Host "Resource group name"
Find-AzureRmResourceGroup | where {$_.name -EQ $ResourceGroupName}
I am a PS newbie and I was looking for a solution to this question.
Instead of searching directly on SO I tried to investigate on my own using PS help (to get more experience on PS) and I came up with a working solution.
Then I searched SO to see how I compared to experts answers.
I guess my solution is less elegant but more compact. I report it here so others can give their opinions:
if (!(Get-AzResourceGroup $rgname -ErrorAction SilentlyContinue))
{ "not found"}
else
{"found"}
Explanation of my logic: I analyzed the Get-AzResourceGroup output and saw it's either an array with found Resource groups elements or null if no group is found. I chose the not (!) form which is a bit longer but allows to skip the else condition. Most frequently we just need to create the resource group if it doesn't exist and do nothing if it exists already.
I was also looking for the same thing but there was a additional condition in my scenario.
So I figured it out like this. To get the scenario details follow
$rg="myrg"
$Subscriptions = Get-AzSubscription
$Rglist=#()
foreach ($Subscription in $Subscriptions){
$Rglist +=(Get-AzResourceGroup).ResourceGroupName
}
$rgfinal=$rg
$i=1
while($rgfinal -in $Rglist){
$rgfinal=$rg +"0" + $i++
}
Write-Output $rgfinal
Set-AzContext -Subscription "Subscription Name"
$createrg= New-AzResourceGroup -Name $rgfinal -Location "location"
Had a similar challenge, I solved it using the script below:
$blobs = Get-AzureStorageBlob -Container "dummycontainer" -Context $blobContext -ErrorAction SilentlyContinue
## Loop through all the blobs
foreach ($blob in $blobs) {
write-host -Foregroundcolor Yellow $blob.Name
if ($blob.Name -ne "dummyblobname" ) {
Write-Host "Blob Not Found"
}
else {
Write-Host "bLOB already exist"
}
}

A positional parameter cannot be found that accepts argument when running New-AzureQuickVM

I've the following PowerShell script:
Param(
$AccountName = "AccountName",
$Guid = "Get-Random",
$ImageName = "ImageName",
$vmName = "VM-$Guid",
$ServiceName = "ServiceName",
$adminLogin = "adminLogin",
$adminPasswd = "adminPasswd!",
$location = "South Central US",
$instanceSize = "Medium",
$subscriptionDataFile = "file.publishsettings"
)
########################Import Azure Public Setting And Assign Storage###########################
Import-AzurePublishSettingsFile $subscriptionDataFile
Set-AzureSubscription -SubscriptionName $AccountName -CurrentStorageAccountName scrprod -PassThru
#########################Create A VM From Existing Image And Remove It##########################
for($i=1; $i -le 5; $i++)
{
New-AzureQuickVM –Windows –Location $location –ServiceName $ServiceName `
–Name $vmName –InstanceSize $InstanceSize –ImageName $ImageName–AdminUsername $adminLogin –Password $adminPasswd -WaitForBoot
})
and I get the following exception:
New-AzureQuickVM : A positional parameter cannot be found that accepts argument 'â€Windows â€Location'.
What am I doing wrong?
Second I'd like to create 5 VM's with a unique name - Is that the correct way to do it?
Thanks,
Oren
I believe the encoding of your text file is incorrect, or you are using the incorrect characters (perhaps from a cut and paste).
Your code
New-AzureQuickVM –Windows –Location
Is somehow being evaluated as
New-AzureQuickVM 'â€Windows â€Location'
I suggest deleting the - characters before Windows and Location (and elsewhere likely) and then re-typing it. Also check your file's encoding and character set.
You have formatting errors in the call of the New-AzureQuickVM cmdlet, most notably the backtick after $ServiceName could cause issues if not immediately followed by a new line. Also, there should be a space between $ImageName and -AdminUsername.
I terms of the guid, I would create one using $guid = ([guid]::NewGuid()).ToString() but really the definition of random is up to you.

Azure Powershell - Check to see if resource exists

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
}
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"
}
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
}
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
}
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
}

Azure: How to check storage account exists in Azure with Get-AzureStorageAccount

I am building a power shell script to automate the setup of a website environment in Azure. This web uses an account storage. I want to the script not to create the account storage if exists.
I thought that using Get-AzureStorageAccount this way may work but it does not:
Write-Verbose "[Start] creating $Name storage account $Location location"
$storageAcct = Get-AzureStorageAccount –StorageAccountName $Name
if (!$storageAcct)
{
$storageAcct = New-AzureStorageAccount -StorageAccountName $Name -Location $Location -Verbose
if ($storageAcct)
{
Write-Verbose "[Finish] creating $Name storage account in $Location location"
}
else
{
throw "Failed to create a Windows Azure storage account. Failure in New-AzureStorage.ps1"
}
}
else
{
Write-Verbose "$Name storage account in $Location location already exists, skipping creation"
}
The issue is I don't know how to handle the return of Get-AzureStorageAccount.
Thank you very much in advance!
I would suggest using the Test-AzureName cmdlet to determine if it exists. So, something like this.
if (!(Test-AzureName -Storage $Name))
{
Write-Host "Creating Storage Account $Name"
New-AzureStorageAccount -StorageAccountName $Name -Location $Location
}
You can use Test-AzureName for other services too, such as Cloud Services, WebSites, and ServiceBus. It returns True if it exists, False otherwise.
Get-AzureRmStorageAccountNameAvailability -Name "accountname"
Try this:
$Name = "myStorageAccount"
$Location = "myLocation"
Write-Host "[Start] creating $Name storage account $Location location"
try{
Get-AzureStorageAccount –StorageAccountName $Name -ErrorAction Stop | Out-Null
Write-Host "$Name storage account in $Location location already exists, skipping creation"
}
catch{
Write-Host "[Finish] creating $Name storage account in $Location location"
New-AzureStorageAccount -StorageAccountName $Name -Location $Location -Verbose
}
Test-AzureName didn't work with our build agents and we already had a try/catch in code so a second one would require building it out as a function. I opted for that standard get and check if null, use -ErrorAction Ignore to stop it throwing an exception
# Check for storage account and create if not found
$StorageAccount = Get-AzureRmStorageAccount -Name $StorageAccountName -ResourceGroupName $StorageAccountRG -ErrorAction Ignore
if ($StorageAccount -eq $null)
{
New-AzureRmStorageAccount -Location "West Europe" -Name $StorageAccountName -ResourceGroupName $StorageAccountRG -SkuName Standard_LRS -Kind Storage
$StorageAccount = Get-AzureRmStorageAccount -Name $StorageAccountName -ResourceGroupName $StorageAccountRG
}
#Rick Rainey's solution works if you're logged in using Add-AzureAccount. However, Azure and powershell have a conflicting and confusing suite of login accounts (Windows Live versus AD) and login mechanisms (Classic: Add-AzureAccount; Resource manager: Login-AzureRmAccount). Some Azure powershell cmdlets require a specific login; further, some require a specific account type!
To clear through this thicket of complicated, undocumented, and confusing permission issues, we always use an AD account, logging in via Login-AzureRmAccount. We also use Azure resource manager (ARM) resources and cmdlets, following Microsoft's movement to ARM as its recommended and strategic approach. However, #RIck's solution is one which the ARM login doesn't work with. :-( So you need another approach, which is #Darren's (for storage). However, for a generic replacement for Test-AzureName I'd suggest Find-AzureRmResource. In the case of storage
$StorageObject = Find-AzureRmResource -ResourceType "Microsoft.Storage/storageAccounts" | Where-Object {$_.Name -eq $storageName}
if ( !$StorageObject ) {
$storageLocation = (Get-AzureRmResourceGroup -ResourceGroupName $resourceGroup).Location
$storageType = "Standard_LRS"
New-AzureRmStorageAccount -ResourceGroupName $resourceGroup -Name $storageName -Location $storageLocation -Type $storageType
}
You should use the latest Powershell module Az.
if ($(Get-AzStorageAccount -ResourceGroupName $resourceGroupName -Name $storageAccountName) -eq $null)
{
# does not exist
}
With the current Az module for PowerShell Version 7, the Get-AzStorageAccountNameAvailability cmdlet might offer a more efficient solution as it was designed specifically for this task. Here is an example:
# ... declare variables and specify values ...
$checkNameAvail = (Get-AzStorageAccountNameAvailability -Name $storageAccountName) | `
Select-Object NameAvailable
if ($checkNameAvail.NameAvailable)
{
Write-Host 'Account name available! Please wait while your resource is being created'
# Create account. Variables used in this example would have been declared earlier in the script.
$storageAccount = (New-AzStorageAccount -ResourceGroupName $resourceGroupName `
-AccountName $storageAccountName `
-Location $location `
-SkuName $skuType `
-AllowBlobPublicAccess $false -EnableHttpsTrafficOnly $true)
# ...
}
else
{
# This section of the script executes if the name is not available
Write-Host "The name <$storageAccountName> is not available. Suggest a new globally unique name!"
}
The condition above will return False, and execute the else statement because the boolean value returned by the cmdlet is in [0] as shown in the PowerShell command-line test below. The availability information (boolean) can thus be stripped from the object returned by the cmdlet and (as in this example) used as a condition in the rest of the script.
PS C:\> Get-AzStorageAccountNameAvailability -Name testaccount1
NameAvailable Reason Message
------------- ------ -------
False AlreadyExists The storage account named testaccount1 is already taken.
Use the error variable
Get-AzStorageAccount -ResourceGroupName 'RG-QA-TEST' -Name 'staccountfor12334ff' -ErrorVariable ev1 -ErrorAction SilentlyContinue
if ($ev1) {
Write-Host "-------------------------- Creating OEM Storage"
//create storage account
}
I had this challenge when setting up Azure storage accounts for Static website hosting using Powershell in Octopus Deploy.
Here's how I fixed it:
Using the Az module for Azure Powershell I did the following:
# Define Variables
$RESOURCE_GROUP_NAME = my-resource-group
$LOCATION = northeurope
$STORAGE_ACCOUNT_NAME = myapplication
$SKU_NAME = Standard_GRS
$STORAGE_KIND = StorageV2
# Check Storage Account and Create if not Found
$STORAGE_ACCOUNT = Get-AzStorageAccount -ResourceGroupName $RESOURCE_GROUP_NAME -Name $STORAGE_ACCOUNT_NAME -ErrorAction Ignore
if ($STORAGE_ACCOUNT -eq $null) {
Write-Host 'Creating storage account'
New-AzStorageAccount -ResourceGroupName $RESOURCE_GROUP_NAME -AccountName $STORAGE_ACCOUNT_NAME -Location $LOCATION -SkuName $SKU_NAME -Kind $STORAGE_KIND
Write-Host "$STORAGE_ACCOUNT_NAME storage account successfully created"
}
else {
Write-Host "$STORAGE_ACCOUNT_NAME storage account already exists"
}
Note:
-ErrorAction Ignore - This ignores the exception that would arise if the storage account does not exist
Write-Host " " - Double quotes were used to allow for string interpolation since we are connecting strings and variables.
That's all.
I hope this helps