fog-aws 3.6.7 → 3.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +12 -0
- data/CHANGELOG.md +18 -3
- data/Gemfile +1 -1
- data/README.md +20 -0
- data/lib/fog/aws/credential_fetcher.rb +32 -3
- data/lib/fog/aws/models/compute/flavors.rb +460 -0
- data/lib/fog/aws/models/storage/file.rb +124 -3
- data/lib/fog/aws/parsers/storage/upload_part_copy_object.rb +18 -0
- data/lib/fog/aws/requests/compute/request_spot_instances.rb +1 -1
- data/lib/fog/aws/requests/storage/upload_part_copy.rb +92 -0
- data/lib/fog/aws/storage.rb +1 -0
- data/lib/fog/aws/version.rb +1 -1
- data/tests/credentials_tests.rb +30 -0
- data/tests/requests/storage/multipart_copy_tests.rb +80 -0
- metadata +9 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ac0628bad4edf849a2b1395bd829d18ae77bff352841e68fbc7ecdb475ef82b
|
4
|
+
data.tar.gz: 5a545b7e8ad44c321273fac7b87b11b79be3a9af1c2d038b2790ea95c529df30
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06156a44eec55618672a3d5beed5d35c0e7195ba07a3a515e944db462edbd6b4e56f6ff693bd5dd0013090c2083f395cf9f310013a164d3a3163c7ea82f96b9e
|
7
|
+
data.tar.gz: ebf606599061ed26cf2f1995e91690aebb7b409b15fe1d6ee465ef3e36a87b9c714e376e9bf6fee9c276a45a994972d94a24ef49d27f92e8b64ee6a47a9ae082
|
data/.travis.yml
CHANGED
@@ -19,6 +19,14 @@ matrix:
|
|
19
19
|
gemfile: Gemfile
|
20
20
|
- rvm: 2.5.0
|
21
21
|
gemfile: gemfiles/Gemfile-edge
|
22
|
+
- rvm: 2.6.6
|
23
|
+
gemfile: Gemfile
|
24
|
+
- rvm: 2.6.6
|
25
|
+
gemfile: gemfiles/Gemfile-edge
|
26
|
+
- rvm: 2.7.2
|
27
|
+
gemfile: Gemfile
|
28
|
+
- rvm: 2.7.2
|
29
|
+
gemfile: gemfiles/Gemfile-edge
|
22
30
|
- rvm: jruby-head
|
23
31
|
gemfile: Gemfile
|
24
32
|
allow_failures:
|
@@ -32,6 +40,10 @@ matrix:
|
|
32
40
|
gemfile: gemfiles/Gemfile-edge
|
33
41
|
- rvm: 2.5.0
|
34
42
|
gemfile: gemfiles/Gemfile-edge
|
43
|
+
- rvm: 2.6.6
|
44
|
+
gemfile: gemfiles/Gemfile-edge
|
45
|
+
- rvm: 2.7.2
|
46
|
+
gemfile: gemfiles/Gemfile-edge
|
35
47
|
notifications:
|
36
48
|
email: false
|
37
49
|
irc:
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,23 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [v3.
|
3
|
+
## [v3.7.0](https://github.com/fog/fog-aws/tree/v3.7.0) (2020-12-01)
|
4
|
+
[Full Changelog](https://github.com/fog/fog-aws/compare/v3.7.0...HEAD)
|
4
5
|
|
5
|
-
|
6
|
+
**Closed issues:**
|
7
|
+
|
8
|
+
- File\#copy does not support files above 5 GB [\#577](https://github.com/fog/fog-aws/issues/577)
|
9
|
+
- fog-aws: AWS extended length resource ID issues \(8-\>18\) [\#517](https://github.com/fog/fog-aws/issues/517)
|
10
|
+
|
11
|
+
**Merged pull requests:**
|
12
|
+
|
13
|
+
- Add all m6gd, r6g, r6gd, c6g, and c6gd instance classes [\#582](https://github.com/fog/fog-aws/pull/582) ([calebwoofenden](https://github.com/calebwoofenden))
|
14
|
+
- Test Ruby v2.6.6 and v2.7.2 in CI [\#581](https://github.com/fog/fog-aws/pull/581) ([stanhu](https://github.com/stanhu))
|
15
|
+
- Add multi-threaded support for File\#copy [\#579](https://github.com/fog/fog-aws/pull/579) ([stanhu](https://github.com/stanhu))
|
16
|
+
- Add support for multipart Fog::AWS::Storage::File\#copy [\#578](https://github.com/fog/fog-aws/pull/578) ([stanhu](https://github.com/stanhu))
|
17
|
+
- Add AssumeRoleWithWebIdentity to fetch\_credentials [\#576](https://github.com/fog/fog-aws/pull/576) ([jpac-run](https://github.com/jpac-run))
|
18
|
+
|
19
|
+
## [v3.6.7](https://github.com/fog/fog-aws/tree/v3.6.7) (2020-08-26)
|
20
|
+
[Full Changelog](https://github.com/fog/fog-aws/compare/v3.6.6...v3.6.7)
|
6
21
|
|
7
22
|
**Merged pull requests:**
|
8
23
|
|
@@ -293,6 +308,7 @@
|
|
293
308
|
|
294
309
|
- Update changelog for 1.4.0 [\#383](https://github.com/fog/fog-aws/pull/383) ([greysteil](https://github.com/greysteil))
|
295
310
|
- Allow specifying kms key id to use [\#382](https://github.com/fog/fog-aws/pull/382) ([fcheung](https://github.com/fcheung))
|
311
|
+
- added support to retrieve and create vpc with ipv6 cidr block [\#381](https://github.com/fog/fog-aws/pull/381) ([chanakyacool](https://github.com/chanakyacool))
|
296
312
|
- Add MaxResults filter to describe reserved instances offerings [\#376](https://github.com/fog/fog-aws/pull/376) ([KevinLoiseau](https://github.com/KevinLoiseau))
|
297
313
|
- Fix Fog::Compute::AWS::Images\#all [\#375](https://github.com/fog/fog-aws/pull/375) ([eddiej](https://github.com/eddiej))
|
298
314
|
- Fix AWS credential mocking [\#374](https://github.com/fog/fog-aws/pull/374) ([v-yarotsky](https://github.com/v-yarotsky))
|
@@ -310,7 +326,6 @@
|
|
310
326
|
|
311
327
|
**Merged pull requests:**
|
312
328
|
|
313
|
-
- added support to retrieve and create vpc with ipv6 cidr block [\#381](https://github.com/fog/fog-aws/pull/381) ([chanakyacool](https://github.com/chanakyacool))
|
314
329
|
- add NextContinuationToken support to GetBucket operation [\#370](https://github.com/fog/fog-aws/pull/370) ([khoan](https://github.com/khoan))
|
315
330
|
- Add a top-level require that matches the gem name [\#367](https://github.com/fog/fog-aws/pull/367) ([lanej](https://github.com/lanej))
|
316
331
|
- Fixed credential refresh when instance metadata host is inaccessible [\#366](https://github.com/fog/fog-aws/pull/366) ([ankane](https://github.com/ankane))
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -105,6 +105,26 @@ directory.files
|
|
105
105
|
directory.files.new(key: 'user/1/Gemfile').url(Time.now + 60)
|
106
106
|
```
|
107
107
|
|
108
|
+
#### Copying a file
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
directory = s3.directories.new(key: 'gaudi-portal-dev')
|
112
|
+
file = directory.files.get('user/1/Gemfile')
|
113
|
+
file.copy("target-bucket", "user/2/Gemfile.copy")
|
114
|
+
```
|
115
|
+
|
116
|
+
To speed transfers of large files, the `concurrency` option can be used
|
117
|
+
to spawn multiple threads. Note that the file must be at least 5 MB for
|
118
|
+
multipart uploads to work. For example:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
directory = s3.directories.new(key: 'gaudi-portal-dev')
|
122
|
+
file = directory.files.get('user/1/Gemfile')
|
123
|
+
file.multipart_chunk_size = 10 * 1024 * 1024
|
124
|
+
file.concurrency = 10
|
125
|
+
file.copy("target-bucket", "user/2/Gemfile.copy")
|
126
|
+
```
|
127
|
+
|
108
128
|
## Documentation
|
109
129
|
|
110
130
|
See the [online documentation](http://www.rubydoc.info/github/fog/fog-aws) for a complete API reference.
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Fog
|
2
4
|
module AWS
|
3
5
|
module CredentialFetcher
|
@@ -9,6 +11,8 @@ module Fog
|
|
9
11
|
|
10
12
|
CONTAINER_CREDENTIALS_HOST = "http://169.254.170.2"
|
11
13
|
|
14
|
+
STS_GLOBAL_ENDPOINT = "https://sts.amazonaws.com"
|
15
|
+
|
12
16
|
module ServiceMethods
|
13
17
|
def fetch_credentials(options)
|
14
18
|
if options[:use_iam_profile] && Fog.mocking?
|
@@ -23,6 +27,30 @@ module Fog
|
|
23
27
|
connection = options[:connection] || Excon.new(CONTAINER_CREDENTIALS_HOST)
|
24
28
|
credential_path = options[:credential_path] || ENV["AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"]
|
25
29
|
role_data = connection.get(:path => credential_path, :idempotent => true, :expects => 200).body
|
30
|
+
session = Fog::JSON.decode(role_data)
|
31
|
+
|
32
|
+
if region.nil?
|
33
|
+
connection = options[:metadata_connection] || Excon.new(INSTANCE_METADATA_HOST)
|
34
|
+
token_header = fetch_credentials_token_header(connection, options[:disable_imds_v2])
|
35
|
+
region = connection.get(:path => INSTANCE_METADATA_AZ, :idempotent => true, :expects => 200, :headers => token_header).body[0..-2]
|
36
|
+
end
|
37
|
+
elsif ENV["AWS_WEB_IDENTITY_TOKEN_FILE"]
|
38
|
+
params = {
|
39
|
+
:Action => "AssumeRoleWithWebIdentity",
|
40
|
+
:RoleArn => options[:role_arn] || ENV.fetch("AWS_ROLE_ARN"),
|
41
|
+
:RoleSessionName => options[:role_session_name] || ENV.fetch("AWS_ROLE_SESSION_NAME"),
|
42
|
+
:WebIdentityToken => File.read(options[:aws_web_identity_token_file] || ENV.fetch("AWS_WEB_IDENTITY_TOKEN_FILE")),
|
43
|
+
:Version => "2011-06-15",
|
44
|
+
}
|
45
|
+
connection = options[:connection] || Excon.new(STS_GLOBAL_ENDPOINT, :query => params)
|
46
|
+
document = Nokogiri::XML(connection.get(:idempotent => true, :expects => 200).body)
|
47
|
+
|
48
|
+
session = {
|
49
|
+
"AccessKeyId" => document.css("AccessKeyId").children.text,
|
50
|
+
"SecretAccessKey" => document.css("SecretAccessKey").children.text,
|
51
|
+
"Token" => document.css("SessionToken").children.text,
|
52
|
+
"Expiration" => document.css("Expiration").children.text,
|
53
|
+
}
|
26
54
|
|
27
55
|
if region.nil?
|
28
56
|
connection = options[:metadata_connection] || Excon.new(INSTANCE_METADATA_HOST)
|
@@ -34,16 +62,17 @@ module Fog
|
|
34
62
|
token_header = fetch_credentials_token_header(connection, options[:disable_imds_v2])
|
35
63
|
role_name = connection.get(:path => INSTANCE_METADATA_PATH, :idempotent => true, :expects => 200, :headers => token_header).body
|
36
64
|
role_data = connection.get(:path => INSTANCE_METADATA_PATH+role_name, :idempotent => true, :expects => 200, :headers => token_header).body
|
65
|
+
session = Fog::JSON.decode(role_data)
|
66
|
+
|
37
67
|
region ||= connection.get(:path => INSTANCE_METADATA_AZ, :idempotent => true, :expects => 200, :headers => token_header).body[0..-2]
|
38
68
|
end
|
39
|
-
|
40
|
-
session = Fog::JSON.decode(role_data)
|
69
|
+
|
41
70
|
credentials = {}
|
42
71
|
credentials[:aws_access_key_id] = session['AccessKeyId']
|
43
72
|
credentials[:aws_secret_access_key] = session['SecretAccessKey']
|
44
73
|
credentials[:aws_session_token] = session['Token']
|
45
74
|
credentials[:aws_credentials_expire_at] = Time.xmlschema session['Expiration']
|
46
|
-
|
75
|
+
|
47
76
|
# set region by default to the one the instance is in.
|
48
77
|
credentials[:region] = region
|
49
78
|
#these indicate the metadata service is unavailable or has no profile setup
|
@@ -366,6 +366,106 @@ module Fog
|
|
366
366
|
:ebs_optimized_available => true,
|
367
367
|
:instance_store_volumes => 0
|
368
368
|
},
|
369
|
+
{
|
370
|
+
:id => 'm6g.metal',
|
371
|
+
:name => 'M6G Metal',
|
372
|
+
:bits => 64,
|
373
|
+
:cores => 64,
|
374
|
+
:disk => 0,
|
375
|
+
:ram => 274878,
|
376
|
+
:ebs_optimized_available => true,
|
377
|
+
:instance_store_volumes => 0
|
378
|
+
},
|
379
|
+
{
|
380
|
+
:id => 'm6gd.medium',
|
381
|
+
:name => 'M6GD Medium',
|
382
|
+
:bits => 64,
|
383
|
+
:cores => 1,
|
384
|
+
:disk => 59,
|
385
|
+
:ram => 4295,
|
386
|
+
:ebs_optimized_available => true,
|
387
|
+
:instance_store_volumes => 1
|
388
|
+
},
|
389
|
+
{
|
390
|
+
:id => 'm6gd.large',
|
391
|
+
:name => 'M6GD Large',
|
392
|
+
:bits => 64,
|
393
|
+
:cores => 2,
|
394
|
+
:disk => 118,
|
395
|
+
:ram => 8590,
|
396
|
+
:ebs_optimized_available => true,
|
397
|
+
:instance_store_volumes => 1
|
398
|
+
},
|
399
|
+
{
|
400
|
+
:id => 'm6gd.xlarge',
|
401
|
+
:name => 'M6GD Extra Large',
|
402
|
+
:bits => 64,
|
403
|
+
:cores => 4,
|
404
|
+
:disk => 237,
|
405
|
+
:ram => 17180,
|
406
|
+
:ebs_optimized_available => true,
|
407
|
+
:instance_store_volumes => 1
|
408
|
+
},
|
409
|
+
{
|
410
|
+
:id => 'm6gd.2xlarge',
|
411
|
+
:name => 'M6GD Double Extra Large',
|
412
|
+
:bits => 64,
|
413
|
+
:cores => 8,
|
414
|
+
:disk => 474,
|
415
|
+
:ram => 34360,
|
416
|
+
:ebs_optimized_available => true,
|
417
|
+
:instance_store_volumes => 1
|
418
|
+
},
|
419
|
+
{
|
420
|
+
:id => 'm6gd.4xlarge',
|
421
|
+
:name => 'M6GD Quadruple Extra Large',
|
422
|
+
:bits => 64,
|
423
|
+
:cores => 16,
|
424
|
+
:disk => 950,
|
425
|
+
:ram => 68719,
|
426
|
+
:ebs_optimized_available => true,
|
427
|
+
:instance_store_volumes => 1
|
428
|
+
},
|
429
|
+
{
|
430
|
+
:id => 'm6gd.8xlarge',
|
431
|
+
:name => 'M6GD Octuple Extra Large',
|
432
|
+
:bits => 64,
|
433
|
+
:cores => 32,
|
434
|
+
:disk => 1900,
|
435
|
+
:ram => 137439,
|
436
|
+
:ebs_optimized_available => true,
|
437
|
+
:instance_store_volumes => 1
|
438
|
+
},
|
439
|
+
{
|
440
|
+
:id => 'm6gd.12xlarge',
|
441
|
+
:name => 'M6GD Twelve Extra Large',
|
442
|
+
:bits => 64,
|
443
|
+
:cores => 48,
|
444
|
+
:disk => 2850,
|
445
|
+
:ram => 206158,
|
446
|
+
:ebs_optimized_available => true,
|
447
|
+
:instance_store_volumes => 2
|
448
|
+
},
|
449
|
+
{
|
450
|
+
:id => 'm6gd.16xlarge',
|
451
|
+
:name => 'M6GD Sixteen Extra Large',
|
452
|
+
:bits => 64,
|
453
|
+
:cores => 64,
|
454
|
+
:disk => 3800,
|
455
|
+
:ram => 274878,
|
456
|
+
:ebs_optimized_available => true,
|
457
|
+
:instance_store_volumes => 2
|
458
|
+
},
|
459
|
+
{
|
460
|
+
:id => 'm6gd.metal',
|
461
|
+
:name => 'M6GD Metal',
|
462
|
+
:bits => 64,
|
463
|
+
:cores => 64,
|
464
|
+
:disk => 3800,
|
465
|
+
:ram => 274878,
|
466
|
+
:ebs_optimized_available => true,
|
467
|
+
:instance_store_volumes => 2
|
468
|
+
},
|
369
469
|
{
|
370
470
|
:id => 'm1.small',
|
371
471
|
:name => 'M1 Small Instance',
|
@@ -776,6 +876,186 @@ module Fog
|
|
776
876
|
:ebs_optimized_available => true,
|
777
877
|
:instance_store_volumes => 0
|
778
878
|
},
|
879
|
+
{
|
880
|
+
:id => 'c6g.medium',
|
881
|
+
:name => 'C6G Medium',
|
882
|
+
:bits => 64,
|
883
|
+
:cores => 1,
|
884
|
+
:disk => 0,
|
885
|
+
:ram => 2147,
|
886
|
+
:ebs_optimized_available => true,
|
887
|
+
:instance_store_volumes => 0
|
888
|
+
},
|
889
|
+
{
|
890
|
+
:id => 'c6g.large',
|
891
|
+
:name => 'C6G Large',
|
892
|
+
:bits => 64,
|
893
|
+
:cores => 2,
|
894
|
+
:disk => 0,
|
895
|
+
:ram => 4295,
|
896
|
+
:ebs_optimized_available => true,
|
897
|
+
:instance_store_volumes => 0
|
898
|
+
},
|
899
|
+
{
|
900
|
+
:id => 'c6g.xlarge',
|
901
|
+
:name => 'C6G Extra Large',
|
902
|
+
:bits => 64,
|
903
|
+
:cores => 4,
|
904
|
+
:disk => 0,
|
905
|
+
:ram => 8590,
|
906
|
+
:ebs_optimized_available => true,
|
907
|
+
:instance_store_volumes => 0
|
908
|
+
},
|
909
|
+
{
|
910
|
+
:id => 'c6g.2xlarge',
|
911
|
+
:name => 'C6G Double Extra Large',
|
912
|
+
:bits => 64,
|
913
|
+
:cores => 8,
|
914
|
+
:disk => 0,
|
915
|
+
:ram => 17180,
|
916
|
+
:ebs_optimized_available => true,
|
917
|
+
:instance_store_volumes => 0
|
918
|
+
},
|
919
|
+
{
|
920
|
+
:id => 'c6g.4xlarge',
|
921
|
+
:name => 'C6G Quadruple Extra Large',
|
922
|
+
:bits => 64,
|
923
|
+
:cores => 16,
|
924
|
+
:disk => 0,
|
925
|
+
:ram => 34360,
|
926
|
+
:ebs_optimized_available => true,
|
927
|
+
:instance_store_volumes => 0
|
928
|
+
},
|
929
|
+
{
|
930
|
+
:id => 'c6g.8xlarge',
|
931
|
+
:name => 'C6G Octuple Extra Large',
|
932
|
+
:bits => 64,
|
933
|
+
:cores => 32,
|
934
|
+
:disk => 0,
|
935
|
+
:ram => 68719,
|
936
|
+
:ebs_optimized_available => true,
|
937
|
+
:instance_store_volumes => 0
|
938
|
+
},
|
939
|
+
{
|
940
|
+
:id => 'c6g.12xlarge',
|
941
|
+
:name => 'C6G Twelve Extra Large',
|
942
|
+
:bits => 64,
|
943
|
+
:cores => 48,
|
944
|
+
:disk => 0,
|
945
|
+
:ram => 103079,
|
946
|
+
:ebs_optimized_available => true,
|
947
|
+
:instance_store_volumes => 0
|
948
|
+
},
|
949
|
+
{
|
950
|
+
:id => 'c6g.16xlarge',
|
951
|
+
:name => 'C6G Sixteen Extra Large',
|
952
|
+
:bits => 64,
|
953
|
+
:cores => 64,
|
954
|
+
:disk => 0,
|
955
|
+
:ram => 137439,
|
956
|
+
:ebs_optimized_available => true,
|
957
|
+
:instance_store_volumes => 0
|
958
|
+
},
|
959
|
+
{
|
960
|
+
:id => 'c6g.metal',
|
961
|
+
:name => 'C6G Metal',
|
962
|
+
:bits => 64,
|
963
|
+
:cores => 64,
|
964
|
+
:disk => 0,
|
965
|
+
:ram => 137439,
|
966
|
+
:ebs_optimized_available => true,
|
967
|
+
:instance_store_volumes => 0
|
968
|
+
},
|
969
|
+
{
|
970
|
+
:id => 'c6gd.medium',
|
971
|
+
:name => 'C6GD Medium',
|
972
|
+
:bits => 64,
|
973
|
+
:cores => 1,
|
974
|
+
:disk => 59,
|
975
|
+
:ram => 2147,
|
976
|
+
:ebs_optimized_available => true,
|
977
|
+
:instance_store_volumes => 1
|
978
|
+
},
|
979
|
+
{
|
980
|
+
:id => 'c6gd.large',
|
981
|
+
:name => 'C6GD Large',
|
982
|
+
:bits => 64,
|
983
|
+
:cores => 2,
|
984
|
+
:disk => 118,
|
985
|
+
:ram => 4295,
|
986
|
+
:ebs_optimized_available => true,
|
987
|
+
:instance_store_volumes => 1
|
988
|
+
},
|
989
|
+
{
|
990
|
+
:id => 'c6gd.xlarge',
|
991
|
+
:name => 'C6GD Extra Large',
|
992
|
+
:bits => 64,
|
993
|
+
:cores => 4,
|
994
|
+
:disk => 237,
|
995
|
+
:ram => 8590,
|
996
|
+
:ebs_optimized_available => true,
|
997
|
+
:instance_store_volumes => 1
|
998
|
+
},
|
999
|
+
{
|
1000
|
+
:id => 'c6gd.2xlarge',
|
1001
|
+
:name => 'C6GD Double Extra Large',
|
1002
|
+
:bits => 64,
|
1003
|
+
:cores => 8,
|
1004
|
+
:disk => 474,
|
1005
|
+
:ram => 17180,
|
1006
|
+
:ebs_optimized_available => true,
|
1007
|
+
:instance_store_volumes => 1
|
1008
|
+
},
|
1009
|
+
{
|
1010
|
+
:id => 'c6gd.4xlarge',
|
1011
|
+
:name => 'C6GD Quadruple Extra Large',
|
1012
|
+
:bits => 64,
|
1013
|
+
:cores => 16,
|
1014
|
+
:disk => 950,
|
1015
|
+
:ram => 34360,
|
1016
|
+
:ebs_optimized_available => true,
|
1017
|
+
:instance_store_volumes => 1
|
1018
|
+
},
|
1019
|
+
{
|
1020
|
+
:id => 'c6gd.8xlarge',
|
1021
|
+
:name => 'C6GD Octuple Extra Large',
|
1022
|
+
:bits => 64,
|
1023
|
+
:cores => 32,
|
1024
|
+
:disk => 1900,
|
1025
|
+
:ram => 68719,
|
1026
|
+
:ebs_optimized_available => true,
|
1027
|
+
:instance_store_volumes => 1
|
1028
|
+
},
|
1029
|
+
{
|
1030
|
+
:id => 'c6gd.12xlarge',
|
1031
|
+
:name => 'C6GD Twelve Extra Large',
|
1032
|
+
:bits => 64,
|
1033
|
+
:cores => 48,
|
1034
|
+
:disk => 2850,
|
1035
|
+
:ram => 103079,
|
1036
|
+
:ebs_optimized_available => true,
|
1037
|
+
:instance_store_volumes => 2
|
1038
|
+
},
|
1039
|
+
{
|
1040
|
+
:id => 'c6gd.16xlarge',
|
1041
|
+
:name => 'C6GD Sixteen Extra Large',
|
1042
|
+
:bits => 64,
|
1043
|
+
:cores => 64,
|
1044
|
+
:disk => 3800,
|
1045
|
+
:ram => 137439,
|
1046
|
+
:ebs_optimized_available => true,
|
1047
|
+
:instance_store_volumes => 2
|
1048
|
+
},
|
1049
|
+
{
|
1050
|
+
:id => 'c6gd.metal',
|
1051
|
+
:name => 'C6GD Metal',
|
1052
|
+
:bits => 64,
|
1053
|
+
:cores => 64,
|
1054
|
+
:disk => 3800,
|
1055
|
+
:ram => 137439,
|
1056
|
+
:ebs_optimized_available => true,
|
1057
|
+
:instance_store_volumes => 2
|
1058
|
+
},
|
779
1059
|
{
|
780
1060
|
:id => 'g2.2xlarge',
|
781
1061
|
:name => 'GPU Double Extra Large',
|
@@ -1696,6 +1976,186 @@ module Fog
|
|
1696
1976
|
:ebs_optimized_available => true,
|
1697
1977
|
:instance_store_volumes => 4
|
1698
1978
|
},
|
1979
|
+
{
|
1980
|
+
:id => 'r6g.medium',
|
1981
|
+
:name => 'R6G Medium',
|
1982
|
+
:bits => 64,
|
1983
|
+
:cores => 1,
|
1984
|
+
:disk => 0,
|
1985
|
+
:ram => 8590,
|
1986
|
+
:ebs_optimized_available => true,
|
1987
|
+
:instance_store_volumes => 0
|
1988
|
+
},
|
1989
|
+
{
|
1990
|
+
:id => 'r6g.large',
|
1991
|
+
:name => 'R6G Large',
|
1992
|
+
:bits => 64,
|
1993
|
+
:cores => 2,
|
1994
|
+
:disk => 0,
|
1995
|
+
:ram => 17180,
|
1996
|
+
:ebs_optimized_available => true,
|
1997
|
+
:instance_store_volumes => 0
|
1998
|
+
},
|
1999
|
+
{
|
2000
|
+
:id => 'r6g.xlarge',
|
2001
|
+
:name => 'R6G Extra Large',
|
2002
|
+
:bits => 64,
|
2003
|
+
:cores => 4,
|
2004
|
+
:disk => 0,
|
2005
|
+
:ram => 34360,
|
2006
|
+
:ebs_optimized_available => true,
|
2007
|
+
:instance_store_volumes => 0
|
2008
|
+
},
|
2009
|
+
{
|
2010
|
+
:id => 'r6g.2xlarge',
|
2011
|
+
:name => 'R6G Double Extra Large',
|
2012
|
+
:bits => 64,
|
2013
|
+
:cores => 8,
|
2014
|
+
:disk => 0,
|
2015
|
+
:ram => 68719,
|
2016
|
+
:ebs_optimized_available => true,
|
2017
|
+
:instance_store_volumes => 0
|
2018
|
+
},
|
2019
|
+
{
|
2020
|
+
:id => 'r6g.4xlarge',
|
2021
|
+
:name => 'R6G Quadruple Extra Large',
|
2022
|
+
:bits => 64,
|
2023
|
+
:cores => 16,
|
2024
|
+
:disk => 0,
|
2025
|
+
:ram => 137439,
|
2026
|
+
:ebs_optimized_available => true,
|
2027
|
+
:instance_store_volumes => 0
|
2028
|
+
},
|
2029
|
+
{
|
2030
|
+
:id => 'r6g.8xlarge',
|
2031
|
+
:name => 'R6G Octuple Extra Large',
|
2032
|
+
:bits => 64,
|
2033
|
+
:cores => 32,
|
2034
|
+
:disk => 0,
|
2035
|
+
:ram => 274878,
|
2036
|
+
:ebs_optimized_available => true,
|
2037
|
+
:instance_store_volumes => 0
|
2038
|
+
},
|
2039
|
+
{
|
2040
|
+
:id => 'r6g.12xlarge',
|
2041
|
+
:name => 'R6G Twelve Extra Large',
|
2042
|
+
:bits => 64,
|
2043
|
+
:cores => 48,
|
2044
|
+
:disk => 0,
|
2045
|
+
:ram => 412317,
|
2046
|
+
:ebs_optimized_available => true,
|
2047
|
+
:instance_store_volumes => 0
|
2048
|
+
},
|
2049
|
+
{
|
2050
|
+
:id => 'r6g.16xlarge',
|
2051
|
+
:name => 'R6G Sixteen Extra Large',
|
2052
|
+
:bits => 64,
|
2053
|
+
:cores => 64,
|
2054
|
+
:disk => 0,
|
2055
|
+
:ram => 549756,
|
2056
|
+
:ebs_optimized_available => true,
|
2057
|
+
:instance_store_volumes => 0
|
2058
|
+
},
|
2059
|
+
{
|
2060
|
+
:id => 'r6g.metal',
|
2061
|
+
:name => 'R6G Metal',
|
2062
|
+
:bits => 64,
|
2063
|
+
:cores => 64,
|
2064
|
+
:disk => 0,
|
2065
|
+
:ram => 549756,
|
2066
|
+
:ebs_optimized_available => true,
|
2067
|
+
:instance_store_volumes => 0
|
2068
|
+
},
|
2069
|
+
{
|
2070
|
+
:id => 'r6gd.medium',
|
2071
|
+
:name => 'R6GD Medium',
|
2072
|
+
:bits => 64,
|
2073
|
+
:cores => 1,
|
2074
|
+
:disk => 59,
|
2075
|
+
:ram => 8590,
|
2076
|
+
:ebs_optimized_available => true,
|
2077
|
+
:instance_store_volumes => 1
|
2078
|
+
},
|
2079
|
+
{
|
2080
|
+
:id => 'r6gd.large',
|
2081
|
+
:name => 'R6GD Large',
|
2082
|
+
:bits => 64,
|
2083
|
+
:cores => 2,
|
2084
|
+
:disk => 118,
|
2085
|
+
:ram => 17180,
|
2086
|
+
:ebs_optimized_available => true,
|
2087
|
+
:instance_store_volumes => 1
|
2088
|
+
},
|
2089
|
+
{
|
2090
|
+
:id => 'r6gd.xlarge',
|
2091
|
+
:name => 'R6GD Extra Large',
|
2092
|
+
:bits => 64,
|
2093
|
+
:cores => 4,
|
2094
|
+
:disk => 237,
|
2095
|
+
:ram => 34360,
|
2096
|
+
:ebs_optimized_available => true,
|
2097
|
+
:instance_store_volumes => 1
|
2098
|
+
},
|
2099
|
+
{
|
2100
|
+
:id => 'r6gd.2xlarge',
|
2101
|
+
:name => 'R6GD Double Extra Large',
|
2102
|
+
:bits => 64,
|
2103
|
+
:cores => 8,
|
2104
|
+
:disk => 474,
|
2105
|
+
:ram => 68719,
|
2106
|
+
:ebs_optimized_available => true,
|
2107
|
+
:instance_store_volumes => 1
|
2108
|
+
},
|
2109
|
+
{
|
2110
|
+
:id => 'r6gd.4xlarge',
|
2111
|
+
:name => 'R6GD Quadruple Extra Large',
|
2112
|
+
:bits => 64,
|
2113
|
+
:cores => 16,
|
2114
|
+
:disk => 950,
|
2115
|
+
:ram => 137439,
|
2116
|
+
:ebs_optimized_available => true,
|
2117
|
+
:instance_store_volumes => 1
|
2118
|
+
},
|
2119
|
+
{
|
2120
|
+
:id => 'r6gd.8xlarge',
|
2121
|
+
:name => 'R6GD Octuple Extra Large',
|
2122
|
+
:bits => 64,
|
2123
|
+
:cores => 32,
|
2124
|
+
:disk => 1900,
|
2125
|
+
:ram => 274878,
|
2126
|
+
:ebs_optimized_available => true,
|
2127
|
+
:instance_store_volumes => 1
|
2128
|
+
},
|
2129
|
+
{
|
2130
|
+
:id => 'r6gd.12xlarge',
|
2131
|
+
:name => 'R6GD Twelve Extra Large',
|
2132
|
+
:bits => 64,
|
2133
|
+
:cores => 48,
|
2134
|
+
:disk => 2850,
|
2135
|
+
:ram => 412317,
|
2136
|
+
:ebs_optimized_available => true,
|
2137
|
+
:instance_store_volumes => 2
|
2138
|
+
},
|
2139
|
+
{
|
2140
|
+
:id => 'r6gd.16xlarge',
|
2141
|
+
:name => 'R6GD Sixteen Extra Large',
|
2142
|
+
:bits => 64,
|
2143
|
+
:cores => 64,
|
2144
|
+
:disk => 3800,
|
2145
|
+
:ram => 549756,
|
2146
|
+
:ebs_optimized_available => true,
|
2147
|
+
:instance_store_volumes => 2
|
2148
|
+
},
|
2149
|
+
{
|
2150
|
+
:id => 'r6gd.metal',
|
2151
|
+
:name => 'R6GD Metal',
|
2152
|
+
:bits => 64,
|
2153
|
+
:cores => 64,
|
2154
|
+
:disk => 3800,
|
2155
|
+
:ram => 549756,
|
2156
|
+
:ebs_optimized_available => true,
|
2157
|
+
:instance_store_volumes => 2
|
2158
|
+
},
|
1699
2159
|
{
|
1700
2160
|
:id => "x1.16xlarge",
|
1701
2161
|
:name => "X1 Sixteen Extra Large",
|
@@ -4,6 +4,10 @@ module Fog
|
|
4
4
|
module AWS
|
5
5
|
class Storage
|
6
6
|
class File < Fog::Model
|
7
|
+
MIN_MULTIPART_CHUNK_SIZE = 5242880
|
8
|
+
MAX_SINGLE_PUT_SIZE = 5368709120
|
9
|
+
MULTIPART_COPY_THRESHOLD = 15728640
|
10
|
+
|
7
11
|
# @see AWS Object docs http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectOps.html
|
8
12
|
|
9
13
|
identity :key, :aliases => 'Key'
|
@@ -27,14 +31,54 @@ module Fog
|
|
27
31
|
attribute :kms_key_id, :aliases => 'x-amz-server-side-encryption-aws-kms-key-id'
|
28
32
|
attribute :tags, :aliases => 'x-amz-tagging'
|
29
33
|
|
34
|
+
UploadPartData = Struct.new(:part_number, :upload_options, :etag)
|
35
|
+
|
36
|
+
class PartList
|
37
|
+
def initialize(parts = [])
|
38
|
+
@parts = parts
|
39
|
+
@mutex = Mutex.new
|
40
|
+
end
|
41
|
+
|
42
|
+
def push(part)
|
43
|
+
@mutex.synchronize { @parts.push(part) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def shift
|
47
|
+
@mutex.synchronize { @parts.shift }
|
48
|
+
end
|
49
|
+
|
50
|
+
def clear!
|
51
|
+
@mutex.synchronize { @parts.clear }
|
52
|
+
end
|
53
|
+
|
54
|
+
def size
|
55
|
+
@mutex.synchronize { @parts.size }
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_a
|
59
|
+
@mutex.synchronize { @parts.dup }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
30
63
|
# @note Chunk size to use for multipart uploads.
|
31
64
|
# Use small chunk sizes to minimize memory. E.g. 5242880 = 5mb
|
32
65
|
attr_reader :multipart_chunk_size
|
33
66
|
def multipart_chunk_size=(mp_chunk_size)
|
34
|
-
raise ArgumentError.new("minimum multipart_chunk_size is
|
67
|
+
raise ArgumentError.new("minimum multipart_chunk_size is #{MIN_MULTIPART_CHUNK_SIZE}") if mp_chunk_size < MIN_MULTIPART_CHUNK_SIZE
|
35
68
|
@multipart_chunk_size = mp_chunk_size
|
36
69
|
end
|
37
70
|
|
71
|
+
# @note Number of threads used to copy files.
|
72
|
+
def concurrency=(concurrency)
|
73
|
+
raise ArgumentError.new('minimum concurrency is 1') if concurrency.to_i < 1
|
74
|
+
|
75
|
+
@concurrency = concurrency.to_i
|
76
|
+
end
|
77
|
+
|
78
|
+
def concurrency
|
79
|
+
@concurrency || 1
|
80
|
+
end
|
81
|
+
|
38
82
|
def acl
|
39
83
|
requires :directory, :key
|
40
84
|
service.get_object_acl(directory.key, key).body['AccessControlList']
|
@@ -99,7 +143,17 @@ module Fog
|
|
99
143
|
#
|
100
144
|
def copy(target_directory_key, target_file_key, options = {})
|
101
145
|
requires :directory, :key
|
102
|
-
|
146
|
+
|
147
|
+
# With a single PUT operation you can upload objects up to 5 GB in size. Automatically set MP for larger objects.
|
148
|
+
self.multipart_chunk_size = MIN_MULTIPART_CHUNK_SIZE * 2 if !multipart_chunk_size && self.content_length.to_i > MAX_SINGLE_PUT_SIZE
|
149
|
+
|
150
|
+
if multipart_chunk_size && self.content_length.to_i >= multipart_chunk_size
|
151
|
+
upload_part_options = options.merge({ 'x-amz-copy-source' => "#{directory.key}/#{key}" })
|
152
|
+
multipart_copy(options, upload_part_options, target_directory_key, target_file_key)
|
153
|
+
else
|
154
|
+
service.copy_object(directory.key, key, target_directory_key, target_file_key, options)
|
155
|
+
end
|
156
|
+
|
103
157
|
target_directory = service.directories.new(:key => target_directory_key)
|
104
158
|
target_directory.files.head(target_file_key)
|
105
159
|
end
|
@@ -214,7 +268,7 @@ module Fog
|
|
214
268
|
options.merge!(encryption_headers)
|
215
269
|
|
216
270
|
# With a single PUT operation you can upload objects up to 5 GB in size. Automatically set MP for larger objects.
|
217
|
-
self.multipart_chunk_size =
|
271
|
+
self.multipart_chunk_size = MIN_MULTIPART_CHUNK_SIZE if !multipart_chunk_size && Fog::Storage.get_body_size(body) > MAX_SINGLE_PUT_SIZE
|
218
272
|
|
219
273
|
if multipart_chunk_size && Fog::Storage.get_body_size(body) >= multipart_chunk_size && body.respond_to?(:read)
|
220
274
|
data = multipart_save(options)
|
@@ -294,6 +348,30 @@ module Fog
|
|
294
348
|
service.complete_multipart_upload(directory.key, key, upload_id, part_tags)
|
295
349
|
end
|
296
350
|
|
351
|
+
def multipart_copy(options, upload_part_options, target_directory_key, target_file_key)
|
352
|
+
# Initiate the upload
|
353
|
+
res = service.initiate_multipart_upload(target_directory_key, target_file_key, options)
|
354
|
+
upload_id = res.body["UploadId"]
|
355
|
+
|
356
|
+
# Store ETags of upload parts
|
357
|
+
part_tags = []
|
358
|
+
pending = PartList.new(create_part_list(upload_part_options))
|
359
|
+
thread_count = self.concurrency
|
360
|
+
completed = PartList.new
|
361
|
+
errors = upload_in_threads(target_directory_key, target_file_key, upload_id, pending, completed, thread_count)
|
362
|
+
|
363
|
+
raise error.first if errors.any?
|
364
|
+
|
365
|
+
part_tags = completed.to_a.sort_by { |part| part.part_number }.map(&:etag)
|
366
|
+
rescue => e
|
367
|
+
# Abort the upload & reraise
|
368
|
+
service.abort_multipart_upload(target_directory_key, target_file_key, upload_id) if upload_id
|
369
|
+
raise
|
370
|
+
else
|
371
|
+
# Complete the upload
|
372
|
+
service.complete_multipart_upload(target_directory_key, target_file_key, upload_id, part_tags)
|
373
|
+
end
|
374
|
+
|
297
375
|
def encryption_headers
|
298
376
|
if encryption && encryption_key
|
299
377
|
encryption_customer_key_headers
|
@@ -318,6 +396,49 @@ module Fog
|
|
318
396
|
'x-amz-server-side-encryption-customer-key-md5' => Base64.encode64(OpenSSL::Digest::MD5.digest(encryption_key.to_s)).chomp!
|
319
397
|
}
|
320
398
|
end
|
399
|
+
|
400
|
+
def create_part_list(upload_part_options)
|
401
|
+
current_pos = 0
|
402
|
+
count = 0
|
403
|
+
pending = []
|
404
|
+
|
405
|
+
while current_pos < self.content_length do
|
406
|
+
start_pos = current_pos
|
407
|
+
end_pos = [current_pos + self.multipart_chunk_size, self.content_length - 1].min
|
408
|
+
range = "bytes=#{start_pos}-#{end_pos}"
|
409
|
+
part_options = upload_part_options.dup
|
410
|
+
part_options['x-amz-copy-source-range'] = range
|
411
|
+
pending << UploadPartData.new(count + 1, part_options, nil)
|
412
|
+
count += 1
|
413
|
+
current_pos = end_pos + 1
|
414
|
+
end
|
415
|
+
|
416
|
+
pending
|
417
|
+
end
|
418
|
+
|
419
|
+
def upload_in_threads(target_directory_key, target_file_key, upload_id, pending, completed, thread_count)
|
420
|
+
threads = []
|
421
|
+
|
422
|
+
thread_count.times do
|
423
|
+
thread = Thread.new do
|
424
|
+
begin
|
425
|
+
while part = pending.shift
|
426
|
+
part_upload = service.upload_part_copy(target_directory_key, target_file_key, upload_id, part.part_number, part.upload_options)
|
427
|
+
part.etag = part_upload.body['ETag']
|
428
|
+
completed.push(part)
|
429
|
+
end
|
430
|
+
rescue => error
|
431
|
+
pending.clear!
|
432
|
+
error
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
thread.abort_on_exception = true
|
437
|
+
threads << thread
|
438
|
+
end
|
439
|
+
|
440
|
+
threads.map(&:value).compact
|
441
|
+
end
|
321
442
|
end
|
322
443
|
end
|
323
444
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Fog
|
2
|
+
module Parsers
|
3
|
+
module AWS
|
4
|
+
module Storage
|
5
|
+
class UploadPartCopyObject < Fog::Parsers::Base
|
6
|
+
def end_element(name)
|
7
|
+
case name
|
8
|
+
when 'ETag'
|
9
|
+
@response[name] = value.gsub('"', '')
|
10
|
+
when 'LastModified'
|
11
|
+
@response[name] = Time.parse(value)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -113,7 +113,7 @@ module Fog
|
|
113
113
|
raise Fog::AWS::Compute::Error.new(message)
|
114
114
|
end
|
115
115
|
|
116
|
-
if !image_id.match(/^ami-[a-f0-9]{8}$/)
|
116
|
+
if !image_id.match(/^ami-[a-f0-9]{8,17}$/)
|
117
117
|
message = "The image id '[#{image_id}]' does not exist"
|
118
118
|
raise Fog::AWS::Compute::NotFound.new(message)
|
119
119
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Fog
|
2
|
+
module AWS
|
3
|
+
class Storage
|
4
|
+
class Real
|
5
|
+
require 'fog/aws/parsers/storage/upload_part_copy_object'
|
6
|
+
|
7
|
+
# Upload a part for a multipart copy
|
8
|
+
#
|
9
|
+
# @param target_bucket_name [String] Name of bucket to create copy in
|
10
|
+
# @param target_object_name [String] Name for new copy of object
|
11
|
+
# @param upload_id [String] Id of upload to add part to
|
12
|
+
# @param part_number [String] Index of part in upload
|
13
|
+
# @param options [Hash]:
|
14
|
+
# @option options [String] x-amz-metadata-directive Specifies whether to copy metadata from source or replace with data in request. Must be in ['COPY', 'REPLACE']
|
15
|
+
# @option options [String] x-amz-copy_source-if-match Copies object if its etag matches this value
|
16
|
+
# @option options [Time] x-amz-copy_source-if-modified_since Copies object it it has been modified since this time
|
17
|
+
# @option options [String] x-amz-copy_source-if-none-match Copies object if its etag does not match this value
|
18
|
+
# @option options [Time] x-amz-copy_source-if-unmodified-since Copies object it it has not been modified since this time
|
19
|
+
# @option options [Time] x-amz-copy-source-range Specifes the range of bytes to copy from the source object
|
20
|
+
#
|
21
|
+
# @return [Excon::Response]
|
22
|
+
# * body [Hash]:
|
23
|
+
# * ETag [String] - etag of new object
|
24
|
+
# * LastModified [Time] - date object was last modified
|
25
|
+
#
|
26
|
+
# @see https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html
|
27
|
+
#
|
28
|
+
def upload_part_copy(target_bucket_name, target_object_name, upload_id, part_number, options = {})
|
29
|
+
headers = options
|
30
|
+
request({
|
31
|
+
:expects => 200,
|
32
|
+
:idempotent => true,
|
33
|
+
:headers => headers,
|
34
|
+
:bucket_name => target_bucket_name,
|
35
|
+
:object_name => target_object_name,
|
36
|
+
:method => 'PUT',
|
37
|
+
:query => {'uploadId' => upload_id, 'partNumber' => part_number},
|
38
|
+
:parser => Fog::Parsers::AWS::Storage::UploadPartCopyObject.new,
|
39
|
+
})
|
40
|
+
end
|
41
|
+
end # Real
|
42
|
+
|
43
|
+
class Mock # :nodoc:all
|
44
|
+
require 'fog/aws/requests/storage/shared_mock_methods'
|
45
|
+
include Fog::AWS::Storage::SharedMockMethods
|
46
|
+
|
47
|
+
def upload_part_copy(target_bucket_name, target_object_name, upload_id, part_number, options = {})
|
48
|
+
copy_source = options['x-amz-copy-source']
|
49
|
+
copy_range = options['x-amz-copy-source-range']
|
50
|
+
|
51
|
+
raise 'No x-amz-copy-source header provided' unless copy_source
|
52
|
+
raise 'No x-amz-copy-source-range header provided' unless copy_range
|
53
|
+
|
54
|
+
source_bucket_name, source_object_name = copy_source.split('/', 2)
|
55
|
+
verify_mock_bucket_exists(source_bucket_name)
|
56
|
+
|
57
|
+
source_bucket = self.data[:buckets][source_bucket_name]
|
58
|
+
source_object = source_bucket && source_bucket[:objects][source_object_name] && source_bucket[:objects][source_object_name].first
|
59
|
+
upload_info = get_upload_info(target_bucket_name, upload_id)
|
60
|
+
|
61
|
+
response = Excon::Response.new
|
62
|
+
|
63
|
+
if source_object
|
64
|
+
start_pos, end_pos = byte_range(copy_range, source_object[:body].length)
|
65
|
+
upload_info[:parts][part_number] = source_object[:body][start_pos..end_pos]
|
66
|
+
|
67
|
+
response.status = 200
|
68
|
+
response.body = {
|
69
|
+
# just use the part number as the ETag, for simplicity
|
70
|
+
'ETag' => part_number.to_i,
|
71
|
+
'LastModified' => Time.parse(source_object['Last-Modified'])
|
72
|
+
}
|
73
|
+
response
|
74
|
+
else
|
75
|
+
response.status = 404
|
76
|
+
raise(Excon::Errors.status_error({:expects => 200}, response))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def byte_range(range, size)
|
81
|
+
matches = range.match(/bytes=(\d*)-(\d*)/)
|
82
|
+
|
83
|
+
return nil unless matches
|
84
|
+
|
85
|
+
end_pos = [matches[2].to_i, size].min
|
86
|
+
|
87
|
+
[matches[1].to_i, end_pos]
|
88
|
+
end
|
89
|
+
end # Mock
|
90
|
+
end # Storage
|
91
|
+
end # AWS
|
92
|
+
end # Fog
|
data/lib/fog/aws/storage.rb
CHANGED
data/lib/fog/aws/version.rb
CHANGED
data/tests/credentials_tests.rb
CHANGED
@@ -60,6 +60,35 @@ Shindo.tests('AWS | credentials', ['aws']) do
|
|
60
60
|
|
61
61
|
ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] = nil
|
62
62
|
|
63
|
+
ENV['AWS_WEB_IDENTITY_TOKEN_FILE'] = File.dirname(__FILE__) + '/lorem.txt'
|
64
|
+
ENV['AWS_ROLE_ARN'] = "dummyrole"
|
65
|
+
ENV['AWS_ROLE_SESSION_NAME'] = "dummyrolesessionname"
|
66
|
+
document =
|
67
|
+
'<AssumeRoleWithWebIdentityResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">'\
|
68
|
+
'<AssumeRoleWithWebIdentityResult>'\
|
69
|
+
'<Credentials>'\
|
70
|
+
'<SessionToken>dummytoken</SessionToken>'\
|
71
|
+
'<SecretAccessKey>dummysecret</SecretAccessKey>'\
|
72
|
+
"<Expiration>#{expires_at.xmlschema}</Expiration>"\
|
73
|
+
'<AccessKeyId>dummykey</AccessKeyId>'\
|
74
|
+
'</Credentials>'\
|
75
|
+
'</AssumeRoleWithWebIdentityResult>'\
|
76
|
+
'</AssumeRoleWithWebIdentityResponse>'
|
77
|
+
|
78
|
+
Excon.stub({method: :get, path: "/", idempotent: true}, { status: 200, body: document})
|
79
|
+
|
80
|
+
tests('#fetch_credentials token based') do
|
81
|
+
returns(
|
82
|
+
aws_access_key_id: 'dummykey',
|
83
|
+
aws_secret_access_key: 'dummysecret',
|
84
|
+
aws_session_token: 'dummytoken',
|
85
|
+
region: 'us-west-1',
|
86
|
+
aws_credentials_expire_at: expires_at
|
87
|
+
) { Fog::AWS::Compute.fetch_credentials(use_iam_profile: true) }
|
88
|
+
end
|
89
|
+
|
90
|
+
ENV['AWS_WEB_IDENTITY_TOKEN_FILE'] = nil
|
91
|
+
|
63
92
|
compute = Fog::AWS::Compute.new(use_iam_profile: true)
|
64
93
|
|
65
94
|
tests('#refresh_credentials_if_expired') do
|
@@ -100,6 +129,7 @@ Shindo.tests('AWS | credentials', ['aws']) do
|
|
100
129
|
end
|
101
130
|
ensure
|
102
131
|
ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] = nil
|
132
|
+
ENV['AWS_WEB_IDENTITY_TOKEN_FILE'] = nil
|
103
133
|
Excon.stubs.clear
|
104
134
|
Excon.defaults[:mock] = old_mock_value
|
105
135
|
Fog.mock! if fog_was_mocked
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
Shindo.tests('Fog::Storage[:aws] | copy requests', ["aws"]) do
|
4
|
+
|
5
|
+
@directory = Fog::Storage[:aws].directories.create(:key => uniq_id('fogmultipartcopytests'))
|
6
|
+
@large_data = SecureRandom.hex * 19 * 1024 * 1024
|
7
|
+
@large_blob = Fog::Storage[:aws].put_object(@directory.identity, 'large_object', @large_data)
|
8
|
+
|
9
|
+
tests('copies an empty object') do
|
10
|
+
Fog::Storage[:aws].put_object(@directory.identity, 'empty_object', '')
|
11
|
+
|
12
|
+
file = Fog::Storage[:aws].directories.new(key: @directory.identity).files.get('empty_object')
|
13
|
+
file.multipart_chunk_size = Fog::AWS::Storage::File::MIN_MULTIPART_CHUNK_SIZE
|
14
|
+
|
15
|
+
tests("#copy_object('#{@directory.identity}', 'empty_copied_object'").succeeds do
|
16
|
+
file.copy(@directory.identity, 'empty_copied_object')
|
17
|
+
end
|
18
|
+
|
19
|
+
copied = Fog::Storage[:aws].directories.new(key: @directory.identity).files.get('empty_copied_object')
|
20
|
+
test("copied is the same") { copied.body == file.body }
|
21
|
+
end
|
22
|
+
|
23
|
+
tests('copies a small object') do
|
24
|
+
Fog::Storage[:aws].put_object(@directory.identity, 'fog_object', lorem_file)
|
25
|
+
|
26
|
+
file = Fog::Storage[:aws].directories.new(key: @directory.identity).files.get('fog_object')
|
27
|
+
|
28
|
+
tests("#copy_object('#{@directory.identity}', 'copied_object'").succeeds do
|
29
|
+
file.copy(@directory.identity, 'copied_object')
|
30
|
+
end
|
31
|
+
|
32
|
+
copied = Fog::Storage[:aws].directories.new(key: @directory.identity).files.get('copied_object')
|
33
|
+
test("copied is the same") { copied.body == file.body }
|
34
|
+
end
|
35
|
+
|
36
|
+
tests('copies a file needing a single part') do
|
37
|
+
data = '*' * Fog::AWS::Storage::File::MIN_MULTIPART_CHUNK_SIZE
|
38
|
+
Fog::Storage[:aws].put_object(@directory.identity, '1_part_object', data)
|
39
|
+
|
40
|
+
file = Fog::Storage[:aws].directories.new(key: @directory.identity).files.get('1_part_object')
|
41
|
+
file.multipart_chunk_size = Fog::AWS::Storage::File::MIN_MULTIPART_CHUNK_SIZE
|
42
|
+
|
43
|
+
tests("#copy_object('#{@directory.identity}', '1_part_copied_object'").succeeds do
|
44
|
+
file.copy(@directory.identity, '1_part_copied_object')
|
45
|
+
end
|
46
|
+
|
47
|
+
copied = Fog::Storage[:aws].directories.new(key: @directory.identity).files.get('1_part_copied_object')
|
48
|
+
test("copied is the same") { copied.body == file.body }
|
49
|
+
end
|
50
|
+
|
51
|
+
tests('copies a file with many parts') do
|
52
|
+
file = Fog::Storage[:aws].directories.new(key: @directory.identity).files.get('large_object')
|
53
|
+
file.multipart_chunk_size = Fog::AWS::Storage::File::MIN_MULTIPART_CHUNK_SIZE
|
54
|
+
|
55
|
+
tests("#copy_object('#{@directory.identity}', 'large_copied_object'").succeeds do
|
56
|
+
file.copy(@directory.identity, 'large_copied_object')
|
57
|
+
end
|
58
|
+
|
59
|
+
copied = Fog::Storage[:aws].directories.new(key: @directory.identity).files.get('large_copied_object')
|
60
|
+
|
61
|
+
test("concurrency defaults to 1") { file.concurrency == 1 }
|
62
|
+
test("copied is the same") { copied.body == file.body }
|
63
|
+
end
|
64
|
+
|
65
|
+
tests('copies a file with many parts with 10 threads') do
|
66
|
+
file = Fog::Storage[:aws].directories.new(key: @directory.identity).files.get('large_object')
|
67
|
+
file.multipart_chunk_size = Fog::AWS::Storage::File::MIN_MULTIPART_CHUNK_SIZE
|
68
|
+
file.concurrency = 10
|
69
|
+
|
70
|
+
test("concurrency is set to 10") { file.concurrency == 10 }
|
71
|
+
|
72
|
+
tests("#copy_object('#{@directory.identity}', 'copied_object_with_10_threads'").succeeds do
|
73
|
+
file.copy(@directory.identity, 'copied_object_with_10_threads')
|
74
|
+
end
|
75
|
+
|
76
|
+
copied = Fog::Storage[:aws].directories.new(key: @directory.identity).files.get('copied_object_with_10_threads')
|
77
|
+
|
78
|
+
test("copied is the same") { copied.body == file.body }
|
79
|
+
end
|
80
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fog-aws
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Lane
|
8
8
|
- Wesley Beary
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-
|
12
|
+
date: 2020-12-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -754,6 +754,7 @@ files:
|
|
754
754
|
- lib/fog/aws/parsers/storage/initiate_multipart_upload.rb
|
755
755
|
- lib/fog/aws/parsers/storage/list_multipart_uploads.rb
|
756
756
|
- lib/fog/aws/parsers/storage/list_parts.rb
|
757
|
+
- lib/fog/aws/parsers/storage/upload_part_copy_object.rb
|
757
758
|
- lib/fog/aws/parsers/sts/assume_role.rb
|
758
759
|
- lib/fog/aws/parsers/sts/assume_role_with_saml.rb
|
759
760
|
- lib/fog/aws/parsers/sts/assume_role_with_web_identity.rb
|
@@ -1442,6 +1443,7 @@ files:
|
|
1442
1443
|
- lib/fog/aws/requests/storage/shared_mock_methods.rb
|
1443
1444
|
- lib/fog/aws/requests/storage/sync_clock.rb
|
1444
1445
|
- lib/fog/aws/requests/storage/upload_part.rb
|
1446
|
+
- lib/fog/aws/requests/storage/upload_part_copy.rb
|
1445
1447
|
- lib/fog/aws/requests/sts/assume_role.rb
|
1446
1448
|
- lib/fog/aws/requests/sts/assume_role_with_saml.rb
|
1447
1449
|
- lib/fog/aws/requests/sts/assume_role_with_web_identity.rb
|
@@ -1709,6 +1711,7 @@ files:
|
|
1709
1711
|
- tests/requests/storage/bucket_tests.rb
|
1710
1712
|
- tests/requests/storage/cors_utils_tests.rb
|
1711
1713
|
- tests/requests/storage/delete_multiple_objects_tests.rb
|
1714
|
+
- tests/requests/storage/multipart_copy_tests.rb
|
1712
1715
|
- tests/requests/storage/multipart_upload_tests.rb
|
1713
1716
|
- tests/requests/storage/object_tests.rb
|
1714
1717
|
- tests/requests/storage/versioning_tests.rb
|
@@ -1726,7 +1729,7 @@ homepage: https://github.com/fog/fog-aws
|
|
1726
1729
|
licenses:
|
1727
1730
|
- MIT
|
1728
1731
|
metadata: {}
|
1729
|
-
post_install_message:
|
1732
|
+
post_install_message:
|
1730
1733
|
rdoc_options: []
|
1731
1734
|
require_paths:
|
1732
1735
|
- lib
|
@@ -1741,8 +1744,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1741
1744
|
- !ruby/object:Gem::Version
|
1742
1745
|
version: '0'
|
1743
1746
|
requirements: []
|
1744
|
-
rubygems_version: 3.
|
1745
|
-
signing_key:
|
1747
|
+
rubygems_version: 3.1.2
|
1748
|
+
signing_key:
|
1746
1749
|
specification_version: 4
|
1747
1750
|
summary: Module for the 'fog' gem to support Amazon Web Services.
|
1748
1751
|
test_files: []
|