How to "parse" Azure resource id object with powershell - azure

I am currently trying to pull data from an Azure policy for some automation with:
(Get-AzPolicyState -Filter "ComplianceState eq 'NonCompliant'" | Where-Object {$.PolicyDefinitionReferenceId -eq "azure backup should be enabled for virtual machines_1"} | Where-Object {$.SubscriptionId -eq "0000"}).ResourceId
Type Name: System.String
Example output
/subscriptions/00/resourcegroups/rg-test/providers/microsoft.compute/virtualmachines/vm-test
/subscriptions/00/resourcegroups/rg-test2/providers/microsoft.compute/virtualmachines/vm-test2
I am confused on how I can just pull the resource group name and virtual machine name only into a variable array.
The resource group name is always preceded by /resourcegroups/ and VM name is always preceded by /virtualmachines/.
Any guidance would be greatly appreciated. Thank you!

If you just want to extract your VM name and groupName from resourceID, just try the code below:
function parseGroupAndName{
param (
[string]$resourceID
)
$array = $resourceID.Split('/')
$indexG = 0..($array.Length -1) | where {$array[$_] -eq 'resourcegroups'}
$indexV = 0..($array.Length -1) | where {$array[$_] -eq 'virtualmachines'}
$result = $array.get($indexG+1),$array.get($indexV+1)
return $result
}
$resourceID = '/subscriptions/00/resourcegroups/rg-test/providers/microsoft.compute/virtualmachines/vm-test'
parseGroupAndName -resourceID $resourceID
Result:

more simple :
$resourceID = '/subscriptions/xxxx/resourceGroups/rrrrrrr/providers/aaaa/bbbb/nnnnn'
$cc=Get-AzResource -ResourceId
$cc.ResourceType
aaaaa/bbbb
$cc.ResourceGroupName
rrrrrr
$cc.Name
nnnnnnn

Related

How to output Subscription name with Get-AzVM

I am currently trying to output a list of VMs that are not compliant with a policy, all is working except I cant figure out how to output the subscription the VM lives in, since its not a property of Get-AzVm. If someone can please help me out, I am embarrassed I cant figure it out since it seems pretty simple. The current output will use the last subscription context for all the VMs, even though I have multiple subscriptions. Thanks a lot!
$vmsNotBackedUp = #()
$vms_results = #()
$subscriptions = Get-AzSubscription
#set policy definition
$poldef = '013e242c-8828-4970-87b3-ab247555486d'
#Get VMs resource ID that are not backed up from Azure Policy, store in $resourceIDs variable
foreach ($sub in $subscriptions) {
Set-AzContext -Subscription $sub.Id
$resourceIDs =(Get-AzPolicyState -Filter "PolicyDefinitionName eq '$poldef' and ComplianceState eq 'NonCompliant'").ResourceId
$vmsNotBackedUp += Get-AzVM | Where-Object{$_.Id -in $resourceIDs}
$currentContext = $sub.Name
$currentContext
}
Write-Output("The Following VMs were not able to be backed up, may need investigation")
#$vmsNotBackedUp|Select-Object -Property Name,ResourceGroupName,Location
foreach ($vm in $vmsNotBackedUp) {
$output_data = [PSCustomObject]#{
vmName = $vm.Name
ResourceGroup = $vm.ResourceGroupName
vmLocation = $vm.Location
vmOS = $vm.StorageProfile.OsDisk.OsType
vmSub = $currentContext
}
$vms_results += $output_data
}
Since you already have the subscription ID in $sub.Id, you could add this as a property to the VMs you enumerate in your script. Something like this:
$vmsNotBackedUp += Get-AzVM |
Where-Object{$_.Id -in $resourceIDs} |
Add-Member -MemberType NoteProperty -Name 'Subscription' -Value $sub.id -PassThru

Recursively list all resource tags within Azure Resource Groups

We have a large number of Azure Subscriptions which currently run into the hundreds.
I'm looking to generate a report (ideally using Azure Powershell or Azure CLI) to recursively extract a list of all tags assigned to every single resource within every resource group, for between 40-50 of the subscriptions.
Currently, I can list all tags assigned at Resource Group level, but I simply can't find a way to list the tags assigned to the individual resources within each Resource Group. The list of subscriptions and resource groups on which I'd like to extract this report, are saved in a CSV file which includes two columns displaying the Subscription name and Resource Group respectively.
Any tips on how to achieve the above would be fantastic and most appreciated.
Not detailed code but the idea here.
1.You should write a loop, in the loop, change the subscription each time by using this cmdlet:
Set-AzContext -Subscription $subscription_name.
2.Then get all the resource group in the specified subscription by using this cmdlet:
$resource_groups = Get-AzResourceGroup
3.Then write a nested loop(loop for each resource group), in this nested loop, use this cmdlet to get all azure resources within a resource group:
foreach($rg in $resource_groups){
$azure_resources = Get-AzResource -ResourceGroupName $rg.ResourceGroupName
}
4.Write another nested loop in step 3, this loop is used to go though all the azure resources within the specified resource group. Then use the code below to fetch tags for each azure resource within the resource group:
foreach($r in $azure_resources){
#the following code can get all the tags for one resource
$r.tags
}
Based on Ivan Yang's logic. I have built the PowerShell Script;
#---------DECLARE VARIABLES------------------------------------#
$bnsSubscription = Get-AzSubscription
$day = Get-Date -Format " ddMMMyyyy"
$tagPath = "C:\mytempfolder\"+"$day-Tag-Details.csv"
$tagFolderPath = "C:\mytempfolder\"
#---------DECLARE VARIABLES------------------------------------#
function Get-ResourceTag {
foreach ($subs in $bnsSubscription) {
Select-AzSubscription -SubscriptionName $subs.Name | Out-Null
Write-Host 'The selected Subscription is' ($subs).Name
New-Item -ItemType file -Path "$tagFolderPath\$($subs.Name).csv" -Force
$resource_groups = Get-AzResourceGroup
$resource_groups_details = Get-AzResourceGroup | Sort-Location ResourceGroupName | Format-Table -GroupBy Location ResourceGroupName,ProvisioningState,Tags
Write-Host 'The selected Resource Group is' ($resource_groups).Name 'and the tag information as follows'
#$resource_groups_details
$resource_groups | Select-Object ResourceGroupName,Tags | Export-CSV -Path "$tagFolderPath\$($subs.Name).csv" -Append
$OutputFile = #()
foreach($rg in $resource_groups){
$azure_resources = Get-AzResource -ResourceGroupName $rg.ResourceGroupName
$TestTags = $Resource.Tags.GetEnumerator()
foreach($r in $azure_resources){
Write-Host 'The selected resource is' ($r).Name 'and the information as follows'
$RGHT = New-Object "System.Collections.Generic.List[System.Object]"
$RGHT.Add("RGName",$r.ResourceGroupName)
$RGHT.Add("ResourceName",$r.name)
$RGHT.Add("Location",$r.Location)
$RGHT.Add("Id",$r.ResourceId)
$RGHT.Add("ResourceType",$r.ResourceType)
$RGHT.Add("ResourceTags",$r.Tags)
$OutputFile += New-Object psobject -Property $RGHT
$OutputFile | Export-Csv -Path "C:\mytempfolder\test22.csv" -append -NoClobber -NoTypeInformation -Encoding UTF8 -Force
}
}
}
}
#---------CALL FUNCTION------------------------------------#
Get-ResourceTag

Using Objects in Powershell to do command

What im trying to do is the following:
Im getting a list of all VM`s that have some set values such as being in use and NOT having Azure Benefits turned on.
What i have is that i made a tiny script to get all machines within an subscription and select on the basis mentioned above.
What i want to do with that output is do the command Update-azureVM in bulk.
Could someone help me with this ? do i need to export the values to an excel and use that sheet to do a bulk update-AzureVM
here is the code that i have setup at the moment:
$returnObj = #()
$VMs=Get-AzVm -status
foreach ($VM in $VMs)
{
$obj = New-Object psobject -Property #{
"VmSize" = $VM.HardwareProfile.VmSize;
"VmName" = $vm.Name;
"PowerState" = $vm.PowerState;
"License_Type" = $vm.LicenseType;
}
$returnObj += $obj | select VmSize, VmName, PowerState, License_Type
}
$returnObj |
Where-Object{$_.PowerState -ne "VM deallocated"} |
Where-Object{$_.License_Type -ne "Windows_Server"} |
Where-Object{$_.License_Type -ne "Windows_Client"} |
Export-Csv C:\temp\freek.csv
Thank you all in advance!

Azure Powershell - Script to obtain VM info across subscriptions

Trying to run a script that will connect to each subscription, and pull the
$azureSubs = Get-AzureRMSubscription
$azureSubs | ForEach-Object {Select-AzureRMSubscription $_ | Out-Null; Get-AzureRMVM | select resourcegroupname, name, licensetype -WarningAction SilentlyContinue}
This works, BUT I'd like to add two more pieces of information: the "OSType" and "VMSize"
If I do a GET-AZURERMVM, in the table for that subscription that the command is run in, the two pieces of information I need are there: VmSize and OsType
However, when I try to add them to the query, the columns are blank.
I believe the VmSize is in the HardwareProfile, and OsType is in the OsProfile, as if I run a "Get-AzureRMVM -name (name) -resourcegroupname (RGname)", then it shows "Hardware Profile: VMSize" and "OSProfile: ComputerName, AdminUsername windowsConfiguration, Secrets"
Ultimate goal is to get the script that will, for each subscription, print results like:
ResourceGroupName | Name | License Type | VMSize | OS Type
TEST_RG | Test_VM | Windows_Server | DS3_v2 | Windows
Test_RG | Test_VM2 | | DS3_v2 | Linux
etc.
Thankful for any help; sorry for such a noob question. Have spent so much time trying to figure this out...
Something like the following would work.
What you were missing mainly was calculated properties.
This is what allow you to perform a select of custom property.
Some notes:
In your code, you used -WarningAction SilentlyContinue on the Select statement. You need to put it on the Get-AzureRMVM CmdLet instead.
This is my opinion but unless you are writing one-liners on purposes, try aerating your code more. It will make it way easier to read, debug and maintain.
This is the code you wrote, modified to include the calculated properties and with the WarningAction parameter set to Get-AzureRMVM instead of the Select statement.
$azureSubs = Get-AzureRMSubscription
$Vms = $azureSubs | ForEach-Object {Select-AzureRMSubscription $_ | Out-Null; Get-AzureRMVM -WarningAction SilentlyContinue | select resourcegroupname, name, licensetype, #{Name="VMSize";Expression={$_.HardwareProfile.VmSize}},#{Name="OsType";Expression={$_.StorageProfile.OsDisk.OsType}}}
$Vms | ft
The same thing, with some progress indication without forcing everything on one line.
$azureSubs = Get-AzureRMSubscription
$Vms = New-Object 'System.Collections.Generic.List[PSObject]'
ForEach ($sub in $azureSubs) {
Select-AzureRMSubscription $sub | Out-Null
Write-Host "Processing Subscription $($sub.Name)".PadRight(50,' ') -ForegroundColor Cyan -NoNewline
[PsObject[]]$items = Get-AzureRMVM -WarningAction SilentlyContinue |
select resourcegroupname,
name,
licensetype,
#{Name="VMSize";Expression={$_.HardwareProfile.VmSize}},
#{Name="OsType";Expression={$_.StorageProfile.OsDisk.OsType}}
Write-Host "($($items.count) retrieved)"
if ($items -ne $null) {
$vms.AddRange($items)
}
}
$vms | Format-Table
You are looking for something like this on the select side
select resourcegroupname, name, licensetype, #{Name="VMSize";Expression={$_.HardwareProfile.VmSize}}, #{Name="OsType";Expression={$_.StorageProfile.OsDisk.OsType}}

How to get all Azure Resources without tags in a Azure Resource Group

In my Azure dev/test lab (DTL), there are many resources which were not tagged. How can I get a list of all untagged resources under DTL/resource group?
Here's a simple PowerShell loop to get untagged resources.
$resources = Get-AzureRmResource
foreach($resource in $resources)
{
if ($resource.Tags -eq $null)
{
echo $resource.Name, $resource.ResourceType
}
}
Other ways to query this information and also set tags programmatically or as part of resource deployments are described here.
If you want to avoid the situation of ending up with untagged resources, you could enforce a customized policy that all resources should have a value for a particular tag.
Here is the idiomatic PowerShell to supplement #huysmania's answer which is expressed in procedural language mindset (and updated for the new PowerShell Az cmdlets):
Get-AzResource | Where-Object Tags -eq $null | Select-Object -Property Name, ResourceType
and the terse (alias) form:
Get-AzResource | ? Tags -eq $null | select Name, ResourceType
I usually just run this command to output a table of untagged resources using Get-AzResource. It filters Azure resources with tags that are $null or empty using Where-Object.
Get-AzResource `
| Where-Object {$null -eq $_.Tags -or $_.Tags.Count -eq 0} `
| Format-Table -AutoSize
If you want to list untagged resources for a specific resource group, you can just add the -ResourceGroupName switch to Get-AzResource.
$resourceGroupName = "My Resource Group"
Get-AzResource -ResourceGroupName $resourceGroupName `
| Where-Object {$null -eq $_.Tags -or $_.Tags.Count -eq 0} `
| Format-Table -AutoSize
Note: The above uses the newer Azure PowerShell Az module, which is replacement for AzureRM.
<#Bellow is PowerShell script to locate untagged resources -
you may change the script out put as per your requirement.
Hope must be helpful. Thanks!#>
Write-Host "List all resource where Tag value is not Set"
Write-Host "********************************************"
#Fetch all resource details
$resources=get-AzureRmResource
foreach ($resource in $resources) {
$tagcount=(get-AzureRmResource | where-object {$_.Name -match $resource.Name}).Tags.count
if($tagcount -eq 0) {
Write-Host "Resource Name - "$resource.Name
Write-Host "Resource Type and RG Name : " $resource.resourcetype " & " $resource.resourcegroupname "`n"
}
}
This link has the solution for this question. It beautifully explains assigning and querying tags using powershell.
$resourceGroupName = 'InternalReportingRGDev'
$azureRGInfo = Get-AzureRmResourceGroup -Name $resourceGroupName
foreach ($item in $azureRGInfo)
{
Find-AzureRmResource -ResourceGroupNameEquals $item.ResourceGroupName | ForEach-Object {Set-AzureRmResource -ResourceId $PSItem.ResourceId -Tag $item.Tags -Force }
}

Resources