-
-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(estimation): ✨ Added support for Static Web Apps
- Loading branch information
1 parent
307f444
commit 99d778c
Showing
11 changed files
with
252 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
using System.Text.Json; | ||
using ACE; | ||
|
||
namespace ACE_Tests.Reworked.StaticWebApp | ||
{ | ||
[Parallelizable(ParallelScope.Self)] | ||
public class StaticWebAppTests | ||
{ | ||
[Test] | ||
public void StaticWebApp_WhenFreeTierIsUsed_NoCostShouldBeReported() | ||
{ | ||
var outputFilename = $"ace_test_{DateTime.Now.Ticks}"; | ||
var exitCode = Program.Main([ | ||
"templates/reworked/static-web-app/static-web-app-free.bicep", | ||
"cf70b558-b930-45e4-9048-ebcefb926adf", | ||
"arm-estimator-tests-rg", | ||
"--generateJsonOutput", | ||
"--jsonOutputFilename", | ||
outputFilename, | ||
"--inline", | ||
"parLocation=westeurope", | ||
"--debug" | ||
]); | ||
|
||
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(0)); | ||
Assert.That(output.TotalResourceCount, Is.EqualTo(1)); | ||
}); | ||
} | ||
|
||
[Test] | ||
public void StaticWebApp_WhenStandardTierIsUsed_CorrectCostShouldBeReported() | ||
{ | ||
var outputFilename = $"ace_test_{DateTime.Now.Ticks}"; | ||
var exitCode = Program.Main([ | ||
"templates/reworked/static-web-app/static-web-app-standard.bicep", | ||
"cf70b558-b930-45e4-9048-ebcefb926adf", | ||
"arm-estimator-tests-rg", | ||
"--generateJsonOutput", | ||
"--jsonOutputFilename", | ||
outputFilename, | ||
"--inline", | ||
"parLocation=westeurope", | ||
"--mocked-retail-api-response-path", | ||
"mocked-responses/retail-api/static-web-app/standard.json", | ||
"--debug" | ||
]); | ||
|
||
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(9d)); | ||
Assert.That(output.TotalResourceCount, Is.EqualTo(1)); | ||
}); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
ace-tests/mocked-responses/retail-api/static-web-app/standard.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{ | ||
"Url": "https://prices.azure.com/api/retail/prices?currencyCode='USD'&$filter=priceType eq 'Consumption' and serviceId eq 'DZH317GT8G5N' and armRegionName eq 'westeurope' and skuName eq 'Standard' and productName eq 'Static Web Apps' and meterName eq 'Standard App'", | ||
"BillingCurrency": "USD", | ||
"CustomerEntityId": "Default", | ||
"CustomerEntityType": "Retail", | ||
"Items": [ | ||
{ | ||
"currencyCode": "USD", | ||
"tierMinimumUnits": 0.0, | ||
"retailPrice": 9.0, | ||
"unitPrice": 9.0, | ||
"armRegionName": "westeurope", | ||
"location": "EU West", | ||
"effectiveStartDate": "2021-05-01T00:00:00Z", | ||
"meterId": "56c80fab-f20c-5e41-951d-667dc9503604", | ||
"meterName": "Standard App", | ||
"productId": "DZH318Z08W5K", | ||
"skuId": "DZH318Z08W5K/0002", | ||
"productName": "Static Web Apps", | ||
"skuName": "Standard", | ||
"serviceName": "Azure App Service", | ||
"serviceId": "DZH317GT8G5N", | ||
"serviceFamily": "Compute", | ||
"unitOfMeasure": "1/Month", | ||
"type": "Consumption", | ||
"isPrimaryMeterRegion": true, | ||
"armSkuName": "" | ||
} | ||
], | ||
"NextPageLink": null, | ||
"Count": 1 | ||
} |
12 changes: 12 additions & 0 deletions
12
ace-tests/templates/reworked/static-web-app/static-web-app-free.bicep
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
param parSuffix string = utcNow('yyyyMMddhhmmss') | ||
param parLocation string = resourceGroup().location | ||
|
||
resource app 'Microsoft.Web/staticSites@2023-01-01' = { | ||
#disable-next-line use-stable-resource-identifiers | ||
name: 'static-site-${parSuffix}' | ||
location: parLocation | ||
sku: { | ||
name: 'Free' | ||
} | ||
properties: {} | ||
} |
12 changes: 12 additions & 0 deletions
12
ace-tests/templates/reworked/static-web-app/static-web-app-standard.bicep
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
param parSuffix string = utcNow('yyyyMMddhhmmss') | ||
param parLocation string = resourceGroup().location | ||
|
||
resource app 'Microsoft.Web/staticSites@2023-01-01' = { | ||
#disable-next-line use-stable-resource-identifiers | ||
name: 'static-site-${parSuffix}' | ||
location: parLocation | ||
sku: { | ||
name: 'Standard' | ||
} | ||
properties: {} | ||
} |
12 changes: 3 additions & 9 deletions
12
ace/Products/ContainerRegistry/ContainerRegistryQueryFilter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
ace/Products/StaticWebApp/StaticWebAppEstimationCalculation.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
using ACE.Calculation; | ||
using ACE.WhatIf; | ||
|
||
namespace ACE; | ||
|
||
internal class StaticWebAppEstimationCalculation(RetailItem[] items, CommonResourceIdentifier id, WhatIfAfterBeforeChange change, double conversionRate) | ||
: BaseEstimation(items, id, change, conversionRate), IEstimationCalculation | ||
{ | ||
public IOrderedEnumerable<RetailItem> GetItems() | ||
{ | ||
return this.items.OrderByDescending(_ => _.retailPrice); | ||
} | ||
|
||
public TotalCostSummary GetTotalCost(WhatIfChange[] changess, IDictionary<string, string>? usagePatterns) | ||
{ | ||
double? estimatedCost = 0; | ||
var items = GetItems(); | ||
var summary = new TotalCostSummary(); | ||
|
||
foreach (var item in items) | ||
{ | ||
double? cost = 0; | ||
cost += item.retailPrice; | ||
|
||
estimatedCost += cost; | ||
|
||
if (summary.DetailedCost.ContainsKey(item.meterName!)) | ||
{ | ||
summary.DetailedCost[item.meterName!] += cost; | ||
} | ||
else | ||
{ | ||
summary.DetailedCost.Add(item.meterName!, cost); | ||
} | ||
} | ||
|
||
summary.TotalCost = estimatedCost.GetValueOrDefault(); | ||
|
||
return summary; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using ACE.WhatIf; | ||
using Microsoft.Extensions.Logging; | ||
|
||
internal class StaticWebAppQueryFilter(WhatIfAfterBeforeChange afterState, ILogger logger) : IQueryFilter | ||
{ | ||
private const string ServiceId = "DZH317GT8G5N"; | ||
|
||
private readonly WhatIfAfterBeforeChange afterState = afterState; | ||
private readonly ILogger logger = logger; | ||
|
||
public string? GetFiltersBasedOnDesiredState(string location) | ||
{ | ||
var sku = this.afterState.sku?.name; | ||
if (sku == null) | ||
{ | ||
this.logger.LogError("Can't create a filter for Static Web App when SKU is unavailable."); | ||
return null; | ||
} | ||
|
||
if(sku == "Free") | ||
{ | ||
return "FREE"; | ||
} | ||
|
||
return $"serviceId eq '{ServiceId}' and armRegionName eq '{location}' and skuName eq '{sku}' and productName eq 'Static Web Apps' and meterName eq 'Standard App'"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
using ACE.Extensions; | ||
using ACE.WhatIf; | ||
using Microsoft.Extensions.Logging; | ||
|
||
internal class StaticWebAppRetailQuery(WhatIfChange change, CommonResourceIdentifier id, ILogger logger, CurrencyCode currency, WhatIfChange[] changes, TemplateSchema template) | ||
: BaseRetailQuery(change, id, logger, currency, changes, template), IRetailQuery | ||
{ | ||
public RetailAPIResponse? GetFakeResponse() | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
public string? GetQueryUrl(string location) | ||
{ | ||
if (this.change.after == null && this.change.before == null) | ||
{ | ||
this.logger.LogError("Can't generate Retail API query if desired state is unavailable."); | ||
return null; | ||
} | ||
|
||
var change = this.change.GetChange(); | ||
if (change == null) | ||
{ | ||
this.logger.LogError("Couldn't determine after / before state."); | ||
return null; | ||
} | ||
|
||
var filter = new StaticWebAppQueryFilter(change, this.logger).GetFiltersBasedOnDesiredState(location); | ||
if(filter == "FREE") | ||
{ | ||
return filter; | ||
} | ||
|
||
return $"{baseQuery}{filter}"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters