@@ -83,6 +83,22 @@ func (er *endpointsResolver) EndpointFor(service, region string, opts ...func(*e
83
83
return endpoints .DefaultResolver ().EndpointFor (service , region , opts ... )
84
84
}
85
85
86
+ func isUnknownEndpointError (err error ) bool {
87
+ _ , ok := err .(endpoints.UnknownEndpointError )
88
+ return ok
89
+ }
90
+
91
+ func regionHasDualStackS3 (region string ) (bool , error ) {
92
+ _ , err := endpoints .DefaultResolver ().EndpointFor ("s3" , region , endpoints .UseDualStackEndpointOption )
93
+ if isUnknownEndpointError (err ) {
94
+ return false , nil
95
+ }
96
+ if err != nil {
97
+ return false , err
98
+ }
99
+ return true , nil
100
+ }
101
+
86
102
type driver struct {
87
103
Context context.Context
88
104
Config * imageregistryv1.ImageRegistryConfigStorageS3
@@ -224,6 +240,18 @@ func (d *driver) getCABundle() (string, error) {
224
240
}
225
241
}
226
242
243
+ // useDualStack returns true if the driver should use dual-stack endpoints
244
+ func (d * driver ) useDualStack () (bool , error ) {
245
+ if d .Config .RegionEndpoint != "" {
246
+ return true , nil
247
+ }
248
+ ok , err := regionHasDualStackS3 (d .Config .Region )
249
+ if err != nil {
250
+ return false , fmt .Errorf ("failed to determine if region %s has dual stack S3: %w" , d .Config .Region , err )
251
+ }
252
+ return ok , nil
253
+ }
254
+
227
255
// getS3Service returns a client that allows us to interact
228
256
// with the aws S3 service
229
257
func (d * driver ) getS3Service () (* s3.S3 , error ) {
@@ -290,7 +318,14 @@ func (d *driver) getS3Service() (*s3.S3, error) {
290
318
awsOptions .Config .HTTPClient .Transport = d .roundTripper
291
319
}
292
320
293
- awsOptions .Config .WithUseDualStack (true )
321
+ useDualStack , err := d .useDualStack ()
322
+ if err != nil {
323
+ return nil , err
324
+ }
325
+ if useDualStack {
326
+ awsOptions .Config .WithUseDualStack (true )
327
+ }
328
+
294
329
if d .Config .RegionEndpoint != "" {
295
330
if ! d .Config .VirtualHostedStyle {
296
331
awsOptions .Config .WithS3ForcePathStyle (true )
@@ -358,10 +393,17 @@ func (d *driver) ConfigEnv() (envs envvar.List, err error) {
358
393
envvar.EnvVar {Name : "REGISTRY_STORAGE_S3_REGION" , Value : d .Config .Region },
359
394
envvar.EnvVar {Name : "REGISTRY_STORAGE_S3_ENCRYPT" , Value : d .Config .Encrypt },
360
395
envvar.EnvVar {Name : "REGISTRY_STORAGE_S3_VIRTUALHOSTEDSTYLE" , Value : d .Config .VirtualHostedStyle },
361
- envvar.EnvVar {Name : "REGISTRY_STORAGE_S3_USEDUALSTACK" , Value : true },
362
396
envvar.EnvVar {Name : "REGISTRY_STORAGE_S3_CREDENTIALSCONFIGPATH" , Value : filepath .Join (imageRegistrySecretMountpoint , imageRegistrySecretDataKey )},
363
397
)
364
398
399
+ useDualStack , err := d .useDualStack ()
400
+ if err != nil {
401
+ return nil , err
402
+ }
403
+ if useDualStack {
404
+ envs = append (envs , envvar.EnvVar {Name : "REGISTRY_STORAGE_S3_USEDUALSTACK" , Value : true })
405
+ }
406
+
365
407
if d .Config .CloudFront != nil {
366
408
// Use structs to make ordering deterministic
367
409
type cloudFrontOptions struct {
0 commit comments