fluent-plugin-azurestorage-gen2 0.2.8 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +35 -0
- data/VERSION +1 -1
- data/lib/fluent/plugin/out_azurestorage_gen2.rb +150 -49
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9dfe2426009f9375ce47d7285a6030af693c148
|
4
|
+
data.tar.gz: 9e76fe1f92164e6e3807482f04d7f2cf6fecc19b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbdac55653f0e83acde54dc2ace5e58e43f6954b84bb0179526a4230adf59619be469f313508ecbeb772dc447473cd62e9d3fbaff9cb3af5d45b3d1ba6fdab45
|
7
|
+
data.tar.gz: 95475a64f3447e017da418c4faa87dabc932c12205b2050e9e4dd1382128f919415e466a94c68a90bd22be6be7cc3aaf4a426a9ffb1d4efff2bbb4a87925ef81
|
data/README.md
CHANGED
@@ -31,6 +31,7 @@ $ gem install fluent-plugin-azurestorage-gen2
|
|
31
31
|
azure_storage_account mystorageabfs
|
32
32
|
azure_container mycontainer
|
33
33
|
azure_instance_msi /subscriptions/mysubscriptionid
|
34
|
+
azure_client_id <msi client id>
|
34
35
|
azure_object_key_format %{path}-%{index}.%{file_extension}
|
35
36
|
azure_oauth_refresh_interval 3600
|
36
37
|
time_slice_format %Y%m%d-%H
|
@@ -92,6 +93,14 @@ Your Azure Storage Access Key(Primary or Secondary). This also can be got from A
|
|
92
93
|
|
93
94
|
Your Azure Managed Service Identity ID. When storage key authentication is not used, the plugin uses OAuth2 to authenticate as given MSI. This authentication method only works on Azure VM. If the VM has only one MSI assigned, this parameter becomes optional and the only MSI will be used. Otherwise this parameter is required.
|
94
95
|
|
96
|
+
### azure_client_id
|
97
|
+
|
98
|
+
Azure AD client id is a specific explicit identity to use when authenticating to Azure AD. Mutually exclusive with azure_object_id and azure_instance_msi. (for now, you need to define next to `azure_instance_msi`)
|
99
|
+
|
100
|
+
### azure_object_id
|
101
|
+
|
102
|
+
Azure AD object id is a specific explicit identity to use when authenticating to Azure AD. Mutually exclusive with azure_client_id and azure_instance_msi. (for now, you need to define next to `azure_instance_msi`)
|
103
|
+
|
95
104
|
### azure_oauth_tenant_id (Preview)
|
96
105
|
|
97
106
|
Azure account tenant id from your Azure Directory. Required if OAuth based credential mechanism is used.
|
@@ -140,6 +149,10 @@ If that setting is disabled, the worker won't fail on initialization (getting fi
|
|
140
149
|
|
141
150
|
The defaultt `url_domain_suffix` is `.dfs.core.windows.net`, you can override this in case of private endpoints.
|
142
151
|
|
152
|
+
### url_storage_resource
|
153
|
+
|
154
|
+
The url that is used during accessing a resource. Default value: `https://storage.azure.com/`
|
155
|
+
|
143
156
|
### azure_object_key_format
|
144
157
|
|
145
158
|
The format of Azure Storage object keys. You can use several built-in variables:
|
@@ -148,6 +161,7 @@ The format of Azure Storage object keys. You can use several built-in variables:
|
|
148
161
|
- %{time_slice}
|
149
162
|
- %{index}
|
150
163
|
- %{file_extension}
|
164
|
+
- %{upload_timestamp}
|
151
165
|
|
152
166
|
to decide keys dynamically.
|
153
167
|
|
@@ -155,6 +169,7 @@ to decide keys dynamically.
|
|
155
169
|
%{time_slice} is the time-slice in text that are formatted with *time_slice_format*.
|
156
170
|
%{index} is the sequential number starts from 0, increments when multiple files are uploaded to Azure Storage in the same time slice.
|
157
171
|
%{file_extention} is always "gz" for now.
|
172
|
+
%{upload_timestamp} is an upload timestamp in text that are formatted with *upload_timestamp_format*. Difference between time_slice and upload_timestamp is that the second one is the actual system timestamp (other one is from the metadata)
|
158
173
|
|
159
174
|
The default format is "%{path}%{time_slice}_%{index}.%{file_extension}".
|
160
175
|
|
@@ -279,10 +294,30 @@ Format of the time used as the file name. Default is '%Y%m%d'. Use '%Y%m%d%H' to
|
|
279
294
|
|
280
295
|
The time to wait old logs. Default is 10 minutes.
|
281
296
|
|
297
|
+
### upload_timestamp_format
|
298
|
+
|
299
|
+
Format of the upload timestamp used as the file name. Can be used instead of index in case of `write_only` option is enabled. Default value is '%H%M%S%L'.
|
300
|
+
|
282
301
|
### utc
|
283
302
|
|
284
303
|
Use UTC instead of local time.
|
285
304
|
|
305
|
+
### write_only
|
306
|
+
|
307
|
+
If that option is enabled, HEAD calls are skipped during blob operations. (so make sure to set the chunk limit to 4MB in order to avoid HEAD operation because of the append operation needs the last position of the uploaded blobs).
|
308
|
+
|
309
|
+
### proxy_url
|
310
|
+
|
311
|
+
Proxy URL for Azure endpoint.
|
312
|
+
|
313
|
+
### proxy_username
|
314
|
+
|
315
|
+
Proxy username for Azure proxy endpoint (used only if `proxy_url` is filled)
|
316
|
+
|
317
|
+
### proxy_password
|
318
|
+
|
319
|
+
Proxy password for Azure `proxy_username` (used only if `proxy_url` is filled)
|
320
|
+
|
286
321
|
## TODOs
|
287
322
|
|
288
323
|
- add storage key support
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2
|
1
|
+
0.3.2
|
@@ -24,6 +24,8 @@ module Fluent::Plugin
|
|
24
24
|
config_param :azure_storage_account, :string, :default => nil
|
25
25
|
config_param :azure_storage_access_key, :string, :default => nil, :secret => true
|
26
26
|
config_param :azure_instance_msi, :string, :default => nil
|
27
|
+
config_param :azure_client_id, :string, :default => nil
|
28
|
+
config_param :azure_object_id, :string, :default => nil
|
27
29
|
config_param :azure_oauth_app_id, :string, :default => nil, :secret => true
|
28
30
|
config_param :azure_oauth_secret, :string, :default => nil, :secret => true
|
29
31
|
config_param :azure_oauth_tenant_id, :string, :default => nil
|
@@ -39,9 +41,16 @@ module Fluent::Plugin
|
|
39
41
|
config_param :enable_retry, :bool, :default => false
|
40
42
|
config_param :startup_fail_on_error, :bool, :default => true
|
41
43
|
config_param :url_domain_suffix, :string, :default => '.dfs.core.windows.net'
|
44
|
+
config_param :url_storage_resource, :string, :default => 'https://storage.azure.com/'
|
42
45
|
config_param :format, :string, :default => "out_file"
|
43
46
|
config_param :time_slice_format, :string, :default => '%Y%m%d'
|
47
|
+
config_param :hex_random_length, :integer, default: 4
|
44
48
|
config_param :command_parameter, :string, :default => nil
|
49
|
+
config_param :proxy_url, :string, :default => nil
|
50
|
+
config_param :proxy_username, :string, :default => nil
|
51
|
+
config_param :proxy_password, :string, :default => nil, :secret => true
|
52
|
+
config_param :write_only, :bool, :default => false
|
53
|
+
config_param :upload_timestamp_format, :string, :default => '%H%M%S%L'
|
45
54
|
|
46
55
|
DEFAULT_FORMAT_TYPE = "out_file"
|
47
56
|
ACCESS_TOKEN_API_VERSION = "2018-02-01"
|
@@ -51,7 +60,7 @@ module Fluent::Plugin
|
|
51
60
|
config_section :format do
|
52
61
|
config_set_default :@type, DEFAULT_FORMAT_TYPE
|
53
62
|
end
|
54
|
-
|
63
|
+
|
55
64
|
config_section :buffer do
|
56
65
|
config_set_default :chunk_keys, ['time']
|
57
66
|
config_set_default :timekey, (60 * 60 * 24)
|
@@ -74,17 +83,7 @@ module Fluent::Plugin
|
|
74
83
|
end
|
75
84
|
|
76
85
|
@formatter = formatter_create
|
77
|
-
|
78
|
-
if @localtime
|
79
|
-
@path_slicer = Proc.new {|path|
|
80
|
-
Time.now.strftime(path)
|
81
|
-
}
|
82
|
-
else
|
83
|
-
@path_slicer = Proc.new {|path|
|
84
|
-
Time.now.utc.strftime(path)
|
85
|
-
}
|
86
|
-
end
|
87
|
-
|
86
|
+
|
88
87
|
if @azure_container.nil?
|
89
88
|
raise Fluent::ConfigError, "azure_container is needed"
|
90
89
|
end
|
@@ -98,7 +97,7 @@ module Fluent::Plugin
|
|
98
97
|
else
|
99
98
|
@final_file_extension = @compressor.ext
|
100
99
|
end
|
101
|
-
|
100
|
+
@values_for_object_chunk = {}
|
102
101
|
end
|
103
102
|
|
104
103
|
def multi_workers_ready?
|
@@ -110,12 +109,20 @@ module Fluent::Plugin
|
|
110
109
|
if !@skip_container_check
|
111
110
|
if @failsafe_container_check
|
112
111
|
begin
|
113
|
-
|
112
|
+
if @write_only && @auto_create_container
|
113
|
+
create_container
|
114
|
+
else
|
115
|
+
ensure_container
|
116
|
+
end
|
114
117
|
rescue Exception => e
|
115
118
|
log.warn("#{e.message}, container list/create failsafe is enabled. Continue without those operations.")
|
116
119
|
end
|
117
120
|
else
|
118
|
-
|
121
|
+
if @write_only && @auto_create_container
|
122
|
+
create_container
|
123
|
+
else
|
124
|
+
ensure_container
|
125
|
+
end
|
119
126
|
end
|
120
127
|
end
|
121
128
|
super
|
@@ -127,17 +134,16 @@ module Fluent::Plugin
|
|
127
134
|
end
|
128
135
|
|
129
136
|
def write(chunk)
|
130
|
-
metadata = chunk.metadata
|
131
137
|
if @store_as.nil? || @store_as == "none"
|
132
|
-
generate_log_name(
|
138
|
+
generate_log_name(chunk, @current_index)
|
133
139
|
if @last_azure_storage_path != @azure_storage_path
|
134
140
|
@current_index = 0
|
135
|
-
generate_log_name(
|
141
|
+
generate_log_name(chunk, @current_index)
|
136
142
|
end
|
137
143
|
raw_data = chunk.read
|
138
144
|
unless raw_data.empty?
|
139
145
|
log.debug "azurestorage_gen2: processing raw data", chunk_id: dump_unique_id_hex(chunk.unique_id)
|
140
|
-
upload_blob(raw_data,
|
146
|
+
upload_blob(raw_data, chunk)
|
141
147
|
end
|
142
148
|
chunk.close rescue nil
|
143
149
|
@last_azure_storage_path = @azure_storage_path
|
@@ -147,51 +153,76 @@ module Fluent::Plugin
|
|
147
153
|
begin
|
148
154
|
@compressor.compress(chunk, tmp)
|
149
155
|
tmp.rewind
|
150
|
-
generate_log_name(
|
156
|
+
generate_log_name(chunk, @current_index)
|
151
157
|
if @last_azure_storage_path != @azure_storage_path
|
152
158
|
@current_index = 0
|
153
|
-
generate_log_name(
|
159
|
+
generate_log_name(chunk, @current_index)
|
154
160
|
end
|
155
161
|
log.debug "azurestorage_gen2: Start uploading temp file: #{tmp.path}"
|
156
162
|
content = File.open(tmp.path, 'rb') { |file| file.read }
|
157
|
-
upload_blob(content,
|
163
|
+
upload_blob(content, chunk)
|
158
164
|
@last_azure_storage_path = @azure_storage_path
|
159
165
|
ensure
|
160
166
|
tmp.close(true) rescue nil
|
161
167
|
end
|
168
|
+
@values_for_object_chunk.delete(chunk.unique_id)
|
162
169
|
end
|
163
170
|
|
164
171
|
end
|
165
172
|
|
166
173
|
private
|
167
|
-
def upload_blob(content,
|
174
|
+
def upload_blob(content, chunk)
|
168
175
|
log.debug "azurestorage_gen2: Uploading blob: #{@azure_storage_path}"
|
169
|
-
|
170
|
-
if existing_content_length == 0
|
176
|
+
if @write_only
|
171
177
|
create_blob(@azure_storage_path)
|
178
|
+
append_blob(content, chunk, 0)
|
179
|
+
else
|
180
|
+
existing_content_length = get_blob_properties(@azure_storage_path)
|
181
|
+
if existing_content_length == 0
|
182
|
+
create_blob(@azure_storage_path)
|
183
|
+
end
|
184
|
+
append_blob(content, chunk, existing_content_length)
|
172
185
|
end
|
173
|
-
append_blob(content, metadata, existing_content_length)
|
174
186
|
end
|
175
187
|
|
176
188
|
private
|
177
|
-
def generate_log_name(
|
189
|
+
def generate_log_name(chunk, index)
|
190
|
+
metadata = chunk.metadata
|
178
191
|
time_slice = if metadata.timekey.nil?
|
179
192
|
''.freeze
|
180
193
|
else
|
181
194
|
Time.at(metadata.timekey).utc.strftime(@time_slice_format)
|
182
195
|
end
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
196
|
+
if @localtime
|
197
|
+
hms_slicer = Time.now.strftime("%H%M%S")
|
198
|
+
upload_timestamp = Time.now.strftime(@upload_timestamp_format)
|
199
|
+
else
|
200
|
+
hms_slicer = Time.now.utc.strftime("%H%M%S")
|
201
|
+
upload_timestamp = Time.now.utc.strftime(@upload_timestamp_format)
|
202
|
+
end
|
203
|
+
|
204
|
+
@values_for_object_chunk[chunk.unique_id] ||= {
|
205
|
+
"%{hex_random}" => hex_random(chunk),
|
206
|
+
}
|
207
|
+
values_for_object_key_pre = {
|
208
|
+
"%{path}" => @path,
|
187
209
|
"%{index}" => index,
|
188
210
|
"%{uuid_flush}" => uuid_random,
|
189
|
-
"%{file_extension}" => @final_file_extension
|
211
|
+
"%{file_extension}" => @final_file_extension,
|
212
|
+
"%{upload_timestamp}" => upload_timestamp,
|
190
213
|
}
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
214
|
+
values_for_object_key_post = {
|
215
|
+
"%{date_slice}" => time_slice,
|
216
|
+
"%{time_slice}" => time_slice,
|
217
|
+
"%{hms_slice}" => hms_slicer,
|
218
|
+
}.merge!(@values_for_object_chunk[chunk.unique_id])
|
219
|
+
storage_path = @azure_object_key_format.gsub(%r(%{[^}]+})) do |matched_key|
|
220
|
+
values_for_object_key_pre.fetch(matched_key, matched_key)
|
221
|
+
end
|
222
|
+
storage_path = extract_placeholders(storage_path, chunk)
|
223
|
+
storage_path = storage_path.gsub(%r(%{[^}]+}), values_for_object_key_post)
|
224
|
+
storage_path = "/" + storage_path unless storage_path.start_with?("/")
|
225
|
+
@azure_storage_path = storage_path
|
195
226
|
end
|
196
227
|
|
197
228
|
def setup_access_token
|
@@ -243,11 +274,22 @@ module Fluent::Plugin
|
|
243
274
|
# https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/tutorial-linux-vm-access-storage#get-an-access-token-and-use-it-to-call-azure-storage
|
244
275
|
private
|
245
276
|
def acquire_access_token_msi
|
246
|
-
params = { :"api-version" => ACCESS_TOKEN_API_VERSION, :resource => "
|
277
|
+
params = { :"api-version" => ACCESS_TOKEN_API_VERSION, :resource => "#{@url_storage_resource}" }
|
247
278
|
unless @azure_instance_msi.nil?
|
248
279
|
params[:msi_res_id] = @azure_instance_msi
|
249
280
|
end
|
250
|
-
|
281
|
+
unless @azure_client_id.nil?
|
282
|
+
params[:client_id] = @azure_client_id
|
283
|
+
end
|
284
|
+
unless @azure_object_id.nil?
|
285
|
+
params[:object_id] = @azure_object_id
|
286
|
+
end
|
287
|
+
req_opts = {
|
288
|
+
:params => params,
|
289
|
+
:headers => { Metadata: "true" }
|
290
|
+
}
|
291
|
+
add_proxy_options(req_opts)
|
292
|
+
request = Typhoeus::Request.new("http://169.254.169.254/metadata/identity/oauth2/token", req_opts)
|
251
293
|
request.on_complete do |response|
|
252
294
|
if response.success?
|
253
295
|
data = JSON.parse(response.body)
|
@@ -262,10 +304,16 @@ module Fluent::Plugin
|
|
262
304
|
|
263
305
|
private
|
264
306
|
def acquire_access_token_oauth_app
|
265
|
-
params = { :"api-version" => ACCESS_TOKEN_API_VERSION, :resource => "
|
307
|
+
params = { :"api-version" => ACCESS_TOKEN_API_VERSION, :resource => "#{@url_storage_resource}"}
|
266
308
|
headers = {:"Content-Type" => "application/x-www-form-urlencoded"}
|
267
|
-
content = "grant_type=client_credentials&client_id=#{@azure_oauth_app_id}&client_secret=#{@azure_oauth_secret}&resource
|
268
|
-
|
309
|
+
content = "grant_type=client_credentials&client_id=#{@azure_oauth_app_id}&client_secret=#{@azure_oauth_secret}&resource=#{@url_storage_resource}"
|
310
|
+
req_opts = {
|
311
|
+
:params => params,
|
312
|
+
:body => content,
|
313
|
+
:headers => headers
|
314
|
+
}
|
315
|
+
add_proxy_options(req_opts)
|
316
|
+
request = Typhoeus::Request.new("https://login.microsoftonline.com/#{@azure_oauth_tenant_id}/oauth2/token", req_opts)
|
269
317
|
request.on_complete do |response|
|
270
318
|
if response.success?
|
271
319
|
data = JSON.parse(response.body)
|
@@ -280,7 +328,7 @@ module Fluent::Plugin
|
|
280
328
|
|
281
329
|
private
|
282
330
|
def acquire_access_token_by_az
|
283
|
-
access_token=`az account get-access-token --resource
|
331
|
+
access_token=`az account get-access-token --resource #{@url_storage_resource} --query accessToken -o tsv`
|
284
332
|
log.debug "azurestorage_gen2: Token response: #{access_token}"
|
285
333
|
@azure_access_token = access_token.chomp
|
286
334
|
end
|
@@ -292,7 +340,13 @@ module Fluent::Plugin
|
|
292
340
|
params = {:resource => "filesystem" }
|
293
341
|
auth_header = create_auth_header("head", datestamp, "#{@azure_container}", headers, params)
|
294
342
|
headers[:Authorization] = auth_header
|
295
|
-
|
343
|
+
req_opts = {
|
344
|
+
:method => :head,
|
345
|
+
:params => params,
|
346
|
+
:headers => headers
|
347
|
+
}
|
348
|
+
add_proxy_options(req_opts)
|
349
|
+
request = Typhoeus::Request.new("https://#{azure_storage_account}#{@url_domain_suffix}/#{@azure_container}", req_opts)
|
296
350
|
request.on_complete do |response|
|
297
351
|
if response.success?
|
298
352
|
log.info "azurestorage_gen2: Container '#{@azure_container}' exists."
|
@@ -319,7 +373,13 @@ module Fluent::Plugin
|
|
319
373
|
params = {:resource => "filesystem" }
|
320
374
|
auth_header = create_auth_header("put", datestamp, "#{@azure_container}", headers, params)
|
321
375
|
headers[:Authorization] = auth_header
|
322
|
-
|
376
|
+
req_opts = {
|
377
|
+
:method => :put,
|
378
|
+
:params => params,
|
379
|
+
:headers => headers
|
380
|
+
}
|
381
|
+
add_proxy_options(req_opts)
|
382
|
+
request = Typhoeus::Request.new("https://#{azure_storage_account}#{@url_domain_suffix}/#{@azure_container}", req_opts)
|
323
383
|
request.on_complete do |response|
|
324
384
|
if response.success?
|
325
385
|
log.debug "azurestorage_gen2: Container '#{@azure_container}' created, response code: #{response.code}"
|
@@ -339,7 +399,13 @@ module Fluent::Plugin
|
|
339
399
|
params = {:resource => "file", :recursive => "false"}
|
340
400
|
auth_header = create_auth_header("put", datestamp, "#{@azure_container}#{blob_path}", headers, params)
|
341
401
|
headers[:Authorization] = auth_header
|
342
|
-
|
402
|
+
req_opts = {
|
403
|
+
:method => :put,
|
404
|
+
:params => params,
|
405
|
+
:headers => headers
|
406
|
+
}
|
407
|
+
add_proxy_options(req_opts)
|
408
|
+
request = Typhoeus::Request.new("https://#{azure_storage_account}#{@url_domain_suffix}/#{@azure_container}#{blob_path}", req_opts)
|
343
409
|
request.on_complete do |response|
|
344
410
|
if response.success?
|
345
411
|
log.debug "azurestorage_gen2: Blob '#{blob_path}' has been created, response code: #{response.code}"
|
@@ -362,7 +428,14 @@ module Fluent::Plugin
|
|
362
428
|
params = {:action => "append", :position => "#{position}"}
|
363
429
|
auth_header = create_auth_header("patch", datestamp, "#{@azure_container}#{blob_path}", headers, params)
|
364
430
|
headers[:Authorization] = auth_header
|
365
|
-
|
431
|
+
req_opts = {
|
432
|
+
:method => :patch,
|
433
|
+
:params => params,
|
434
|
+
:headers => headers,
|
435
|
+
:body => content
|
436
|
+
}
|
437
|
+
add_proxy_options(req_opts)
|
438
|
+
request = Typhoeus::Request.new("https://#{azure_storage_account}#{@url_domain_suffix}/#{@azure_container}#{blob_path}", req_opts)
|
366
439
|
request.on_complete do |response|
|
367
440
|
if response.success?
|
368
441
|
log.debug "azurestorage_gen2: Blob '#{blob_path}' has been appended, response code: #{response.code}"
|
@@ -387,7 +460,13 @@ module Fluent::Plugin
|
|
387
460
|
params = {:action => "flush", :position => "#{position}"}
|
388
461
|
auth_header = create_auth_header("patch", datestamp, "#{@azure_container}#{blob_path}",headers, params)
|
389
462
|
headers[:Authorization] = auth_header
|
390
|
-
|
463
|
+
req_opts = {
|
464
|
+
:method => :patch,
|
465
|
+
:params => params,
|
466
|
+
:headers => headers
|
467
|
+
}
|
468
|
+
add_proxy_options(req_opts)
|
469
|
+
request = Typhoeus::Request.new("https://#{azure_storage_account}#{@url_domain_suffix}/#{@azure_container}#{blob_path}", req_opts)
|
391
470
|
request.on_complete do |response|
|
392
471
|
if response.success?
|
393
472
|
log.debug "azurestorage_gen2: Blob '#{blob_path}' flush was successful, response code: #{response.code}"
|
@@ -408,7 +487,13 @@ module Fluent::Plugin
|
|
408
487
|
content_length = -1
|
409
488
|
auth_header = create_auth_header("head", datestamp, "#{@azure_container}#{blob_path}", headers, params)
|
410
489
|
headers[:Authorization] = auth_header
|
411
|
-
|
490
|
+
req_opts = {
|
491
|
+
:method => :head,
|
492
|
+
:params => params,
|
493
|
+
:headers => headers
|
494
|
+
}
|
495
|
+
add_proxy_options(req_opts)
|
496
|
+
request = Typhoeus::Request.new("https://#{azure_storage_account}#{@url_domain_suffix}/#{@azure_container}#{blob_path}", req_opts)
|
412
497
|
request.on_complete do |response|
|
413
498
|
if response.success?
|
414
499
|
log.debug "azurestorage_gen2: Get blob properties for '#{blob_path}', response headers: #{response.headers}"
|
@@ -427,7 +512,7 @@ module Fluent::Plugin
|
|
427
512
|
end
|
428
513
|
|
429
514
|
private
|
430
|
-
def append_blob(content,
|
515
|
+
def append_blob(content, chunk, existing_content_length)
|
431
516
|
position = 0
|
432
517
|
log.debug "azurestorage_gen2: append_blob.start: Content size: #{content.length}"
|
433
518
|
loop do
|
@@ -476,6 +561,16 @@ module Fluent::Plugin
|
|
476
561
|
"SharedKey #{@azure_storage_account}:#{signed(method, datestamp, resource, headers, params)}"
|
477
562
|
end
|
478
563
|
end
|
564
|
+
|
565
|
+
private
|
566
|
+
def add_proxy_options(req_opts = {})
|
567
|
+
unless @proxy_url.nil?
|
568
|
+
req_opts[:proxy] = @proxy_url
|
569
|
+
unless @proxy_username.nil? || @proxy_password.nil?
|
570
|
+
req_opts[:proxyuserpwd] = "#{@proxy_username}:#{@proxy_password}"
|
571
|
+
end
|
572
|
+
end
|
573
|
+
end
|
479
574
|
|
480
575
|
private
|
481
576
|
def signed(method, datestamp, resource, headers, params)
|
@@ -545,6 +640,12 @@ module Fluent::Plugin
|
|
545
640
|
require 'uuidtools'
|
546
641
|
::UUIDTools::UUID.random_create.to_s
|
547
642
|
end
|
643
|
+
|
644
|
+
def hex_random(chunk)
|
645
|
+
unique_hex = Fluent::UniqueId.hex(chunk.unique_id)
|
646
|
+
unique_hex.reverse!
|
647
|
+
unique_hex[0...@hex_random_length]
|
648
|
+
end
|
548
649
|
|
549
650
|
def timekey_to_timeformat(timekey)
|
550
651
|
case timekey
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-azurestorage-gen2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oliver Szabo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|