Summary
Azure Advisor recommendations are never surfaced in CUDly for any Azure subscription. The account test passes and credentials are valid, but the recommendations page always shows 0 after a refresh.
Verified test environment:
- Subscription:
4c45d0c3-42d9-439a-a0fe-333f6837e837
az advisor recommendation list --category Cost returns 11 recommendations (9 VM reservations, 2 Savings Plans)
- CUDly account test: ✅ passes
- CUDly recommendations after refresh: ❌ 0
Root Cause
extractServiceType() in providers/azure/recommendations.go (line 171) maps service type by inspecting ImpactedField:
switch {
case contains(impactedField, "Microsoft.Compute"):
case contains(impactedField, "Microsoft.Sql"):
case contains(impactedField, "Microsoft.Cache"):
default:
return "" // ← ALL subscription-scoped recommendations fall here
}
Azure Advisor reservation and savings plan recommendations set ImpactedField to "Microsoft.Subscriptions/subscriptions", not a resource-specific namespace. This means extractServiceType always returns "", convertAdvisorRecommendation returns nil (line 134), and every Azure Advisor recommendation is silently discarded.
All 11 recommendations in the test subscription have:
"impactedField": "Microsoft.Subscriptions/subscriptions"
Fix
The actual service type is available in ExtendedProperties:
"extendedProperties": {
"reservedResourceType": "virtualmachines",
"recommendationSubCategory": "Reservations",
"sku": "Standard_D2as_v4"
}
extractServiceType should fall back to ExtendedProperties["reservedResourceType"] when ImpactedField doesn't match a known resource namespace:
if rec.Properties.ExtendedProperties != nil {
if rrt, ok := rec.Properties.ExtendedProperties["reservedResourceType"]; ok && rrt != nil {
switch strings.ToLower(*rrt) {
case "virtualmachines":
return string(common.ServiceCompute)
case "sqldatabases":
return string(common.ServiceRelationalDB)
case "rediscache":
return string(common.ServiceCache)
}
}
if subcat, ok := rec.Properties.ExtendedProperties["recommendationSubCategory"]; ok && subcat != nil {
if strings.EqualFold(*subcat, "SavingsPlan") {
return string(common.ServiceCompute) // or a dedicated ServiceSavingsPlan type
}
}
}
Additional Issues in the Same File
annualSavingsAmount is never parsed (lines 158–161) — comment says "for now just note it's available". rec.EstimatedSavings is always 0 for all Azure Advisor recommendations even if the fix above is applied.
- Pagination errors silently break the loop (line 104–105) — bare
break with no log or error propagation.
- Advisor errors silently suppressed (line 66) —
if err == nil pattern means failures produce 0 recommendations with no signal to the caller or logs.
Expected Behavior
After the fix to extractServiceType, the 11 recommendations currently visible in Azure Advisor should appear in CUDly after a refresh.
Summary
Azure Advisor recommendations are never surfaced in CUDly for any Azure subscription. The account test passes and credentials are valid, but the recommendations page always shows 0 after a refresh.
Verified test environment:
4c45d0c3-42d9-439a-a0fe-333f6837e837az advisor recommendation list --category Costreturns 11 recommendations (9 VM reservations, 2 Savings Plans)Root Cause
extractServiceType()inproviders/azure/recommendations.go(line 171) maps service type by inspectingImpactedField:Azure Advisor reservation and savings plan recommendations set
ImpactedFieldto"Microsoft.Subscriptions/subscriptions", not a resource-specific namespace. This meansextractServiceTypealways returns"",convertAdvisorRecommendationreturnsnil(line 134), and every Azure Advisor recommendation is silently discarded.All 11 recommendations in the test subscription have:
Fix
The actual service type is available in
ExtendedProperties:extractServiceTypeshould fall back toExtendedProperties["reservedResourceType"]whenImpactedFielddoesn't match a known resource namespace:Additional Issues in the Same File
annualSavingsAmountis never parsed (lines 158–161) — comment says "for now just note it's available".rec.EstimatedSavingsis always0for all Azure Advisor recommendations even if the fix above is applied.breakwith no log or error propagation.if err == nilpattern means failures produce 0 recommendations with no signal to the caller or logs.Expected Behavior
After the fix to
extractServiceType, the 11 recommendations currently visible in Azure Advisor should appear in CUDly after a refresh.