Repository navigation
fix(azure): attribute single-scope savings plans billed to a billing account - #468
Conversation
|
Warning Review limit reached
This review includes 4 billable files and costs up to $1.00.
Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing. Or wait 16 minutes for your next included review. View limit details
Comment |
e1d3708 to
bf03f8c
Compare
Independent adversarial review: CLEAN at
|
…account
Plans billed to an EA billing account or an MCA billing profile used to
fail the whole savings plan inventory ("does not identify a subscription"),
so the duplicate checker blocked every purchase on those tenants.
planOwnedBy now classifies the billing scope as an exact subscription
(unchanged), an exact EA account or MCA account/billingProfiles scope, or
an error. For a billing-account scope only AppliedScopeType Single
resolves; Shared, ManagementGroup, nil and unknown values fail closed. A
Single plan names its subscription through SubscriptionID or ResourceGroupID
(exact shapes, blank SubscriptionID treated as absent, the two must agree,
a non-blank ManagementGroupID is an error). The named subscription owns
the plan because no subscription pays for it; a plan naming another
subscription is skipped and counted in one aggregate log line per call.
Errors and logs never contain the billing-account id.
Out of scope: Shared billing-account plans stay fail-closed (#272 stays
open), and plans billed by another subscription but applied to this one
are tracked in #466.
Refs #272
Refs #466
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
d7296ee to
c6457a8
Compare
|
#467 merged as
The commit is identical, so the CLEAN verdict for |
|
CI is green on head |
|
@coderabbitai review |
|
|
Merged by squash at the reviewed head
CR waived: quota, adversarial review + local verification + green CI. #272 stays open: shared-scope billing-account plans are a product decision, and #466 covers plans billed to another subscription. A retrospective CodeRabbit review will run when quota returns. |
Summary
This is PR B of the #272 slice. It is stacked on #467 (PR A), so merge #467 first, then retarget this PR to
mainso CI runs.Since #207, Azure savings plan inventory has failed closed.
GetExistingCommitmentserrors for every plan whosebillingScopeIdis not the client subscription. A tenant that buys savings plans at billing-account scope (EA or MCA) therefore gets no inventory and no duplicate check. This slice handles the case that can be attributed without guessing: a plan billed to a billing account whose applied scope is Single and names exactly one subscription.How each billing scope and applied scope is handled (
scope.go):/subscriptions/<sub>/providers/Microsoft.Billing/billingAccounts/{id}, or MCA.../billingAccounts/{id}/billingProfiles/{id}:and_./subscriptions/<sub>. ResourceGroupID must be exactly/subscriptions/<sub>/resourceGroups/<rg>. A blank SubscriptionID is treated as unset. When both are present they must agree. TenantID is ignored, because a subscription GUID belongs to one tenant.Out of scope.
Refs #272, #466
Verification (macOS, Go 1.26.9)
Commands
(cd providers/azure && GOWORK=off go test -race -short ./...)passes.make buildandmake vetpass.Tests
TestPlanOwnedBy_BillingAccountScopescovers both shapes, the suffix, trailing-slash and empty-profile rejections, blank-sub-with-RG, nil properties, an unknown enum, a management group, a sub/RG disagreement, and mixed-case literals. It also asserts that no error contains the account id.TestGetExistingCommitments_SDKBillingAccountSingleScoperuns SDK-shaped JSON through the real pager intoDuplicateCheckerfor five cases: ea-ours, mca-rg-ours, ea-other, single-no-subscription and shared.TestGetExistingCommitments_AggregateSkipLogis non-parallel and restores the log writer.client_test.go, onlyaccount-single-oursandaccount-single-otherchanged expectation.Fail-before. These fail on PR A's code: those two rows, 10 scope subtests, and the SDK cases ea-ours, mca-rg-ours and ea-other. The independent reviewer re-ran this after the tests were compacted.
Deletion probes. The reviewer ran these in scratch copies, and each fails a test:
billingProfiles,resourceGroupsor account-prefix comparison case-sensitiveReview. The plan had two passes and the diff had two passes, all by the same non-author reviewer. Pass 1 added strict scope shapes, the sub/RG rules and the aggregate log, and filed #466. Diff pass 1 added the mixed-case cases. No actionable findings remain on
d7296ee.This uses SDK-shaped fixtures only. No Azure call or purchase was made.
🤖 Generated with Claude Code