fog-aws 3.7.0 → 3.11.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/CHANGELOG.md +246 -18
- data/README.md +1 -1
- data/fog-aws.gemspec +5 -4
- data/lib/fog/aws/credential_fetcher.rb +3 -1
- data/lib/fog/aws/models/compute/server.rb +2 -0
- data/lib/fog/aws/models/storage/file.rb +16 -12
- data/lib/fog/aws/models/storage/files.rb +32 -2
- data/lib/fog/aws/requests/compute/run_instances.rb +44 -0
- data/lib/fog/aws/requests/storage/delete_multiple_objects.rb +18 -8
- data/lib/fog/aws/requests/storage/get_object.rb +1 -1
- data/lib/fog/aws/requests/storage/shared_mock_methods.rb +1 -0
- data/lib/fog/aws/requests/storage/upload_part_copy.rb +27 -0
- data/lib/fog/aws/storage.rb +42 -3
- data/lib/fog/aws/version.rb +1 -1
- data/tests/credentials_tests.rb +12 -0
- data/tests/helpers/succeeds_helper.rb +2 -2
- data/tests/models/storage/directory_tests.rb +113 -2
- data/tests/models/storage/files_tests.rb +32 -0
- data/tests/requests/storage/bucket_tests.rb +1 -1
- data/tests/requests/storage/multipart_copy_tests.rb +14 -1
- data/tests/requests/storage/object_tests.rb +7 -0
- data/tests/requests/storage/versioning_tests.rb +38 -0
- metadata +11 -22
- data/.gitignore +0 -17
- data/.travis.yml +0 -65
- data/Gemfile +0 -14
- data/Rakefile +0 -14
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/gemfiles/Gemfile-edge +0 -14
- data/gemfiles/Gemfile-ruby-2.0 +0 -7
- data/lib/fog/aws/iam/default_policies.json +0 -1574
- data/lib/fog/aws/iam/default_policy_versions.json +0 -3373
- data/stale.yml +0 -17
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Fog::Aws
|
|
2
2
|
|
|
3
3
|

|
|
4
|
-
[](https://github.com/fog/fog-aws/actions/workflows/ruby.yml)
|
|
5
5
|
[](https://codeclimate.com/github/fog/fog-aws)
|
|
6
6
|
[](https://codeclimate.com/github/fog/fog-aws)
|
|
7
7
|
|
data/fog-aws.gemspec
CHANGED
|
@@ -14,17 +14,18 @@ Gem::Specification.new do |spec|
|
|
|
14
14
|
spec.homepage = "https://github.com/fog/fog-aws"
|
|
15
15
|
spec.license = "MIT"
|
|
16
16
|
|
|
17
|
-
spec.files =
|
|
17
|
+
spec.files = Dir['lib/**/*.rb', 'tests/**/*', 'CHANGELOG.md', 'CONTRIBUTING.md',
|
|
18
|
+
'CONTRIBUTORS.md', 'LICENSE.md', 'README.md', 'fog-aws.gemspec',]
|
|
18
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
19
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
20
21
|
spec.require_paths = ["lib"]
|
|
21
22
|
|
|
22
23
|
spec.required_ruby_version = '>= 2.0.0'
|
|
23
24
|
|
|
24
|
-
spec.add_development_dependency 'bundler'
|
|
25
|
-
spec.add_development_dependency 'github_changelog_generator', '~> 1.
|
|
25
|
+
spec.add_development_dependency 'bundler'
|
|
26
|
+
spec.add_development_dependency 'github_changelog_generator', '~> 1.16'
|
|
26
27
|
spec.add_development_dependency 'rake', '>= 12.3.3'
|
|
27
|
-
spec.add_development_dependency 'rubyzip', '~>
|
|
28
|
+
spec.add_development_dependency 'rubyzip', '~> 2.3.0'
|
|
28
29
|
spec.add_development_dependency 'shindo', '~> 0.3'
|
|
29
30
|
|
|
30
31
|
spec.add_dependency 'fog-core', '~> 2.1'
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
3
5
|
module Fog
|
|
4
6
|
module AWS
|
|
5
7
|
module CredentialFetcher
|
|
@@ -38,7 +40,7 @@ module Fog
|
|
|
38
40
|
params = {
|
|
39
41
|
:Action => "AssumeRoleWithWebIdentity",
|
|
40
42
|
:RoleArn => options[:role_arn] || ENV.fetch("AWS_ROLE_ARN"),
|
|
41
|
-
:RoleSessionName => options[:role_session_name] || ENV
|
|
43
|
+
:RoleSessionName => options[:role_session_name] || ENV["AWS_ROLE_SESSION_NAME"] || "fog-aws-#{SecureRandom.hex}",
|
|
42
44
|
:WebIdentityToken => File.read(options[:aws_web_identity_token_file] || ENV.fetch("AWS_WEB_IDENTITY_TOKEN_FILE")),
|
|
43
45
|
:Version => "2011-06-15",
|
|
44
46
|
}
|
|
@@ -50,6 +50,7 @@ module Fog
|
|
|
50
50
|
attribute :subnet_id, :aliases => 'subnetId'
|
|
51
51
|
attribute :tenancy
|
|
52
52
|
attribute :tags, :aliases => 'tagSet'
|
|
53
|
+
attribute :tag_specifications, :aliases => 'tagSpecifications'
|
|
53
54
|
attribute :user_data
|
|
54
55
|
attribute :virtualization_type, :aliases => 'virtualizationType'
|
|
55
56
|
attribute :vpc_id, :aliases => 'vpcId'
|
|
@@ -166,6 +167,7 @@ module Fog
|
|
|
166
167
|
'SecurityGroupId' => security_group_ids,
|
|
167
168
|
'SubnetId' => subnet_id,
|
|
168
169
|
'UserData' => user_data,
|
|
170
|
+
'TagSpecifications' => tag_specifications,
|
|
169
171
|
}
|
|
170
172
|
options.delete_if {|key, value| value.nil?}
|
|
171
173
|
|
|
@@ -4,8 +4,11 @@ module Fog
|
|
|
4
4
|
module AWS
|
|
5
5
|
class Storage
|
|
6
6
|
class File < Fog::Model
|
|
7
|
-
MIN_MULTIPART_CHUNK_SIZE
|
|
8
|
-
|
|
7
|
+
# @deprecated use {Fog::AWS::Storage::MIN_MULTIPART_CHUNK_SIZE} instead
|
|
8
|
+
MIN_MULTIPART_CHUNK_SIZE = Fog::AWS::Storage::MIN_MULTIPART_CHUNK_SIZE
|
|
9
|
+
# @deprecated use {Fog::AWS::Storage::MAX_SINGLE_PUT_SIZE} instead
|
|
10
|
+
MAX_SINGLE_PUT_SIZE = Fog::AWS::Storage::MAX_SINGLE_PUT_SIZE
|
|
11
|
+
# @deprecated not used for anything
|
|
9
12
|
MULTIPART_COPY_THRESHOLD = 15728640
|
|
10
13
|
|
|
11
14
|
# @see AWS Object docs http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectOps.html
|
|
@@ -30,6 +33,7 @@ module Fog
|
|
|
30
33
|
attribute :version, :aliases => 'x-amz-version-id'
|
|
31
34
|
attribute :kms_key_id, :aliases => 'x-amz-server-side-encryption-aws-kms-key-id'
|
|
32
35
|
attribute :tags, :aliases => 'x-amz-tagging'
|
|
36
|
+
attribute :website_redirect_location, :aliases => 'x-amz-website-redirect-location'
|
|
33
37
|
|
|
34
38
|
UploadPartData = Struct.new(:part_number, :upload_options, :etag)
|
|
35
39
|
|
|
@@ -64,7 +68,7 @@ module Fog
|
|
|
64
68
|
# Use small chunk sizes to minimize memory. E.g. 5242880 = 5mb
|
|
65
69
|
attr_reader :multipart_chunk_size
|
|
66
70
|
def multipart_chunk_size=(mp_chunk_size)
|
|
67
|
-
|
|
71
|
+
service.validate_chunk_size(mp_chunk_size, 'multipart_chunk_size')
|
|
68
72
|
@multipart_chunk_size = mp_chunk_size
|
|
69
73
|
end
|
|
70
74
|
|
|
@@ -144,11 +148,11 @@ module Fog
|
|
|
144
148
|
def copy(target_directory_key, target_file_key, options = {})
|
|
145
149
|
requires :directory, :key
|
|
146
150
|
|
|
147
|
-
|
|
148
|
-
self.multipart_chunk_size = MIN_MULTIPART_CHUNK_SIZE * 2 if !multipart_chunk_size && self.content_length.to_i > MAX_SINGLE_PUT_SIZE
|
|
151
|
+
self.multipart_chunk_size = service.max_copy_chunk_size if multipart_chunk_size.nil?
|
|
149
152
|
|
|
150
|
-
if multipart_chunk_size && self.content_length.to_i >= multipart_chunk_size
|
|
151
|
-
upload_part_options = options.
|
|
153
|
+
if multipart_chunk_size > 0 && self.content_length.to_i >= multipart_chunk_size
|
|
154
|
+
upload_part_options = options.select { |key, _| ALLOWED_UPLOAD_PART_OPTIONS.include?(key.to_sym) }
|
|
155
|
+
upload_part_options = upload_part_options.merge({ 'x-amz-copy-source' => "#{directory.key}/#{key}" })
|
|
152
156
|
multipart_copy(options, upload_part_options, target_directory_key, target_file_key)
|
|
153
157
|
else
|
|
154
158
|
service.copy_object(directory.key, key, target_directory_key, target_file_key, options)
|
|
@@ -248,6 +252,7 @@ module Fog
|
|
|
248
252
|
# @option options [String] storage_class sets x-amz-storage-class HTTP header. Defaults to 'STANDARD'. Or, 'REDUCED_REDUNDANCY'
|
|
249
253
|
# @option options [String] encryption sets HTTP encryption header. Set to 'AES256' to encrypt files at rest on S3
|
|
250
254
|
# @option options [String] tags sets x-amz-tagging HTTP header. For example, 'Org-Id=1' or 'Org-Id=1&Service=MyService'
|
|
255
|
+
# @option options [String] website_redirect_location sets x-amz-website-redirect-location HTTP header. For example, 'website_redirect_location=http://www.rubydoc.info/github/fog/fog-aws'
|
|
251
256
|
# @return [Boolean] true if no errors
|
|
252
257
|
#
|
|
253
258
|
def save(options = {})
|
|
@@ -265,12 +270,11 @@ module Fog
|
|
|
265
270
|
options.merge!(metadata)
|
|
266
271
|
options['x-amz-storage-class'] = storage_class if storage_class
|
|
267
272
|
options['x-amz-tagging'] = tags if tags
|
|
273
|
+
options['x-amz-website-redirect-location'] = website_redirect_location if website_redirect_location
|
|
268
274
|
options.merge!(encryption_headers)
|
|
269
275
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
if multipart_chunk_size && Fog::Storage.get_body_size(body) >= multipart_chunk_size && body.respond_to?(:read)
|
|
276
|
+
self.multipart_chunk_size = service.max_put_chunk_size if multipart_chunk_size.nil?
|
|
277
|
+
if multipart_chunk_size > 0 && Fog::Storage.get_body_size(body) >= multipart_chunk_size && body.respond_to?(:read)
|
|
274
278
|
data = multipart_save(options)
|
|
275
279
|
merge_attributes(data.body)
|
|
276
280
|
else
|
|
@@ -360,7 +364,7 @@ module Fog
|
|
|
360
364
|
completed = PartList.new
|
|
361
365
|
errors = upload_in_threads(target_directory_key, target_file_key, upload_id, pending, completed, thread_count)
|
|
362
366
|
|
|
363
|
-
raise
|
|
367
|
+
raise errors.first if errors.any?
|
|
364
368
|
|
|
365
369
|
part_tags = completed.to_a.sort_by { |part| part.part_number }.map(&:etag)
|
|
366
370
|
rescue => e
|
|
@@ -17,6 +17,15 @@ module Fog
|
|
|
17
17
|
|
|
18
18
|
model Fog::AWS::Storage::File
|
|
19
19
|
|
|
20
|
+
DASHED_HEADERS = %w(
|
|
21
|
+
Cache-Control
|
|
22
|
+
Content-Disposition
|
|
23
|
+
Content-Encoding
|
|
24
|
+
Content-Length
|
|
25
|
+
Content-MD5
|
|
26
|
+
Content-Type
|
|
27
|
+
).freeze
|
|
28
|
+
|
|
20
29
|
def all(options = {})
|
|
21
30
|
requires :directory
|
|
22
31
|
options = {
|
|
@@ -114,8 +123,29 @@ module Fog
|
|
|
114
123
|
end
|
|
115
124
|
|
|
116
125
|
def normalize_headers(data)
|
|
117
|
-
data.headers['Last-Modified'] = Time.parse(data
|
|
118
|
-
|
|
126
|
+
data.headers['Last-Modified'] = Time.parse(fetch_and_delete_header(data, 'Last-Modified'))
|
|
127
|
+
|
|
128
|
+
etag = fetch_and_delete_header(data, 'ETag').gsub('"','')
|
|
129
|
+
data.headers['ETag'] = etag
|
|
130
|
+
|
|
131
|
+
DASHED_HEADERS.each do |header|
|
|
132
|
+
value = fetch_and_delete_header(data, header)
|
|
133
|
+
data.headers[header] = value if value
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
private
|
|
138
|
+
|
|
139
|
+
def fetch_and_delete_header(response, header)
|
|
140
|
+
value = response.get_header(header)
|
|
141
|
+
|
|
142
|
+
return unless value
|
|
143
|
+
|
|
144
|
+
response.headers.keys.each do |key|
|
|
145
|
+
response.headers.delete(key) if key.downcase == header.downcase
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
value
|
|
119
149
|
end
|
|
120
150
|
end
|
|
121
151
|
end
|
|
@@ -44,6 +44,11 @@ module Fog
|
|
|
44
44
|
# * 'PrivateIpAddresses.Primary'<~Bool> - Indicates whether the private IP address is the primary private IP address.
|
|
45
45
|
# * 'SecondaryPrivateIpAddressCount'<~Bool> - The number of private IP addresses to assign to the network interface.
|
|
46
46
|
# * 'AssociatePublicIpAddress'<~String> - Indicates whether to assign a public IP address to an instance in a VPC. The public IP address is assigned to a specific network interface
|
|
47
|
+
# * 'TagSpecifications'<~Array>: array of hashes
|
|
48
|
+
# * 'ResourceType'<~String> - Type of resource to apply tags on, e.g: instance or volume
|
|
49
|
+
# * 'Tags'<~Array> - List of hashs reprensenting tag to be set
|
|
50
|
+
# * 'Key'<~String> - Tag name
|
|
51
|
+
# * 'Value'<~String> - Tag value
|
|
47
52
|
# * 'ClientToken'<~String> - unique case-sensitive token for ensuring idempotency
|
|
48
53
|
# * 'DisableApiTermination'<~Boolean> - specifies whether or not to allow termination of the instance from the api
|
|
49
54
|
# * 'SecurityGroup'<~Array> or <~String> - Name of security group(s) for instances (not supported for VPC)
|
|
@@ -144,6 +149,45 @@ module Fog
|
|
|
144
149
|
end
|
|
145
150
|
end
|
|
146
151
|
end
|
|
152
|
+
if tag_specifications = options.delete('TagSpecifications')
|
|
153
|
+
# From https://docs.aws.amazon.com/sdk-for-ruby/v2/api/Aws/EC2/Client.html#run_instances-instance_method
|
|
154
|
+
# And https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html
|
|
155
|
+
# Discussed at https://github.com/fog/fog-aws/issues/603
|
|
156
|
+
#
|
|
157
|
+
# Example
|
|
158
|
+
#
|
|
159
|
+
# TagSpecifications: [
|
|
160
|
+
# {
|
|
161
|
+
# ResourceType: "instance",
|
|
162
|
+
# Tags: [
|
|
163
|
+
# {
|
|
164
|
+
# Key: "Project",
|
|
165
|
+
# Value: "MyProject",
|
|
166
|
+
# },
|
|
167
|
+
# ],
|
|
168
|
+
# },
|
|
169
|
+
# {
|
|
170
|
+
# ResourceType: "volume",
|
|
171
|
+
# Tags: [
|
|
172
|
+
# {
|
|
173
|
+
# Key: "Project",
|
|
174
|
+
# Value: "MyProject",
|
|
175
|
+
# },
|
|
176
|
+
# ],
|
|
177
|
+
# },
|
|
178
|
+
# ]
|
|
179
|
+
tag_specifications.each_with_index do |val, idx|
|
|
180
|
+
resource_type = val["ResourceType"]
|
|
181
|
+
tags = val["Tags"]
|
|
182
|
+
options["TagSpecification.#{idx}.ResourceType"] = resource_type
|
|
183
|
+
tags.each_with_index do |tag, tag_idx|
|
|
184
|
+
aws_tag_key = "TagSpecification.#{idx}.Tag.#{tag_idx}.Key"
|
|
185
|
+
aws_tag_value = "TagSpecification.#{idx}.Tag.#{tag_idx}.Value"
|
|
186
|
+
options[aws_tag_key] = tag["Key"]
|
|
187
|
+
options[aws_tag_value] = tag["Value"]
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
147
191
|
|
|
148
192
|
idempotent = !(options['ClientToken'].nil? || options['ClientToken'].empty?)
|
|
149
193
|
|
|
@@ -36,13 +36,20 @@ module Fog
|
|
|
36
36
|
data << "<Quiet>true</Quiet>" if headers.delete(:quiet)
|
|
37
37
|
version_ids = headers.delete('versionId')
|
|
38
38
|
object_names.each do |object_name|
|
|
39
|
-
data << "<Object>"
|
|
40
|
-
data << "<Key>#{CGI.escapeHTML(object_name)}</Key>"
|
|
41
39
|
object_version = version_ids.nil? ? nil : version_ids[object_name]
|
|
42
40
|
if object_version
|
|
43
|
-
|
|
41
|
+
object_version = object_version.is_a?(String) ? [object_version] : object_version
|
|
42
|
+
object_version.each do |version_id|
|
|
43
|
+
data << "<Object>"
|
|
44
|
+
data << "<Key>#{CGI.escapeHTML(object_name)}</Key>"
|
|
45
|
+
data << "<VersionId>#{CGI.escapeHTML(version_id)}</VersionId>"
|
|
46
|
+
data << "</Object>"
|
|
47
|
+
end
|
|
48
|
+
else
|
|
49
|
+
data << "<Object>"
|
|
50
|
+
data << "<Key>#{CGI.escapeHTML(object_name)}</Key>"
|
|
51
|
+
data << "</Object>"
|
|
44
52
|
end
|
|
45
|
-
data << "</Object>"
|
|
46
53
|
end
|
|
47
54
|
data << "</Delete>"
|
|
48
55
|
|
|
@@ -72,10 +79,13 @@ module Fog
|
|
|
72
79
|
response.body = { 'DeleteResult' => [] }
|
|
73
80
|
version_ids = headers.delete('versionId')
|
|
74
81
|
object_names.each do |object_name|
|
|
75
|
-
object_version = version_ids.nil? ? nil : version_ids[object_name]
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
82
|
+
object_version = version_ids.nil? ? [nil] : version_ids[object_name]
|
|
83
|
+
object_version = object_version.is_a?(String) ? [object_version] : object_version
|
|
84
|
+
object_version.each do |version_id|
|
|
85
|
+
response.body['DeleteResult'] << delete_object_helper(bucket,
|
|
86
|
+
object_name,
|
|
87
|
+
version_id)
|
|
88
|
+
end
|
|
79
89
|
end
|
|
80
90
|
else
|
|
81
91
|
response.status = 404
|
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
module Fog
|
|
2
2
|
module AWS
|
|
3
3
|
class Storage
|
|
4
|
+
# From https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html
|
|
5
|
+
ALLOWED_UPLOAD_PART_OPTIONS = %i(
|
|
6
|
+
x-amz-copy-source
|
|
7
|
+
x-amz-copy-source-if-match
|
|
8
|
+
x-amz-copy-source-if-modified-since
|
|
9
|
+
x-amz-copy-source-if-none-match
|
|
10
|
+
x-amz-copy-source-if-unmodified-since
|
|
11
|
+
x-amz-copy-source-range
|
|
12
|
+
x-amz-copy-source-server-side-encryption-customer-algorithm
|
|
13
|
+
x-amz-copy-source-server-side-encryption-customer-key
|
|
14
|
+
x-amz-copy-source-server-side-encryption-customer-key-MD5
|
|
15
|
+
x-amz-expected-bucket-owner
|
|
16
|
+
x-amz-request-payer
|
|
17
|
+
x-amz-server-side-encryption-customer-algorithm
|
|
18
|
+
x-amz-server-side-encryption-customer-key
|
|
19
|
+
x-amz-server-side-encryption-customer-key-MD5
|
|
20
|
+
x-amz-source-expected-bucket-owner
|
|
21
|
+
).freeze
|
|
22
|
+
|
|
4
23
|
class Real
|
|
5
24
|
require 'fog/aws/parsers/storage/upload_part_copy_object'
|
|
6
25
|
|
|
@@ -45,6 +64,8 @@ module Fog
|
|
|
45
64
|
include Fog::AWS::Storage::SharedMockMethods
|
|
46
65
|
|
|
47
66
|
def upload_part_copy(target_bucket_name, target_object_name, upload_id, part_number, options = {})
|
|
67
|
+
validate_options!(options)
|
|
68
|
+
|
|
48
69
|
copy_source = options['x-amz-copy-source']
|
|
49
70
|
copy_range = options['x-amz-copy-source-range']
|
|
50
71
|
|
|
@@ -86,6 +107,12 @@ module Fog
|
|
|
86
107
|
|
|
87
108
|
[matches[1].to_i, end_pos]
|
|
88
109
|
end
|
|
110
|
+
|
|
111
|
+
def validate_options!(options)
|
|
112
|
+
options.keys.each do |key|
|
|
113
|
+
raise "Invalid UploadPart option: #{key}" unless ::Fog::AWS::Storage::ALLOWED_UPLOAD_PART_OPTIONS.include?(key.to_sym)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
89
116
|
end # Mock
|
|
90
117
|
end # Storage
|
|
91
118
|
end # AWS
|
data/lib/fog/aws/storage.rb
CHANGED
|
@@ -14,6 +14,9 @@ module Fog
|
|
|
14
14
|
'https' => 443
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
MIN_MULTIPART_CHUNK_SIZE = 5242880
|
|
18
|
+
MAX_SINGLE_PUT_SIZE = 5368709120
|
|
19
|
+
|
|
17
20
|
VALID_QUERY_KEYS = %w[
|
|
18
21
|
acl
|
|
19
22
|
cors
|
|
@@ -43,7 +46,7 @@ module Fog
|
|
|
43
46
|
]
|
|
44
47
|
|
|
45
48
|
requires :aws_access_key_id, :aws_secret_access_key
|
|
46
|
-
recognizes :endpoint, :region, :host, :port, :scheme, :persistent, :use_iam_profile, :aws_session_token, :aws_credentials_expire_at, :path_style, :acceleration, :instrumentor, :instrumentor_name, :aws_signature_version, :enable_signature_v4_streaming, :virtual_host, :cname
|
|
49
|
+
recognizes :endpoint, :region, :host, :port, :scheme, :persistent, :use_iam_profile, :aws_session_token, :aws_credentials_expire_at, :path_style, :acceleration, :instrumentor, :instrumentor_name, :aws_signature_version, :enable_signature_v4_streaming, :virtual_host, :cname, :max_put_chunk_size, :max_copy_chunk_size
|
|
47
50
|
|
|
48
51
|
secrets :aws_secret_access_key, :hmac
|
|
49
52
|
|
|
@@ -117,6 +120,17 @@ module Fog
|
|
|
117
120
|
module Utils
|
|
118
121
|
attr_accessor :region
|
|
119
122
|
|
|
123
|
+
# Amazon S3 limits max chunk size that can be uploaded/copied in a single request to 5GB.
|
|
124
|
+
# Other S3-compatible storages (like, Ceph) do not have such limit.
|
|
125
|
+
# Ceph shows much better performance when file is copied as a whole, in a single request.
|
|
126
|
+
# fog-aws user can use these settings to configure chunk sizes.
|
|
127
|
+
# A non-positive value will tell fog-aws to use a single put/copy request regardless of file size.
|
|
128
|
+
#
|
|
129
|
+
# @return [Integer]
|
|
130
|
+
# @see https://docs.aws.amazon.com/AmazonS3/latest/userguide/copy-object.html
|
|
131
|
+
attr_reader :max_put_chunk_size
|
|
132
|
+
attr_reader :max_copy_chunk_size
|
|
133
|
+
|
|
120
134
|
def cdn
|
|
121
135
|
@cdn ||= Fog::AWS::CDN.new(
|
|
122
136
|
:aws_access_key_id => @aws_access_key_id,
|
|
@@ -171,6 +185,12 @@ module Fog
|
|
|
171
185
|
params_to_url(params)
|
|
172
186
|
end
|
|
173
187
|
|
|
188
|
+
# @param value [int]
|
|
189
|
+
# @param description [str]
|
|
190
|
+
def validate_chunk_size(value, description)
|
|
191
|
+
raise "#{description} (#{value}) is less than minimum #{MIN_MULTIPART_CHUNK_SIZE}" unless value <= 0 || value >= MIN_MULTIPART_CHUNK_SIZE
|
|
192
|
+
end
|
|
193
|
+
|
|
174
194
|
private
|
|
175
195
|
|
|
176
196
|
def validate_signature_version!
|
|
@@ -179,6 +199,16 @@ module Fog
|
|
|
179
199
|
end
|
|
180
200
|
end
|
|
181
201
|
|
|
202
|
+
def init_max_put_chunk_size!(options = {})
|
|
203
|
+
@max_put_chunk_size = options.fetch(:max_put_chunk_size, MAX_SINGLE_PUT_SIZE)
|
|
204
|
+
validate_chunk_size(@max_put_chunk_size, 'max_put_chunk_size')
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def init_max_copy_chunk_size!(options = {})
|
|
208
|
+
@max_copy_chunk_size = options.fetch(:max_copy_chunk_size, MAX_SINGLE_PUT_SIZE)
|
|
209
|
+
validate_chunk_size(@max_copy_chunk_size, 'max_copy_chunk_size')
|
|
210
|
+
end
|
|
211
|
+
|
|
182
212
|
def v4_signed_params_for_url(params, expires)
|
|
183
213
|
now = Fog::Time.now
|
|
184
214
|
|
|
@@ -284,10 +314,10 @@ module Fog
|
|
|
284
314
|
path_style = params.fetch(:path_style, @path_style)
|
|
285
315
|
if !path_style
|
|
286
316
|
if COMPLIANT_BUCKET_NAMES !~ bucket_name
|
|
287
|
-
Fog::Logger.warning("fog: the specified s3 bucket name(#{bucket_name}) is not a valid dns name, which will negatively impact performance. For details see:
|
|
317
|
+
Fog::Logger.warning("fog: the specified s3 bucket name(#{bucket_name}) is not a valid dns name, which will negatively impact performance. For details see: https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html")
|
|
288
318
|
path_style = true
|
|
289
319
|
elsif scheme == 'https' && !path_style && bucket_name =~ /\./
|
|
290
|
-
Fog::Logger.warning("fog: the specified s3 bucket name(#{bucket_name}) contains a '.' so is not accessible over https as a virtual hosted bucket, which will negatively impact performance. For details see:
|
|
320
|
+
Fog::Logger.warning("fog: the specified s3 bucket name(#{bucket_name}) contains a '.' so is not accessible over https as a virtual hosted bucket, which will negatively impact performance. For details see: https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html")
|
|
291
321
|
path_style = true
|
|
292
322
|
end
|
|
293
323
|
end
|
|
@@ -298,6 +328,8 @@ module Fog
|
|
|
298
328
|
host = params.fetch(:cname, bucket_name)
|
|
299
329
|
elsif path_style
|
|
300
330
|
path = bucket_to_path bucket_name, path
|
|
331
|
+
elsif host.start_with?("#{bucket_name}.")
|
|
332
|
+
# no-op
|
|
301
333
|
else
|
|
302
334
|
host = [bucket_name, host].join('.')
|
|
303
335
|
end
|
|
@@ -450,6 +482,10 @@ module Fog
|
|
|
450
482
|
|
|
451
483
|
|
|
452
484
|
@path_style = options[:path_style] || false
|
|
485
|
+
|
|
486
|
+
init_max_put_chunk_size!(options)
|
|
487
|
+
init_max_copy_chunk_size!(options)
|
|
488
|
+
|
|
453
489
|
@signature_version = options.fetch(:aws_signature_version, 4)
|
|
454
490
|
validate_signature_version!
|
|
455
491
|
setup_credentials(options)
|
|
@@ -513,6 +549,9 @@ module Fog
|
|
|
513
549
|
validate_signature_version!
|
|
514
550
|
@path_style = options[:path_style] || false
|
|
515
551
|
|
|
552
|
+
init_max_put_chunk_size!(options)
|
|
553
|
+
init_max_copy_chunk_size!(options)
|
|
554
|
+
|
|
516
555
|
@region = options[:region] || DEFAULT_REGION
|
|
517
556
|
|
|
518
557
|
if @endpoint = options[:endpoint]
|