Skip to content

feat(azure/ri-exchange): list exchangeable Azure VM reservations (refs #473) - #595

Merged
cristim merged 1 commit into
feat/multicloud-web-frontendfrom
feat/azure-ri-exchange
May 20, 2026
Merged

feat(azure/ri-exchange): list exchangeable Azure VM reservations (refs #473)#595
cristim merged 1 commit into
feat/multicloud-web-frontendfrom
feat/azure-ri-exchange

Conversation

@cristim

@cristim cristim commented May 20, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds ListExchangeableReservations to the Azure compute client, filtering tenant-wide VM reservations to those with ProvisioningState==Succeeded and InstanceFlexibility==On (the Azure exchange eligibility criteria)
  • Wires a new GET /api/ri-exchange/azure-instances route protected by view:purchases permission; accepts optional ?subscription_id= query parameter
  • Covers both layers with unit tests using injected stubs -- no live Azure credentials needed in CI

This is the list half of Azure Convertible RI exchange parity. The find-compatible-offerings (CalculateExchange) and execute steps are tracked in a follow-up issue.

Test plan

  • providers/azure module: go test ./... -- 361 pass
  • internal/api package: go test ./internal/api/... -- 1158 pass
  • Pre-commit hooks pass (gofmt, go vet, go mod tidy, gocyclo, gosec, trivy)

Summary by CodeRabbit

Release Notes

  • New Features
    • Added a new REST API endpoint enabling users to query and list exchangeable Azure reserved instances with optional subscription ID filtering.
    • Integrated Azure reserved instances exchange functionality to retrieve and display instance eligibility information based on provisioning status and configuration requirements.

Review Change Stack

…#473)

Add ListExchangeableReservations to the Azure compute client, returning all
VM reservations with ProvisioningState==Succeeded and InstanceFlexibility==On
(the criteria Azure requires for the cross-SKU/cross-region exchange path).

Wire a new GET /api/ri-exchange/azure-instances handler that requires
view:purchases permission and accepts an optional ?subscription_id= query
parameter. Both layers are covered by unit tests using injected stubs --
no live Azure credentials needed in CI.

The find-compatible-offerings (CalculateExchange) and execute steps are
tracked separately in a follow-up issue.
@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3d4cdf35-67c5-4b00-8206-c06003703b8b

📥 Commits

Reviewing files that changed from the base of the PR and between bc8831b and 1409234.

⛔ Files ignored due to path filters (2)
  • go.sum is excluded by !**/*.sum
  • providers/azure/go.sum is excluded by !**/*.sum
📒 Files selected for processing (9)
  • go.mod
  • internal/api/handler.go
  • internal/api/handler_ri_exchange.go
  • internal/api/handler_ri_exchange_test.go
  • internal/api/router.go
  • providers/azure/go.mod
  • providers/azure/services/compute/client.go
  • providers/azure/services/compute/exchange.go
  • providers/azure/services/compute/exchange_test.go

📝 Walkthrough

Walkthrough

This PR implements end-to-end Azure Reserved Instance exchange discovery. It adds the Azure SDK reservations module, implements provider-side filtering and pagination to identify exchangeable VM reservations meeting specific criteria (succeeded provisioning, On instance flexibility), exposes a new authenticated HTTP endpoint with test-injectable Azure client factories, and wires the routing. The solution enforces eligibility via provisioning state, resource type, and instance flexibility checks, and gracefully handles ARM resource ID parsing and missing optional fields.

Changes

Azure RI Exchange Discovery

Layer / File(s) Summary
Dependencies & Provider Integration
go.mod, providers/azure/go.mod, providers/azure/services/compute/client.go
Azure SDK reservations module added to both root and provider-scoped go.mod files; ComputeClient extended with optional exchangeablePager field to support test injection.
Provider Domain Model & Eligibility Logic
providers/azure/services/compute/exchange.go
ExchangeableReservation type and ExchangeableReservationPager interface introduced; eligibility filtering enforces VM resource type, Succeeded provisioning state, and On instance flexibility; field extraction handles optional ARM response pointers safely; order ID parsed from ARM resource path.
Provider Pagination & Iteration
providers/azure/services/compute/exchange.go
ListExchangeableReservations implements pager construction (injected test pager or real ARM client), page iteration, eligibility filtering, and error wrapping with no partial result fallback.
Provider Tests
providers/azure/services/compute/exchange_test.go
Mock pager implementations for pagination and error cases; test builders for reservation fixtures with configurable resource type and state; coverage for ineligibility filters, field mapping, multi-page aggregation, mixed eligibility, and error propagation.
API Injection Point & Factory
internal/api/handler.go, internal/api/handler_ri_exchange.go
Handler.azureExchangeFactory field added for test injection; azureExchangeClient interface and buildAzureExchangeClient method implement real Azure credential acquisition or test stub selection.
API Handler Implementation
internal/api/handler_ri_exchange.go
listExchangeableAzureRIs enforces view:purchases permission, reads optional subscription_id query param, builds Azure exchange client, and calls provider ListExchangeableReservations; ExchangeableAzureRIsResponse struct defined for JSON response.
API Handler Tests
internal/api/handler_ri_exchange_test.go
Stub Azure exchange client with configurable responses; test cases verify auth enforcement, response shaping for empty and populated lists, error propagation, and subscription_id parameter passing through factory.
API Routing
internal/api/router.go
New GET endpoint /api/ri-exchange/azure-instances registered at AuthUser protection level; handler wrapper delegates to Handler.listExchangeableAzureRIs.

Sequence Diagram

sequenceDiagram
  participant User as User/Client
  participant Router as Router
  participant Handler as Handler
  participant Factory as Azure<br/>Exchange Factory
  participant Compute as Compute Client
  participant ARM as ARM Pager
  
  User->>Router: GET /api/ri-exchange/azure-instances
  Router->>Handler: listExchangeableAzureRIs(ctx, req)
  Handler->>Handler: Check view:purchases permission
  Handler->>Handler: Read subscription_id from query
  Handler->>Factory: buildAzureExchangeClient(subscriptionID)
  Factory->>Compute: NewDefaultAzureCredential or stub
  Compute-->>Factory: credential/error
  Factory-->>Handler: azureExchangeClient or error
  Handler->>Compute: ListExchangeableReservations(ctx)
  Compute->>ARM: NewListAllPager (real or injected)
  loop For each page
    Compute->>ARM: NextPage(ctx)
    ARM-->>Compute: page items
    Compute->>Compute: isExchangeEligible filter
    Compute->>Compute: convertToExchangeableReservation
  end
  Compute-->>Handler: []ExchangeableReservation or error
  Handler->>Handler: Build ExchangeableAzureRIsResponse
  Handler-->>User: JSON response
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

The PR introduces new types, filtering logic, and provider-level paging implementation across multiple files. Moderate complexity stems from ARM SDK integration details, eligibility predicate enforcement, and field extraction safety. The handler-level API integration follows established patterns. Review requires attention to eligibility criteria correctness, order ID parsing robustness, and error handling completeness.

Possibly Related Issues

  • #557: Implements Azure Reserved Instance exchange discovery endpoint and provider integration—directly aligns with this PR's objectives to surface exchangeable Azure RIs via HTTP API with provider-side eligibility filtering and pagination.

Poem

🐰 A registry of VMs now shine so bright,
Exchangeable reservations, filtered just right,
ARM's pages turn, eligibility gleams,
Azure unfolds its most flexile dreams!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding support for listing exchangeable Azure VM reservations, which is the core feature across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/azure-ri-exchange

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

@cristim cristim added priority/p2 Backlog-worthy severity/medium Moderate harm urgency/this-quarter Within the quarter impact/many Affects most users effort/l Weeks type/feat New capability triaged Item has been triaged labels May 20, 2026
@cristim

cristim commented May 20, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim

cristim commented May 20, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim
cristim merged commit bc81d15 into feat/multicloud-web-frontend May 20, 2026
5 checks passed
@cristim
cristim deleted the feat/azure-ri-exchange branch June 3, 2026 21:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/l Weeks impact/many Affects most users priority/p2 Backlog-worthy severity/medium Moderate harm triaged Item has been triaged type/feat New capability urgency/this-quarter Within the quarter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant