Repository navigation
Conversation
…chase and validate
PurchaseCommitment and buildValidateBody put SavingsPlanDetails.PlanType
("Compute") straight into sku.name. The SavingsPlanOrderAlias and
validatePurchase APIs name the SKU "Compute_Savings_Plan", the armSkuName
the Benefit Recommendations API returns and the SDK's
SavingsPlanOrderAliasCreate example sends.
Map PlanType to the ARM SKU name at the request boundary: "Compute" and
"Compute_Savings_Plan" both send "Compute_Savings_Plan"; any other value
fails closed before an Azure call. The PlanType vocabulary itself is
unchanged.
Closes LeanerCloud#387
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Comment |
Independent review verdict: CLEAN at 3251bd6Reviewer: fresh Claude agent (Sonnet, high effort), not the author, cold brief. The PR body was treated as a claim. Coordinator: claude-cc-reviewer. Blocking findings: none. What was verified:
Non-blocking notes:
What was attacked and how:
Gate:
|
Independent adversarial review: CLEAN at
|
|
Correction to my verdict above: that review ran on Sonnet. This repo's review gate ( |
|
Retraction of my correction above: it was wrong. I read the review gate from a stale local checkout. On |
|
Merge driver status: draft; waiting on the author to mark it ready. The independent verdict is posted above. Once it is un-drafted, I will update the branch with |
Root cause
savingsplans.Client.PurchaseCommitmentandbuildValidateBodycopiedSavingsPlanDetails.PlanTypestraight intosku.name. CUDly's PlanType is"Compute"(fromGetRecommendations/ benefit recommendations, #371 / #373, andGetValidResourceTypes). Azure names the SKUCompute_Savings_Plan. That is thearmSkuNamethe Benefit Recommendations API returns (this package already checks it asarmSkuComputeSavingsPlan), and the armbillingbenefits v1.0.0 SDK examples generated from the REST spec (SavingsPlanOrderAliasCreate.json,SavingsPlanOrderAliasCreateSingleScope.json,SavingsPlansPurchaseValidate.json) send it assku.name. So every Azure savings plan purchase and validate request sentsku.name: "Compute".Fix
The issue asked for a decision on the vocabulary. This PR maps at the request boundary, so the PlanType vocabulary stays as it is:
savingsPlanSKUName(planType)inclient.go:"Compute"and"Compute_Savings_Plan"both map to"Compute_Savings_Plan". Any other value returns an error.PurchaseCommitmentandbuildValidateBody(used byValidateOffering) use it. An unmapped PlanType now fails before any Azure call (BeginCreate/ValidatePurchaseare never reached), instead of sending asku.namethe API would reject. The match is exact: no case folding and no trimming, the same strictness ascommitmentCurrency.displayName(cudly-Compute-1yr),GetOfferingDetails.ResourceTypeand recommendation output are unchanged.Closes #387
Verification
All of this is unit / mock / fixture evidence. No real Azure API was called and nothing was purchased. Tests ran with
AWS_CONFIG_FILE=/dev/null AWS_SHARED_CREDENTIALS_FILE=/dev/nullbecause this machine's default AWS profile is invalid. That has no effect on the Azure module.New tests in
providers/azure/services/savingsplans/sku_name_test.go:TestSKUName_ComputePlanTypeSendsARMSKU: checks thesku.namecaptured from both theBeginCreatebody and theValidatePurchasebody, for PlanTypeComputeandCompute_Savings_Plan.TestSKUName_RecommendationRoundTrip: takes a recommendation fromGetRecommendationson the existing 2024-08-01 benefit-recommendation fixture row (armSkuName: Compute_Savings_Plan), purchases and validates it, and checks that the same SKU is sent.TestSKUName_UnknownPlanTypeFailsClosed:"",MachineLearning,compute," Compute"and"Compute_Savings_Plan "each return an error, and the alias and RP mocks record zero calls.Fail before (fix stashed, on
7383c3a):(Before the fix,
TestSKUName_UnknownPlanTypeFailsClosedalso failed, because the purchase went through to the mock.)Pass after:
Mutation probes. Each one was applied by hand, the tests were run, and the change was reverted:
PlanTypeagain: ComputePlanType and RoundTrip failPlanTypeagain: ComputePlanType and RoundTrip failCompute_Savings_Planinstead of failing: UnknownPlanTypeFailsClosed failscompute," Compute"): UnknownPlanTypeFailsClosed failsReal-cloud gap: the expected
sku.namecomes from the SDK's spec-generated examples and from the Benefit RecommendationsarmSkuName. It has not been checked against a liveSavingsPlanOrderAliasPUT orvalidatecall, and no purchase was made. The first real purchase or validate run would confirm it.Out of scope (deliberately not changed)
GetValidResourceTypesstill lists"MachineLearning". I don't know of a billingbenefits SKU name for it, so aMachineLearningPlanType now fails closed with a clear error instead of sendingsku.name: "MachineLearning". Whether to remove it from the list, or map it if Azure has such a SKU, is a separate decision.fetchOnDemandRateputs the plan type into a Retail PricesarmSkuName eq '<planType>'filter. It has no non-test callers, and it is unclear whether the right value there is a VM SKU or the savings plan SKU. Left alone.client_test.gois already over the 500-line guideline, so the new tests went into their own file instead of being added to it.Maintainer: please mirror the issue's triage labels on this PR:
priority/p2,severity/medium,urgency/this-quarter,impact/few,effort/s,type/bug,triaged.🤖 Generated with Claude Code