Skip to content

Commit

Permalink
fix(estimation): 🩹 Fixed calculation of Burstable SKU in PostgreSQL
Browse files Browse the repository at this point in the history
  • Loading branch information
kamil-mrzyglod committed Apr 9, 2024
1 parent b4bd608 commit 5562534
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 19 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
**/dist/**
**/.terraform
**/.terraform.lock.hcl
**/tfplan
**/tfplan
**/.mono
**.csv
3 changes: 0 additions & 3 deletions ace-tests/Reworked/KeyVault/KeyVaultUsagePatternsTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
using System.Text.Json;
using ACE;

namespace ACE_Tests.Reworked.KeyVault;

[Parallelizable(ParallelScope.Self)]
Expand Down
34 changes: 34 additions & 0 deletions ace-tests/Reworked/PostgreSQL/PostgreSQLTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
namespace ACE_Tests.Reworked.PostgreSQL;

[Parallelizable(ParallelScope.Self)]
public class PostgreSQLTests
{
[Test]
public void PostgreSQL_Basic_WhenThereIsBurstableSKU_ItShouldNotThrowExceptionAndGiveCorrectEstimation()
{
var outputFilename = $"ace_test_{DateTime.Now.Ticks}";
var exitCode = Program.Main([
"templates/reworked/postgresql/fix-261.bicep",
"cf70b558-b930-45e4-9048-ebcefb926adf",
"arm-estimator-tests-rg",
"--generateJsonOutput",
"--jsonOutputFilename",
outputFilename,
"--debug",
"--mocked-retail-api-response-path",
"mocked-responses/retail-api/postgresql/burstable.json"
]);

Assert.That(exitCode, Is.EqualTo(0));

var outputFile = File.ReadAllText($"{outputFilename}.json");
var output = JsonSerializer.Deserialize<EstimationOutput>(outputFile, Shared.JsonSerializerOptions);

Assert.That(output, Is.Not.Null);
Assert.Multiple(() =>
{
Assert.That(output.TotalCost.OriginalValue, Is.EqualTo(14.990300000000001d));
Assert.That(output.TotalResourceCount, Is.EqualTo(1));
});
}
}
4 changes: 3 additions & 1 deletion ace-tests/Usings.cs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
global using NUnit.Framework;
global using ACE_Tests;
global using ACE_Tests;
global using ACE;
global using System.Text.Json;
1 change: 1 addition & 0 deletions ace-tests/azure-cost-estimator-tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
<None Remove="mocked-responses\retail-api\asr\inferred-3.json" />
<None Remove="mocked-responses\retail-api\automation-account\usage-patterns.json" />
<None Remove="templates/reworked/key-vault/usage-patterns-1.bicep" />
<None Remove="templates/reworked/postgresql/fix-261.bicep" />
<None Remove="templates/reworked/static-web-app/static-web-app-free.bicep" />
<None Remove="templates/reworked/static-web-app/static-web-app-standard.bicep" />
<None Remove="templates/reworked/virtual-network/peering-1-2.bicep" />
Expand Down
142 changes: 142 additions & 0 deletions ace-tests/mocked-responses/retail-api/postgresql/burstable.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
{
"Url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=priceType eq 'Consumption' and serviceId eq 'DZH3199QPQTD' and ((armRegionName eq 'westeurope' and skuName eq 'B1MS' and productName eq 'Azure Database for PostgreSQL Flexible Server Burstable BS Series Compute') or (armRegionName eq 'westeurope' and productName eq 'Az DB for PostgreSQL Flexible Server Storage'))",
"BillingCurrency": "USD",
"CustomerEntityId": "Default",
"CustomerEntityType": "Retail",
"Items": [
{
"currencyCode": "USD",
"tierMinimumUnits": 0.0,
"retailPrice": 0.104,
"unitPrice": 0.104,
"armRegionName": "westeurope",
"location": "EU West",
"effectiveStartDate": "2023-10-01T00:00:00Z",
"meterId": "1c8e77ad-b61c-5291-be61-cf764b588c92",
"meterName": "PMD V2 Throughput Prov Throughput (MBps)",
"productId": "DZH318Z0DCRX",
"skuId": "DZH318Z0DCRX/00LF",
"productName": "Az DB for PostgreSQL Flexible Server Storage",
"skuName": "PMD V2 Throughput",
"serviceName": "Azure Database for PostgreSQL",
"serviceId": "DZH3199QPQTD",
"serviceFamily": "Databases",
"unitOfMeasure": "1/Month",
"type": "Consumption",
"isPrimaryMeterRegion": true,
"armSkuName": "V2 throughput"
},
{
"currencyCode": "USD",
"tierMinimumUnits": 0.0,
"retailPrice": 0.1369,
"unitPrice": 0.1369,
"armRegionName": "westeurope",
"location": "EU West",
"effectiveStartDate": "2021-06-01T00:00:00Z",
"meterId": "36845e2a-736f-5a9d-af4e-b2dc7547a06f",
"meterName": "Storage Data Stored",
"productId": "DZH318Z0DCRX",
"skuId": "DZH318Z0DCRX/001G",
"productName": "Az DB for PostgreSQL Flexible Server Storage",
"skuName": "Storage",
"serviceName": "Azure Database for PostgreSQL",
"serviceId": "DZH3199QPQTD",
"serviceFamily": "Databases",
"unitOfMeasure": "1 GB/Month",
"type": "Consumption",
"isPrimaryMeterRegion": true,
"armSkuName": "Storage"
},
{
"currencyCode": "USD",
"tierMinimumUnits": 0.0,
"retailPrice": 0.1369,
"unitPrice": 0.1369,
"armRegionName": "westeurope",
"location": "EU West",
"effectiveStartDate": "2023-10-01T00:00:00Z",
"meterId": "50d9a511-fb6e-5113-8003-5a1ef7abca11",
"meterName": "Premium Managed Disk V2 Data Stored",
"productId": "DZH318Z0DCRX",
"skuId": "DZH318Z0DCRX/00C6",
"productName": "Az DB for PostgreSQL Flexible Server Storage",
"skuName": "Premium Managed Disk V2",
"serviceName": "Azure Database for PostgreSQL",
"serviceId": "DZH3199QPQTD",
"serviceFamily": "Databases",
"unitOfMeasure": "1 GiB/Month",
"type": "Consumption",
"isPrimaryMeterRegion": true,
"armSkuName": "Premium Managed Disk"
},
{
"currencyCode": "USD",
"tierMinimumUnits": 0.0,
"retailPrice": 0.0199,
"unitPrice": 0.0199,
"armRegionName": "westeurope",
"location": "EU West",
"effectiveStartDate": "2021-12-01T00:00:00Z",
"meterId": "5e31969e-0b91-5186-81a1-7475fabe1262",
"meterName": "B1MS",
"productId": "DZH318Z0DCRL",
"skuId": "DZH318Z0DCRL/003J",
"productName": "Azure Database for PostgreSQL Flexible Server Burstable BS Series Compute",
"skuName": "B1MS",
"serviceName": "Azure Database for PostgreSQL",
"serviceId": "DZH3199QPQTD",
"serviceFamily": "Databases",
"unitOfMeasure": "1 Hour",
"type": "Consumption",
"isPrimaryMeterRegion": true,
"armSkuName": "B1MS"
},
{
"currencyCode": "USD",
"tierMinimumUnits": 0.0,
"retailPrice": 0.0595,
"unitPrice": 0.0595,
"armRegionName": "westeurope",
"location": "EU West",
"effectiveStartDate": "2023-03-01T00:00:00Z",
"meterId": "75ef37c1-50db-5bc2-8bf5-ba9b97da69d2",
"meterName": "IOPS Scaling Provisioned IOPS",
"productId": "DZH318Z0DCRX",
"skuId": "DZH318Z0DCRX/00CG",
"productName": "Az DB for PostgreSQL Flexible Server Storage",
"skuName": "IOPS Scaling",
"serviceName": "Azure Database for PostgreSQL",
"serviceId": "DZH3199QPQTD",
"serviceFamily": "Databases",
"unitOfMeasure": "1/Month",
"type": "Consumption",
"isPrimaryMeterRegion": true,
"armSkuName": "IOPS Scaling"
},
{
"currencyCode": "USD",
"tierMinimumUnits": 0.0,
"retailPrice": 0.026,
"unitPrice": 0.026,
"armRegionName": "westeurope",
"location": "EU West",
"effectiveStartDate": "2023-10-01T00:00:00Z",
"meterId": "a3b9a7f9-8335-5ff1-b3bb-b8b82c26ac2a",
"meterName": "PMD V2 IOPS Provisioned IOPS",
"productId": "DZH318Z0DCRX",
"skuId": "DZH318Z0DCRX/00LJ",
"productName": "Az DB for PostgreSQL Flexible Server Storage",
"skuName": "PMD V2 IOPS",
"serviceName": "Azure Database for PostgreSQL",
"serviceId": "DZH3199QPQTD",
"serviceFamily": "Databases",
"unitOfMeasure": "1/Month",
"type": "Consumption",
"isPrimaryMeterRegion": true,
"armSkuName": "V2 IOPS"
}
],
"NextPageLink": null,
"Count": 6
}
20 changes: 20 additions & 0 deletions ace-tests/templates/reworked/postgresql/fix-261.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
param parSuffix string = utcNow('yyyyMMddhhmmss')
param parLocation string = resourceGroup().location

resource db1 'Microsoft.DBforPostgreSQL/flexibleServers@2022-12-01' = {
#disable-next-line use-stable-resource-identifiers
name: 'postgresqlserver1-${parSuffix}'
location: parLocation
sku: {
name: 'Standard_B1ms'
tier: 'Burstable'
}
properties: {
createMode: 'Default'
administratorLogin: 'login'
administratorLoginPassword: 'password'
storage: {
storageSizeGB: 64
}
}
}
28 changes: 14 additions & 14 deletions ace/Products/PostgreSQL/PostgreSQLFlexibleQueryFilter.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
using ACE.WhatIf;
using Microsoft.Extensions.Logging;
using System;
using System.Text.Json;

internal class PostgreSQLFlexibleQueryFilter : IQueryFilter
internal class PostgreSQLFlexibleQueryFilter(WhatIfAfterBeforeChange afterState, ILogger logger) : IQueryFilter
{
private const string ServiceId = "DZH3199QPQTD";

private readonly WhatIfAfterBeforeChange afterState;
private readonly ILogger logger;

public PostgreSQLFlexibleQueryFilter(WhatIfAfterBeforeChange afterState, ILogger logger)
{
this.afterState = afterState;
this.logger = logger;
}
private readonly WhatIfAfterBeforeChange afterState = afterState;
private readonly ILogger logger = logger;

public string? GetFiltersBasedOnDesiredState(string location)
{
Expand All @@ -28,29 +21,36 @@ public PostgreSQLFlexibleQueryFilter(WhatIfAfterBeforeChange afterState, ILogger
var tierId = this.afterState.sku?.tier;
var skuParts = sku.Split("_");
var familyId = skuParts[1];
var cores = skuParts[2];
var skuName = $"{cores} vCore";

string? skuProductName;
string? storageProductName;
string? productName;
string? skuName;

// Note that for some reasons some product names for PostgreSQL contain non-breaking space \u00A0
// meaning query won't work if we miss them. We may use armSkuName in the future
if (tierId == "Burstable")
{
// Always fun when there're magical edge cases :F
if(familyId.Equals("B1ms", StringComparison.CurrentCultureIgnoreCase) || familyId.Equals("B2s", StringComparison.CurrentCultureIgnoreCase))
{
familyId = familyId.ToUpper();
}

skuName = familyId;
skuProductName = "Burstable BS";
storageProductName = "Az DB for PostgreSQL Flexible Server Storage";
productName = $"Azure Database for PostgreSQL Flexible Server {skuProductName} Series Compute";
productName = $"Azure Database for PostgreSQL Flexible Server Burstable BS Series Compute";
}
else if (tierId == "GeneralPurpose")
{
skuName = $"{skuParts[2]} vCore";
skuProductName = $"General Purpose\u00A0{familyId}\u00A0";
storageProductName = "Az DB for PostgreSQL Flexible Server Storage";
productName = $"Azure Database for PostgreSQL Flexible Server {skuProductName}Series Compute";
}
else
{
skuName = $"{skuParts[2]} vCore";
skuProductName = $"Memory Optimized\u00A0{familyId}\u00A0";
storageProductName = "Az DB for PostgreSQL Flexible Server Storage";

Expand Down

0 comments on commit 5562534

Please sign in to comment.