Summary: This wiki page shows how I used copilot to get all unattached disks in an Azure subscription. It's part of the 'copilot' tag series in which I showcase the use of copilot in infrastructure related tasks.
Date: 2 December 2025
I've been using copilot for a while now, and I mostly use it without using a prompt. I let it finish my sentences, or create a small comment and wait for a few seconds to let copilot to give me some hints on how to proceed. But sometimes I also use a prompt, and on this page I show you how I used some prompts to create a script.
The hard facts:
Actually, I used two prompts. The first prompt was:
I need an azure cli script that will get all disks from an Azure subscription that have the disk state unattached. In the output I want to see the name, the resourcegroup, the last ownership update time, the location, the time created, the disk size, and the following tags: k8s-azure-created-by, kubernetes.io-created-for-pvc-namespace, kubernetes.io-created-for-pvc-name
This created a script, which with some small modifications worked, except that it didn't return the tags. I found that using the azure cli query option didn't retrieve the tags, so I added another prompt:
The output doesn't display the tags. I think the az disk list can't resolve the tag information. I think you need to retrieve the tags separately for each disk
This created a new script, which again needed some small modifications.
Note that this is the script after my modifications. For the modifications, see below. Copilot also provided the possible ways to start the script:
# Display the output for a subscription .\get-unattached-disks.ps1 -SubscriptionId "your-subscription-id" # Export to CSV .\get-unattached-disks.ps1 -SubscriptionId "your-subscription-id" -OutputToCSV -OutputPath "my-disks.csv"
# Get all unattached disks from Azure subscription with detailed information # This script retrieves disks with state "Unattached" and displays relevant metadata param( [string]$SubscriptionId = $null, [switch]$OutputToCSV = $false, [string]$OutputPath = "unattached-disks.csv" ) # Set subscription if provided if ($SubscriptionId) { Write-Host "Setting subscription to: $SubscriptionId" -ForegroundColor Yellow az account set --subscription $SubscriptionId } # Get current subscription info $currentSub = az account show --query "{name:name, id:id}" -o json | ConvertFrom-Json Write-Host "Current subscription: $($currentSub.name) ($($currentSub.id))" -ForegroundColor Green # First get basic disk information for unattached disks $basicQuery = @" [?diskState=='Unattached'].{Name: name, ResourceGroup: resourceGroup, LastOwnershipUpdateTime: LastOwnershipUpdateTime, Location: location, TimeCreated: timeCreated, DiskSizeGB: diskSizeGB} "@ Write-Host "Retrieving basic disk information..." -ForegroundColor Yellow $basicDisks = az disk list --query $basicQuery -o json | ConvertFrom-Json if ($basicDisks.Count -eq 0) { Write-Host "No unattached disks found in the subscription." -ForegroundColor Green exit 0 } Write-Host "Found $($basicDisks.Count) unattached disk(s). Retrieving tag information..." -ForegroundColor Yellow # Now retrieve tags for each disk individually $disks = @() $counter = 0 foreach ($disk in $basicDisks) { $counter++ Write-Progress -Activity "Retrieving disk tags" -Status "Processing disk $counter of $($basicDisks.Count): $($disk.Name)" -PercentComplete (($counter / $basicDisks.Count) * 100) # Get tags for this specific disk $tags = az disk show --name $disk.Name --resource-group $disk.ResourceGroup --query "tags" -o json | ConvertFrom-Json # Create enriched disk object $enrichedDisk = [PSCustomObject]@{ Name = $disk.Name ResourceGroup = $disk.ResourceGroup LastOwnershipUpdateTime = $disk.LastOwnershipUpdateTime Location = $disk.Location TimeCreated = $disk.TimeCreated DiskSizeGB = $disk.DiskSizeGB CreatedBy = $tags.'k8s-azure-created-by' PVCNamespace = $tags.'kubernetes.io-created-for-pvc-namespace' PVCName = $tags.'kubernetes.io-created-for-pvc-name' #AllTags = $tags } $disks += $enrichedDisk } Write-Progress -Activity "Retrieving disk tags" -Completed Write-Host "Completed retrieving tag information for all disks." -ForegroundColor Green Write-Host "" if ($OutputToCSV) { # Output to CSV $disks | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8 Write-Host "Results exported to: $OutputPath" -ForegroundColor Green } else { # Display in table format $disks | Format-Table -AutoSize -Property @( 'Name', 'ResourceGroup', @{Name='LastOwnershipUpdate'; Expression={$_.LastOwnershipUpdateTime}; Width=20}, 'Location', @{Name='TimeCreated'; Expression={$_.TimeCreated}; Width=20}, @{Name='SizeGB'; Expression={$_.DiskSizeGB}; Width=8}, @{Name='CreatedBy'; Expression={$_.CreatedBy}; Width=20}, @{Name='PVCNamespace'; Expression={$_.PVCNamespace}; Width=15}, @{Name='PVCName'; Expression={$_.PVCName}; Width=15} ) } # Summary Write-Host "" Write-Host "=== SUMMARY ===" -ForegroundColor Cyan Write-Host "Total unattached disks: $($disks.Count)" -ForegroundColor White $totalSizeGB = ($disks | Measure-Object -Property DiskSizeGB -Sum).Sum Write-Host "Total size: $totalSizeGB GB" -ForegroundColor White # Group by resource group $byResourceGroup = $disks | Group-Object -Property ResourceGroup | Sort-Object Count -Descending Write-Host "" Write-Host "By Resource Group:" -ForegroundColor Cyan foreach ($group in $byResourceGroup) { $groupSizeGB = ($group.Group | Measure-Object -Property DiskSizeGB -Sum).Sum Write-Host " $($group.Name): $($group.Count) disks ($groupSizeGB GB)" -ForegroundColor White } # Show Kubernetes-related disks $k8sDisks = $disks | Where-Object { $_.CreatedBy -or $_.PVCNamespace -or $_.PVCName } if ($k8sDisks.Count -gt 0) { Write-Host "" Write-Host "Kubernetes-related disks: $($k8sDisks.Count)" -ForegroundColor Magenta # Show detailed Kubernetes disk information Write-Host "" Write-Host "Kubernetes Disk Details:" -ForegroundColor Magenta $k8sDisks | Format-Table -AutoSize -Property @( 'Name', @{Name='CreatedBy'; Expression={$_.CreatedBy}; Width=20}, @{Name='PVCNamespace'; Expression={$_.PVCNamespace}; Width=15}, @{Name='PVCName'; Expression={$_.PVCName}; Width=20}, @{Name='SizeGB'; Expression={$_.DiskSizeGB}; Width=8} ) }
Tags
In the first version of the script, the query also tried to retrive the tags. This was not allowed by the query syntax, so I had to remove that from the query.
Basic query
Originally, copilot had a very easy to read query, with every field in a separate line. However, that gave the following error:
ERROR: argument --query: invalid jmespath_type value: "[?diskState=='Unattached'].{"
To learn more about --query, please visit: 'https://learn.microsoft.com/cli/azure/query-azure-cli'
I updated the query to be just on one line, which solved the issue.
Basic query fields
Two of the fields the query would ask for did not work. I had to check the actual field names in the output of `az disk list`. The fields `LastOwnershipUpdateTime` and `diskSizeGB` had wrong casing. I updated them to the correct casing.
All Tags
Even though I didin't ask for it, copilot also added the field `AllTags`, which contained all tags as a hashtable. It worked, but it made the csv output messy, so I commented the field out.
This wiki has been made possible by: