Repository navigation
fix(aws): parse Cost Explorer EstimatedBreakEvenInMonths into BreakEvenMonths - #452
Conversation
…enMonths The RI parser never read ReservationPurchaseRecommendationDetail's EstimatedBreakEvenInMonths, so every AWS RI left BreakEvenMonths at 0 and common.BreakEven always fell back to deriving it from upfront and savings. Parse it through parseOptionalFloat so AWS's own figure takes the provider-wins branch. Absent or "0" stays 0 (unknown, derivation fallback); a present value that is empty, unparsable, non-finite or negative fails the detail like the other CE numeric fields. Closes LeanerCloud#390 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reached
This review includes 2 billable files and costs up to $0.50. Or wait 20 minutes for your next included review. View limit details
Comment |
Independent review verdict: CLEAN at 3db9c1cReviewer: 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. Verified:
Non-blocking notes and questions for the author:
What was attacked and how (providers/aws,
Gate:
|
|
Merge-driver status (claude-go-pr-merge-4): the CLEAN verdict above names the current head, so it stands. CI is green on that head and labels are mirrored. @IAmJSD, two things are needed to merge: rebase onto |
|
Brought up to date with |
|
The head moved to
CI is re-running on |
|
Merged |
|
The head moved to |
|
Merged |
|
Merge gate record at
Squash-merging with |
Root cause
Cost Explorer's
ReservationPurchaseRecommendationDetailincludesEstimatedBreakEvenInMonths, butproviders/aws/recommendations/parser_ri.gonever read it. Every AWS RI therefore hadBreakEvenMonths == 0, socommon.BreakEvenalways took its derivation path (upfront / (net monthly savings + upfront/term)). That path assumesEstimatedMonthlySavingsAmountis net of the amortized upfront, which the AWS docs never say. AWS's own estimate was thrown away.Fix
A new
parseBreakEvenMonthshelper, called fromparseRecommendationDetail, parses the field through the existingparseOptionalFloatintorec.BreakEvenMonths:"7.5") is stored, and the provider-wins branch ofcommon.BreakEvenuses it.--max-break-even-monthsnow filters on AWS's figure."0",BreakEvenMonthsstays 0. That means "unknown" in this field, so the derivation still runs as a fallback. A missing value never becomes a made-up 0 that short-circuits the derivation.EstimatedBreakEvenInMonths. This matches how the other CE numeric fields are handled, so the detail is reported as incomplete instead of being given an invented value.The Savings Plans detail (
SavingsPlansPurchaseRecommendationDetail) has no break-even field in the CE API, so SP recommendations are unchanged and keep using the derivation.No
pkgcode changes and no newpkgAPI. The test importspkg/scorer, which already exists in the published pkg version thatproviders/awspins.Interaction with #392
#392 ("BreakEven treats CommitmentCost 0 as a known zero upfront") changes the derivation inside
common.BreakEven. This PR does not touch that code. When AWS supplies a positiveEstimatedBreakEvenInMonths, the provider-wins branch returns before the code #392 changes, so #392 only affects AWS RIs where the field is absent or"0", plus all SP and other-provider recs. The two PRs should merge cleanly in either order.Verification
All tests run with
AWS_CONFIG_FILE=/dev/null AWS_SHARED_CREDENTIALS_FILE=/dev/null. No real AWS calls: the CE response is built by hand (not recorded), served through a fakeHTTPClient, and decoded by the real SDK deserializer.providers/aws/recommendations/parser_ri_breakeven_sdk_test.go:"7.5"and"4"are stored. Absent and"0"stay 0, andcommon.BreakEvenfalls back to the 6-month derivation."","seven","7.5 months","NaN","+Inf"and"-1"return an error and no recommendation.BreakEvenMonths == 4.2.BreakEvenMonths == 0.parser_ri.goreverted, the stored-value, scorer and corrupt-value subtests all fail. With the fix, they all pass.parseOptionalFloatOrWarn; drop the assignment; skip the call's error; fabricate a value for an absent field.providers/aws:go build ./...,go vet ./...andgo test ./...pass.GOWORK=off go test -race -short ./...passes.--allow-parallel-runners: 0 issues.gocyclo -over 10 parser_ri.go: clean.gofmt: clean.--register-awsplusscripts/setup-git-secrets.shpatterns, temp copy, isolated HOME): changed files scan clean, and a positive probe is still detected.Not verified against a live Cost Explorer account. AWS's documented string format for this field is assumed.
Out of scope
common.BreakEvenor scorer logic (see fix(common): BreakEven treats CommitmentCost 0 as a known zero upfront #392).EstimatedMonthlySavingsAmountis net of amortized upfront. The derivation still makes that assumption when the AWS value is missing.Maintainer: please mirror the issue's labels onto this PR (we cannot label in this repo):
priority/p2,severity/medium,triaged,urgency/this-sprint,impact/many,effort/s,type/bug.Closes #390
🤖 Generated with Claude Code