Repository navigation
fix(azure/savingsplans): take the inventory resource type from the SKU, not the ARM name - #494
Conversation
…U, not the ARM name convertSavingsPlan set ResourceType from the ARM resource name, which is GUID-shaped, while recommendations use "Compute". recfilter.DuplicateChecker keys on ResourceType, so an owned plan never suppressed a repeat recommendation and the duplicate guard failed open. ResourceType now comes from sku.name: Compute_Savings_Plan maps to the shared computeResourceType constant used on both sides. A missing, empty or unknown SKU returns an error, so GetExistingCommitments fails closed through the existing "incomplete savings plan inventory" path. There is no fallback to Name. Not verified against a live response: the SKU value comes from the armbillingbenefits SDK examples. Closes #492 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…U case-insensitively SKU errors now include the plan ID and say the SKU mapping needs extending. The SKU is matched with strings.EqualFold against the existing armSkuComputeSavingsPlan constant, so one plan with different casing does not block the whole subscription. The dedupe test now builds its recommendation through convertBenefitRecommendation, so a wrong constant on either side fails it. Refs #492 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@coderabbitai review |
|
Warning Review limit reached
This review includes 7 billable files and costs up to $1.75.
Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing. Or wait 21 minutes for your next included review. View limit details
Comment |
|
Independent review verdict: CLEAN at bbe16c7Reviewer: fresh Claude agent (Sonnet, high effort), not the author, cold brief, focused on the money path. The PR body was treated as a claim. Coordinator: claude-cc-reviewer. Blocking findings: none. Inventory and recommendations now emit the same type:
A missing or unknown SKU fails loud:
End to end: on an inventory error, Other consumers: no other consumer of the savings-plan inventory What was attacked and how (
Not verified: against a live Azure response, as the body says. Gate: labels are mirrored from #492 (p1). Merge once CI is green. |
…r return LeanerCloud#494 made convertSavingsPlan return an error and require a SKU. Propagate the error for plans billed to another subscription too, and give the covering-path fixtures the Compute_Savings_Plan SKU. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary
convertSavingsPlan(providers/azure/services/savingsplans/client.go) set the inventory commitment'sResourceTypefrom the ARM resource name. That name is the last segment of the savings plan ID (GUID-shaped in thearmbillingbenefitsSDK examples), while recommendations use"Compute".recfilter.DuplicateCheckerkeys onResourceType, so an owned plan would never suppress a repeat recommendation and the duplicate guard failed open.ResourceTypenow comes fromsku.name:Compute_Savings_Plan(the existingarmSkuComputeSavingsPlanconst, the only savings plan SKU in the SDK) maps to a sharedcomputeResourceType = "Compute", which the recommendation side now also uses. The match is case-insensitive (Azure SKU names are), so one plan with different casing does not block the subscription.GetExistingCommitments(fail closed, the same path as the existing empty-region and scope errors). The error names the plan ID and says to extend the SKU mapping inconvertSavingsPlan.sp.Nameis no longer read for the type;CommitmentIDstill comes fromsp.ID. Plans owned by other subscriptions are skipped before conversion, as on main.Closes #492
Not verified live
As the issue says, no real
SavingsPlanClient.NewListAllPagerresponse was inspected. The SKU value and the GUID-shaped name come from the SDK model and examples. If a real response lackedsku.name, inventory now errors and purchasing stops for that subscription (fail closed) instead of silently allowing a duplicate.Tests
TestOwnedPlanSuppressesComputeRecommendation: a fixture with a GUIDnameandsku.name: Compute_Savings_Plan, the recommendation built by the realconvertBenefitRecommendationfrom an SDK-shaped row, through the real client andDuplicateChecker. Fails on origin/main (the recommendation passes through), passes after.FailsClosedOnBadSKU: missing SKU, nil name, empty, and unknown SKU makeGetExistingCommitmentserror; the message names the plan ID.TestGetExistingCommitments_SKUMatchIsCaseInsensitive."name": "Compute"now also carry a SKU; the happy-path test asserts"Compute".Mutation probes (scratch copies): reading
sp.Nameagain, an inventory-only wrong const, an unknown SKU returning nil, and accepting any SKU each fail tests.Verification
make build,make vet,(cd providers/azure && GOWORK=off go test -race -short ./...), pinned golangci-lint v2.10.1 (0 issues), gofmt, and the commit/pre-push hooks pass. Fixture-based evidence only.Local review: two adversarial passes by a non-author reviewer. Pass 1 asked for the plan ID in the errors, case-insensitive matching, and an end-to-end recommendation in the dedupe test (all in the second commit); pass 2 found nothing actionable.
Overlap with #491
#491 also edits this file. Its
appendCoveringForeignPlanand new tests call the single-valueconvertSavingsPlanand use plan fixtures without a SKU, so whichever PR merges second needs a rebase plus a small compile and fixture fix (one textual hunk inappendOwnedPlans).🤖 Generated with Claude Code