Skip to content

v0.2.0

Latest

Choose a tag to compare

@haflidif haflidif released this 02 Jul 11:27
· 1 commit to main since this release
2f6c1d3

Added

  • Continuous integration (.github/workflows/ci.yml) — runs on every push and pull
    request to main: parses every script under Windows PowerShell 5.1 (the toolkit's
    compatibility target), scans for PowerShell 7-only syntax, and runs PSScriptAnalyzer
    against a checked-in PSScriptAnalyzerSettings.psd1. The build fails on any parse error
    or Error-severity finding; Warnings are surfaced as annotations for triage.
  • Subscription / RG structural-limit visibility (Get-SubscriptionLimits.ps1) — a read-only
    collector for ARM control-plane limits that silently block deployments but are not capacity
    quotas. It counts live objects via Azure Resource Graph and the ARM control plane and compares
    each against the documented limit on Microsoft Learn: resource groups per subscription (vs 980),
    tags applied to the subscription (vs 50), and resources per resource group per type (vs 800,
    near/at-limit rows only). Opt-in switches add tags-per-resource density (-IncludeTagDensity,
    vs 50), subscription deployment history per location and distinct deployment locations
    (-IncludeDeploymentHistory, vs 800 / 10), role assignments at/below the subscription scope
    (-IncludeRoleAssignments, vs the fixed 4000), and an Informational resources-per-region
    inventory (-IncludeRegionInventory). Every row carries LimitSource=MicrosoftLearnDocumented,
    IsTrueQuota=False and a DocReference to the exact Learn article — these are documented ARM
    constants, not adjustable capacity quotas, and they do not feed the compute-only quota-groups
    feature. Reader-only. Resolves #16.
  • PaaS quota visibility (Get-PaasQuota.ps1) — a read-only collector for the data-PaaS tier.
    Azure SQL is reported as true quota from the Microsoft.Sql usage APIs: subscription/region
    counters (ServerQuota, VCoreQuota, RegionalVCoreQuotaForSQLDBAndDW, Managed Instance vCore
    quotas, etc.) and per-logical-server DTU quota (server_dtu_quota), each emitted generically with
    used / limit / available / PctUsed and OK / NearLimit / AtLimit flags; free-tier /
    promotional countdown counters (*Free*, *DaysLeft) are classified Informational so a healthy
    "full" countdown is not mistaken for exhaustion. Cosmos DB has no verified subscription/region
    RU/s quota API, so it is reported honestly as inventory: the per-account configured
    totalThroughputLimit (a real limit only when positive) and, optionally
    (-IncludeCosmosThroughputInventory), provisioned RU/s per SQL-API database and container, all
    flagged IsInformational. Scope via -Service AzureSQL|CosmosDB|All; supports -Location,
    -AllLocations and the standard subscription selectors. Does not feed the compute-only
    quota-groups feature. Reader-only. Resolves #15.
  • Storage quota visibility (Get-StorageQuota.ps1) — a read-only collector that reports the
    per-subscription, per-region storage-account count quota (the data behind
    az storage account show-usage, default limit 250) with used / limit / available / PctUsed and an
    OK / NearLimit / AtLimit flag (threshold via -NearLimitPct, default 80). Optionally
    (-IncludeDiskCapacityInventory) it adds an informational managed-disk capacity inventory —
    total provisioned GiB by region and disk SKU, summed from Resource Graph — explicitly flagged
    IsQuota=False / Informational with a blank limit, because Azure exposes no general
    per-subscription managed-disk capacity quota usage API. Supports -Location, -AllLocations and the
    standard subscription selectors. Reader-only. Resolves #14.
  • App Service quota visibility (Get-AppServiceQuota.ps1) — a read-only collector that joins App
    Service Plan inventory (Resource Graph) with the subscription/region
    Microsoft.Web/locations/{loc}/usages and per-plan Microsoft.Web/serverfarms/{name}/usages APIs
    (api-version 2025-05-01). Emits three row scopes — SubscriptionRegion, AppServicePlan, and an
    InventoryDerived row comparing each plan's current instance count to its documented tier scale-out
    ceiling (Basic 3 / Standard 10 / Premium v1 20 / Premium v2-v4 30 / Isolated 100) — with
    used / limit / available / PctUsed, NearLimit / AtLimit and PlanAtInstanceCeiling flags.
    True API-reported quota rows (IsTrueQuota=True) are kept distinct from documented/inventory rows via
    LimitBasis; SKUs without a fixed ceiling (Consumption / Flex Consumption) are flagged
    HasUnknownLimit rather than given a fabricated limit. Supports -Location, -AllLocations and the
    standard subscription selectors. Reader-only. Resolves #7.
  • Network quota visibility (Get-NetworkQuota.ps1) — a read-only collector that reports
    per-subscription, per-region Microsoft.Network usage vs limit (the data behind
    az network list-usages / the Microsoft.Network/locations/{loc}/usages API): Virtual Networks,
    Public IP Addresses, Network Interfaces, Load Balancers, NAT Gateways and the rest. Networking quota
    is a common, silent deployment blocker — you cannot create a VM if the subscription is out of public
    IPs or NICs in the region, regardless of compute headroom. Each counter is emitted with
    used / limit / available / PctUsed and NearLimit / AtLimit flags (threshold via
    -NearLimitPct, default 80). Counters the API returns with the placeholder 2147483647 limit are
    marked IsUnbounded (no fabricated math); per-VNet sub-counters (…PerVirtualNetwork) are flagged
    PerResourceScope. Supports -Location, -AllLocations, and the standard subscription selectors.
    Reader-only. Resolves #13.
  • AKS scale-headroom check (Get-AksScaleHeadroom.ps1) — a read-only derivation that answers
    "if every node pool scaled to its autoscaler maxCount, would we run out of family quota?" It
    joins data the toolkit already reads — AKS node pools (Resource Graph), Microsoft.Compute/skus
    (VM size → family + vCPUs) and az vm list-usage (per-family used/limit) — to compute the
    incremental vCPUs each pool needs to reach its target, aggregates per VM family, and flags
    families that cannot fully scale within current quota. Pools in the same family are summed
    before comparison; Spot pools are checked against the separate regional low-priority pool, never
    the regular family quota; autoscale-disabled pools target their current count. Emits a per-pool
    detail CSV and a per-family rollup CSV, with Finding codes
    (OK / QuotaShortfall / MissingSkuMetadata / MissingQuotaFamily / SpotQuotaCheckNeeded).
    Reader-only. Resolves #12.
  • Capacity Reservation inventory (Get-CapacityReservations.ps1) — a read-only collector that
    enumerates Microsoft.Compute/capacityReservationGroups and their child capacityReservations
    across visible subscriptions (ARM read, api-version 2024-07-01, $expand=instanceView) and reports,
    per reservation, the SKU, region, zone, reserved instance count, the capacity actually reserved at
    runtime, how many instances are consuming it, and idle / over-allocated / at-capacity flags. This
    closes the loop on the one construct that guarantees capacity (as distinct from quota), which
    docs/concepts.md already teaches. Reader-only; empty and unreadable (shared-scope) groups are
    surfaced as explicit rows. Resolves #11.
  • Spot Placement Score lens (Get-SpotPlacementScore.ps1) — a read-only collector that calls the
    Azure Spot Placement Score API (Microsoft.Compute/locations/.../placementScores/spot/generate,
    api-version 2025-06-05) to return an allocation-likelihood signal (High / Medium / Low) per
    VM size × region × zone — the closest programmatic answer to the toolkit's "quota ≠ capacity"
    caveat. It scores Spot capacity (a proxy for regional pressure, not an on-demand guarantee), is
    time-sensitive (every row timestamped), and needs the read-only built-in "Compute Recommendations
    Role"
    in addition to Reader. Chunks requests to the API limits (≤8 regions × ≤5 sizes) and handles
    throttling / missing-role responses gracefully.
  • Quota Group rollout (opt-in write tool)Deploy-QuotaGroups.ps1, a generic,
    config-driven, idempotent engine that provisions Azure Quota Groups
    (Microsoft.Quota/groupQuotas) from a JSON design: registers providers, creates groups at
    a management-group scope, adds members, requests pooled group limits, and allocates quota to
    subscriptions. Requires PowerShell 7+, supports -WhatIf, and is guarded by ShouldProcess.
    This is the toolkit's only write capability and is kept separate from the read-only scans.
  • Quota Group config bridge (New-QuotaGroupConfig.ps1) — turns a quota report into a
    deploy-ready design, auto-detecting either the toolkit-native wide quota-usage CSV (from
    Get-QuotaUsage.ps1) or an external azure-quota-reports CSV; computes allocations and
    pooled group limits with a configurable headroom buffer.
  • Synthetic examples/quota-groups.sample.json design and a Quota Groups rollout
    guide; a "Services & coverage" matrix in the README.
  • AI & agent governance section in AGENTS.md — states the toolkit runs no AI models and sends
    no data to any model or third party; the only AI relationship is an agent operating it under the
    file's read-only-by-default guardrails.
  • Synthetic demo data generator (New-DemoDataset.ps1) — produces a complete,
    self-consistent fictional dataset ("Zava Inc") from a deterministic seed, with no Azure
    access required, so the dashboard can be previewed entirely offline. The generated universe
    exercises a range of dashboard states (SKU blocks and zone gaps, near-capacity quota, a GPU
    crunch, a pooled quota group, AKS lifecycle states, zone-redundant HA databases).

Changed

  • Positioning reframed to "read-only by default." Docs, badges and templates no longer claim
    zero mutations now that the opt-in Deploy-QuotaGroups.ps1 rollout ships: the README badge reads
    Mutations: opt-in only, and AGENTS.md / contributor guidance keep the analysis path strictly
    read-only while documenting the single opt-in write tool (Validate + -WhatIf + confirm before
    any execute run). No behaviour change to the analysis scripts.
  • Official Microsoft Learn references added throughout the docs — inline links at first mention
    of each concept (availability zones, regions, vCPU quotas, quota groups, VM sizes, Spot, Resource
    Graph, AKS / PostgreSQL / MySQL reliability) plus a consolidated "Further reading" table in
    concepts.md and pointers from the README, dashboard and quota-groups guides.
  • Documentation aligned across the expanded feature set. The README services matrix now lists
    Spot placement (Get-SpotPlacementScore) with an RBAC footnote; the "what it answers" lists in
    the README, docs/index.md and AGENTS.md now cover the non-compute quota surface (networking,
    App Service, storage, SQL/Cosmos, subscription/RG limits), capacity reservations and Spot; the
    concepts.md "Further reading" table gains Learn links for those services; and the
    "Reader-only" claims are clarified to note Spot placement needs the read-only Compute
    Recommendations Role.
  • Removed dead code surfaced by PSScriptAnalyzer — unused $allRegions in
    Get-RegionFootprint.ps1 (the region set is recomputed as $compareRegions in the
    comparison pass) and an unused $subCount in Get-SkuCatalogue.ps1. No behaviour change.

Fixed

  • Deploy-QuotaGroups.ps1 no longer breaks the Windows PowerShell 5.1 parser. The opt-in
    rollout tool used PowerShell 7-only ternary (? :) and null-coalescing (??) operators in
    seven places, so it failed to even tokenise under 5.1 and tripped the new CI parse gate. All
    were rewritten as 5.1-safe if/else expressions. (Executing a real rollout still requires
    PowerShell 7+, as before — this only ensures the script parses cleanly everywhere.)
  • New-EnablementRequest.ps1 now parses under Windows PowerShell 5.1. The file contained a
    single non-ASCII em-dash without a byte-order mark, which Windows PowerShell 5.1 decoded as
    ANSI and mis-tokenised, breaking the script. Replaced with an ASCII hyphen so the file stays
    pure ASCII like the rest of the toolkit. Also caught by the new CI parse gate.