Skip to content

Commit 9503cfa

Browse files
authored
Support for Loading Service Specific Configuration from External Sources During Client Creation (#474)
1 parent dad4b8d commit 9503cfa

File tree

19 files changed

+702
-44
lines changed

19 files changed

+702
-44
lines changed

aws/config.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,16 @@ type Config struct {
7878
// Disabling this feature is useful when you want to use local endpoints
7979
// for testing that do not support the modeled host prefix pattern.
8080
DisableEndpointHostPrefix bool
81+
82+
// ConfigResolver defines how additional configuration can be loaded by clients.
83+
AdditionalConfig ConfigResolver
84+
}
85+
86+
// ConfigResolver is an interface that encapsulates the behavior of loading
87+
// additional configuration.
88+
type ConfigResolver interface {
89+
// ResolveConfig calls the provide function passing a slice of configuration sources
90+
ResolveConfig(func(configs []interface{}) error) error
8191
}
8292

8393
// NewConfig returns a new Config pointer that can be chained with builder

aws/external/config.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,16 @@ func (cs Configs) ResolveAWSConfig(resolvers []AWSConfigResolver) (aws.Config, e
100100
return cfg, nil
101101
}
102102

103+
// ResolveConfig calls the provide function passing slice of configuration sources.
104+
// This implements the aws.ConfigResolver interface.
105+
func (cs Configs) ResolveConfig(f func(configs []interface{}) error) error {
106+
var cfgs []interface{}
107+
for i := range cs {
108+
cfgs = append(cfgs, cs[i])
109+
}
110+
return f(cfgs)
111+
}
112+
103113
// LoadDefaultAWSConfig reads the SDK's default external configurations, and
104114
// populates an AWS Config with the values from the external configurations.
105115
//

aws/external/env_config.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package external
22

33
import (
4+
"fmt"
45
"io/ioutil"
56
"os"
7+
"strings"
68

79
"github.com/aws/aws-sdk-go-v2/aws"
810
)
@@ -37,6 +39,8 @@ const (
3739
AWSConfigFileEnvVar = "AWS_CONFIG_FILE"
3840

3941
AWSCustomCABundleEnvVar = "AWS_CA_BUNDLE"
42+
43+
S3UseARNRegionEnvVar = "AWS_S3_USE_ARN_REGION"
4044
)
4145

4246
var (
@@ -134,6 +138,12 @@ type EnvConfig struct {
134138
//
135139
// AWS_CA_BUNDLE=$HOME/my_custom_ca_bundle
136140
CustomCABundle string
141+
142+
// Specifies if the S3 service should allow ARNs to direct the region
143+
// the client's requests are sent to.
144+
//
145+
// AWS_S3_USE_ARN_REGION=true
146+
S3UseARNRegion *bool
137147
}
138148

139149
// LoadEnvConfig reads configuration values from the OS's environment variables.
@@ -168,6 +178,24 @@ func NewEnvConfig() (EnvConfig, error) {
168178

169179
cfg.CustomCABundle = os.Getenv(AWSCustomCABundleEnvVar)
170180

181+
s3UseARNRegion := os.Getenv(S3UseARNRegionEnvVar)
182+
if len(s3UseARNRegion) != 0 {
183+
var v bool
184+
185+
switch {
186+
case strings.EqualFold(s3UseARNRegion, "false"):
187+
v = false
188+
case strings.EqualFold(s3UseARNRegion, "true"):
189+
v = true
190+
default:
191+
return cfg, fmt.Errorf(
192+
"invalid value for environment variable, %s=%s, need true or false",
193+
S3UseARNRegionEnvVar, s3UseARNRegion)
194+
}
195+
196+
cfg.S3UseARNRegion = &v
197+
}
198+
171199
return cfg, nil
172200
}
173201

@@ -226,6 +254,16 @@ func (c EnvConfig) GetCustomCABundle() ([]byte, error) {
226254
return ioutil.ReadFile(c.CustomCABundle)
227255
}
228256

257+
// GetS3UseARNRegion returns whether to allow ARNs to direct the region
258+
// the S3 client's requests are sent to.
259+
func (c EnvConfig) GetS3UseARNRegion() (value, ok bool, err error) {
260+
if c.S3UseARNRegion == nil {
261+
return false, false, nil
262+
}
263+
264+
return *c.S3UseARNRegion, true, nil
265+
}
266+
229267
func setFromEnvVal(dst *string, keys []string) {
230268
for _, k := range keys {
231269
if v := os.Getenv(k); len(v) > 0 {

aws/external/env_config_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,14 @@ func TestNewEnvConfig(t *testing.T) {
215215
SharedConfigFile: "/path/to/config/file",
216216
},
217217
},
218+
{
219+
Env: map[string]string{
220+
"AWS_S3_USE_ARN_REGION": "true",
221+
},
222+
Config: EnvConfig{
223+
S3UseARNRegion: aws.Bool(true),
224+
},
225+
},
218226
}
219227

220228
for _, c := range cases {

aws/external/shared_config.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ const (
2626

2727
// Additional Config fields
2828
regionKey = `region`
29+
30+
// S3 ARN Region Usage
31+
s3UseARNRegionKey = "s3_use_arn_region"
2932
)
3033

3134
// DefaultSharedConfigProfile is the default profile to be used when
@@ -96,6 +99,22 @@ type SharedConfig struct {
9699
//
97100
// region
98101
Region string
102+
103+
// Specifies if the S3 service should allow ARNs to direct the region
104+
// the client's requests are sent to.
105+
//
106+
// s3_use_arn_region=true
107+
S3UseARNRegion *bool
108+
}
109+
110+
// GetS3UseARNRegion retions if the S3 service should allow ARNs to direct the region
111+
// the client's requests are sent to.
112+
func (c *SharedConfig) GetS3UseARNRegion() (value, ok bool, err error) {
113+
if c.S3UseARNRegion == nil {
114+
return false, false, nil
115+
}
116+
117+
return *c.S3UseARNRegion, true, nil
99118
}
100119

101120
// GetRegion returns the region for the profile if a region is set.
@@ -337,6 +356,12 @@ func (c *SharedConfig) setFromIniFile(profile string, file sharedConfigFile) err
337356
c.Region = v
338357
}
339358

359+
// S3 Use ARN Region
360+
if section.Has(s3UseARNRegionKey) {
361+
v := section.Bool(s3UseARNRegionKey)
362+
c.S3UseARNRegion = &v
363+
}
364+
340365
return nil
341366
}
342367

aws/external/shared_config_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,14 @@ func TestNewSharedConfig(t *testing.T) {
157157
Err: awserr.New("INIParseError", "", nil),
158158
},
159159
},
160+
{
161+
Profile: "valid_arn_region",
162+
Filenames: []string{testConfigFilename},
163+
Expected: SharedConfig{
164+
Profile: "valid_arn_region",
165+
S3UseARNRegion: aws.Bool(true),
166+
},
167+
},
160168
}
161169

162170
for i, c := range cases {

aws/external/testdata/shared_config

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,6 @@ aws_secret_access_key = assume_role_w_creds_secret
6868
[assume_role_wo_creds]
6969
role_arn = assume_role_wo_creds_role_arn
7070
source_profile = assume_role_wo_creds
71+
72+
[valid_arn_region]
73+
s3_use_arn_region=true

models/protocol_tests/generate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ func generateTestSuite(filename string) string {
449449
s.Rename(svcPrefix + "TestShape" + name)
450450
}
451451

452-
svcCode := addImports(suite.API.ServiceGoCode())
452+
svcCode := addImports(suite.API.ClientGoCode())
453453
if i == 0 {
454454
importMatch := reImportRemoval.FindStringSubmatch(svcCode)
455455
buf.WriteString(importMatch[0] + "\n\n")

0 commit comments

Comments
 (0)