Tag Archives: AzureRM.Consumption

[Azure] Automation Runbook – Retrieve total cost of resourcegroup or subscription

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.