diff --git a/CHANGELOG.md b/CHANGELOG.md index 603abd6d..f94aac05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -217,6 +217,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/). - **AWS/OpenSearch:** the STS account-ID lookup used for post-purchase tagging caches only a successful result, so one throttled or timed-out `GetCallerIdentity` no longer disables tagging for the client's lifetime (#53). - **AWS/recommendations:** `normalizeRegionName` maps the current `Europe (Ireland|Frankfurt|London|Paris|Stockholm)` Cost Explorer display names to region codes, so coverage lookups keyed by region code match those recommendations (#53). +- **AWS/recommendations:** `normalizeRegionName` also maps `Asia Pacific (Malaysia|Thailand)`, `Canada West (Calgary)` and `Mexico (Central)` to `ap-southeast-5`, `ap-southeast-7`, `ca-west-1` and `mx-central-1` (#53). - **AWS/Savings Plans:** `GetExistingCommitments` returns an error naming the plan ID and value when a plan has an unparseable start or end date, instead of silently leaving the date zero (#53). - **AWS/Savings Plans:** `GetExistingCommitments` returns an error naming the plan ID when a plan has no start or end date; a zero start date was never treated as recent by the purchase dedupe, so a duplicate purchase could slip through (#53). - **AWS/RDS:** `PurchaseCommitment` refuses an offering whose upfront (`FixedPrice` x count) exceeds the approved recommendation upfront by more than 5%, or that is priced in a non-USD currency; a zero approved upfront is not checked (#53). diff --git a/providers/aws/recommendations/converters.go b/providers/aws/recommendations/converters.go index c451ad89..bce4fa59 100644 --- a/providers/aws/recommendations/converters.go +++ b/providers/aws/recommendations/converters.go @@ -132,6 +132,10 @@ func normalizeRegionName(region string) string { "Europe (Zurich)": "eu-central-2", "Asia Pacific (Melbourne)": "ap-southeast-4", "Israel (Tel Aviv)": "il-central-1", + "Asia Pacific (Malaysia)": "ap-southeast-5", + "Asia Pacific (Thailand)": "ap-southeast-7", + "Canada West (Calgary)": "ca-west-1", + "Mexico (Central)": "mx-central-1", } if normalized, ok := regionMap[region]; ok { diff --git a/providers/aws/recommendations/converters_test.go b/providers/aws/recommendations/converters_test.go index 47f458e3..6f6aa9ad 100644 --- a/providers/aws/recommendations/converters_test.go +++ b/providers/aws/recommendations/converters_test.go @@ -558,6 +558,10 @@ func TestNormalizeRegionName(t *testing.T) { {name: "Europe (London)", region: "Europe (London)", expected: "eu-west-2"}, {name: "Europe (Paris)", region: "Europe (Paris)", expected: "eu-west-3"}, {name: "Europe (Stockholm)", region: "Europe (Stockholm)", expected: "eu-north-1"}, + {name: "Asia Pacific (Malaysia)", region: "Asia Pacific (Malaysia)", expected: "ap-southeast-5"}, + {name: "Asia Pacific (Thailand)", region: "Asia Pacific (Thailand)", expected: "ap-southeast-7"}, + {name: "Canada West (Calgary)", region: "Canada West (Calgary)", expected: "ca-west-1"}, + {name: "Mexico (Central)", region: "Mexico (Central)", expected: "mx-central-1"}, { name: "Unknown region returns as-is", region: "Unknown Region", @@ -572,3 +576,27 @@ func TestNormalizeRegionName(t *testing.T) { }) } } + +// TestNormalizeRegionName_NoCollisions pins that distinct display names map to +// distinct region codes, so a new alias cannot silently shadow another region. +func TestNormalizeRegionName_NoCollisions(t *testing.T) { + t.Parallel() + byCode := map[string]string{} + for name, code := range map[string]string{ + "Asia Pacific (Malaysia)": "ap-southeast-5", + "Asia Pacific (Thailand)": "ap-southeast-7", + "Canada West (Calgary)": "ca-west-1", + "Mexico (Central)": "mx-central-1", + "Canada (Central)": "ca-central-1", + "Asia Pacific (Jakarta)": "ap-southeast-3", + "Asia Pacific (Singapore)": "ap-southeast-1", + "Asia Pacific (Sydney)": "ap-southeast-2", + "Asia Pacific (Melbourne)": "ap-southeast-4", + } { + got := normalizeRegionName(name) + assert.Equal(t, code, got, name) + prev, dup := byCode[got] + assert.False(t, dup, "%q and %q both map to %q", prev, name, got) + byCode[got] = name + } +}