fluent-plugin-kinesis 2.2.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/PULL_REQUEST_TEMPLATE.md +6 -0
- data/.travis.yml +18 -7
- data/CHANGELOG.md +9 -2
- data/CODE_OF_CONDUCT.md +4 -0
- data/CONTRIBUTING.md +61 -0
- data/README.md +34 -38
- data/benchmark/task.rake +6 -10
- data/fluent-plugin-kinesis.gemspec +20 -13
- data/gemfiles/{Gemfile.td-agent-2.3.5 → Gemfile.fluentd-0.14.10} +1 -6
- data/gemfiles/Gemfile.td-agent-3.1.1 +31 -0
- data/gemfiles/Gemfile.td-agent-3.2.0 +31 -0
- data/gemfiles/Gemfile.td-agent-3.2.1 +31 -0
- data/gemfiles/Gemfile.td-agent-3.3.0 +31 -0
- data/lib/fluent/plugin/kinesis.rb +112 -117
- data/lib/fluent/plugin/kinesis_helper/aggregator.rb +49 -47
- data/lib/fluent/plugin/kinesis_helper/api.rb +139 -137
- data/lib/fluent/plugin/kinesis_helper/client.rb +118 -128
- data/lib/fluent/plugin/out_kinesis_firehose.rb +31 -29
- data/lib/fluent/plugin/out_kinesis_streams.rb +41 -39
- data/lib/fluent/plugin/out_kinesis_streams_aggregated.rb +45 -43
- data/lib/fluent_plugin_kinesis/version.rb +1 -1
- metadata +57 -24
@@ -16,178 +16,180 @@ require 'fluent_plugin_kinesis/version'
|
|
16
16
|
require 'fluent/configurable'
|
17
17
|
|
18
18
|
module Fluent
|
19
|
-
module
|
20
|
-
module
|
21
|
-
|
19
|
+
module Plugin
|
20
|
+
module KinesisHelper
|
21
|
+
module API
|
22
|
+
MaxRecordSize = 1024 * 1024 # 1 MB
|
22
23
|
|
23
|
-
|
24
|
-
include Fluent::Configurable
|
25
|
-
config_param :max_record_size, :integer, default: MaxRecordSize
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.included(mod)
|
29
|
-
mod.include APIParams
|
30
|
-
end
|
31
|
-
|
32
|
-
def configure(conf)
|
33
|
-
super
|
34
|
-
if @max_record_size > MaxRecordSize
|
35
|
-
raise ConfigError, "max_record_size can't be grater than #{MaxRecordSize/1024} KB."
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
module BatchRequest
|
40
|
-
module BatchRequestParams
|
24
|
+
module APIParams
|
41
25
|
include Fluent::Configurable
|
42
|
-
config_param :
|
43
|
-
config_param :reset_backoff_if_success, :bool, default: true
|
44
|
-
config_param :batch_request_max_count, :integer, default: nil
|
45
|
-
config_param :batch_request_max_size, :integer, default: nil
|
26
|
+
config_param :max_record_size, :integer, default: MaxRecordSize
|
46
27
|
end
|
47
28
|
|
48
29
|
def self.included(mod)
|
49
|
-
mod.include
|
30
|
+
mod.include APIParams
|
50
31
|
end
|
51
32
|
|
52
33
|
def configure(conf)
|
53
34
|
super
|
54
|
-
if @
|
55
|
-
|
56
|
-
elsif @batch_request_max_count > self.class::BatchRequestLimitCount
|
57
|
-
raise ConfigError, "batch_request_max_count can't be grater than #{self.class::BatchRequestLimitCount}."
|
58
|
-
end
|
59
|
-
if @batch_request_max_size.nil?
|
60
|
-
@batch_request_max_size = self.class::BatchRequestLimitSize
|
61
|
-
elsif @batch_request_max_size > self.class::BatchRequestLimitSize
|
62
|
-
raise ConfigError, "batch_request_max_size can't be grater than #{self.class::BatchRequestLimitSize}."
|
35
|
+
if @max_record_size > MaxRecordSize
|
36
|
+
raise ConfigError, "max_record_size can't be grater than #{MaxRecordSize/1024} KB."
|
63
37
|
end
|
64
38
|
end
|
65
39
|
|
66
|
-
|
67
|
-
|
68
|
-
|
40
|
+
module BatchRequest
|
41
|
+
module BatchRequestParams
|
42
|
+
include Fluent::Configurable
|
43
|
+
config_param :retries_on_batch_request, :integer, default: 8
|
44
|
+
config_param :reset_backoff_if_success, :bool, default: true
|
45
|
+
config_param :batch_request_max_count, :integer, default: nil
|
46
|
+
config_param :batch_request_max_size, :integer, default: nil
|
47
|
+
end
|
69
48
|
|
70
|
-
|
71
|
-
|
72
|
-
def split_to_batches(records, &block)
|
73
|
-
batch = []
|
74
|
-
size = 0
|
75
|
-
records.each do |record|
|
76
|
-
record_size = size_of_values(record)
|
77
|
-
if batch.size+1 > @batch_request_max_count or size+record_size > @batch_request_max_size
|
78
|
-
yield(batch, size)
|
79
|
-
batch = []
|
80
|
-
size = 0
|
81
|
-
end
|
82
|
-
batch << record
|
83
|
-
size += record_size
|
49
|
+
def self.included(mod)
|
50
|
+
mod.include BatchRequestParams
|
84
51
|
end
|
85
|
-
yield(batch, size) if batch.size > 0
|
86
|
-
end
|
87
52
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
# The root cause is unknown so far, so I'd like to add debug print only. It should be fixed in the future.
|
100
|
-
log.debug("#{Thread.current.object_id} sleep start")
|
101
|
-
sleep(wait_second)
|
102
|
-
log.debug("#{Thread.current.object_id} sleep finish")
|
103
|
-
batch_request_with_retry(retry_records(failed_records), retry_count+1, backoff: backoff, &block)
|
104
|
-
else
|
105
|
-
give_up_retries(failed_records)
|
53
|
+
def configure(conf)
|
54
|
+
super
|
55
|
+
if @batch_request_max_count.nil?
|
56
|
+
@batch_request_max_count = self.class::BatchRequestLimitCount
|
57
|
+
elsif @batch_request_max_count > self.class::BatchRequestLimitCount
|
58
|
+
raise ConfigError, "batch_request_max_count can't be grater than #{self.class::BatchRequestLimitCount}."
|
59
|
+
end
|
60
|
+
if @batch_request_max_size.nil?
|
61
|
+
@batch_request_max_size = self.class::BatchRequestLimitSize
|
62
|
+
elsif @batch_request_max_size > self.class::BatchRequestLimitSize
|
63
|
+
raise ConfigError, "batch_request_max_size can't be grater than #{self.class::BatchRequestLimitSize}."
|
106
64
|
end
|
107
65
|
end
|
108
|
-
end
|
109
66
|
|
110
|
-
|
111
|
-
|
112
|
-
end
|
113
|
-
|
114
|
-
def collect_failed_records(records, res)
|
115
|
-
failed_records = []
|
116
|
-
results(res).each_with_index do |record, index|
|
117
|
-
next unless record[:error_code]
|
118
|
-
original = case request_type
|
119
|
-
when :streams, :firehose; records[index]
|
120
|
-
when :streams_aggregated; records
|
121
|
-
end
|
122
|
-
failed_records.push(
|
123
|
-
original: original,
|
124
|
-
error_code: record[:error_code],
|
125
|
-
error_message: record[:error_message]
|
126
|
-
)
|
67
|
+
def size_of_values(record)
|
68
|
+
record.compact.map(&:size).inject(:+) || 0
|
127
69
|
end
|
128
|
-
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def split_to_batches(records, &block)
|
74
|
+
batch = []
|
75
|
+
size = 0
|
76
|
+
records.each do |record|
|
77
|
+
record_size = size_of_values(record)
|
78
|
+
if batch.size+1 > @batch_request_max_count or size+record_size > @batch_request_max_size
|
79
|
+
yield(batch, size)
|
80
|
+
batch = []
|
81
|
+
size = 0
|
129
82
|
end
|
83
|
+
batch << record
|
84
|
+
size += record_size
|
85
|
+
end
|
86
|
+
yield(batch, size) if batch.size > 0
|
87
|
+
end
|
130
88
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
89
|
+
def batch_request_with_retry(batch, retry_count=0, backoff: nil, &block)
|
90
|
+
backoff ||= Backoff.new
|
91
|
+
res = yield(batch)
|
92
|
+
if failed_count(res) > 0
|
93
|
+
failed_records = collect_failed_records(batch, res)
|
94
|
+
if retry_count < @retries_on_batch_request
|
95
|
+
backoff.reset if @reset_backoff_if_success and any_records_shipped?(res)
|
96
|
+
wait_second = backoff.next
|
97
|
+
msg = 'Retrying to request batch. Retry count: %3d, Retry records: %3d, Wait seconds %3.2f' % [retry_count+1, failed_records.size, wait_second]
|
98
|
+
log.warn(truncate msg)
|
99
|
+
# TODO: sleep() doesn't wait the given seconds sometime.
|
100
|
+
# The root cause is unknown so far, so I'd like to add debug print only. It should be fixed in the future.
|
101
|
+
log.debug("#{Thread.current.object_id} sleep start")
|
102
|
+
sleep(wait_second)
|
103
|
+
log.debug("#{Thread.current.object_id} sleep finish")
|
104
|
+
batch_request_with_retry(retry_records(failed_records), retry_count+1, backoff: backoff, &block)
|
105
|
+
else
|
106
|
+
give_up_retries(failed_records)
|
107
|
+
end
|
108
|
+
end
|
137
109
|
end
|
138
|
-
end
|
139
110
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
when :streams_aggregated; :failed_record_count
|
144
|
-
when :firehose; :failed_put_count
|
145
|
-
end
|
146
|
-
res[failed_field]
|
147
|
-
end
|
111
|
+
def any_records_shipped?(res)
|
112
|
+
results(res).size > failed_count(res)
|
113
|
+
end
|
148
114
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
115
|
+
def collect_failed_records(records, res)
|
116
|
+
failed_records = []
|
117
|
+
results(res).each_with_index do |record, index|
|
118
|
+
next unless record[:error_code]
|
119
|
+
original = case request_type
|
120
|
+
when :streams, :firehose; records[index]
|
121
|
+
when :streams_aggregated; records
|
154
122
|
end
|
155
|
-
|
156
|
-
|
123
|
+
failed_records.push(
|
124
|
+
original: original,
|
125
|
+
error_code: record[:error_code],
|
126
|
+
error_message: record[:error_message]
|
127
|
+
)
|
128
|
+
end
|
129
|
+
failed_records
|
130
|
+
end
|
157
131
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
end
|
132
|
+
def retry_records(failed_records)
|
133
|
+
case request_type
|
134
|
+
when :streams, :firehose
|
135
|
+
failed_records.map{|r| r[:original] }
|
136
|
+
when :streams_aggregated
|
137
|
+
failed_records.first[:original]
|
138
|
+
end
|
139
|
+
end
|
167
140
|
|
168
|
-
|
169
|
-
|
170
|
-
|
141
|
+
def failed_count(res)
|
142
|
+
failed_field = case request_type
|
143
|
+
when :streams; :failed_record_count
|
144
|
+
when :streams_aggregated; :failed_record_count
|
145
|
+
when :firehose; :failed_put_count
|
146
|
+
end
|
147
|
+
res[failed_field]
|
171
148
|
end
|
172
149
|
|
173
|
-
def
|
174
|
-
|
175
|
-
|
176
|
-
|
150
|
+
def results(res)
|
151
|
+
result_field = case request_type
|
152
|
+
when :streams; :records
|
153
|
+
when :streams_aggregated; :records
|
154
|
+
when :firehose; :request_responses
|
155
|
+
end
|
156
|
+
res[result_field]
|
177
157
|
end
|
178
158
|
|
179
|
-
def
|
180
|
-
|
159
|
+
def give_up_retries(failed_records)
|
160
|
+
failed_records.each {|record|
|
161
|
+
log.error(truncate 'Could not put record, Error: %s/%s, Record: %s' % [
|
162
|
+
record[:error_code],
|
163
|
+
record[:error_message],
|
164
|
+
record[:original]
|
165
|
+
])
|
166
|
+
}
|
181
167
|
end
|
182
168
|
|
183
|
-
|
169
|
+
class Backoff
|
170
|
+
def initialize
|
171
|
+
@count = 0
|
172
|
+
end
|
184
173
|
|
185
|
-
|
186
|
-
|
187
|
-
|
174
|
+
def next
|
175
|
+
value = calc(@count)
|
176
|
+
@count += 1
|
177
|
+
value
|
178
|
+
end
|
179
|
+
|
180
|
+
def reset
|
181
|
+
@count = 0
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
188
185
|
|
189
|
-
|
190
|
-
|
186
|
+
def calc(count)
|
187
|
+
(2 ** count) * scaling_factor
|
188
|
+
end
|
189
|
+
|
190
|
+
def scaling_factor
|
191
|
+
0.3 + (0.5-rand) * 0.1
|
192
|
+
end
|
191
193
|
end
|
192
194
|
end
|
193
195
|
end
|
@@ -16,152 +16,142 @@ require 'fluent/configurable'
|
|
16
16
|
require 'aws-sdk-core'
|
17
17
|
|
18
18
|
module Fluent
|
19
|
-
module
|
20
|
-
module
|
21
|
-
module
|
22
|
-
|
23
|
-
|
19
|
+
module Plugin
|
20
|
+
module KinesisHelper
|
21
|
+
module Client
|
22
|
+
module ClientParams
|
23
|
+
include Fluent::Configurable
|
24
|
+
config_param :region, :string, default: nil
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
config_param :http_proxy, :string, default: nil, secret: true
|
27
|
+
config_param :endpoint, :string, default: nil
|
28
|
+
config_param :ssl_verify_peer, :bool, default: true
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
30
|
+
config_param :aws_key_id, :string, default: nil, secret: true
|
31
|
+
config_param :aws_sec_key, :string, default: nil, secret: true
|
32
|
+
config_section :assume_role_credentials, multi: false do
|
33
|
+
desc "The Amazon Resource Name (ARN) of the role to assume"
|
34
|
+
config_param :role_arn, :string, secret: true
|
35
|
+
desc "An identifier for the assumed role session"
|
36
|
+
config_param :role_session_name, :string
|
37
|
+
desc "An IAM policy in JSON format"
|
38
|
+
config_param :policy, :string, default: nil
|
39
|
+
desc "The duration, in seconds, of the role session (900-3600)"
|
40
|
+
config_param :duration_seconds, :integer, default: nil
|
41
|
+
desc "A unique identifier that is used by third parties when assuming roles in their customers' accounts."
|
42
|
+
config_param :external_id, :string, default: nil, secret: true
|
43
|
+
desc "A http proxy url for requests to aws sts service"
|
44
|
+
config_param :sts_http_proxy, :string, default: nil, secret: true
|
45
|
+
end
|
46
|
+
config_section :instance_profile_credentials, multi: false do
|
47
|
+
desc "Number of times to retry when retrieving credentials"
|
48
|
+
config_param :retries, :integer, default: nil
|
49
|
+
desc "IP address (default:169.254.169.254)"
|
50
|
+
config_param :ip_address, :string, default: nil
|
51
|
+
desc "Port number (default:80)"
|
52
|
+
config_param :port, :integer, default: nil
|
53
|
+
desc "Number of seconds to wait for the connection to open"
|
54
|
+
config_param :http_open_timeout, :float, default: nil
|
55
|
+
desc "Number of seconds to wait for one block to be read"
|
56
|
+
config_param :http_read_timeout, :float, default: nil
|
57
|
+
# config_param :delay, :integer or :proc, :default => nil
|
58
|
+
# config_param :http_degub_output, :io, :default => nil
|
59
|
+
end
|
60
|
+
config_section :shared_credentials, multi: false do
|
61
|
+
desc "Path to the shared file. (default: $HOME/.aws/credentials)"
|
62
|
+
config_param :path, :string, default: nil
|
63
|
+
desc "Profile name. Default to 'default' or ENV['AWS_PROFILE']"
|
64
|
+
config_param :profile_name, :string, default: nil
|
65
|
+
end
|
64
66
|
end
|
65
|
-
end
|
66
67
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
def configure(conf)
|
72
|
-
super
|
73
|
-
@region = client.config.region if @region.nil?
|
74
|
-
end
|
68
|
+
def self.included(mod)
|
69
|
+
mod.include ClientParams
|
70
|
+
end
|
75
71
|
|
76
|
-
|
77
|
-
|
78
|
-
|
72
|
+
def configure(conf)
|
73
|
+
super
|
74
|
+
@region = client.config.region if @region.nil?
|
75
|
+
end
|
79
76
|
|
80
|
-
|
77
|
+
def client
|
78
|
+
@client ||= client_class.new(client_options)
|
79
|
+
end
|
81
80
|
|
82
|
-
|
83
|
-
@aws_sdk_v2 ||= Gem.loaded_specs['aws-sdk-core'].version < Gem::Version.create('3')
|
84
|
-
end
|
81
|
+
private
|
85
82
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
if aws_sdk_v2?
|
90
|
-
require 'aws-sdk'
|
91
|
-
else
|
83
|
+
def client_class
|
84
|
+
case request_type
|
85
|
+
when :streams, :streams_aggregated
|
92
86
|
require 'aws-sdk-kinesis'
|
93
|
-
|
94
|
-
|
95
|
-
when :firehose
|
96
|
-
if aws_sdk_v2?
|
97
|
-
require 'aws-sdk'
|
98
|
-
else
|
87
|
+
Aws::Kinesis::Client
|
88
|
+
when :firehose
|
99
89
|
require 'aws-sdk-firehose'
|
90
|
+
Aws::Firehose::Client
|
100
91
|
end
|
101
|
-
Aws::Firehose::Client
|
102
92
|
end
|
103
|
-
end
|
104
93
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
94
|
+
def client_options
|
95
|
+
options = setup_credentials
|
96
|
+
options.update(
|
97
|
+
user_agent_suffix: "fluent-plugin-kinesis/#{request_type}/#{FluentPluginKinesis::VERSION}"
|
98
|
+
)
|
99
|
+
options.update(region: @region) unless @region.nil?
|
100
|
+
options.update(http_proxy: @http_proxy) unless @http_proxy.nil?
|
101
|
+
options.update(endpoint: @endpoint) unless @endpoint.nil?
|
102
|
+
options.update(ssl_verify_peer: @ssl_verify_peer) unless @ssl_verify_peer.nil?
|
103
|
+
if @debug
|
104
|
+
options.update(logger: Logger.new(log.out))
|
105
|
+
options.update(log_level: :debug)
|
106
|
+
end
|
107
|
+
options
|
117
108
|
end
|
118
|
-
options
|
119
|
-
end
|
120
109
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
110
|
+
def setup_credentials
|
111
|
+
options = {}
|
112
|
+
credentials_options = {}
|
113
|
+
case
|
114
|
+
when @aws_key_id && @aws_sec_key
|
115
|
+
options[:access_key_id] = @aws_key_id
|
116
|
+
options[:secret_access_key] = @aws_sec_key
|
117
|
+
when @assume_role_credentials
|
118
|
+
c = @assume_role_credentials
|
119
|
+
credentials_options[:role_arn] = c.role_arn
|
120
|
+
credentials_options[:role_session_name] = c.role_session_name
|
121
|
+
credentials_options[:policy] = c.policy if c.policy
|
122
|
+
credentials_options[:duration_seconds] = c.duration_seconds if c.duration_seconds
|
123
|
+
credentials_options[:external_id] = c.external_id if c.external_id
|
124
|
+
if c.sts_http_proxy and @region
|
125
|
+
credentials_options[:client] = Aws::STS::Client.new(region: @region, http_proxy: c.sts_http_proxy)
|
126
|
+
elsif @region
|
127
|
+
credentials_options[:client] = Aws::STS::Client.new(region: @region)
|
128
|
+
elsif c.sts_http_proxy
|
129
|
+
credentials_options[:client] = Aws::STS::Client.new(http_proxy: c.sts_http_proxy)
|
130
|
+
end
|
131
|
+
options[:credentials] = Aws::AssumeRoleCredentials.new(credentials_options)
|
132
|
+
when @instance_profile_credentials
|
133
|
+
c = @instance_profile_credentials
|
134
|
+
credentials_options[:retries] = c.retries if c.retries
|
135
|
+
credentials_options[:ip_address] = c.ip_address if c.ip_address
|
136
|
+
credentials_options[:port] = c.port if c.port
|
137
|
+
credentials_options[:http_open_timeout] = c.http_open_timeout if c.http_open_timeout
|
138
|
+
credentials_options[:http_read_timeout] = c.http_read_timeout if c.http_read_timeout
|
139
|
+
if ENV["AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"]
|
140
|
+
options[:credentials] = Aws::ECSCredentials.new(credentials_options)
|
141
|
+
else
|
142
|
+
options[:credentials] = Aws::InstanceProfileCredentials.new(credentials_options)
|
143
|
+
end
|
144
|
+
when @shared_credentials
|
145
|
+
c = @shared_credentials
|
146
|
+
credentials_options[:path] = c.path if c.path
|
147
|
+
credentials_options[:profile_name] = c.profile_name if c.profile_name
|
148
|
+
options[:credentials] = Aws::SharedCredentials.new(credentials_options)
|
152
149
|
else
|
153
|
-
|
150
|
+
# Use default credentials
|
151
|
+
# See http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Client.html
|
154
152
|
end
|
155
|
-
|
156
|
-
c = @shared_credentials
|
157
|
-
credentials_options[:path] = c.path if c.path
|
158
|
-
credentials_options[:profile_name] = c.profile_name if c.profile_name
|
159
|
-
options[:credentials] = Aws::SharedCredentials.new(credentials_options)
|
160
|
-
else
|
161
|
-
# Use default credentials
|
162
|
-
# See http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Client.html
|
153
|
+
options
|
163
154
|
end
|
164
|
-
options
|
165
155
|
end
|
166
156
|
end
|
167
157
|
end
|