fluent-plugin-kinesis 1.3.0 → 2.0.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -23
  3. data/CHANGELOG.md +13 -0
  4. data/Gemfile +9 -9
  5. data/LICENSE.txt +201 -40
  6. data/Makefile +24 -31
  7. data/README.md +179 -308
  8. data/Rakefile +9 -13
  9. data/benchmark/task.rake +96 -58
  10. data/fluent-plugin-kinesis.gemspec +15 -19
  11. data/gemfiles/Gemfile.fluentd-0.12 +10 -10
  12. data/lib/fluent/plugin/kinesis.rb +166 -0
  13. data/lib/fluent/plugin/kinesis_helper/aggregator.rb +99 -0
  14. data/lib/fluent/plugin/kinesis_helper/api.rb +152 -121
  15. data/lib/fluent/plugin/kinesis_helper/client.rb +125 -12
  16. data/lib/fluent/plugin/out_kinesis_firehose.rb +40 -27
  17. data/lib/fluent/plugin/out_kinesis_streams.rb +51 -30
  18. data/lib/fluent/plugin/out_kinesis_streams_aggregated.rb +76 -0
  19. data/lib/fluent_plugin_kinesis/version.rb +10 -10
  20. metadata +18 -70
  21. data/README-v0.4.md +0 -348
  22. data/benchmark/dummy.conf +0 -0
  23. data/gemfiles/Gemfile.aws-sdk-2.4 +0 -20
  24. data/gemfiles/Gemfile.fluentd-0.10.58 +0 -20
  25. data/gemfiles/Gemfile.fluentd-0.14.11 +0 -20
  26. data/gemfiles/Gemfile.ruby-2.0 +0 -21
  27. data/gemfiles/Gemfile.ruby-2.1 +0 -21
  28. data/lib/fluent/plugin/kinesis_helper.rb +0 -36
  29. data/lib/fluent/plugin/kinesis_helper/class_methods.rb +0 -123
  30. data/lib/fluent/plugin/kinesis_helper/credentials.rb +0 -51
  31. data/lib/fluent/plugin/kinesis_helper/error.rb +0 -43
  32. data/lib/fluent/plugin/kinesis_helper/format.rb +0 -85
  33. data/lib/fluent/plugin/kinesis_helper/initialize.rb +0 -59
  34. data/lib/fluent/plugin/kinesis_helper/kpl.rb +0 -82
  35. data/lib/fluent/plugin/out_kinesis.rb +0 -323
  36. data/lib/fluent/plugin/out_kinesis_producer.rb +0 -48
  37. data/lib/fluent/plugin/patched_detach_process_impl.rb +0 -103
  38. data/lib/kinesis_producer.rb +0 -24
  39. data/lib/kinesis_producer/binary.rb +0 -10
  40. data/lib/kinesis_producer/daemon.rb +0 -270
  41. data/lib/kinesis_producer/library.rb +0 -122
  42. data/lib/kinesis_producer/protobuf/config.pb.rb +0 -66
  43. data/lib/kinesis_producer/protobuf/messages.pb.rb +0 -151
  44. data/lib/kinesis_producer/tasks/binary.rake +0 -73
@@ -0,0 +1,99 @@
1
+ #
2
+ # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
5
+ # may not use this file except in compliance with the License. A copy of
6
+ # the License is located at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # or in the "license" file accompanying this file. This file is
11
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12
+ # ANY KIND, either express or implied. See the License for the specific
13
+ # language governing permissions and limitations under the License.
14
+
15
+ require 'fluent/configurable'
16
+ require 'google/protobuf'
17
+
18
+ Google::Protobuf::DescriptorPool.generated_pool.build do
19
+ add_message "AggregatedRecord" do
20
+ repeated :partition_key_table, :string, 1
21
+ repeated :explicit_hash_key_table, :string, 2
22
+ repeated :records, :message, 3, "Record"
23
+ end
24
+ add_message "Tag" do
25
+ optional :key, :string, 1
26
+ optional :value, :string, 2
27
+ end
28
+ add_message "Record" do
29
+ optional :partition_key_index, :uint64, 1
30
+ optional :explicit_hash_key_index, :uint64, 2
31
+ optional :data, :bytes, 3
32
+ repeated :tags, :message, 4, "Tag"
33
+ end
34
+ end
35
+
36
+ module Fluent
37
+ module KinesisHelper
38
+ class Aggregator
39
+ AggregatedRecord = Google::Protobuf::DescriptorPool.generated_pool.lookup("AggregatedRecord").msgclass
40
+ Tag = Google::Protobuf::DescriptorPool.generated_pool.lookup("Tag").msgclass
41
+ Record = Google::Protobuf::DescriptorPool.generated_pool.lookup("Record").msgclass
42
+
43
+ class InvalidEncodingError < ::StandardError; end
44
+
45
+ MagicNumber = ['F3899AC2'].pack('H*')
46
+
47
+ def aggregate(records, partition_key)
48
+ message = AggregatedRecord.encode(AggregatedRecord.new(
49
+ partition_key_table: ['a', partition_key],
50
+ records: records.map{|data|
51
+ Record.new(partition_key_index: 1, data: data)
52
+ },
53
+ ))
54
+ [MagicNumber, message, Digest::MD5.digest(message)].pack("A4A*A16")
55
+ end
56
+
57
+ def deaggregate(encoded)
58
+ unless aggregated?(encoded)
59
+ raise InvalidEncodingError, "Invalid MagicNumber #{encoded[0..3]}}"
60
+ end
61
+ message, digest = encoded[4..encoded.length-17], encoded[encoded.length-16..-1]
62
+ if Digest::MD5.digest(message) != digest
63
+ raise InvalidEncodingError, "Digest mismatch #{digest}"
64
+ end
65
+ decoded = AggregatedRecord.decode(message)
66
+ records = decoded.records.map(&:data)
67
+ partition_key = decoded.partition_key_table[1]
68
+ [records, partition_key]
69
+ end
70
+
71
+ def aggregated?(encoded)
72
+ encoded[0..3] == MagicNumber
73
+ end
74
+
75
+ def aggregated_size_offset(partition_key)
76
+ data = 'd'
77
+ encoded = aggregate([record(data)], partition_key)
78
+ finalize(encoded).size - data.size
79
+ end
80
+
81
+ module Mixin
82
+ AggregateOffset = 25
83
+ RecordOffset = 10
84
+
85
+ module Params
86
+ include Fluent::Configurable
87
+ end
88
+
89
+ def self.included(mod)
90
+ mod.include Params
91
+ end
92
+
93
+ def aggregator
94
+ @aggregator ||= Aggregator.new
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -1,163 +1,194 @@
1
1
  #
2
- # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  #
4
- # Licensed under the Amazon Software License (the "License").
5
- # You may not use this file except in compliance with the License.
6
- # A copy of the License is located at
4
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
5
+ # may not use this file except in compliance with the License. A copy of
6
+ # the License is located at
7
7
  #
8
- # http://aws.amazon.com/asl/
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
9
  #
10
- # or in the "license" file accompanying this file. This file is distributed
11
- # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12
- # express or implied. See the License for the specific language governing
13
- # permissions and limitations under the License.
10
+ # or in the "license" file accompanying this file. This file is
11
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12
+ # ANY KIND, either express or implied. See the License for the specific
13
+ # language governing permissions and limitations under the License.
14
14
 
15
15
  require 'fluent_plugin_kinesis/version'
16
+ require 'fluent/configurable'
16
17
 
17
18
  module Fluent
18
19
  module KinesisHelper
19
20
  module API
21
+ MaxRecordSize = 1024 * 1024 # 1 MB
22
+
23
+ module APIParams
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
+
20
32
  def configure(conf)
21
33
  super
22
- if @batch_request_max_count > self.class::BatchRequestLimitCount
23
- raise ConfigError, "batch_request_max_count can't be grater than #{self.class::BatchRequestLimitCount}."
24
- end
25
- if @batch_request_max_size > self.class::BatchRequestLimitSize
26
- raise ConfigError, "batch_request_max_size can't be grater than #{self.class::BatchRequestLimitSize}."
34
+ if @max_record_size > MaxRecordSize
35
+ raise ConfigError, "max_record_size can't be grater than #{MaxRecordSize/1024} KB."
27
36
  end
28
- @region = client.config.region if @region.nil?
29
37
  end
30
38
 
31
- def start
32
- detach_multi_process do
33
- super
39
+ module BatchRequest
40
+ module BatchRequestParams
41
+ include Fluent::Configurable
42
+ config_param :retries_on_batch_request, :integer, default: 8
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
34
46
  end
35
- end
36
47
 
37
- private
38
-
39
- def client_options
40
- options = {
41
- user_agent_suffix: "fluent-plugin-kinesis/#{request_type}/#{FluentPluginKinesis::VERSION}",
42
- credentials: credentials,
43
- }
44
- options.update(region: @region) unless @region.nil?
45
- options.update(http_proxy: @http_proxy) unless @http_proxy.nil?
46
- options.update(endpoint: @endpoint) unless @endpoint.nil?
47
- options.update(ssl_verify_peer: @ssl_verify_peer) unless @ssl_verify_peer.nil?
48
- if @debug
49
- options.update(logger: Logger.new(log.out))
50
- options.update(log_level: :debug)
48
+ def self.included(mod)
49
+ mod.include BatchRequestParams
51
50
  end
52
- options
53
- end
54
-
55
- def split_to_batches(records)
56
- batch_by_limit(records, @batch_request_max_count, @batch_request_max_size)
57
- end
58
51
 
59
- def batch_by_limit(records, max_count, max_size)
60
- result, buf, size = records.inject([[],[],0]){|(result, buf, size), record|
61
- record_size = size_of_values(record)
62
- if buf.size+1 > max_count or size+record_size > max_size
63
- result << buf
64
- buf = []
65
- size = 0
52
+ def configure(conf)
53
+ super
54
+ if @batch_request_max_count.nil?
55
+ @batch_request_max_count = self.class::BatchRequestLimitCount
56
+ elsif @batch_request_max_count > self.class::BatchRequestLimitCount
57
+ raise ConfigError, "batch_request_max_count can't be grater than #{self.class::BatchRequestLimitCount}."
66
58
  end
67
- buf << record
68
- size += record_size
69
- [result, buf, size]
70
- }
71
- result << buf
72
- 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}."
63
+ end
64
+ end
73
65
 
74
- def size_of_values(record)
75
- record.values_at(:data, :partition_key).compact.map(&:size).inject(:+) || 0
76
- end
66
+ def size_of_values(record)
67
+ record.compact.map(&:size).inject(:+) || 0
68
+ end
77
69
 
78
- def batch_request_with_retry(batch, retry_count=0, backoff: nil)
79
- backoff ||= Backoff.new
80
- res = batch_request(batch)
81
- if failed_count(res) > 0
82
- failed_records = collect_failed_records(batch, res)
83
- if retry_count < @retries_on_batch_request
84
- backoff.reset if @reset_backoff_if_success and any_records_shipped?(res)
85
- sleep(backoff.next)
86
- log.warn(truncate 'Retrying to request batch. Retry count: %d, Retry records: %d' % [retry_count, failed_records.size])
87
- retry_batch = failed_records.map{|r| r[:original] }
88
- batch_request_with_retry(retry_batch, retry_count + 1, backoff: backoff)
89
- else
90
- give_up_retries(failed_records)
70
+ private
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
91
84
  end
85
+ yield(batch, size) if batch.size > 0
92
86
  end
93
- end
94
-
95
- def any_records_shipped?(res)
96
- results(res).size > failed_count(res)
97
- end
98
87
 
99
- def collect_failed_records(records, res)
100
- failed_records = []
101
- results(res).each_with_index do |record, index|
102
- next unless record[:error_code]
103
- failed_records.push(
104
- original: records[index],
105
- error_code: record[:error_code],
106
- error_message: record[:error_message]
107
- )
88
+ def batch_request_with_retry(batch, retry_count=0, backoff: nil, &block)
89
+ backoff ||= Backoff.new
90
+ res = yield(batch)
91
+ if failed_count(res) > 0
92
+ failed_records = collect_failed_records(batch, res)
93
+ if retry_count < @retries_on_batch_request
94
+ backoff.reset if @reset_backoff_if_success and any_records_shipped?(res)
95
+ wait_second = backoff.next
96
+ msg = 'Retrying to request batch. Retry count: %3d, Retry records: %3d, Wait seconds %3.2f' % [retry_count+1, failed_records.size, wait_second]
97
+ log.warn(truncate msg)
98
+ # TODO: sleep() doesn't wait the given seconds sometime.
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)
106
+ end
107
+ end
108
108
  end
109
- failed_records
110
- end
111
109
 
112
- def failed_count(res)
113
- failed_field = case request_type
114
- when :streams; :failed_record_count
115
- when :firehose; :failed_put_count
116
- end
117
- res[failed_field]
118
- end
110
+ def any_records_shipped?(res)
111
+ results(res).size > failed_count(res)
112
+ end
119
113
 
120
- def results(res)
121
- result_field = case request_type
122
- when :streams; :records
123
- when :firehose; :request_responses
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
124
121
  end
125
- res[result_field]
126
- end
122
+ failed_records.push(
123
+ original: original,
124
+ error_code: record[:error_code],
125
+ error_message: record[:error_message]
126
+ )
127
+ end
128
+ failed_records
129
+ end
127
130
 
128
- def give_up_retries(failed_records)
129
- failed_records.each {|record|
130
- log.error(truncate 'Could not put record, Error: %s/%s, Record: %s' % [
131
- record[:error_code],
132
- record[:error_message],
133
- record[:original]
134
- ])
135
- }
136
- end
131
+ def retry_records(failed_records)
132
+ case request_type
133
+ when :streams, :firehose
134
+ failed_records.map{|r| r[:original] }
135
+ when :streams_aggregated
136
+ failed_records.first[:original]
137
+ end
138
+ end
137
139
 
138
- class Backoff
139
- def initialize
140
- @count = 0
140
+ def failed_count(res)
141
+ failed_field = case request_type
142
+ when :streams; :failed_record_count
143
+ when :streams_aggregated; :failed_record_count
144
+ when :firehose; :failed_put_count
145
+ end
146
+ res[failed_field]
141
147
  end
142
148
 
143
- def next
144
- value = calc(@count)
145
- @count += 1
146
- value
149
+ def results(res)
150
+ result_field = case request_type
151
+ when :streams; :records
152
+ when :streams_aggregated; :records
153
+ when :firehose; :request_responses
154
+ end
155
+ res[result_field]
147
156
  end
148
157
 
149
- def reset
150
- @count = 0
158
+ def give_up_retries(failed_records)
159
+ failed_records.each {|record|
160
+ log.error(truncate 'Could not put record, Error: %s/%s, Record: %s' % [
161
+ record[:error_code],
162
+ record[:error_message],
163
+ record[:original]
164
+ ])
165
+ }
151
166
  end
152
167
 
153
- private
168
+ class Backoff
169
+ def initialize
170
+ @count = 0
171
+ end
154
172
 
155
- def calc(count)
156
- (2 ** count) * scaling_factor
157
- end
173
+ def next
174
+ value = calc(@count)
175
+ @count += 1
176
+ value
177
+ end
178
+
179
+ def reset
180
+ @count = 0
181
+ end
182
+
183
+ private
158
184
 
159
- def scaling_factor
160
- 0.3 + (0.5-rand) * 0.1
185
+ def calc(count)
186
+ (2 ** count) * scaling_factor
187
+ end
188
+
189
+ def scaling_factor
190
+ 0.3 + (0.5-rand) * 0.1
191
+ end
161
192
  end
162
193
  end
163
194
  end
@@ -1,20 +1,75 @@
1
1
  #
2
- # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ # Copyright 2014-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  #
4
- # Licensed under the Amazon Software License (the "License").
5
- # You may not use this file except in compliance with the License.
6
- # A copy of the License is located at
4
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
5
+ # may not use this file except in compliance with the License. A copy of
6
+ # the License is located at
7
7
  #
8
- # http://aws.amazon.com/asl/
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
9
  #
10
- # or in the "license" file accompanying this file. This file is distributed
11
- # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12
- # express or implied. See the License for the specific language governing
13
- # permissions and limitations under the License.
10
+ # or in the "license" file accompanying this file. This file is
11
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
12
+ # ANY KIND, either express or implied. See the License for the specific
13
+ # language governing permissions and limitations under the License.
14
+
15
+ require 'fluent/configurable'
14
16
 
15
17
  module Fluent
16
18
  module KinesisHelper
17
19
  module Client
20
+ module ClientParams
21
+ include Fluent::Configurable
22
+ config_param :region, :string, default: nil
23
+
24
+ config_param :http_proxy, :string, default: nil, secret: true
25
+ config_param :endpoint, :string, default: nil
26
+ config_param :ssl_verify_peer, :bool, default: true
27
+
28
+ config_param :aws_key_id, :string, default: nil, secret: true
29
+ config_param :aws_sec_key, :string, default: nil, secret: true
30
+ config_section :assume_role_credentials, multi: false do
31
+ desc "The Amazon Resource Name (ARN) of the role to assume"
32
+ config_param :role_arn, :string, secret: true
33
+ desc "An identifier for the assumed role session"
34
+ config_param :role_session_name, :string
35
+ desc "An IAM policy in JSON format"
36
+ config_param :policy, :string, default: nil
37
+ desc "The duration, in seconds, of the role session (900-3600)"
38
+ config_param :duration_seconds, :integer, default: nil
39
+ desc "A unique identifier that is used by third parties when assuming roles in their customers' accounts."
40
+ config_param :external_id, :string, default: nil, secret: true
41
+ end
42
+ config_section :instance_profile_credentials, multi: false do
43
+ desc "Number of times to retry when retrieving credentials"
44
+ config_param :retries, :integer, default: nil
45
+ desc "IP address (default:169.254.169.254)"
46
+ config_param :ip_address, :string, default: nil
47
+ desc "Port number (default:80)"
48
+ config_param :port, :integer, default: nil
49
+ desc "Number of seconds to wait for the connection to open"
50
+ config_param :http_open_timeout, :float, default: nil
51
+ desc "Number of seconds to wait for one block to be read"
52
+ config_param :http_read_timeout, :float, default: nil
53
+ # config_param :delay, :integer or :proc, :default => nil
54
+ # config_param :http_degub_output, :io, :default => nil
55
+ end
56
+ config_section :shared_credentials, multi: false do
57
+ desc "Path to the shared file. (default: $HOME/.aws/credentials)"
58
+ config_param :path, :string, default: nil
59
+ desc "Profile name. Default to 'default' or ENV['AWS_PROFILE']"
60
+ config_param :profile_name, :string, default: nil
61
+ end
62
+ end
63
+
64
+ def self.included(mod)
65
+ mod.include ClientParams
66
+ end
67
+
68
+ def configure(conf)
69
+ super
70
+ @region = client.config.region if @region.nil?
71
+ end
72
+
18
73
  def client
19
74
  @client ||= client_class.new(client_options)
20
75
  end
@@ -23,14 +78,72 @@ module Fluent
23
78
 
24
79
  def client_class
25
80
  case request_type
26
- when :streams
81
+ when :streams, :streams_aggregated
82
+ require 'aws-sdk-kinesis'
27
83
  Aws::Kinesis::Client
28
84
  when :firehose
85
+ require 'aws-sdk-firehose'
29
86
  Aws::Firehose::Client
30
- when :producer
31
- KinesisProducer::Library
32
87
  end
33
88
  end
89
+
90
+ def client_options
91
+ options = setup_credentials
92
+ options.update(
93
+ user_agent_suffix: "fluent-plugin-kinesis/#{request_type}/#{FluentPluginKinesis::VERSION}"
94
+ )
95
+ options.update(region: @region) unless @region.nil?
96
+ options.update(http_proxy: @http_proxy) unless @http_proxy.nil?
97
+ options.update(endpoint: @endpoint) unless @endpoint.nil?
98
+ options.update(ssl_verify_peer: @ssl_verify_peer) unless @ssl_verify_peer.nil?
99
+ if @debug
100
+ options.update(logger: Logger.new(log.out))
101
+ options.update(log_level: :debug)
102
+ end
103
+ options
104
+ end
105
+
106
+ def setup_credentials
107
+ options = {}
108
+ credentials_options = {}
109
+ case
110
+ when @aws_key_id && @aws_sec_key
111
+ options[:access_key_id] = @aws_key_id
112
+ options[:secret_access_key] = @aws_sec_key
113
+ when @assume_role_credentials
114
+ c = @assume_role_credentials
115
+ credentials_options[:role_arn] = c.role_arn
116
+ credentials_options[:role_session_name] = c.role_session_name
117
+ credentials_options[:policy] = c.policy if c.policy
118
+ credentials_options[:duration_seconds] = c.duration_seconds if c.duration_seconds
119
+ credentials_options[:external_id] = c.external_id if c.external_id
120
+ if @region
121
+ credentials_options[:client] = Aws::STS::Client.new(region: @region)
122
+ end
123
+ options[:credentials] = Aws::AssumeRoleCredentials.new(credentials_options)
124
+ when @instance_profile_credentials
125
+ c = @instance_profile_credentials
126
+ credentials_options[:retries] = c.retries if c.retries
127
+ credentials_options[:ip_address] = c.ip_address if c.ip_address
128
+ credentials_options[:port] = c.port if c.port
129
+ credentials_options[:http_open_timeout] = c.http_open_timeout if c.http_open_timeout
130
+ credentials_options[:http_read_timeout] = c.http_read_timeout if c.http_read_timeout
131
+ if ENV["AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"]
132
+ options[:credentials] = Aws::ECSCredentials.new(credentials_options)
133
+ else
134
+ options[:credentials] = Aws::InstanceProfileCredentials.new(credentials_options)
135
+ end
136
+ when @shared_credentials
137
+ c = @shared_credentials
138
+ credentials_options[:path] = c.path if c.path
139
+ credentials_options[:profile_name] = c.profile_name if c.profile_name
140
+ options[:credentials] = Aws::SharedCredentials.new(credentials_options)
141
+ else
142
+ # Use default credentials
143
+ # See http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Client.html
144
+ end
145
+ options
146
+ end
34
147
  end
35
148
  end
36
149
  end