Repository navigation
fix(aws/recs): Savings Plans recs never set rec.Region, so region filters drop and leak EC2Instance SPs #1582
Description
Reviewed commit: be11bdcb5. Note: origin/main moved to 3e9660d06 during the review; re-verify against current main before changing code, since a finding may have been fixed or moved.
Where
providers/aws/recommendations/parser_sp.go:367-390(the returnedcommon.Recommendationnever setsRegion; the CE-supplied region is stashed only inDetails.Regionat:387, extracted at:252-261)providers/aws/service_client.go:123-137(filterByIncludedRegions) and:140-154(filterByExcludedRegions)- Evidence that EC2Instance SPs are genuinely region-bound:
providers/aws/services/savingsplans/client.go:310-329(the client region-filters the offering lookup onspDetails.Region) andproviders/aws/ladder/adapters.go:129-131(the ladder excludes out-of-region EC2Instance SPs) - Same
rec.Regionpredicate on the CLI path:cmd/multi_service_filters.go:89and:126; per-account persistence atinternal/config/resolver.go:43
What
Savings Plans recommendations are returned with Region left as the empty string. The region CE supplies is parsed and kept, but only inside Details.Region, which neither region filter reads.
Both filters then treat the empty string as "region-agnostic":
filterByIncludedRegionscomparesrec.Regionagainst the include set with no Savings Plans carve-out, so an empty region matches nothing and the rec is dropped.filterByExcludedRegionstreats an empty region as "not excluded", so the rec survives.
Empty region is being used as if it meant "region-agnostic", which is only true for Compute, SageMaker and Database Savings Plans. EC2Instance Savings Plans are region-bound and family-bound, as the purchase path and the ladder both already recognise.
Failure scenario
(a) Include direction. Any caller that sets RecommendationParams.IncludeRegions (persisted per account via internal/config/resolver.go:43, and reachable from the CLI via cmd/multi_service_filters.go) loses 100% of Savings Plans recommendations. An account filtering to us-east-1 loses its us-east-1 EC2Instance SP recommendation along with every Compute SP recommendation. Savings Plans are typically the largest savings line on an AWS account, so the biggest opportunity silently disappears and the result looks like "no SP savings available".
(b) Exclude direction. --exclude-regions eu-west-1 leaves an EC2Instance SP whose Details.Region is eu-west-1 in the result set and eligible for purchase. The operator explicitly excluded that region and a region-locked commitment is bought there anyway, where it will apply only to eu-west-1 capacity.
Both directions fail silently: no warning, no count of dropped or retained recs.
Fix direction
- Set
Regionon the recommendation forEC2_INSTANCE_SPfromec2Fields.region, normalised throughnormalizeRegionName. - Change the two filters so the exemption is gated on the recommendation genuinely being region-agnostic (a
common.CommitmentSavingsPlanwhose plan type is Compute / SageMaker / Database) rather than onRegion == "". An unknown or empty region on a region-bound plan type should not silently pass an explicit region filter in either direction. - Regression tests for both directions: an EC2Instance SP for
us-east-1must surviveIncludeRegions=["us-east-1"], and must be dropped byExcludeRegions=["us-east-1"].
Related
- The same class of bug was fixed on the Azure/parser side in PR feat(mcp): CUDly MCP server for RI/SP/CUD purchases across AWS, Azure, GCP #1495, and is captured in project memory as "empty region is not region-agnostic". Verified: neither feat(mcp): CUDly MCP server for RI/SP/CUD purchases across AWS, Azure, GCP #1495 nor any open issue covers
providers/aws/service_client.goor the missingRegionon the AWS SP parser, so this code path is not fixed by that work. - fix(mcp): default Savings Plans search params + region post-filter (avoid required-param cascade) #1506 covers a region parameter not being honored on the MCP search path for RI recommendations. Different layer and different service, but the same "the region param does not mean what it says" symptom; worth fixing consistently.
Activity
fix(providers/aws): confine the exported region helpers to AWS
fix(cmd): match Savings Plans region filters on Details.Region (#1881)