Skip to content

Commit 7ede46e

Browse files
authored
aws/endpoints: Fix SDK resolving endpoint without region (#420)
Fixes the SDK's endpoint resolve incorrectly resolving endpoints for a service when the region is empty. Also fixes the SDK attempting to resolve a service when the service value is empty. Related to: aws/aws-sdk-go#2911
1 parent dadd7ec commit 7ede46e

File tree

5 files changed

+81
-8
lines changed

5 files changed

+81
-8
lines changed

CHANGELOG_PENDING.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ SDK Enhancements
99

1010
SDK Bugs
1111
---
12-
12+
* `aws/endpoints`: aws/endpoints: Fix SDK resolving endpoint without region ([#420](https://github.com/aws/aws-sdk-go-v2/pull/420))
13+
* Fixes the SDK's endpoint resolve incorrectly resolving endpoints for a service when the region is empty. Also fixes the SDK attempting to resolve a service when the service value is empty.
14+
* Related to [aws/aws-sdk-go#2909](https://github.com/aws/aws-sdk-go/issues/2909)

aws/endpoints/v3model.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,29 @@ func (p partition) canResolveEndpoint(service, region string, strictMatch bool)
7474
return p.RegionRegex.MatchString(region)
7575
}
7676

77+
var allowEmptyRegion = map[string]struct{}{
78+
"ec2metadata": {},
79+
}
80+
81+
func serviceRequiresRegion(service string) bool {
82+
_, allowed := allowEmptyRegion[service]
83+
return !allowed
84+
}
85+
7786
func (p partition) EndpointFor(service, region string, opts ResolveOptions) (resolved aws.Endpoint, err error) {
7887
s, hasService := p.Services[service]
79-
if !hasService && opts.StrictMatching {
88+
if len(service) == 0 || (!hasService && opts.StrictMatching) {
8089
// Only return error if the resolver will not fallback to creating
8190
// endpoint based on service endpoint ID passed in.
8291
return resolved, NewUnknownServiceError(p.ID, service, serviceList(p.Services))
8392
}
8493

94+
if len(region) == 0 && !serviceRequiresRegion(service) && len(s.PartitionEndpoint) != 0 {
95+
region = s.PartitionEndpoint
96+
}
97+
8598
e, hasEndpoint := s.endpointForRegion(region)
86-
if !hasEndpoint && opts.StrictMatching {
99+
if len(region) == 0 || (!hasEndpoint && opts.StrictMatching) {
87100
return resolved, NewUnknownEndpointError(p.ID, service, region, endpointList(s.Endpoints))
88101
}
89102

aws/endpoints/v3model_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/json"
55
"reflect"
66
"regexp"
7+
"strings"
78
"testing"
89
)
910

@@ -522,3 +523,46 @@ func TestResolveEndpoint_AwsGlobal(t *testing.T) {
522523
t.Errorf("expect the signing name to be derived")
523524
}
524525
}
526+
527+
func TestEndpointFor_EmptyRegion(t *testing.T) {
528+
cases := map[string]struct {
529+
Service string
530+
Region string
531+
RealRegion string
532+
ExpectErr string
533+
}{
534+
// Legacy services that previous accepted empty region
535+
"ec2metadata": {Service: "ec2metadata", RealRegion: "aws-global"},
536+
537+
// Other services
538+
"s3": {Service: "s3", Region: "us-east-1", RealRegion: "us-east-1"},
539+
"s3 no region": {Service: "s3", ExpectErr: "could not resolve endpoint"},
540+
}
541+
542+
for name, c := range cases {
543+
t.Run(name, func(t *testing.T) {
544+
actual, err := NewDefaultResolver().ResolveEndpoint(c.Service, c.Region)
545+
if len(c.ExpectErr) != 0 {
546+
if e, a := c.ExpectErr, err.Error(); !strings.Contains(a, e) {
547+
t.Errorf("expect %q error in %q", e, a)
548+
}
549+
return
550+
}
551+
if err != nil {
552+
t.Fatalf("expect no error got, %v", err)
553+
}
554+
555+
expect, err := NewDefaultResolver().ResolveEndpoint(c.Service, c.RealRegion)
556+
if err != nil {
557+
t.Fatalf("failed to get endpoint for default resolver")
558+
}
559+
if e, a := expect.URL, actual.URL; e != a {
560+
t.Errorf("expect %v URL, got %v", e, a)
561+
}
562+
if e, a := expect.SigningRegion, actual.SigningRegion; e != a {
563+
t.Errorf("expect %v signing region, got %v", e, a)
564+
}
565+
566+
})
567+
}
568+
}

example/service/s3/mockPaginator/mockPaginator.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package main
55
import (
66
"context"
77
"fmt"
8+
"log"
89
"os"
910

1011
"github.com/aws/aws-sdk-go-v2/aws/external"
@@ -24,12 +25,15 @@ func main() {
2425

2526
bucket := os.Args[1]
2627
svc := s3.New(cfg)
27-
keys := getKeys(svc, bucket)
28+
keys, err := getKeys(svc, bucket)
29+
if err != nil {
30+
log.Fatalf("failed to get keys, %v", err)
31+
}
2832

2933
fmt.Printf("keys for bucket %q,\n%v\n", bucket, keys)
3034
}
3135

32-
func getKeys(svc s3iface.ClientAPI, bucket string) []string {
36+
func getKeys(svc s3iface.ClientAPI, bucket string) ([]string, error) {
3337
req := svc.ListObjectsRequest(&s3.ListObjectsInput{
3438
Bucket: &bucket,
3539
})
@@ -41,5 +45,9 @@ func getKeys(svc s3iface.ClientAPI, bucket string) []string {
4145
keys = append(keys, *obj.Key)
4246
}
4347
}
44-
return keys
48+
if err := p.Err(); err != nil {
49+
return nil, err
50+
}
51+
52+
return keys, nil
4553
}

example/service/s3/mockPaginator/mockPaginator_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,16 @@ func TestListObjectsPagination(t *testing.T) {
7272
},
7373
}
7474

75-
svc.Client = s3.New(defaults.Config())
75+
cfg := defaults.Config()
76+
cfg.Region = "us-west-2"
77+
78+
svc.Client = s3.New(cfg)
7679
svc.objects = objects
7780

78-
keys := getKeys(svc, "foo")
81+
keys, err := getKeys(svc, "foo")
82+
if err != nil {
83+
t.Fatalf("expect no error, got %v", err)
84+
}
7985
expected := []string{"1", "2", "3"}
8086

8187
if e, a := 3, len(keys); e != a {

0 commit comments

Comments
 (0)