Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
163 commits
Select commit Hold shift + click to select a range
620c7e4
Updated to use package
andr317c Jan 23, 2026
90c592d
Updated setup and added read me
andr317c Jan 23, 2026
3fc9833
early state of locust infra
andr317c Apr 15, 2026
529632c
Add infra-only test path and harden cleanup
andr317c Apr 27, 2026
bd373fc
Document engineInstances and clean up skip-mode summary
andr317c Apr 27, 2026
93495d6
Restructure pipeline: scenarios, tier matrix, history NDJSON, validator
andr317c May 3, 2026
1f61ee6
Remove quality-gates pipeline; private repo doesn't need PR-triggered…
andr317c May 3, 2026
4aa2a35
Trim defensive features and docs for private-repo simplicity
andr317c May 3, 2026
4f1bd7c
Move history-* defaults into the variable group
andr317c May 3, 2026
c2301ec
Rename managed_by=bootstrap-script tag to ensure-script
andr317c May 3, 2026
28e44cf
Fix testSummary: replace compile-time directives with runtime PowerShell
andr317c May 3, 2026
1558c8c
Point pipeline at the new WIF service connection
andr317c May 3, 2026
3a47b17
Update README service connection name
andr317c May 3, 2026
08360dd
Support WIF auth in install script local-exec
andr317c May 4, 2026
28144a9
Skip testSummary on apply-failure; preserve cleanup chain
andr317c May 4, 2026
18e15b9
Drop Clean starter kit; the seeder already provides templates + content
andr317c May 4, 2026
269a521
Unsuppress install-script output in terraform apply log
andr317c May 4, 2026
04028e7
Hardcode admin password so the team can log into the backoffice
andr317c May 4, 2026
5bd5a0f
Drop dead SP-credential terraform variables
andr317c May 4, 2026
a367d29
Fix seeder package version pin for prereleases; fail loudly on dotnet…
andr317c May 4, 2026
05f077d
Pin seeder package to exact 17.0.0-beta.1 for reliability
andr317c May 4, 2026
fcb74b5
Added comma
andr317c May 4, 2026
b5cd657
Reshape ALT test + history layout for cross-run comparison
andr317c May 4, 2026
f998554
Mirror Umbraco Cloud tier specs (single P1v3 ASP + SQL eDTU)
andr317c May 4, 2026
3560b86
Fix server-side metric attribution + drop ALT abbreviation
andr317c May 4, 2026
f8c9f87
Inventory-driven locust workload + polish
andr317c May 4, 2026
2571334
Bump pinned seeder package to 17.0.0-beta.2
andr317c May 5, 2026
9486524
Drop final ALT residue in publish-to-history comment
andr317c May 5, 2026
87824a2
Locustfile: add contact-form write task + pacing-note caveat
andr317c May 5, 2026
f6695b0
Bump contact-form task weight 3 -> 8 for meaningful write signal
andr317c May 5, 2026
c273505
Add scripts/compare-runs.ps1 + README workflow section
andr317c May 6, 2026
70d6e0b
Decompose testCases JSON object into queue-friendly dropdowns
andr317c May 6, 2026
a423358
Refresh stale 'parameters.testCases' reference in prepare-test-cases …
andr317c May 6, 2026
d967748
Replace 8 queue params with single 'profile' dropdown
andr317c May 6, 2026
6c5ea74
Cleaned up
andr317c May 6, 2026
bea0a6a
Split queue UX: tier checkboxes + free-text version + auto .NET
andr317c May 6, 2026
e1d6fd2
Add DeliveryApi scenario + Locust Delivery API task splice
andr317c May 7, 2026
5122ae5
Add history-driven analysis tools: show-trends, check-regression, com…
andr317c May 7, 2026
5e25123
Pipeline + Terraform + scripts: robustness, auth, gates, server-side …
andr317c May 7, 2026
5a159bc
Overhaul README: first-time setup, smoke modes, comparison walkthrough
andr317c May 7, 2026
eeff07a
Revert storage auth to account-key (keeps SP permissions narrow)
andr317c May 7, 2026
af36d6c
Always emit regression-report file, even when history is empty
andr317c May 7, 2026
5a4bcf9
DeliveryApi scenario: add Program.cs overlay registering .AddDelivery…
andr317c May 7, 2026
4a104a1
DeliveryApi Program.cs: drop UseInstallerEndpoints() (gone in v17)
andr317c May 7, 2026
c850485
Parse engine_results.csv (JMeter format) when ALT emits no stats.csv
andr317c May 7, 2026
683697f
Add dashboard: static SPA + Entra-ID-gated SWA + deploy scripts
andr317c May 7, 2026
e2f981b
Dashboard cleanup + Tiers tab + drill-down + server-metric trends
andr317c May 8, 2026
df1bc38
Document dashboard maintenance + troubleshooting
andr317c May 8, 2026
556c769
Replace dashboard SPA with Workbook + Log Analytics ingestion path
andr317c May 8, 2026
139609f
Add backfill-monitoring.ps1: replay blob NDJSON into Log Analytics
andr317c May 8, 2026
6bb1189
ensure-monitoring-infra: friendly remediation when role grant fails
andr317c May 8, 2026
ffa2844
Extract results.zip before scanning for engine_results.csv
andr317c May 10, 2026
06179be
Workbook: showDefault on Workspace param so it auto-resolves
andr317c May 10, 2026
eb7a8b3
Workbook Workspace param: actually auto-fill via deploy-time substitu…
andr317c May 10, 2026
7107a24
Workbook: inline server-side delta union, drop UDF wrapper
andr317c May 10, 2026
e625043
Surface LA ingestion failures, align query window with retention, sin…
andr317c May 10, 2026
3d9059a
Workbook delta cells: fix '{0:p0}' literal rendering
andr317c May 10, 2026
1a9e8ea
Compare: grouped bar chart of p95 per sampler, baseline vs candidate
andr317c May 10, 2026
f298c60
LA retention 365d + Versions tab + drop ago(30d) on dropdown queries
andr317c May 10, 2026
655178d
ensure-history-infra: blob lifecycle policy (Hot → Cool 30d → Archive…
andr317c May 10, 2026
15ce877
Lifecycle: default Archive transition off, Cool-only
andr317c May 10, 2026
7dc004c
Workbook bar charts: pivot to wide format for side-by-side bars
andr317c May 10, 2026
5eb9eb1
Workbook readability pass: column rename, decimal cleanup, titles
andr317c May 10, 2026
0b19ea0
Workbook: capacity-verdict panel + RPS/server-side metrics in Trends
andr317c May 10, 2026
5d779ac
Tiers run #/threshold/precision + Versions overall delta vs baseline
andr317c May 10, 2026
1f911c0
Cost guard: monthly budget alert on the ephemeral RG (opt-in)
andr317c May 10, 2026
601be7b
Workbook: latest-run summary card at top of dashboard
andr317c May 10, 2026
f7d9a74
Surface regression-check verdict in the Workbook Runs tab
andr317c May 10, 2026
5512ecc
Workbook: resource-pressure timeline + AzDO build link on Run #
andr317c May 10, 2026
7258dbd
Fix budget end_date silent expiry + resource-timeline dimension loss
andr317c May 10, 2026
7936ff2
Workbook: tabs + numberFormat top-level + Build URL empty-state
andr317c May 12, 2026
2022e20
Added Jmeter load tests for v13
nhudinh0309 May 12, 2026
003d185
Added Jmeter load tests for v17
nhudinh0309 May 12, 2026
d2f433e
Workbook UX pass: vocab, tabs ordering, capacity Headroom, regression…
andr317c May 12, 2026
8d88db1
Workbook: run-indexed x-axis on Trends charts (was: time-binned Sum)
andr317c May 12, 2026
f044174
Workbook: add Plan CPU avg / SQL DTU avg alongside maxes
andr317c May 12, 2026
6b4deb9
Workbook: jargon sweep — readability over precision
andr317c May 12, 2026
c4a502b
Workbook: fix column_ifexists literal requirement; Err → Error; Compa…
andr317c May 12, 2026
c2357d1
Workbook: remove isempty(scenario_name) filter — there is no run-leve…
andr317c May 12, 2026
366625b
Workbook: remove final isempty(scenario_name) filter; soften version/…
andr317c May 12, 2026
eb9a42d
Workbook: pivot Trends/Resource queries so Workbook treats samplers a…
andr317c May 12, 2026
ac86b65
Workbook: simpler picker labels + non-redundant per-sampler tier table
andr317c May 12, 2026
7c9ab89
Workbook: long-form + group for Versions/Tiers bar charts (grouped, n…
andr317c May 12, 2026
2d6fb08
Workbook: consistency cleanup before next push
andr317c May 12, 2026
c2ed560
Workbook: surface Database physical reads + HTTP 4xx peaks
andr317c May 12, 2026
683a4bb
Workbook: define Max in vocab block
andr317c May 12, 2026
7c1b392
Workbook: vocab block — define Database CPU + align HTTP 4xx/5xx naming
andr317c May 12, 2026
405911f
Remove forceCleanup parameter — manual `az group delete` is simpler
andr317c May 12, 2026
083c697
Rename pipeline parameters for clarity
andr317c May 12, 2026
7fa876d
Split terraformDeploy mega-stage into four focused stages
andr317c May 12, 2026
cc855d2
publish-load-test-results: extract results.zip before scanning for CSVs
andr317c May 13, 2026
80eb0a9
Extract load-test config generation to scripts/generate-loadtest-conf…
andr317c May 13, 2026
2cbc0d5
README: align with parameter renames and stage split
andr317c May 13, 2026
4694554
Switch SQL to per-tier Elastic Pools; split locustfile per scenario
andr317c May 13, 2026
0960ff3
Show VU/duration per profile in the queue UI
andr317c May 13, 2026
63af521
Restore scenario dropdown for queue-time discoverability
andr317c May 13, 2026
c63237f
Set max_size_gb=50 on Elastic Pool (Standard tier minimum)
andr317c May 13, 2026
fd7c39a
Add Enterprise tier + dedicated per-tier App Service SKUs
andr317c May 13, 2026
8cfd821
tiers.json: drop "pending confirmation" caveat
andr317c May 13, 2026
24e5cc7
Remove pr-validation.yml — no PR-triggered checks
andr317c May 13, 2026
445f5e0
Updated
andr317c May 13, 2026
2e52e5c
Refactor: bug fixes, v13–v18 support, dedupe, drift cleanup
andr317c May 13, 2026
78d2b94
resolve-run-config: take tier flags as [string], compare to 'True'
andr317c May 13, 2026
c3b1da2
Group A: introduce scripts/_helpers.ps1 + route storage-key fetch thr…
andr317c May 14, 2026
a02b48e
Group B: bug fixes from add/seed-package-usage
andr317c May 14, 2026
f69d20d
Updated logic to get random published content in v13
nhudinh0309 May 14, 2026
8376e62
Updated logic to get random content in v17
nhudinh0309 May 14, 2026
57e9618
Updated name when saving document type
nhudinh0309 May 14, 2026
ed9c7da
Group C: dead-code removal from add/seed-package-usage
andr317c May 14, 2026
f0ab7d9
Group D: consistency — Mandatory params, Write-PipelineError, comment…
andr317c May 14, 2026
aa21cb6
Group E: v13–v18 support (adapted to dashboard's naming)
andr317c May 14, 2026
dc32764
Group F: README updates for v13–v18 support + Pitfalls section
andr317c May 14, 2026
7d69e5d
Align dashboard with seed branch: shared parser, helper use, optional…
andr317c May 14, 2026
84d751b
Added step to view content page after publishing
nhudinh0309 May 15, 2026
bdca44b
WIP: pre-review improvements across scripts, workbook, locustfile
andr317c May 18, 2026
5ccd171
check-regression: split cellKey with limit 3
andr317c May 18, 2026
3a1760b
ensure-monitoring-infra: add run_started_at column
andr317c May 18, 2026
436ba64
publish-load-test-results: flatten across all metric timeseries
andr317c May 18, 2026
d03e6ff
show-trends: version-aware sort for $versions
andr317c May 18, 2026
7a7957b
azure-pipeline: gate regressionCheck on runLoadTests Succeeded, not s…
andr317c May 18, 2026
e71855d
pr-validation: add JSON syntax check
andr317c May 18, 2026
99f2bb4
locust: randomise contact-form payload + catch_response assert
andr317c May 18, 2026
68d5fa3
workbook: chronological x-axis on trends + resources charts
andr317c May 18, 2026
adc3377
workbook: filter Tiers/Versions pickers to parse_status=ok rows
andr317c May 18, 2026
1b3b719
validator: hard-block majors lacking a published seeder
andr317c May 18, 2026
d3da82b
README: sweep drift vs current pipeline + workbook
andr317c May 18, 2026
b9d8019
Merge add/seed-package-usage (taking theirs on conflicts)
andr317c May 18, 2026
b88c2a7
resolve-run-config: hard-block majors lacking a published seeder
andr317c May 18, 2026
9d0b1fc
locust: randomise contact-form payload + catch_response assert
andr317c May 18, 2026
482d6fa
README: fix Local-checks paths after merge
andr317c May 18, 2026
2b5b62a
README: reflect seeder-availability gating + DTU run name
andr317c May 18, 2026
97edb82
publish-load-test-results: restore LA mirror + window guard lost in m…
andr317c May 18, 2026
2d46a63
ensure-monitoring-infra: add pool_dtu_max column
andr317c May 18, 2026
ebf1261
azure-pipeline: restore ensureMonitoringInfra stage lost in merge
andr317c May 18, 2026
ce9787b
README: pipeline workflow now reflects ensureMonitoringInfra stage
andr317c May 18, 2026
e27d697
Enable v13-v18: assume seeders shipped (v18 falls back to v17)
andr317c May 18, 2026
5e63c15
README: drop PR-triggered CI reference
andr317c May 18, 2026
3690d2d
Cleaned up
andr317c May 18, 2026
84d90c9
Updated to support 13
andr317c May 19, 2026
d106b5f
seeder: capture per-case duration into LoadTestSummary_CL
andr317c May 19, 2026
c69f4ac
load-test-job: warm every endpoint + surface seeder duration
andr317c May 19, 2026
61bfb6d
workbook: aggregate Tiers across runs, filter cold-start, fix drill-d…
andr317c May 19, 2026
03836f7
dashboard: per-run drill-down series + shared build cache
andr317c May 20, 2026
959dd1a
workbook: harden joins, top-issues fix, sampler picker, legend cleanup
andr317c May 20, 2026
bed15d8
load-test-job: warm every URL, drop suspect seeder=0
andr317c May 20, 2026
2a214b5
publish: surface Azure Monitor failures to pipeline summary
andr317c May 20, 2026
707a1d8
workbook: Sampler picker multi-select with All
andr317c May 20, 2026
3614689
publish: warn on zero datapoints from Azure Monitor
andr317c May 20, 2026
71bac45
pipeline: pass seeder results across stages via output variable
andr317c May 20, 2026
13bc0ec
pipeline: add seederPresetOverride, drop skipLoadTests
andr317c May 20, 2026
ef3662b
pipeline: tighten override label phrasing
andr317c May 20, 2026
0210d89
load-test-job: shorten run description under ALT 100-char cap
andr317c May 20, 2026
ca4b7b6
workbook: normalize join keys before summarize
andr317c May 20, 2026
f7a29e8
workbook: polish round — glossary tab, drill dropdown, side-by-side c…
andr317c May 20, 2026
63cc0ff
docs: README catches up with the last few commits
andr317c May 20, 2026
e711f27
workbook: Sampler picker isRequired so empty selection can't break KQL
andr317c May 20, 2026
ad978a9
workbook: Glossary Layout note includes Top issues in scope
andr317c May 20, 2026
6d4df26
workbook: remove Top issues panel
andr317c May 20, 2026
85960e4
workbook: regression-side aggregation uses take_any instead of arg_max
andr317c May 20, 2026
4c5095e
Merge pull request #7 from umbraco/add/dashboard-improvements
andr317c May 20, 2026
265e4d0
Merge pull request #5 from umbraco/add/dashboard
andr317c May 20, 2026
bad38cd
Merge pull request #4 from umbraco/add/jmeter-load-test-scripts
andr317c May 21, 2026
6cedc64
install-script: drop build cache, retry az webapp stop, fail-safe deploy
andr317c May 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,13 @@
*.exe
*.backup
*.tfstate

# Re-allow project files that the broad rules above would otherwise ignore.
!loadtests/tiers.json
!loadtests/scenarios/**/*.json
!dashboards/*.workbook.json
!**/.terraform.lock.hcl

.terraform/
.idea/
__pycache__/
6 changes: 0 additions & 6 deletions LoadTestVersions.yaml

This file was deleted.

927 changes: 927 additions & 0 deletions README.md

Large diffs are not rendered by default.

60 changes: 60 additions & 0 deletions Terraform/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 32 additions & 11 deletions Terraform/main.tf
Original file line number Diff line number Diff line change
@@ -1,27 +1,48 @@
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = ">=4.20.0"
source = "hashicorp/azurerm"
version = "~> 4.20"
}
}

required_version = ">= 1.3.9"

# Local state is fine for the ephemeral RG-per-run model. Uncomment the backend below
# for shared state (pre-create the `tfstate` container in the history storage account).
# backend "azurerm" {
# resource_group_name = "umbraco-loadtest-history-rg"
# storage_account_name = "<your-history-storage-account>"
# container_name = "tfstate"
# key = "loadtest.tfstate"
# }
}

provider "azurerm" {
features {}
}

# Read tier catalog from loadtests/tiers.json.
locals {
tier_specs = jsondecode(file("${path.module}/../loadtests/tiers.json")).tiers
}

module "umbraco" {
source = "./modules/umbraco"
source = "./modules/umbraco"

resource_name_prefix = var.resource_name_prefix
resource_group_location = var.resource_group_location
resource_group_name = var.resource_group_name
umbraco_cms_versions = var.umbraco_cms_versions
# Azure Login Credentials
client_id = var.client_id
client_secret = var.client_secret
tenant_id = var.tenant_id
app_service_plan_sku = var.app_service_plan_sku
}
resource_group_location = var.resource_group_location

tier_specs = local.tier_specs
test_cases = var.test_cases
seeder_preset = var.seeder_preset
pool_dtu_override = var.pool_dtu_override
app_sku_override = var.app_sku_override

budget_alert_amount = var.budget_alert_amount
budget_alert_threshold_pct = var.budget_alert_threshold_pct
budget_alert_emails = var.budget_alert_emails

build_id = var.build_id
}
198 changes: 167 additions & 31 deletions Terraform/modules/umbraco/main.tf
Original file line number Diff line number Diff line change
@@ -1,55 +1,191 @@
# Resource group
locals {
tiers_in_use = toset([for v in var.test_cases : v.tier])

# Azure SQL admin login must start with a letter; prefix one since random_string can start with a digit.
sql_admin_login = "u${random_string.admin_login.result}"

# Per-DB DTU cap per tier, with the queue-time override applied if set.
# The override lets a run size SQL independently of the app tier to isolate
# which side is the bottleneck.
tier_db_dtu = {
for t in local.tiers_in_use :
t => var.pool_dtu_override != 0 ? var.pool_dtu_override : var.tier_specs[t].dtu_max
}

# Pool eDTU capacity: smallest valid Standard pool that can hold a DB at the
# tier cap. Standard pool minimum is 50; bump to 100 when the per-DB cap
# requires it. Beyond 100 the next valid Standard step is 200.
tier_pool_dtu = {
for t, db_dtu in local.tier_db_dtu :
t => db_dtu <= 50 ? 50 : db_dtu <= 100 ? 100 : 200
}

common_tags = {
project = "umbraco-loadtest"
managed_by = "terraform"
build_id = var.build_id
}
}

resource "azurerm_resource_group" "rg" {
name = var.resource_group_name
location = var.resource_group_location
tags = local.common_tags
}

# Cost guard: monthly budget on the ephemeral RG that emails when MTD spend
# crosses the threshold percentage. Skipped entirely when budget_alert_emails
# is empty (the default) so it stays opt-in.
#
# Trade-offs:
# * Monthly grain is Azure's smallest budget window — there's no per-run /
# per-hour. A single run accruing $4 won't fire (well below 80% × $50);
# the alert protects against MULTIPLE forgotten gates compounding within
# a billing month, OR a runaway loop.
# * The budget resource itself is destroyed when terraform destroy runs at
# end-of-pipeline cleanup, so an "orphaned" RG that survives cleanup also
# loses its budget — at which point you'd want a subscription-scope budget
# instead. Out of scope here; this RG-scope budget covers the normal case.
resource "azurerm_consumption_budget_resource_group" "ephemeral" {
count = length(var.budget_alert_emails) > 0 ? 1 : 0
name = "${var.resource_group_name}-budget"
resource_group_id = azurerm_resource_group.rg.id

amount = var.budget_alert_amount
time_grain = "Monthly"

# Start of current month, in UTC. formatdate keeps it stable across re-applies
# within the same month; a re-apply in a new month will roll the start date
# forward, which is the desired behavior for monthly grain.
#
# end_date is set explicitly ~10 years out. azurerm provider defaults this
# to start_date + 1 year, which silently disables the budget after 12
# months from initial apply — easy to miss because Terraform doesn't drift-
# detect a "budget that no longer monitors anything". Pushing it ~decade
# out makes the time window long enough that re-applies (which always
# happen on each pipeline run) will refresh start_date well before
# end_date matters.
time_period {
start_date = formatdate("YYYY-MM-01'T'00:00:00'Z'", timestamp())
end_date = formatdate("YYYY-MM-01'T'00:00:00'Z'", timeadd(timestamp(), "87600h"))
}

notification {
enabled = true
threshold = var.budget_alert_threshold_pct
operator = "GreaterThan"
threshold_type = "Actual"
contact_emails = var.budget_alert_emails
}

lifecycle {
# start_date drifts via timestamp() on every plan; ignoring its diff
# avoids spurious "in-place update" plans that don't change semantics.
ignore_changes = [time_period]
}
}

# Random string for SQL server login
resource "random_string" "admin_login" {
length = 16
special = false
depends_on = [azurerm_resource_group.rg]
length = 15
special = false
}

# SQL admin password. Azure SQL needs 3 of 4 char categories; force upper+lower+numeric.
resource "random_password" "admin_password" {
length = 16
special = false
depends_on = [azurerm_resource_group.rg]
length = 24
special = false
min_upper = 1
min_lower = 1
min_numeric = 1
}

# App Service Plan
# One plan per tier in use; same-tier cases share it (only one app hot at a time).
# Override lets a run size the app independently of the tier (paired with
# pool_dtu_override on the SQL side) to isolate app-vs-SQL bottlenecks.
resource "azurerm_service_plan" "appserviceplan" {
name = "${var.resource_name_prefix}-appserviceplan"
for_each = local.tiers_in_use
name = "${var.resource_name_prefix}-asp-${lower(each.key)}"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
os_type = "Windows"

# We are using a variable for the sku version because we want to be able to change it if needed.
sku_name = var.app_service_plan_sku
sku_name = var.app_sku_override != "" ? var.app_sku_override : var.tier_specs[each.key].app_sku
tags = merge(local.common_tags, { tier = each.key })
}

# SQL server per tier - hosts the tier's Elastic Pool. One server per tier keeps
# the case-level resource graph identical between same-tier cases (they share
# server + pool) and matches the Cloud model where each plan has its own pool.
resource "azurerm_mssql_server" "sql_server" {
for_each = local.tiers_in_use
name = "${var.resource_name_prefix}-sql-${lower(each.key)}"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
version = "12.0"
administrator_login = local.sql_admin_login
administrator_login_password = random_password.admin_password.result
minimum_tls_version = "1.2"
tags = merge(local.common_tags, { tier = each.key })
}

resource "azurerm_load_test" "load_test" {
location = var.resource_group_location
name = "${var.resource_name_prefix}-loadtest"
resource_group_name = var.resource_group_name
resource "azurerm_mssql_firewall_rule" "allow_azure_services" {
for_each = local.tiers_in_use
name = "AllowAzureServices-${lower(each.key)}"
server_id = azurerm_mssql_server.sql_server[each.key].id
start_ip_address = "0.0.0.0"
end_ip_address = "0.0.0.0"
}

depends_on = [azurerm_service_plan.appserviceplan]
# Standard-tier Elastic Pool per tier. Pool eDTU is the smallest valid Standard
# size that can hold a DB at the tier cap; per-DB max DTU equals the cap.
# max_size_gb=50 is the Standard-tier minimum; our test data is well under that,
# so the floor is enough and avoids paying for storage we won't use.
resource "azurerm_mssql_elasticpool" "pool" {
for_each = local.tiers_in_use
name = "${var.resource_name_prefix}-pool-${lower(each.key)}"
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
server_name = azurerm_mssql_server.sql_server[each.key].name
max_size_gb = 50
tags = merge(local.common_tags, { tier = each.key })

sku {
name = "StandardPool"
tier = "Standard"
capacity = local.tier_pool_dtu[each.key]
}

per_database_settings {
min_capacity = 0
max_capacity = local.tier_db_dtu[each.key]
}
}

# We create a module called versions, the reason for that is because we want to have multiple app services with different Umbraco Versions.
# Azure Load Testing resource lives in a long-lived RG (see scripts/ensure-history-infra.ps1).

module "versions" {
# We use a for_each so it creates a module for each version of Umbraco we have defined in variables.
for_each = var.umbraco_cms_versions
source = "./versions"
for_each = var.test_cases
source = "./versions"

resource_name_prefix = var.resource_name_prefix
resource_group_name = azurerm_resource_group.rg.name
resource_group_location = azurerm_resource_group.rg.location
service_plan_id = azurerm_service_plan.appserviceplan.id
dotnet_version = each.value["dotnet_version"]
umbraco_cms_version = each.value["umbraco_version"]
admin_login = random_string.admin_login.result
admin_password = random_password.admin_password.result
client_id = var.client_id
client_secret = var.client_secret
tenant_id = var.tenant_id
}
service_plan_id = azurerm_service_plan.appserviceplan[each.value.tier].id

test_case_id = each.key
dotnet_version = each.value.dotnet_version
umbraco_version = each.value.umbraco_version
scenario = each.value.scenario
app_settings_overlay = each.value.app_settings_overlay

admin_login = local.sql_admin_login
admin_password = random_password.admin_password.result

sql_server_name = azurerm_mssql_server.sql_server[each.value.tier].name
sql_server_id = azurerm_mssql_server.sql_server[each.value.tier].id
sql_server_fqdn = azurerm_mssql_server.sql_server[each.value.tier].fully_qualified_domain_name
elastic_pool_id = azurerm_mssql_elasticpool.pool[each.value.tier].id
sql_firewall_rule_dependency = azurerm_mssql_firewall_rule.allow_azure_services[each.value.tier].id

seeder_preset = var.seeder_preset
common_tags = local.common_tags
}
Loading