I am trying to write to a powershell script to validate the Resource Group is exist or not.
Conditions-
Check the resource group (myrg) is already exist in azure subscription.
If "condition 1" is FALSE then Create a Resource Group (myrg) Else append 2 digits to the Resource Group name. e.g. (myrg01)
Check the (myrg01)resource group exist in azure subscription.
If "condition 3" is FALSE then Create a Resource Group (myrg01) Else increment the last digit by one for Resource Group name. e.g. (myrg02)
Check the (myrg02) resource group exist in azure subscription.
If "condition 5" is FALSE then Create a Resource Group (myrg02) Else increment the last digit by one for Resource Group name. e.g. (myrg03)
and so on.........
Below is the code which i have written so far and unable to create a desired loop.
$rgname= "myrg"
Get-AzResourceGroup -Name $rgname -ErrorVariable notPresent -ErrorAction SilentlyContinue
if ($notPresent){
Write-Host "ResourceGroup doesn't exist, Creating resource group"
$createRG= New-AzResourceGroup -Name $rgname -Location $region -Tag $tag
Write-Host $rgname
}
else{
$countcontent = $countcontent + 1
$counter = [int]$countcontent
++$counter
$countString = "{0:d2}" -f ($counter)
Write-Host "ResourceGroup $rgname already exist, Generating a new name for Resource Group"
$rgname= $rgname + $countString
Get-AzResourceGroup -Name $rgname -ErrorVariable notPresent -ErrorAction SilentlyContinue
if ($notpresent){
$createRG= New-AzResourceGroup -Name $rgname -Location $region -Tag $tag
Write-Host $rgname
Clear-Variable countcontent
Clear-Variable counter
Clear-Variable countString
}
}
Got a workaround
$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"
Related
I have a script which snapshots all my disks in a certain RG.
However when I do the snapshotting, I need them to be spat out into another tenant/subscription for a migration project!
I've got as far as snapshotting everything and spitting them into a different RG but I need to take it a step further and spit them into the same named RG but in a different tenant/sub.
My script is below:
Login-AzureRmAccount -Credential $psCred –SubscriptionId $SubscriptionId -ErrorAction Stop | out-null
Connect-AzureRmAccount
Get-AzureRmSubscription -SubscriptionId $SubscriptionId | Select-AzureRmSubscription
$tagResList = Get-AzureRmResource -TagName Environment -TagValue Staging
#$tagResList = Find-AzureRmResource -ResourceGroupNameEquals testrs
#$tagRsList[0].ResourceId.Split("//")
#subscriptions
#<SubscriptionId>
#resourceGroups
#<ResourceGroupName>
#providers
#Microsoft.Compute
#virtualMachines
#<vmName>
foreach($tagRes in $tagResList) {
if($tagRes.ResourceId -match "Microsoft.Compute")
{
$vmInfo = Get-AzureRmVM sandbox207478603000 #$tagRes.ResourceId.Split("//")[4] -Name $tagRes.ResourceId.Split("//")[8]
#Set local variables
$location = $vmInfo.Location
$resourceGroupName = $vmInfo.ResourceGroupName
$timestamp = Get-Date -f MM-dd-yyyy_HH_mm_ss
#Snapshot name of OS data disk
$snapshotName = $vmInfo.Name + $timestamp
#Create snapshot configuration
$snapshot = New-AzureRmSnapshotConfig -SourceUri $vmInfo.StorageProfile.OsDisk.ManagedDisk.Id -Location $location -CreateOption copy
#Take snapshot
New-AzureRmSnapshot -Snapshot $snapshot -SnapshotName $snapshotName snapshots $resourceGroupName
if($vmInfo.StorageProfile.DataDisks.Count -ge 1){
#Condition with more than one data disks
for($i=0; $i -le $vmInfo.StorageProfile.DataDisks.Count - 1; $i++){
#Snapshot name of OS data disk
$snapshotName = $vmInfo.StorageProfile.DataDisks[$i].Name + $timestamp
#Create snapshot configuration
$snapshot = New-AzureRmSnapshotConfig -SourceUri $vmInfo.StorageProfile.DataDisks[$i].ManagedDisk.Id -Location $location -CreateOption copy
#Take snapshot
New-AzureRmSnapshot -Snapshot $snapshot -SnapshotName $snapshotName snapshots $ResourceGroupName
}
}
else{
Write-Host $vmInfo.Name + " doesn't have any additional data disk."
}
}
else{
$tagRes.ResourceId + " is not a compute instance"
}
}
$tagRgList = Get-AzureRmResourceGroup -Tag #{ Environment = "Staging" }
I am not sure if you can save snapshot in another tenant in one command as you'd need to be authenticated there.
I would suggest using azcopy tool to move snapshot files between storage accounts
#######################################
Reviewed your comment and found that indeed you can't use azcopy on vm images.
But you may create access to the snapshot
#Generate the SAS for the snapshot
$sas = Grant-AzSnapshotAccess -ResourceGroupName $ResourceGroupName -SnapshotName $SnapshotName -DurationInSecond $sasExpiryDuration -Access Read
and save it to the destination storage account:
#Copy the snapshot to the storage account
Start-AzStorageBlobCopy -AbsoluteUri $sas.AccessSAS -DestContainer $storageContainerName -DestContext $destinationContext -DestBlob $destinationVHDFileName
More details canbe found here
I am trying to use the command like so:
a = 345
name = "myVM"
Invoke-AzVMRunCommand -ResourceGroupName $RGName -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath $FileName -Parameter #{"b" = "a"; "test" = "name"}
the script in the file isn't really important I am just trying to use params inside of it with values of params from the outside. If I put "b" = 345 it works but with the outside param (a), it doesn't so I wanted to know how to do it.
it does execute the script but ignores the commands using these params.
for reference the script is something like this:
New-Item -Path "." -Name "index.html" -ItemType "file" -Value $b
New-Item -Path "." -Name $test -ItemType "file" -Value "3333333"
We use Invoke-AzVMRunCommand to Invoke a run command on the VM. And the -Parameter is used to run the command parameter.
The the type for -Parameter is Hashtable, which maps keys to values. Any non-null object can be used as a key or as a value.
Invoke command is more like a batch script, so when we want to pass a pre-defined variable we have to use the $ symbol without any double quotes (""). So you can solve your problem by following the code snippet below.
#Example
a = 345
name = "myVM"
Invoke-AzVMRunCommand -ResourceGroupName $RGName -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath $FileName -Parameter #{"b" = $a; "test" = $name}
Read this Invoke-AzVMRunCommand document and about_Hash_Tables document for more information.
Invoke-AzVMRunCommand -ResourceGroupName $RGName -Name $VMName -CommandId 'RunPowerShellScript' -ScriptPath $FileName -Parameter #{"b" = $a; "test" = $name}
It don't work. The same problem.
I have the script which create VM in azure:
$password = ConvertTo-SecureString -String "Qwerty123456" -AsPlainText
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user, $password
$x = Get-Random 10000 -Minimum 10
$location = "East US"
$rgname = "testVM"+$x
$VMName = "vm1"
# Create Resource group
New-AzResourceGroup -name $rgname -Location $location
# Create VM, vnet, publicIP, port 3389
New-AzVM -ResourceGroupName $rgname `
-Location $location `
-Name "verdyshtest" `
-VirtualNetworkName "virtnet" `
-SubnetName 'verdyshnetwork' `
-PublicIpAddressName "verdyshpublicIP" `
-Image Win2019Datacenter `
-OpenPorts 3389 `
-Credential $cred
# Script only running after deploy
Invoke-AzVMRunCommand -ResourceGroupName $rgname -VMName $VMName -CommandId RunPowerShellScript -ScriptPath '.\2 Install app on VM.ps1'
In last count it can't to execute 'invoke-azvmruncommand', because of variable in parameters.
But in New-AzVM cmdlet variables works well.
Had a error:
error
I am reviewing a script that is supposed to delete a vm along with all of the resources attributed to the vm
Write-Host -NoNewline -ForegroundColor Green "Please enter the VM name you would like to remove:"
$VMName = Read-Host
$vm = Get-AzVm -Name $VMName
if ($vm) {
$RGName=$vm.ResourceGroupName
Write-Host -ForegroundColor Cyan 'Resource Group Name is identified as-' $RGName
#boot diagnostics container auto generated in storage account. Auto delete this storageURI property
$diagSa = [regex]::match($vm.DiagnosticsProfile.bootDiagnostics.storageUri, '^http[s]?://(.+?)\.').groups[1].value
Write-Host -ForegroundColor Cyan 'Marking Disks for deletion...'
$tags = #{"VMName"=$VMName; "Delete Ready"="Yes"}
$osDiskName = $vm.StorageProfile.OSDisk.Name
$datadisks = $vm.StorageProfile.DataDisks
$ResourceID = (Get-Azdisk -Name $osDiskName).id
New-AzTag -ResourceId $ResourceID -Tag $tags | Out-Null
if ($vm.StorageProfile.DataDisks.Count -gt 0) {
foreach ($datadisks in $vm.StorageProfile.DataDisks){
$datadiskname=$datadisks.name
$ResourceID = (Get-Azdisk -Name $datadiskname).id
New-AzTag -ResourceId $ResourceID -Tag $tags | Out-Null
}
}
if ($vm.Name.Length -gt 9){
$i = 9
}
else
{
$i = $vm.Name.Length - 1
}
$azResourceParams = #{
'ResourceName' = $VMName
'ResourceType' = 'Microsoft.Compute/virtualMachines'
'ResourceGroupName' = $RGName
}
$vmResource = Get-AzResource #azResourceParams
$vmId = $vmResource.Properties.VmId
$diagContainerName = ('bootdiagnostics-{0}-{1}' -f $vm.Name.ToLower().Substring(0, $i), $vmId)
$diagSaRg = (Get-AzStorageAccount | where { $_.StorageAccountName -eq $diagSa }).ResourceGroupName
$saParams = #{
'ResourceGroupName' = $diagSaRg
'Name' = $diagSa
}
Write-Host -ForegroundColor Cyan 'Removing Boot Diagnostic disk..'
if ($diagSa){
Get-AzStorageAccount #saParams | Get-AzStorageContainer | where {$_.Name-eq $diagContainerName} | Remove-AzStorageContainer -Force
}
else {
Write-Host -ForegroundColor Green "No Boot Diagnostics Disk found attached to the VM!"
}
Write-Host -ForegroundColor Cyan 'Removing Virtual Machine-' $VMName 'in Resource Group-'$RGName '...'
$null = $vm | Remove-AzVM -Force
Write-Host -ForegroundColor Cyan 'Removing Network Interface Cards, Public IP Address(s) used by the VM...'
foreach($nicUri in $vm.NetworkProfile.NetworkInterfaces.Id) {
$nic = Get-AzNetworkInterface -ResourceGroupName $vm.ResourceGroupName -Name $nicUri.Split('/')[-1]
Remove-AzNetworkInterface -Name $nic.Name -ResourceGroupName $vm.ResourceGroupName -Force
foreach($ipConfig in $nic.IpConfigurations) {
if($ipConfig.PublicIpAddress -ne $null){
Remove-AzPublicIpAddress -ResourceGroupName $vm.ResourceGroupName -Name $ipConfig.PublicIpAddress.Id.Split('/')[-1] -Force
}
}
}
Write-Host -ForegroundColor Cyan 'Removing OS disk and Data Disk(s) used by the VM..'
Get-AzResource -tag $tags | where{$_.resourcegroupname -eq $RGName}| Remove-AzResource -force | Out-Null
Write-Host -ForegroundColor Green 'Azure Virtual Machine-' $VMName 'and all the resources associated with the VM were removed sucessfully...'
}
else{
Write-Host -ForegroundColor Red "The VM name entered doesn't exist in your connected Azure Tenant! Kindly check the name entered and restart the script with correct VM name..."
}
I had a question: what does this block of code exactly do:
$diagSa = [regex]::match($vm.DiagnosticsProfile.bootDiagnostics.storageUri, '^http[s]?://(.+?)\.').groups[1].value
I know it matches the storage uri, but how? And why is this needed? I am not sure what the .groups[1].value is referring to either
$diagSa =
[regex]::match($vm.DiagnosticsProfile.bootDiagnostics.storageUri,
'^http[s]?://(.+?).').groups[1].value
I know it matches the storage uri, but how?
You are using the [regex] type accelerator & match method () in the above expression.
The Match() method is a way to instruct PowerShell to attempt to match a string inside of another string. The Match() method has two parameters; the string you'd like to match on and the regular expression you'd like to test against.
Whenever a match is found and a regex group is used; (), the [regex] type accelerator has a Captures property. This Captures property then has a property called Groups. This is a collection that contains lots of attributes of what was matched. The second element in that collection contains the actual value that was matched.
what the .groups[1].value is referring to either
groups[1].values returns the storage account name where the boot diagnostics container resides.
And why is this needed?
When creating an Azure VM, you always have the option of creating a boot diagnostics container. This is useful to troubleshooting VM boot issues but doesn’t get removed when a VM is deleted. Let’s remedy that.
To remove the boot diagnostics container, you first need to figure out the name of the storage account the container resides on. To find that storage account, you’ll have to do some parsing of the storageUri property that’s exists in the DiagnosticsProfile object on the VM.
for more information about [regex]::match().group[1].value expression refer the below blog :
https://mcpmag.com/articles/2015/09/30/regex-groups-with-powershell.aspx
I am using AzCosmosDBSqlContainer to check details of a CosmosDB (SQL api) container in PowerShell; I am getting this error
Object reference not set to an instance of an object
However Get-AzCosmosDBAccount and Get-AzCosmosDBSqlDatabase commands are working fine.
Can someone help me with this?
Command used:
$ResourceGroup="MyResourceGroup"
$CDBAccountName="mycosmosaccount"
$dbname="myDatabase"
$containername="MyContainer"
$cosmosaccount=Get-AzCosmosDBAccount -ResourceGroupName $ResourceGroup -Name $CDBAccountName
$cosmosdbname=Get-AzCosmosDBSqlDatabase -AccountName $cosmosaccount.Name -ResourceGroupName $ResourceGroup -Name $dbname
Get-AzCosmosDBSqlContainer -ResourceGroupName $ResourceGroup -AccountName $cosmosaccount.Name -DatabaseName $cosmosdbname.Name -Name $containername
I found a workaround after getting an update from Microsoft team.
https://github.com/Azure/azure-powershell/issues/11381
This issue is going to be fixed in upcoming version of Az.CosmosDB 0.1.4
Workaround:
Replace "my***Name" with your own values
$resourceGroupName = "myResourceGroupName"
$accountName = "myAccountName"
$databaseName = "mYDatabaseName"
$containerName = "myContainerName"
$apiVersion = "2020-03-01"
$databaseResourceName = $accountName + "/" + $databaseName
$containerResourceName = $databaseResourceName + "/" + $containerName
$containerResourceType = "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers"
Write-Host "List containers in the database"
Get-AzResource -ResourceType $containerResourceType -ApiVersion $apiVersion
-ResourceGroupName $resourceGroupName -Name $databaseResourceName
Write-Host "Show specified container"
Get-AzResource -ResourceType $containerResourceType -ApiVersion $apiVersion
-ResourceGroupName $resourceGroupName -Name $containerResourceName
I am trying to create 2 public ips and then assign one each to nics
for($i=1; $i -lt 3; $i++)
{
New-AzPublicIpAddress -Name "publicIP$i" -ResourceGroupName $resourceGroup.ResourceGroupName -Location $location -AllocationMethod Dynamic
New-AzNetworkInterface -Name "nic$i" -ResourceGroupName $resourcegroup.ResourceGroupName -Location $location -SubnetId $vnet.subnets[0].Id -PublicIpAddressId "publicIP$i.Id" -NetworkSecurityGroupId $nsg.Id
}
I want to assign the output of new-azPublicIpAddress to a variable and then use that variable's id to assign to -pulicIpAddressId.
like this $pip$i = New-AzPublicIpAddress -Name "publicIP$i" -ResourceGroupName $resourceGroup.ResourceGroupName -Location $location -AllocationMethod Dynamic but this does not work
You cannot set a variable with a '$' inside it.
The following is a correct sample.
$pip = New-AzPublicIpAddress -Name "publicIP$i" -ResourceGroupName $resourceGroup.ResourceGroupName -Location $location -AllocationMethod Dynamic
Considering your requirement, I suggest you use an array:
$pipArr = New-Object 'Object[]' 2;
$nicArr = New-Object 'Object[]' 2;
for($i=0; $i -lt 2; $i++)
{
$pipArr[$i] = New-AzPublicIpAddress -Name "publicIP$i" -ResourceGroupName $resourceGroup.ResourceGroupName -Location $location -AllocationMethod Dynamic
$nicArr[$i] = New-AzNetworkInterface -Name "nic$i" -ResourceGroupName $resourcegroup.ResourceGroupName -Location $location -SubnetId $vnet.subnets[0].Id -PublicIpAddressId $pipArr[$i].Id -NetworkSecurityGroupId $nsg.Id
}
In this way, you can get your first public IP with "$pipArr[0]". As it is an array, you can use index with it.
As Jack requested, here's another way of doing the same is the following:
Set-Variable "pip$i" -Value (New-AzPublicIpAddress -Name "publicIP$i" -ResourceGroupName $resourceGroup.ResourceGroupName -Location $location -AllocationMethod Dynamic)
then you can use Get-Variable to get data from the variable:
Get-Variable "pip$i" | Select -ExpandProperty Value
If you just want to have $ inside the variable you can do this:
${pip$i} = something
this will instanciate new variable with the name pip$i, and you could retrieve it similarly as well:
Do-something -Input ${pip$i}