@@ -53,14 +53,17 @@ import (
53
53
func init () {
54
54
fs .Register (& fs.RegInfo {
55
55
Name : "s3" ,
56
- Description : "Amazon S3 Compliant Storage Providers (AWS, Ceph, Dreamhost, IBM COS, Minio)" ,
56
+ Description : "Amazon S3 Compliant Storage Provider (AWS, Alibaba, Ceph, Digital Ocean, Dreamhost, IBM COS, Minio, etc )" ,
57
57
NewFs : NewFs ,
58
58
Options : []fs.Option {{
59
59
Name : fs .ConfigProvider ,
60
60
Help : "Choose your S3 provider." ,
61
61
Examples : []fs.OptionExample {{
62
62
Value : "AWS" ,
63
63
Help : "Amazon Web Services (AWS) S3" ,
64
+ }, {
65
+ Value : "Alibaba" ,
66
+ Help : "Alibaba Cloud Object Storage System (OSS) formerly Aliyun" ,
64
67
}, {
65
68
Value : "Ceph" ,
66
69
Help : "Ceph Object Storage" ,
@@ -76,6 +79,9 @@ func init() {
76
79
}, {
77
80
Value : "Minio" ,
78
81
Help : "Minio Object Storage" ,
82
+ }, {
83
+ Value : "Netease" ,
84
+ Help : "Netease Object Storage (NOS)" ,
79
85
}, {
80
86
Value : "Wasabi" ,
81
87
Help : "Wasabi Object Storage" ,
@@ -150,7 +156,7 @@ func init() {
150
156
}, {
151
157
Name : "region" ,
152
158
Help : "Region to connect to.\n Leave blank if you are using an S3 clone and you don't have a region." ,
153
- Provider : "!AWS" ,
159
+ Provider : "!AWS,Alibaba " ,
154
160
Examples : []fs.OptionExample {{
155
161
Value : "" ,
156
162
Help : "Use this if unsure. Will use v4 signatures and an empty region." ,
@@ -269,10 +275,73 @@ func init() {
269
275
Value : "s3.tor01.objectstorage.service.networklayer.com" ,
270
276
Help : "Toronto Single Site Private Endpoint" ,
271
277
}},
278
+ }, {
279
+ // oss endpoints: https://help.aliyun.com/document_detail/31837.html
280
+ Name : "endpoint" ,
281
+ Help : "Endpoint for OSS API." ,
282
+ Provider : "Alibaba" ,
283
+ Examples : []fs.OptionExample {{
284
+ Value : "oss-cn-hangzhou.aliyuncs.com" ,
285
+ Help : "East China 1 (Hangzhou)" ,
286
+ }, {
287
+ Value : "oss-cn-shanghai.aliyuncs.com" ,
288
+ Help : "East China 2 (Shanghai)" ,
289
+ }, {
290
+ Value : "oss-cn-qingdao.aliyuncs.com" ,
291
+ Help : "North China 1 (Qingdao)" ,
292
+ }, {
293
+ Value : "oss-cn-beijing.aliyuncs.com" ,
294
+ Help : "North China 2 (Beijing)" ,
295
+ }, {
296
+ Value : "oss-cn-zhangjiakou.aliyuncs.com" ,
297
+ Help : "North China 3 (Zhangjiakou)" ,
298
+ }, {
299
+ Value : "oss-cn-huhehaote.aliyuncs.com" ,
300
+ Help : "North China 5 (Huhehaote)" ,
301
+ }, {
302
+ Value : "oss-cn-shenzhen.aliyuncs.com" ,
303
+ Help : "South China 1 (Shenzhen)" ,
304
+ }, {
305
+ Value : "oss-cn-hongkong.aliyuncs.com" ,
306
+ Help : "Hong Kong (Hong Kong)" ,
307
+ }, {
308
+ Value : "oss-us-west-1.aliyuncs.com" ,
309
+ Help : "US West 1 (Silicon Valley)" ,
310
+ }, {
311
+ Value : "oss-us-east-1.aliyuncs.com" ,
312
+ Help : "US East 1 (Virginia)" ,
313
+ }, {
314
+ Value : "oss-ap-southeast-1.aliyuncs.com" ,
315
+ Help : "Southeast Asia Southeast 1 (Singapore)" ,
316
+ }, {
317
+ Value : "oss-ap-southeast-2.aliyuncs.com" ,
318
+ Help : "Asia Pacific Southeast 2 (Sydney)" ,
319
+ }, {
320
+ Value : "oss-ap-southeast-3.aliyuncs.com" ,
321
+ Help : "Southeast Asia Southeast 3 (Kuala Lumpur)" ,
322
+ }, {
323
+ Value : "oss-ap-southeast-5.aliyuncs.com" ,
324
+ Help : "Asia Pacific Southeast 5 (Jakarta)" ,
325
+ }, {
326
+ Value : "oss-ap-northeast-1.aliyuncs.com" ,
327
+ Help : "Asia Pacific Northeast 1 (Japan)" ,
328
+ }, {
329
+ Value : "oss-ap-south-1.aliyuncs.com" ,
330
+ Help : "Asia Pacific South 1 (Mumbai)" ,
331
+ }, {
332
+ Value : "oss-eu-central-1.aliyuncs.com" ,
333
+ Help : "Central Europe 1 (Frankfurt)" ,
334
+ }, {
335
+ Value : "oss-eu-west-1.aliyuncs.com" ,
336
+ Help : "West Europe (London)" ,
337
+ }, {
338
+ Value : "oss-me-east-1.aliyuncs.com" ,
339
+ Help : "Middle East 1 (Dubai)" ,
340
+ }},
272
341
}, {
273
342
Name : "endpoint" ,
274
343
Help : "Endpoint for S3 API.\n Required when using an S3 clone." ,
275
- Provider : "!AWS,IBMCOS" ,
344
+ Provider : "!AWS,IBMCOS,Alibaba " ,
276
345
Examples : []fs.OptionExample {{
277
346
Value : "objects-us-west-1.dream.io" ,
278
347
Help : "Dream Objects endpoint" ,
@@ -449,7 +518,7 @@ func init() {
449
518
}, {
450
519
Name : "location_constraint" ,
451
520
Help : "Location constraint - must be set to match the Region.\n Leave blank if not sure. Used when creating buckets only." ,
452
- Provider : "!AWS,IBMCOS" ,
521
+ Provider : "!AWS,IBMCOS,Alibaba " ,
453
522
}, {
454
523
Name : "acl" ,
455
524
Help : `Canned ACL used when creating buckets and storing or copying objects.
@@ -547,6 +616,20 @@ doesn't copy the ACL from the source but rather writes a fresh one.`,
547
616
Value : "GLACIER" ,
548
617
Help : "Glacier storage class" ,
549
618
}},
619
+ }, {
620
+ Name : "storage_class" ,
621
+ Help : "The storage class to use when storing new objects in OSS." ,
622
+ Provider : "Alibaba" ,
623
+ Examples : []fs.OptionExample {{
624
+ Value : "Standard" ,
625
+ Help : "Standard storage class" ,
626
+ }, {
627
+ Value : "Archive" ,
628
+ Help : "Archive storage mode." ,
629
+ }, {
630
+ Value : "IA" ,
631
+ Help : "Infrequent access storage mode." ,
632
+ }},
550
633
}, {
551
634
Name : "upload_cutoff" ,
552
635
Help : `Cutoff for switching to chunked upload
@@ -714,22 +797,21 @@ func (f *Fs) Features() *fs.Features {
714
797
// retryErrorCodes is a slice of error codes that we will retry
715
798
// See: https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
716
799
var retryErrorCodes = []int {
717
- 409 , // Conflict - various states that could be resolved on a retry
800
+ // 409, // Conflict - various states that could be resolved on a retry
718
801
503 , // Service Unavailable/Slow Down - "Reduce your request rate"
719
802
}
720
803
721
804
//S3 is pretty resilient, and the built in retry handling is probably sufficient
722
805
// as it should notice closed connections and timeouts which are the most likely
723
806
// sort of failure modes
724
807
func shouldRetry (err error ) (bool , error ) {
725
-
726
808
// If this is an awserr object, try and extract more useful information to determine if we should retry
727
809
if awsError , ok := err .(awserr.Error ); ok {
728
810
// Simple case, check the original embedded error in case it's generically retriable
729
811
if fserrors .ShouldRetry (awsError .OrigErr ()) {
730
812
return true , err
731
813
}
732
- //Failing that, if it's a RequestFailure it's probably got an http status code we can check
814
+ // Failing that, if it's a RequestFailure it's probably got an http status code we can check
733
815
if reqErr , ok := err .(awserr.RequestFailure ); ok {
734
816
for _ , e := range retryErrorCodes {
735
817
if reqErr .StatusCode () == e {
@@ -738,7 +820,7 @@ func shouldRetry(err error) (bool, error) {
738
820
}
739
821
}
740
822
}
741
- //Ok, not an awserr, check for generic failure conditions
823
+ // Ok, not an awserr, check for generic failure conditions
742
824
return fserrors .ShouldRetry (err ), err
743
825
}
744
826
@@ -815,6 +897,9 @@ func s3Connection(opt *Options) (*s3.S3, *session.Session, error) {
815
897
if opt .Region == "" {
816
898
opt .Region = "us-east-1"
817
899
}
900
+ if opt .Provider == "Alibaba" || opt .Provider == "Netease" {
901
+ opt .ForcePathStyle = false
902
+ }
818
903
awsConfig := aws .NewConfig ().
819
904
WithRegion (opt .Region ).
820
905
WithMaxRetries (maxRetries ).
0 commit comments