Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions internal/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"
"time"

"github.com/LeanerCloud/cloud-commitments-go/pkg/common"
"github.com/LeanerCloud/cloud-commitments-go/pkg/ladder"
)

Expand Down Expand Up @@ -762,14 +763,14 @@ type SuppressionVariant struct {

// awsLegacyServiceSlugs maps the AWS service slugs that rec rows persisted
// before slug normalisation still carry to their canonical spelling.
// memorydb has no canonical slug and is deliberately absent. Mirrors the legacy
// entries of mapServiceSlug in internal/purchase/execution.go.
// memorydb has no canonical slug and is deliberately absent. Keyed and valued by the
// library constants; a purchase test checks it against mapServiceSlug.
var awsLegacyServiceSlugs = map[string]string{
"ec2": "compute",
"rds": "relational-db",
"elasticache": "cache",
"opensearch": "search",
"redshift": "data-warehouse",
string(common.ServiceEC2): string(common.ServiceCompute),
string(common.ServiceRDS): string(common.ServiceRelationalDB),
string(common.ServiceElastiCache): string(common.ServiceCache),
string(common.ServiceOpenSearch): string(common.ServiceSearch),
string(common.ServiceRedshift): string(common.ServiceDataWarehouse),
}

// CanonicalSuppressionService maps legacy AWS service slugs to their canonical
Expand Down
25 changes: 16 additions & 9 deletions internal/purchase/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -1299,19 +1299,26 @@ func mapServiceSlug(service string) (common.ServiceType, bool) {
"cache": common.ServiceCache,
"search": common.ServiceSearch,
"data-warehouse": common.ServiceDataWarehouse,
// Legacy AWS-only slugs. A new legacy alias must also be added to
// config.awsLegacyServiceSlugs, else suppressions miss it (#1420).
"ec2": common.ServiceEC2,
"rds": common.ServiceRDS,
"elasticache": common.ServiceElastiCache,
"opensearch": common.ServiceOpenSearch,
"redshift": common.ServiceRedshift,
"memorydb": common.ServiceMemoryDB,
}
svc, ok := slugs[service]
if svc, ok := slugs[service]; ok {
return svc, true
}
svc, ok := legacyAWSServiceSlugs[service]
return svc, ok
}

// legacyAWSServiceSlugs are the AWS-only slugs. A new alias must also be added
// to config.awsLegacyServiceSlugs, else suppressions miss it (#1420); a test
// ranges over this map to enforce that.
var legacyAWSServiceSlugs = map[string]common.ServiceType{
"ec2": common.ServiceEC2,
"rds": common.ServiceRDS,
"elasticache": common.ServiceElastiCache,
"opensearch": common.ServiceOpenSearch,
"redshift": common.ServiceRedshift,
"memorydb": common.ServiceMemoryDB,
}

// mapSavingsPlansSlug normalizes both the canonical hyphenated SP slugs and
// the dash-free spellings the frontend has historically sent into the
// matching common.ServiceType. The map covers the legacy umbrella plus the
Expand Down
44 changes: 44 additions & 0 deletions internal/purchase/slug_alias_drift_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package purchase

import (
"testing"

"github.com/LeanerCloud/cloud-commitments-go/pkg/common"
"github.com/LeanerCloud/cloud-commitments-platform/internal/config"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

// TestLegacyAWSSlugsMatchSuppressionAliases guards the pair of alias tables
// (config.awsLegacyServiceSlugs and legacyAWSServiceSlugs) against drifting
// apart, which would let a suppression miss a rec spelled the other way (#1420).
func TestLegacyAWSSlugsMatchSuppressionAliases(t *testing.T) {
canonicalFamily := map[string]common.ServiceType{
"ec2": common.ServiceCompute,
"rds": common.ServiceRelationalDB,
"elasticache": common.ServiceCache,
"opensearch": common.ServiceSearch,
"redshift": common.ServiceDataWarehouse,
}
// Deleting an entry from legacyAWSServiceSlugs must not pass silently.
for key := range canonicalFamily {
require.Contains(t, legacyAWSServiceSlugs, key, "legacy slug %q was removed from legacyAWSServiceSlugs", key)
}
require.Contains(t, legacyAWSServiceSlugs, string(common.ServiceMemoryDB), "legacy slug memorydb was removed from legacyAWSServiceSlugs")
for key := range legacyAWSServiceSlugs {
Comment thread
cristim marked this conversation as resolved.
t.Run(key, func(t *testing.T) {
canonical := config.CanonicalSuppressionService("aws", key)
if key == string(common.ServiceMemoryDB) {
// Documented exception: no canonical slug, passes through.
assert.Equal(t, key, canonical)
return
}
want, ok := canonicalFamily[key]
require.True(t, ok, "legacy key %q has no expected canonical family; add it to this test and config.awsLegacyServiceSlugs", key)
assert.NotEqual(t, key, canonical, "legacy key %q is missing from config.awsLegacyServiceSlugs", key)
got, ok := mapServiceSlug(canonical)
require.True(t, ok, "mapServiceSlug rejects canonical slug %q", canonical)
assert.Equal(t, want, got)
})
}
}
Loading