Hello geeks!
What this script/runbook achieves:
This script retrieves all resources in a resourcegroup, sums up the values of each resource, and emails the total cost via gmail SMTP.
What i get in the mail once a day:
The script:
(I recommend that you download the script, instead of copy/paste)
Download script
<# .SYNOPSIS Displaying the cost of an Azure resourcegroup or subscription and email the total cost via gmail smtp. .DESCRIPTION This script captures all resources in a resourcegroup and calculates the cost based on the last x days. After the cost is retrieved an email will be sent. Don't forget to configure the SMTP settings in the bottom of the script. If you're using Gmail's 2-factor authentication you must create an app-specific password, more info about this here https://support.google.com/mail/answer/185833?hl=en If you want to calculate the cost of all resources in a subscription simply remove "-ResourceGroup $rsgrp" from line $SubConsumptionUsage. Required modules: AzureRM.Automation AzureRM.Consumption AzureRM.Profile AzureRM.Resources AzureRM.Storage AzureRM.Compute This script couldn't be possible if i haven't read Lawrence Wilsons article on octopus.com https://octopus.com/blog/saving-cloud-dollars A big thanks to him! .LINK More information about this script and more can be found on my website http://paegelow.se .NOTES Version: 1.0 Author: Robert Paegelow Creation Date: 2019-02-13 Contact: robert.paegelow@hotmail.com #> ################################### ## Connect to Azure via your RunAsAccount $Conn = Get-AutomationConnection -Name AzureRunAsConnection Connect-AzureRmAccount -ServicePrincipal -Tenant $Conn.TenantID -ApplicationId $Conn.ApplicationID -CertificateThumbprint $Conn.CertificateThumbprint | Out-Null ################################### ############################### ###### S E T T I N G S ###### ## Paste your subscription ID here: $SubscriptionId = "subscription ID" ############################### ################################### # If you set this to 30, the script will only show the cost of the last 30 days $days = "30" ################################### ################################### <# Resourcegroup is not mandatory if you want to show the cost of ALL resources, simply remove "-ResourceGroup $rsgrp" from line $SubConsumptionUsage #> $rsgrp = "group1" ################################### $now = get-Date $startDate = $($now.Date.AddDays(-$days)) $endDate = $($now.Date) $SubConsumptionUsage = Get-AzureRmConsumptionUsageDetail -StartDate $startDate -EndDate $endDate -ResourceGroup $rsgrp $SubIdPrefix = "/subscriptions/" + $SubscriptionId $RgIdPrefix = $SubIdPrefix + "/resourceGroups/" $resourceGroupName = @() $resourceGroups = @() foreach ($line in $SubConsumptionUsage) { if ($line.InstanceId -ne $null ) { $thisRgName = $($line.InstanceId.ToLower()).Replace($RgIdPrefix.ToLower(),"") $toAdd = $thisRgName.Split("/")[0] $toAdd = $toAdd.ToString() $toAdd = $toAdd.ToLower() $toAdd = $toAdd.Trim() if ($resourceGroups.Name -notcontains $toAdd) { $resourceGroupName = [PSCustomObject]@{ Name = $toAdd } $resourceGroups += $resourceGroupName } } } $currentResourceGroups = Get-AzureRmResourceGroup $rgIndexId = 0 foreach ($rg in $resourceGroups) { #$thisRg = $null $RgIdPrefix = $SubIdPrefix + "/resourceGroups/" + $rg.Name $ThisRgCost = $null $SubConsumptionUsage | ? { if ( $_.InstanceId -ne $null) { $($_.InstanceId.ToLower()).StartsWith($RgIdPrefix.ToLower()) } } | ForEach-Object { $ThisRgCost += $_.PretaxCost } $toaddCost = [math]::Round($ThisRgCost,2) $resourceGroups[$rgIndexId] | Add-Member -MemberType NoteProperty -Name "Cost" -Value $toaddCost if ($currentResourceGroups.ResourceGroupName -contains $rg.Name) { $addingResourceGroup = Get-AzureRmResourceGroup -Name $($rg.Name) $resourceGroups[$rgIndexId] | Add-Member -MemberType NoteProperty -Name "NotifyCostLimit" -Value $($addingResourceGroup.tags.NotifyCostLimit) } $rgIndexId ++ } $ActualCost = $resourcegroups.Cost ########################### ### SMTP Settings $email = "email" $pass = "password" $smtpServer = "smtp.gmail.com" $msg = new-object Net.Mail.MailMessage $smtp = new-object Net.Mail.SmtpClient($smtpServer) $smtp.EnableSsl = $true $msg.From = "$email" $msg.To.Add("$email") $msg.BodyEncoding = [system.Text.Encoding]::Unicode $msg.SubjectEncoding = [system.Text.Encoding]::Unicode $msg.IsBodyHTML = $true $msg.Subject = "[Azure] Cost Report" $msg.Body = "Azure cost last 30 days: $ActualCost USD" $SMTP.Credentials = New-Object System.Net.NetworkCredential("$email", "$pass"); $smtp.Send($msg)
Information about the Runbook
In my last post, i shared with you my Azure-hosted Pihole DNS-server.
Since Azure doesn’t cost monopoly money, i wanted to get a daily mail of the total cost of all my pihole-resources in a specific resourcegroup. That’s why this script was made.
This script retrieves all resources in a resourcegroup, sums up the values of each resource, and simply emails the total cost via gmail SMTP.
This script authenticates with your Azure RunAsAccount, if you want to run this script on your PC instead of in an Azure Automation Runbook, simply replace the authentication part of the script (line 41-42) with something like this:
if ([string]::IsNullOrEmpty($(Get-AzureRmContext).Account)) {Login-AzureRmAccount}
Required modules:
- AzureRM.Automation
- AzureRM.Consumption
- AzureRM.Profile
- AzureRM.Resources
- AzureRM.Storage
- AzureRM.Compute
Guide on how to create an azure runbook:
https://docs.microsoft.com/en-us/azure/automation/automation-quickstart-create-runbook
Just want to point out that i am not a professional in any way, and there could be plenty of improvements made to this script. So if you have any ideas of what could be improved, don’t hesitate to comment that down below.