Summary
The four Azure recommendation converters (compute, database, cache, cosmosdb) populate the subset of Details derivable from the reservation recommendation payload only. SDK-catalogue-derived fields — compute Platform/Tenancy/Scope + memory/vCPU, database EngineVersion/AZConfig, cache Shards, cosmos APIType — are deliberately left empty because populating them inline would produce an N+1 API call per recommendation.
Captured in: known_issues/10_azure_provider.md ("New follow-ups surfaced during this resolution" → MEDIUM: Azure converters leave SKU-lookup Details fields empty (deferred N+1 avoidance)).
Current behaviour
Each convertAzure*Recommendation builds a partial Details:
providers/azure/services/compute/client.go:703 → common.ComputeDetails{InstanceType: f.ResourceType} only.
providers/azure/services/database/client.go:608 → common.DatabaseDetails{Engine: "sqlserver", InstanceClass: f.ResourceType} only.
providers/azure/services/cache/client.go:582 → common.CacheDetails{...} partial.
providers/azure/services/cosmosdb/client.go:617 → common.NoSQLDetails{Engine: "cosmos", ThroughputUnits: parsed} only; APIType missing.
Fields requiring SDK calls are deferred:
- Compute:
armcompute.ResourceSKUsClient.ListByLocation for vCPU/MemoryGB/Tenancy/Scope.
- Database:
armsql SKU catalogue for EngineVersion/AZConfig/Deployment.
- Cache:
armredis for Shards/Tier.
- Cosmos:
armcosmos.DatabaseAccountsClient for APIType (sql/mongodb/cassandra/gremlin/table).
Steps to reproduce
- Run
GetRecommendations against an Azure subscription.
- Inspect any returned
Recommendation.Details — compute MemoryGB == 0, database EngineVersion == "", cache Shards == 0, cosmos APIType == "".
- UI rendering treats these as "unknown" and hides the corresponding columns.
Expected behaviour
Full Details population so the UI can render vCPU, memory, engine version, and Cosmos API type without hitting "unknown".
Proposed fix
Single-shot batched SKU lookup per region per service, called ONCE at the start of GetRecommendations for each region appearing in the response, cached in a map[skuName]SKUCatalogueEntry, then consulted as the converter builds each rec's Details. No N+1 storm, full Details population.
Per-service batch endpoints:
armcompute.ResourceSKUsClient.ListByLocation(region)
armsql.SKUsClient.ListByServer(...)
armredis.SKUsClient.ListByLocation(region)
armcosmos.DatabaseAccountsClient.ListByResourceGroup(rg)
Test plan
Per service: a fixture with SKU-specific properties + an assertion that the resulting Details is non-nil and has the expected concrete type + fields. Mock the catalogue lookup to return a known SKU entry; assert the converter consumed it correctly.
References
- Files:
providers/azure/services/{compute,database,cache,cosmosdb}/client.go::convertAzure*Recommendation.
- Known-issue doc:
known_issues/10_azure_provider.md → "New follow-ups surfaced during this resolution".
Severity
Medium — UI degrades to "unknown" for fields that exist in the SDK catalogue. Functional but loses the resolution the catalogue would provide.
Effort
Medium — each service is ~30 LOC for the batched lookup + cache + ~30 LOC for converter wiring + a fixture test.
Summary
The four Azure recommendation converters (compute, database, cache, cosmosdb) populate the subset of
Detailsderivable from the reservation recommendation payload only. SDK-catalogue-derived fields — compute Platform/Tenancy/Scope + memory/vCPU, database EngineVersion/AZConfig, cache Shards, cosmos APIType — are deliberately left empty because populating them inline would produce an N+1 API call per recommendation.Captured in:
known_issues/10_azure_provider.md("New follow-ups surfaced during this resolution" → MEDIUM: Azure converters leave SKU-lookup Details fields empty (deferred N+1 avoidance)).Current behaviour
Each
convertAzure*Recommendationbuilds a partialDetails:providers/azure/services/compute/client.go:703→common.ComputeDetails{InstanceType: f.ResourceType}only.providers/azure/services/database/client.go:608→common.DatabaseDetails{Engine: "sqlserver", InstanceClass: f.ResourceType}only.providers/azure/services/cache/client.go:582→common.CacheDetails{...}partial.providers/azure/services/cosmosdb/client.go:617→common.NoSQLDetails{Engine: "cosmos", ThroughputUnits: parsed}only; APIType missing.Fields requiring SDK calls are deferred:
armcompute.ResourceSKUsClient.ListByLocationfor vCPU/MemoryGB/Tenancy/Scope.armsqlSKU catalogue for EngineVersion/AZConfig/Deployment.armredisfor Shards/Tier.armcosmos.DatabaseAccountsClientfor APIType (sql/mongodb/cassandra/gremlin/table).Steps to reproduce
GetRecommendationsagainst an Azure subscription.Recommendation.Details— computeMemoryGB == 0, databaseEngineVersion == "", cacheShards == 0, cosmosAPIType == "".Expected behaviour
Full
Detailspopulation so the UI can render vCPU, memory, engine version, and Cosmos API type without hitting "unknown".Proposed fix
Single-shot batched SKU lookup per region per service, called ONCE at the start of
GetRecommendationsfor each region appearing in the response, cached in amap[skuName]SKUCatalogueEntry, then consulted as the converter builds each rec's Details. No N+1 storm, full Details population.Per-service batch endpoints:
armcompute.ResourceSKUsClient.ListByLocation(region)armsql.SKUsClient.ListByServer(...)armredis.SKUsClient.ListByLocation(region)armcosmos.DatabaseAccountsClient.ListByResourceGroup(rg)Test plan
Per service: a fixture with SKU-specific properties + an assertion that the resulting
Detailsis non-nil and has the expected concrete type + fields. Mock the catalogue lookup to return a known SKU entry; assert the converter consumed it correctly.References
providers/azure/services/{compute,database,cache,cosmosdb}/client.go::convertAzure*Recommendation.known_issues/10_azure_provider.md→ "New follow-ups surfaced during this resolution".Severity
Medium — UI degrades to "unknown" for fields that exist in the SDK catalogue. Functional but loses the resolution the catalogue would provide.
Effort
Medium — each service is ~30 LOC for the batched lookup + cache + ~30 LOC for converter wiring + a fixture test.