fog-aws 3.6.7 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|