fix(open-data,hubs): align commitment discount eligibility with FOCUS spend and usage categories - #2284
Open
Roland Krummenacher (RolandKrummenacher) wants to merge 1 commit into
Conversation
… categories x_CommitmentDiscountSpendEligibility reported reservation pricing and x_CommitmentDiscountUsageEligibility reported savings plan pricing, which is the reverse of the FOCUS CommitmentDiscountCategory definition the toolkit uses everywhere else: a reservation is a Usage commitment (a quantity of usage) and a savings plan is a Spend commitment (an amount of money). Fixes the four components that carried the swap: - Update-CommitmentDiscountEligibility.ps1: the mapping moves into a new New-EligibilityRow helper so a unit test can pin the direction. - CommitmentDiscountEligibility.csv: the two columns are swapped for all 92,624 meters (36,287 rows change value). Verified against the Retail Prices API for a stratified sample of 12 meters covering all three value combinations. - IngestionSetup_v1_0.kql / IngestionSetup_v1_2.kql: the spend column now reads spMeters and the usage column reads riMeters. The "TODO: Check this to ensure it's correct" comment on the v1_2 block is resolved. The exclusion of reservation price rows from their own eligibility travels with riMeters. - open-data.md: corrects the two column descriptions and the sample rows. The best practice query in compute.md already used the correct mapping and is unchanged. This is a breaking change for consumers: the column names stay the same and the values change, so existing reports and queries return different results. Both changelog entries call that out. Fixes #2279 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Roland Krummenacher (RolandKrummenacher)
requested review from
Brett Wilson (MSBrett) and
Michael Flanakin (flanakin)
as code owners
August 26, 2026 15:36
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🛠️ Description
Fixes #2279.
x_CommitmentDiscountSpendEligibilityreported reservation pricing andx_CommitmentDiscountUsageEligibilityreported savings plan pricing. That is the reverse of the FOCUSCommitmentDiscountCategorydefinition the toolkit uses everywhere else: a reservation is a Usage commitment (you commit to a quantity of usage) and a savings plan is a Spend commitment (you commit to an amount of money).IngestionSetup_v1_2.kqlcontained both mappings ten lines apart — it assignedCommitmentDiscountCategorycorrectly, then assigned the eligibility columns the opposite way, under a// TODO: Check this to ensure it's correctcomment. That TODO is now resolved.What changed
src/scripts/Update-CommitmentDiscountEligibility.ps1New-EligibilityRowhelper and corrected. The change-summary key is now built from the row's own properties, so it can't drift from the CSV column order.src/open-data/CommitmentDiscountEligibility.csvIngestionSetup_v1_0.kql,IngestionSetup_v1_2.kqlspMeters, the usage column readsriMeters.docs-mslearn/toolkit/open-data.mdsrc/powershell/Tests/Unit/Update-CommitmentDiscountEligibility.Tests.ps1The exclusion of reservation price rows from their own eligibility (
and x_SkuPriceType != 'ReservedInstance') travels withriMetersto the usage column: it describes what an on-demand charge could be covered by, not the commitment row itself.The best practice query in
docs-mslearn/best-practices/compute.mdalready used the correct mapping and is unchanged.data-dictionary.mdand the Copilot Studioschema-reference.mdalso already described the columns per FOCUS, and now match the data.🚨 Breaking change
The column names stay the same and the values change. Any report, query, or dashboard reading either column produces different results after this update. Both changelog entries (FinOps hubs and Open data) are marked Breaking change.
For hubs specifically: prices ingested after upgrading carry the corrected values; rows ingested earlier keep the old values until they are reingested.
🧪 Verification
Corrected CSV values checked against the live Azure Retail Prices API (
api-version=2023-01-01-preview,meterRegion='primary') for a stratified sample of 12 meters covering all three value combinations — 12/12 match, including the00020329-e657-5687-9d1a-0be9876e5116meter from the issue and the two other sample rows inopen-data.md:Test runs:
Invoke-Pester ./src/powershell/Tests/Unit/*— 2397 passed, 0 failed (4 pre-existing skips)./src/scripts/Test-PowerShell -Lint— 3587 passed, 0 failedHubsKqlOperators.Tests.ps1+KqlJoinKinds.Tests.ps1— 587 passed, 0 failed📝 Note for #2246
Draft PR #2246 replaces the derived eligibility computation in both ingestion transforms with a lookup against the open data table. It touches the same lines, so it will conflict here. Once the CSV is corrected, that lookup inherits the corrected values — but its
x_SkuPriceType != 'ReservedInstance'guard should move from the spend column to the usage column, as it does in this PR.✅ Checklist
ms.dateupdated on both modifieddocs-mslearnfiles🤖 Generated with Claude Code