Skip to content

Commit bd8766a

Browse files
authored
Merge pull request #5680 from tthvo/compact-svc-endp
🐛 fix: backwards compatibility for AWS service endpoint resolution
2 parents 97cc94c + 9d6124f commit bd8766a

File tree

2 files changed

+91
-17
lines changed

2 files changed

+91
-17
lines changed

pkg/cloud/endpoints/endpoints.go

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@ var (
4646
errServiceEndpointServiceID = errors.New("must use a valid serviceID from the AWS GO SDK")
4747
errServiceEndpointDuplicateServiceID = errors.New("same serviceID defined twice for signing region")
4848
serviceEndpointsMap = map[string]serviceEndpoint{}
49+
compatServiceIDMap = map[string]string{
50+
"s3": s3.ServiceID,
51+
"elasticloadbalancing": elb.ServiceID,
52+
"ec2": ec2.ServiceID,
53+
"tagging": rgapi.ServiceID,
54+
"sqs": sqs.ServiceID,
55+
"events": eventbridge.ServiceID,
56+
"eks": eks.ServiceID,
57+
"ssm": ssm.ServiceID,
58+
"sts": sts.ServiceID,
59+
"secretsmanager": secretsmanager.ServiceID,
60+
}
4961
)
5062

5163
// serviceEndpoint contains AWS Service resolution information for SDK V2.
@@ -87,11 +99,13 @@ func ParseFlag(serviceEndpoints string) error {
8799
}
88100
seenServices = append(seenServices, serviceID)
89101

90-
// convert service ID to UpperCase as service IDs in AWS SDK GO V2 are UpperCase & Go map is Case Sensitve
91-
// This is for backward compabitibility
92-
// Ref: SDK V2 https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/ec2#pkg-constants
93-
// Ref: SDK V1 https://pkg.go.dev/github.com/aws/aws-sdk-go/aws/endpoints#pkg-constants
94-
serviceID = strings.ToUpper(serviceID)
102+
// In v1 sdk, a constant EndpointsID is exported in each service to look up the custom service endpoint.
103+
// For example: https://github.com/aws/aws-sdk-go/blob/070853e88d22854d2355c2543d0958a5f76ad407/service/resourcegroupstaggingapi/service.go#L33-L34
104+
// In v2 SDK, these constants are no longer available.
105+
// For backwards compatibility, we copy those constants from the SDK v1 and map it to ServiceID in SDK v2.
106+
if v2serviceID, ok := compatServiceIDMap[serviceID]; ok {
107+
serviceID = v2serviceID
108+
}
95109

96110
URL, err := url.ParseRequestURI(kv[1])
97111
if err != nil {
@@ -104,6 +118,20 @@ func ParseFlag(serviceEndpoints string) error {
104118
}
105119
serviceEndpointsMap[serviceID] = endpoint
106120
}
121+
122+
// In v1 SDK, elb and elbv2 uses the same identifier, thus the same endpoint.
123+
// elbv2: https://github.com/aws/aws-sdk-go/blob/070853e88d22854d2355c2543d0958a5f76ad407/service/elbv2/service.go#L32-L33
124+
// elb: https://github.com/aws/aws-sdk-go/blob/070853e88d22854d2355c2543d0958a5f76ad407/service/elb/service.go#L32-L33
125+
// For backwards compatibility, if elbv2 endpoint is undefined, the elbv2 endpoint resolver should fall back to elb endpoint if any.
126+
if _, ok := serviceEndpointsMap[elbv2.ServiceID]; !ok {
127+
if elbEp, ok := serviceEndpointsMap[elb.ServiceID]; ok {
128+
serviceEndpointsMap[elbv2.ServiceID] = serviceEndpoint{
129+
ServiceID: elbv2.ServiceID,
130+
URL: elbEp.URL,
131+
SigningRegion: elbEp.SigningRegion,
132+
}
133+
}
134+
}
107135
}
108136
return nil
109137
}

pkg/cloud/endpoints/endpoints_test.go

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,60 @@ package endpoints
1919
import (
2020
"errors"
2121
"testing"
22+
23+
"github.com/google/go-cmp/cmp"
2224
)
2325

2426
func TestParseFlags(t *testing.T) {
2527
testCases := []struct {
26-
name string
27-
flagToParse string
28-
expectedError error
28+
name string
29+
flagToParse string
30+
expectedError error
31+
expectedServiceEndpointsMap map[string]serviceEndpoint
2932
}{
3033
{
31-
name: "no configuration",
32-
flagToParse: "",
33-
expectedError: nil,
34+
name: "no configuration",
35+
flagToParse: "",
36+
expectedServiceEndpointsMap: make(map[string]serviceEndpoint),
3437
},
3538
{
36-
name: "single region, single service",
37-
flagToParse: "us-iso:ec2=https://localhost:8080",
38-
expectedError: nil,
39+
name: "single region, single service",
40+
flagToParse: "us-iso:ec2=https://localhost:8080",
41+
expectedServiceEndpointsMap: map[string]serviceEndpoint{"EC2": {ServiceID: "EC2", URL: "https://localhost:8080", SigningRegion: "us-iso"}},
3942
},
4043
{
41-
name: "single region, multiple services",
42-
flagToParse: "us-iso:ec2=https://localhost:8080,sts=https://elbhost:8080",
43-
expectedError: nil,
44+
name: "single region, multiple services with v1 service IDs",
45+
flagToParse: "us-iso:s3=https://s3.com,elasticloadbalancing=https://elb.com,ec2=https://ec2.com,tagging=https://tagging.com,sqs=https://sqs.com,events=https://events.com,eks=https://eks.com,ssm=https://ssm.com,sts=https://sts.com,secretsmanager=https://secretmanager.com",
46+
expectedServiceEndpointsMap: map[string]serviceEndpoint{
47+
"EC2": {ServiceID: "EC2", URL: "https://ec2.com", SigningRegion: "us-iso"},
48+
"EKS": {ServiceID: "EKS", URL: "https://eks.com", SigningRegion: "us-iso"},
49+
"Elastic Load Balancing": {ServiceID: "Elastic Load Balancing", URL: "https://elb.com", SigningRegion: "us-iso"},
50+
"Elastic Load Balancing v2": {ServiceID: "Elastic Load Balancing v2", URL: "https://elb.com", SigningRegion: "us-iso"},
51+
"EventBridge": {ServiceID: "EventBridge", URL: "https://events.com", SigningRegion: "us-iso"},
52+
"Resource Groups Tagging API": {ServiceID: "Resource Groups Tagging API", URL: "https://tagging.com", SigningRegion: "us-iso"},
53+
"S3": {ServiceID: "S3", URL: "https://s3.com", SigningRegion: "us-iso"},
54+
"SQS": {ServiceID: "SQS", URL: "https://sqs.com", SigningRegion: "us-iso"},
55+
"SSM": {ServiceID: "SSM", URL: "https://ssm.com", SigningRegion: "us-iso"},
56+
"STS": {ServiceID: "STS", URL: "https://sts.com", SigningRegion: "us-iso"},
57+
"Secrets Manager": {ServiceID: "Secrets Manager", URL: "https://secretmanager.com", SigningRegion: "us-iso"},
58+
},
59+
},
60+
{
61+
name: "single region, multiple services with v2 service IDs",
62+
flagToParse: "us-iso:S3=https://s3.com,Elastic Load Balancing=https://elb.com,Elastic Load Balancing v2=https://elbv2.com,EC2=https://ec2.com,Resource Groups Tagging API=https://tagging.com,SQS=https://sqs.com,EventBridge=https://events.com,EKS=https://eks.com,SSM=https://ssm.com,STS=https://sts.com,Secrets Manager=https://secretmanager.com",
63+
expectedServiceEndpointsMap: map[string]serviceEndpoint{
64+
"EC2": {ServiceID: "EC2", URL: "https://ec2.com", SigningRegion: "us-iso"},
65+
"EKS": {ServiceID: "EKS", URL: "https://eks.com", SigningRegion: "us-iso"},
66+
"Elastic Load Balancing": {ServiceID: "Elastic Load Balancing", URL: "https://elb.com", SigningRegion: "us-iso"},
67+
"Elastic Load Balancing v2": {ServiceID: "Elastic Load Balancing v2", URL: "https://elbv2.com", SigningRegion: "us-iso"},
68+
"EventBridge": {ServiceID: "EventBridge", URL: "https://events.com", SigningRegion: "us-iso"},
69+
"Resource Groups Tagging API": {ServiceID: "Resource Groups Tagging API", URL: "https://tagging.com", SigningRegion: "us-iso"},
70+
"S3": {ServiceID: "S3", URL: "https://s3.com", SigningRegion: "us-iso"},
71+
"SQS": {ServiceID: "SQS", URL: "https://sqs.com", SigningRegion: "us-iso"},
72+
"SSM": {ServiceID: "SSM", URL: "https://ssm.com", SigningRegion: "us-iso"},
73+
"STS": {ServiceID: "STS", URL: "https://sts.com", SigningRegion: "us-iso"},
74+
"Secrets Manager": {ServiceID: "Secrets Manager", URL: "https://secretmanager.com", SigningRegion: "us-iso"},
75+
},
4476
},
4577
{
4678
name: "single region, duplicate service",
@@ -56,6 +88,10 @@ func TestParseFlags(t *testing.T) {
5688
name: "multiples regions",
5789
flagToParse: "us-iso:ec2=https://localhost:8080,sts=https://elbhost:8080;gb-iso:ec2=https://localhost:8080,sts=https://elbhost:8080",
5890
expectedError: nil,
91+
expectedServiceEndpointsMap: map[string]serviceEndpoint{
92+
"EC2": {ServiceID: "EC2", URL: "https://localhost:8080", SigningRegion: "gb-iso"},
93+
"STS": {ServiceID: "STS", URL: "https://elbhost:8080", SigningRegion: "gb-iso"},
94+
},
5995
},
6096
{
6197
name: "invalid config",
@@ -66,11 +102,21 @@ func TestParseFlags(t *testing.T) {
66102

67103
for _, tc := range testCases {
68104
t.Run(tc.name, func(t *testing.T) {
105+
defer t.Cleanup(func() {
106+
serviceEndpointsMap = make(map[string]serviceEndpoint)
107+
})
108+
69109
err := ParseFlag(tc.flagToParse)
70110

71111
if !errors.Is(err, tc.expectedError) {
72112
t.Fatalf("did not expect correct error: got %v, expected %v", err, tc.expectedError)
73113
}
114+
115+
if err == nil {
116+
if !cmp.Equal(serviceEndpointsMap, tc.expectedServiceEndpointsMap) {
117+
t.Fatalf("expected serviceEndpointsMap: %#v, but got: %#v", tc.expectedServiceEndpointsMap, serviceEndpointsMap)
118+
}
119+
}
74120
})
75121
}
76122
}

0 commit comments

Comments
 (0)