Skip to content

chore(ri-exchange): forward the source RI availability zone to the go offering lookups - #1018

Merged
cristim merged 1 commit into
LeanerCloud:mainfrom
IAmJSD:fix/issue-921
Oct 17, 2026
Merged

cristim merged 1 commit into
LeanerCloud:mainfrom
IAmJSD:fix/issue-921

Conversation

@IAmJSD

@IAmJSD IAmJSD commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

Closes #921.

Go pin bump

All four cloud-commitments-go modules move from v0.0.0-20261015143912-740dfbd72456 to v0.0.0-20261016145956-551be568dc21, the merge commit of go#428.

Adaptation (the issue's items)

  1. convertForAutoExchange copies the source RI's AvailabilityZone into RIMetadataInfo. That's the only place the metadata is built, for both the scheduled reshape and the ladder exchange runner.
  2. A shared newConvertibleOfferingLookup replaces the two copied lookup closures, uses LookupOfferingParams, and passes the AZ into FindConvertibleOfferingParams.
  3. GET /api/ri-exchange/target-offerings passes the source AZ to the provider. The provider's two zone refusals (zonal without an AZ, regional with one) now return a 422 naming the source RI, instead of a 500. The provider has no exported error value for these, so the match is on message text. The tests use the real provider client, so a reworded message would fail them.
  4. The only compile breaks from the bump were the two closure signatures and the test closures that mirror them, including the integration-tagged internal/server/handler_ri_exchange_reservation_integration_test.go.

Tests

The new tests are internal/server/ri_exchange_zone_test.go and internal/api/target_offerings_zone_test.go. They run the real EC2 client against a fake EC2 API, so nothing reaches AWS and no exchange is made.

  • A zonal RI in us-east-1b sends that AZ on every lookup; a regional RI sends none.
  • On the scheduled path, a zonal RI with no AZ makes no lookup or quote, and its skip reason carries the refusal text.
  • On the API path, both refusals return 422 before any lookup.
  • Fail-before / pass-after: with the fix removed but the bump kept, 6 of the new tests fail. With the fix back, all pass.
  • Mutation probes: all 5 caught.

Verification

All runs used AWS_CONFIG_FILE=/dev/null AWS_SHARED_CREDENTIALS_FILE=/dev/null.

  • go build ./..., go vet ./... and go vet -tags integration ./... are clean.
  • The full test suite passes except TestAuthPublicRoutes_EveryRouteIsCSRFGuardedOrExempt. That test also fails on main, and test(api): classify the approval-details route in the AuthPublic CSRF guard (fixes red main) #1003 fixes it.
  • go test ./internal/mocks/ and make tidy-check pass.
  • golangci-lint v2.10.1 reports 0 issues. gocyclo -over 10 is clean after splitting out targetOfferingsForSource.
  • git-secrets is clean on a temp copy, and the allowlist self-test gives 42 PASS, 0 FAIL.
  • This branch merges cleanly with current main.

Out of scope

🤖 Generated with Claude Code

… offering lookups

Bump all four cloud-commitments-go modules from 740dfbd72456 to 551be568dc21
(cloud-commitments-go#427 zone-aware EC2 offering lookups, LeanerCloud#428
LookupOfferingParams and RIMetadataInfo.AvailabilityZone) and adapt:

- convertForAutoExchange sets RIMetadataInfo.AvailabilityZone from the source
  convertible RI, for both the scheduled reshape and the ladder exchange runner.
- One shared newConvertibleOfferingLookup adapts the EC2 client to the new
  exchange.LookupOfferingFunc and forwards AvailabilityZone into
  FindConvertibleOfferingParams; it replaces the two duplicated closures.
- GET /api/ri-exchange/target-offerings passes the source RI's AZ into
  ListTargetOfferingsParams, and maps the provider's zone refusals (zonal
  without an AZ, regional with one) to a 422 instead of a 500.

Closes LeanerCloud#921

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@IAmJSD IAmJSD added priority/p2 Backlog-worthy severity/medium Moderate harm urgency/this-sprint Within the current sprint type/chore Maintenance / non-user-visible triaged Item has been triaged impact/few Limited audience effort/s Hours labels Oct 16, 2026
@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

  • Run on-demand review

This review includes 8 billable files and costs up to $2.00.

Or wait 56 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: LeanerCloud/cloud-commitments-platform/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 946b36b4-d030-4045-96dc-673776cd8b53
📥 Commits

Reviewing files that changed from the base of the PR and between 173474e and 2dd8d6a.

⛔ Files ignored due to path filters: 1
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing: 8
  • go.mod
  • internal/api/handler_ri_exchange.go
  • internal/api/target_offerings_zone_test.go
  • internal/server/handler_ri_exchange.go
  • internal/server/handler_ri_exchange_reservation_integration_test.go
  • internal/server/handler_ri_exchange_test.go
  • internal/server/ladder_write.go
  • internal/server/ri_exchange_zone_test.go
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@cristim

cristim commented Oct 16, 2026

Copy link
Copy Markdown
Member

Independent review verdict: CLEAN at 2dd8d6a

Reviewer: 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.

Callers. All three take AZ, tenancy and scope from the source RI.

Caller Regional vs zonal Tests
internal/api/handler_ri_exchange.go ~:172 (targetOfferingsForSource) Regional passes no AZ; zonal forwards its AZ. Zonal without an AZ, or regional with one, is refused by the provider and mapped to 422 (:189-206), not 500. ZonalSourceForwards, RegionalSourcePassesNo, ZonalSourceWithoutAZIs422, RegionalSourceWithAZIs422
internal/server/handler_ri_exchange.go ~:85 and :281 (convertForAutoExchange copies inst.AvailabilityZone) The provider decides. An empty AZ on a zonal RI is refused, never silently treated as regional. ZonalRIForwards, RegionalRIPassesNo, ZonalRIWithoutAZRefused, MapsEveryField, CarriesAZ
internal/server/ladder_write.go ~:62 Same shared code Covered only through the shared code; no ladder-specific test

Failure paths: an empty or unknown scope also fails loud (parseEC2Scope). In auto-exchange and ladder, a lookup error becomes a SkippedRecommendation, with no quote, no purchase and no retry inside the run.

Notes (non-blocking):

  1. The go pin predates the offering checks. go.mod bumps all four cloud-commitments-go modules to 551be568 (go#428). That commit does not include go sec(iac): key CI/CD deploy trust on immutable repository IDs #451, fix(server): share rate limits across all replicas #455 or fix(auth): enforce permission scope on config writes #456 (all now on go main). So platform still lacks returned-offering verification, and an empty platform still defaults to Linux/UNIX at the pin (ec2/client.go:953-960). The zone refusals this PR relies on do exist at the pin (:446,449). I recommend a follow-up pin bump to current go main (56785bfe or later) to pick up sec(iac): key CI/CD deploy trust on immutable repository IDs #451, fix(server): share rate limits across all replicas #455 and fix(auth): enforce permission scope on config writes #456, either in this PR or right after it.
  2. The 422 depends on message text. It is matched on the provider's error message, so a reworded message would turn it into a 500. The real-client tests would catch that.

What was attacked and how:

  • go build ./... is clean, and so is go vet ./internal/... (including -tags integration).
  • go test -race -count=1 ./internal/api/... ./internal/server/... passes 4129, with 1 failure: the CSRF guard red-main test, fixed on main by test(api): classify the approval-details route in the AuthPublic CSRF guard (fixes red main) #1003. A rebase is needed.
  • The integration test TestRIExchangeAutoWorkers_ConcreteStoreAndFixtureClient passes against a throwaway Postgres 16. It skips without a DSN.
  • Fail-before: with AZ forwarding removed and the bump kept, 5 tests fail.
  • Mutation probes, all caught: "never pass AZ" and "always pass AZ" across the api, lookup and convert sites.

Gate:

@IAmJSD
IAmJSD marked this pull request as ready for review October 16, 2026 23:16
@cristim

cristim commented Oct 16, 2026

Copy link
Copy Markdown
Member

Closing and reopening to refresh CI on the current main merge ref: main changed this PR's packages after its last CI run. The branch is untouched. (claude-cc-pr-merge-3)

@cristim cristim closed this Oct 16, 2026
@cristim cristim reopened this Oct 16, 2026
@cristim

cristim commented Oct 17, 2026

Copy link
Copy Markdown
Member

Closing and reopening to refresh CI again: #1019 changed internal/api on main during the previous run. Branch untouched. (claude-cc-pr-merge-3)

@cristim cristim closed this Oct 17, 2026
@cristim cristim reopened this Oct 17, 2026
@cristim

cristim commented Oct 17, 2026

Copy link
Copy Markdown
Member

Refreshing CI a third time: main changed internal/api again during the previous run. Branch untouched. (claude-cc-pr-merge-3)

@cristim cristim closed this Oct 17, 2026
@cristim cristim reopened this Oct 17, 2026
@cristim

cristim commented Oct 17, 2026

Copy link
Copy Markdown
Member

Refreshing CI: #1015 (same package, internal/api) merged after this PR's last CI run. Branch untouched. (claude-cc-pr-merge-3)

@cristim cristim closed this Oct 17, 2026
@cristim cristim reopened this Oct 17, 2026
@cristim

cristim commented Oct 17, 2026

Copy link
Copy Markdown
Member

Refreshing CI: #1006 (internal/api) merged during the previous run. Branch untouched. (claude-cc-pr-merge-3)

@cristim cristim closed this Oct 17, 2026
@cristim cristim reopened this Oct 17, 2026
@cristim

cristim commented Oct 17, 2026

Copy link
Copy Markdown
Member

Merge gate record: #1018 at 2dd8d6a

Merged by claude-cc-pr-merge-3 with --match-head-commit 2dd8d6a1.

@cristim
cristim merged commit 07439f5 into LeanerCloud:main Oct 17, 2026
135 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/s Hours impact/few Limited audience priority/p2 Backlog-worthy severity/medium Moderate harm triaged Item has been triaged type/chore Maintenance / non-user-visible urgency/this-sprint Within the current sprint

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chore(ri-exchange): forward the source RI availability zone to the go offering lookups

2 participants