Today on "Random Azure Stuff", I needed to tag all the existing resources in an Azure subscription with the resources CreatedTime property. This script is a mix of PowerShell and the Az CLI since the PS module didn't include CreatedTime. I'm sure you could do the whole thing without PS, but this worked for me.
$taggableArray = "$(taggable)".Split(',')
foreach ($resource in
((az resource list --query "[?tags.CreatedOnDate == null]")
| ConvertFrom-Json | Where { $taggableArray -contains $_.Type }))
{
if($resource.CreatedTime -eq $null) {
Write-Host -Message "--- CreatedTime is not available on $( $resource.Name ) --- "
continue
}
$resourceTags = ($resource.Tags | ConvertTo-Json | ConvertFrom-Json -AsHashTable)
?? @{}
$createdTime = [Datetime]::ParseExact($resource.CreatedTime,
'MM/dd/yyyy HH:mm:ss',$null).ToString('MM/dd/yyyy')
$resourceTags += @{CreatedOnDate=$createdTime}
Set-AzResource -Tag $resourceTags -ResourceId $resource.Id -Force -ErrorAction continue
Write-Host "Resource $( $resource.Name ) has had tags applied"
Write-Host ' '
}
The query let's use skip any resources that already has the CreatedOnDate tag. Additionally, some Azure resources do not support tagging. In order to skip attempting to process these. I got a CSV list from Microsoft's website for this. I then loaded it in Excel, filter the resources that are taggable, got rid of the extra data and then turned that into a comma separated string, which I then stuffed into the "taggable" pipeline variable. Finally, this variable is turned back into an array with the split function.
Next, let's grab all the resources that do not already have our CreatedOnDate. Obviously, you could use whatever tag name you want. We'll convert the resulting JSON to a PS object and then add a "where" clause to filter this down to taggable resource types.
If for some reason the CreatedTime property is not available, we'll just skip it.
For some reason the Tags are not a hash table, so I've added code to convert it. Not the prettiest thing but it worked. If there are no tags then we'll just set it to an empty hash table.
For our needs, we wanted to timestamp as month day year, but you can format as you need.
Next we add this tag with the time stamp and update the tags on the resource. If that errors then ignore it. The pipeline logs will show what fails but since it's just tags, I'd rather the whole thing complete versus stopping in the middle.
And that's it! There were some issues with updating some of the alerting and if a VM is off, it will not update the tags on the VM or any extensions.
Comments
You can also comment directly on GitHub.