fluent-plugin-azure-storage-append-blob-lts 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e1dca8c31f6ec0f0383d24637d3c0b6225d92e8505387a5c1a422d85057f0340
4
- data.tar.gz: 240d435415a53386a245d3449d092eb2d71a85c2e08e989b841ec71b7a20a9f5
3
+ metadata.gz: 0d55d827bbb8aa8906536f7593257e42abf9c6b24e5aa485176cd5aa15284732
4
+ data.tar.gz: ff055bb2b5585ee3a38b2ed18b75ac1aa8ba6a20654be97b13a920a6566472e5
5
5
  SHA512:
6
- metadata.gz: 7744655dfad7169b43df0db53a20c781276d8dba8a83c2858e1809cb281008e9b401b6755ec6fb0efa4eff0311c2e76fc2d2e60164ffd373ef0087b81fabc9cf
7
- data.tar.gz: 046e1e69571d6502d6c06d52d49c3e97234f4b2a44e15210122941d6787bac825769b40f2c1e70cff926f8d5a6ca9cf916ee2aac42b06a82367c7b9c0f410279
6
+ metadata.gz: ea451b6605f9126c9af9e697cacccac03145631926684ac7d001eb6c18ca22755ec13cd647eb3b016cbed48678b890a61ff829644cfd041ef4c88a7495cf215c
7
+ data.tar.gz: e50e9381970ce666d3bc6337526be2e5620d6eced418b9df02a26d6f80f13ce0fb31a45e0cdef3a55090afc6276c328a660b66137005d17b1756948d77ac7491
data/Dockerfile CHANGED
@@ -1,8 +1,8 @@
1
- FROM ruby:latest
1
+ FROM ruby:2.7
2
2
 
3
3
  WORKDIR /plugin
4
4
 
5
- ADD . /plugin
5
+ COPY . /plugin
6
6
 
7
7
  RUN gem install bundler && \
8
8
  gem install fluentd --no-doc && \
data/README.md CHANGED
@@ -24,6 +24,7 @@ And then execute:
24
24
  <match pattern>
25
25
  type azure-storage-append-blob
26
26
 
27
+ azure_cloud <azure cloud environment>
27
28
  azure_storage_account <your azure storage account>
28
29
  azure_storage_access_key <your azure storage access key> # leave empty to use MSI
29
30
  azure_storage_connection_string <your azure storage connection string> # leave empty to use MSI
@@ -36,6 +37,7 @@ And then execute:
36
37
  path logs/
37
38
  azure_object_key_format %{path}%{time_slice}_%{index}.log
38
39
  time_slice_format %Y%m%d-%H
40
+ calculate_checksums true
39
41
  # if you want to use %{tag} or %Y/%m/%d/ like syntax in path / azure_blob_name_format,
40
42
  # need to specify tag for %{tag} and time for %Y/%m/%d in <buffer> argument.
41
43
  <buffer tag,time>
@@ -47,6 +49,12 @@ And then execute:
47
49
  </buffer>
48
50
  </match>
49
51
 
52
+ ### `azure_cloud` (Optional)
53
+
54
+ Default: `AZUREPUBLICCLOUD`
55
+
56
+ Cloud environment used to determine the storage endpoint suffix to use, see [here](https://github.com/Azure/go-autorest/blob/master/autorest/azure/environments.go).
57
+
50
58
  ### `azure_storage_account` (Required)
51
59
 
52
60
  Your Azure Storage Account Name. This can be retrieved from Azure Management portal.
@@ -60,7 +68,7 @@ If all are empty, the plugin will use the local Managed Identity endpoint to obt
60
68
 
61
69
  ### `azure_imds_api_version` (Optional, only for MSI)
62
70
 
63
- Default: 2019-08-15
71
+ Default: `2019-08-15`
64
72
 
65
73
  The Instance Metadata Service is used during the OAuth flow to obtain an access token. This API is versioned and specifying the version is mandatory.
66
74
 
@@ -68,7 +76,7 @@ See [here](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/instanc
68
76
 
69
77
  ### `azure_token_refresh_interval` (Optional, only for MSI)
70
78
 
71
- Default: 60 (1 hour)
79
+ Default: `60` (1 hour)
72
80
 
73
81
  When using MSI, the initial access token needs to be refreshed periodically.
74
82
 
@@ -82,8 +90,9 @@ Azure Identity Client ID to use for accessing Azure Blob service.
82
90
 
83
91
  ### `auto_create_container`
84
92
 
93
+ Default: `true`
94
+
85
95
  This plugin creates the Azure container if it does not already exist exist when you set 'auto_create_container' to true.
86
- The default value is `true`
87
96
 
88
97
  ### `azure_object_key_format`
89
98
 
@@ -127,6 +136,14 @@ The [fluent-mixin-config-placeholders](https://github.com/tagomoris/fluent-mixin
127
136
 
128
137
  Format of the time used in the file name. Default is '%Y%m%d'. Use '%Y%m%d%H' to split files hourly.
129
138
 
139
+ ### `calculate_checksums`
140
+
141
+ Default: `true`
142
+
143
+ Whether to calculate MD5 checksum of the blob contents during append operation and provide it in a header for the blob service.
144
+
145
+ You want to set it to `false` in FIPS-enabled environments.
146
+
130
147
  ### Run tests
131
148
 
132
149
  gem install bundler
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = 'fluent-plugin-azure-storage-append-blob-lts'
6
- spec.version = '0.5.0'
6
+ spec.version = '0.6.0'
7
7
  spec.authors = ['Jonas-Taha El Sesiy']
8
8
  spec.email = ['github@elsesiy.com']
9
9
 
@@ -11,7 +11,7 @@ require 'json'
11
11
 
12
12
  module Fluent
13
13
  module Plugin
14
- class AzureStorageAppendBlobOut < Fluent::Plugin::Output
14
+ class AzureStorageAppendBlobOut < Output
15
15
  Fluent::Plugin.register_output('azure-storage-append-blob', self)
16
16
 
17
17
  helpers :formatter, :inject
@@ -19,18 +19,32 @@ module Fluent
19
19
  DEFAULT_FORMAT_TYPE = 'out_file'.freeze
20
20
  AZURE_BLOCK_SIZE_LIMIT = 4 * 1024 * 1024 - 1
21
21
 
22
+ def initialize
23
+ super
24
+ @use_msi = false
25
+
26
+ # Storage endpoint suffixes for various environments, see https://github.com/Azure/go-autorest/blob/master/autorest/azure/environments.go
27
+ @storage_endpoint_mapping = {
28
+ 'AZURECHINACLOUD' => 'core.chinacloudapi.cn',
29
+ 'AZUREGERMANCLOUD' => 'core.cloudapi.de',
30
+ 'AZUREPUBLICCLOUD' => 'core.windows.net',
31
+ 'AZUREUSGOVERNMENTCLOUD' => 'core.usgovcloudapi.net'
32
+ }
33
+ end
34
+
22
35
  config_param :path, :string, default: ''
23
36
  config_param :azure_storage_account, :string, default: nil
24
37
  config_param :azure_storage_access_key, :string, default: nil, secret: true
25
- config_param :azure_storage_sas_token, :string, default: nil, secret: true
26
38
  config_param :azure_storage_connection_string, :string, default: nil, secret: true
39
+ config_param :azure_storage_sas_token, :string, default: nil, secret: true
40
+ config_param :azure_cloud, :string, default: 'AZUREPUBLICCLOUD'
27
41
  config_param :azure_msi_client_id, :string, default: nil
28
42
  config_param :azure_container, :string, default: nil
29
43
  config_param :azure_imds_api_version, :string, default: '2019-08-15'
30
44
  config_param :azure_token_refresh_interval, :integer, default: 60
31
- config_param :use_msi, :bool, default: false
32
45
  config_param :azure_object_key_format, :string, default: '%{path}%{time_slice}-%{index}.log'
33
46
  config_param :auto_create_container, :bool, default: true
47
+ config_param :calculate_checksums, :bool, default: true
34
48
  config_param :format, :string, default: DEFAULT_FORMAT_TYPE
35
49
  config_param :time_slice_format, :string, default: '%Y%m%d'
36
50
  config_param :localtime, :bool, default: false
@@ -61,6 +75,11 @@ module Fluent
61
75
  end
62
76
  end
63
77
 
78
+ @azure_storage_dns_suffix = @storage_endpoint_mapping[@azure_cloud]
79
+ if @azure_storage_dns_suffix.nil?
80
+ raise ConfigError 'azure_cloud invalid, must be either of AZURECHINACLOUD, AZUREGERMANCLOUD, AZUREPUBLICCLOUD, AZUREUSGOVERNMENTCLOUD'
81
+ end
82
+
64
83
  if (@azure_storage_access_key.nil? || @azure_storage_access_key.empty?) &&
65
84
  (@azure_storage_sas_token.nil? || @azure_storage_sas_token.empty?) &&
66
85
  (@azure_storage_connection_string.nil? || @azure_storage_connection_string.empty?)
@@ -70,6 +89,12 @@ module Fluent
70
89
  raise ConfigError, 'azure_storage_account needs to be specified' if @azure_storage_account.nil?
71
90
  raise ConfigError, 'azure_container needs to be specified' if @azure_container.nil?
72
91
  end
92
+
93
+ @blob_options = {}
94
+
95
+ if !@calculate_checksums
96
+ @blob_options[:content_md5] = ''
97
+ end
73
98
  end
74
99
 
75
100
  def multi_workers_ready?
@@ -80,13 +105,13 @@ module Fluent
80
105
  access_key_request = Faraday.new('http://169.254.169.254/metadata/identity/oauth2/token?' \
81
106
  "api-version=#{@azure_imds_api_version}" \
82
107
  '&resource=https://storage.azure.com/' \
83
- "#{! azure_msi_client_id.nil? ? "&client_id=#{azure_msi_client_id}" : ''}",
108
+ "#{!azure_msi_client_id.nil? ? "&client_id=#{azure_msi_client_id}" : ''}",
84
109
  headers: { 'Metadata' => 'true' }).get
85
110
 
86
111
  if access_key_request.status == 200
87
112
  JSON.parse(access_key_request.body)['access_token']
88
113
  else
89
- raise "Access token request was not sucssessful. Possibly due to missing azure_msi_client_id config parameter."
114
+ raise 'Access token request was not sucssessful. Possibly due to missing azure_msi_client_id config parameter.'
90
115
  end
91
116
  end
92
117
 
@@ -95,7 +120,11 @@ module Fluent
95
120
  if @use_msi
96
121
  token_credential = Azure::Storage::Common::Core::TokenCredential.new get_access_token
97
122
  token_signer = Azure::Storage::Common::Core::Auth::TokenSigner.new token_credential
98
- @bs = Azure::Storage::Blob::BlobService.new(storage_account_name: @azure_storage_account, signer: token_signer)
123
+ @bs = Azure::Storage::Blob::BlobService.new(
124
+ storage_account_name: @azure_storage_account,
125
+ storage_dns_suffix: @azure_storage_dns_suffix,
126
+ signer: token_signer
127
+ )
99
128
 
100
129
  refresh_interval = @azure_token_refresh_interval * 60
101
130
  cancelled = false
@@ -112,7 +141,7 @@ module Fluent
112
141
  elsif !@azure_storage_connection_string.nil? && !@azure_storage_connection_string.empty?
113
142
  @bs = Azure::Storage::Blob::BlobService.create_from_connection_string(@azure_storage_connection_string)
114
143
  else
115
- @bs_params = { storage_account_name: @azure_storage_account }
144
+ @bs_params = { storage_account_name: @azure_storage_account, storage_dns_suffix: @azure_storage_dns_suffix }
116
145
 
117
146
  if !@azure_storage_access_key.nil? && !@azure_storage_access_key.empty?
118
147
  @bs_params.merge!({ storage_access_key: @azure_storage_access_key })
@@ -152,7 +181,11 @@ module Fluent
152
181
  append_blob(content, metadata)
153
182
  @last_azure_storage_path = @azure_storage_path
154
183
  ensure
155
- tmp.close(true) rescue nil
184
+ begin
185
+ tmp.close(true)
186
+ rescue StandardError
187
+ nil
188
+ end
156
189
  end
157
190
  end
158
191
 
@@ -202,34 +235,32 @@ module Fluent
202
235
  position = 0
203
236
  log.debug "azure_storage_append_blob: append_blob.start: Content size: #{content.length}"
204
237
  loop do
205
- begin
206
- size = [content.length - position, AZURE_BLOCK_SIZE_LIMIT].min
207
- log.debug "azure_storage_append_blob: append_blob.chunk: content[#{position}..#{position + size}]"
208
- @bs.append_blob_block(@azure_container, @azure_storage_path, content[position..position + size - 1])
209
- position += size
210
- break if position >= content.length
211
- rescue Azure::Core::Http::HTTPError => e
212
- status_code = e.status_code
213
-
214
- if status_code == 409 # exceeds azure block limit
215
- @current_index += 1
216
- old_azure_storage_path = @azure_storage_path
217
- generate_log_name(metadata, @current_index)
218
-
219
- # If index is not a part of format, rethrow exception.
220
- if old_azure_storage_path == @azure_storage_path
221
- log.warn 'azure_storage_append_blob: append_blob: blocks limit reached, you need to use %{index} for the format.'
222
- raise
223
- end
224
-
225
- log.debug "azure_storage_append_blob: append_blob: blocks limit reached, creating new blob #{@azure_storage_path}."
226
- @bs.create_append_blob(@azure_container, @azure_storage_path)
227
- elsif status_code == 404 # blob not found
228
- log.debug "azure_storage_append_blob: append_blob: #{@azure_storage_path} blob doesn't exist, creating new blob."
229
- @bs.create_append_blob(@azure_container, @azure_storage_path)
230
- else
238
+ size = [content.length - position, AZURE_BLOCK_SIZE_LIMIT].min
239
+ log.debug "azure_storage_append_blob: append_blob.chunk: content[#{position}..#{position + size}]"
240
+ @bs.append_blob_block(@azure_container, @azure_storage_path, content[position..position + size - 1], options=@blob_options)
241
+ position += size
242
+ break if position >= content.length
243
+ rescue Azure::Core::Http::HTTPError => e
244
+ status_code = e.status_code
245
+
246
+ if status_code == 409 # exceeds azure block limit
247
+ @current_index += 1
248
+ old_azure_storage_path = @azure_storage_path
249
+ generate_log_name(metadata, @current_index)
250
+
251
+ # If index is not a part of format, rethrow exception.
252
+ if old_azure_storage_path == @azure_storage_path
253
+ log.warn 'azure_storage_append_blob: append_blob: blocks limit reached, you need to use %{index} for the format.'
231
254
  raise
232
255
  end
256
+
257
+ log.debug "azure_storage_append_blob: append_blob: blocks limit reached, creating new blob #{@azure_storage_path}."
258
+ @bs.create_append_blob(@azure_container, @azure_storage_path)
259
+ elsif status_code == 404 # blob not found
260
+ log.debug "azure_storage_append_blob: append_blob: #{@azure_storage_path} blob doesn't exist, creating new blob."
261
+ @bs.create_append_blob(@azure_container, @azure_storage_path)
262
+ else
263
+ raise
233
264
  end
234
265
  end
235
266
  log.debug 'azure_storage_append_blob: append_blob.complete'
@@ -11,6 +11,7 @@ class AzureStorageAppendBlobOutTest < Test::Unit::TestCase
11
11
  end
12
12
 
13
13
  CONFIG = %(
14
+ azure_cloud AZUREGERMANCLOUD
14
15
  azure_storage_account test_storage_account
15
16
  azure_storage_access_key MY_FAKE_SECRET
16
17
  azure_container test_container
@@ -55,6 +56,7 @@ class AzureStorageAppendBlobOutTest < Test::Unit::TestCase
55
56
 
56
57
  test 'config with access key should set instance variables' do
57
58
  d = create_driver
59
+ assert_equal 'core.cloudapi.de', d.instance.instance_variable_get(:@azure_storage_dns_suffix)
58
60
  assert_equal 'test_storage_account', d.instance.azure_storage_account
59
61
  assert_equal 'MY_FAKE_SECRET', d.instance.azure_storage_access_key
60
62
  assert_equal 'test_container', d.instance.azure_container
@@ -66,7 +68,7 @@ class AzureStorageAppendBlobOutTest < Test::Unit::TestCase
66
68
  d = create_driver conf: MSI_CONFIG
67
69
  assert_equal 'test_storage_account', d.instance.azure_storage_account
68
70
  assert_equal 'test_container', d.instance.azure_container
69
- assert_equal true, d.instance.use_msi
71
+ assert_equal true, d.instance.instance_variable_get(:@use_msi)
70
72
  assert_equal true, d.instance.auto_create_container
71
73
  assert_equal '%{path}%{time_slice}-%{index}.log', d.instance.azure_object_key_format
72
74
  assert_equal 120, d.instance.azure_token_refresh_interval
@@ -76,7 +78,7 @@ class AzureStorageAppendBlobOutTest < Test::Unit::TestCase
76
78
  test 'config with connection string should set instance variables' do
77
79
  d = create_driver conf: CONNSTR_CONFIG
78
80
  assert_equal 'https://test', d.instance.azure_storage_connection_string
79
- assert_equal false, d.instance.use_msi
81
+ assert_equal false, d.instance.instance_variable_get(:@use_msi)
80
82
  assert_equal true, d.instance.auto_create_container
81
83
  end
82
84
  end
@@ -122,11 +124,11 @@ class AzureStorageAppendBlobOutTest < Test::Unit::TestCase
122
124
  end
123
125
  attr_reader :blocks
124
126
 
125
- def append_blob_block(container, path, data)
127
+ def append_blob_block(_container, _path, data, options={})
126
128
  @blocks.append(data)
127
129
  end
128
130
 
129
- def get_container_properties(container)
131
+ def get_container_properties(_container)
130
132
  unless @response.status_code == 200
131
133
  raise Azure::Core::Http::HTTPError.new(@response)
132
134
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-azure-storage-append-blob-lts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonas-Taha El Sesiy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-31 00:00:00.000000000 Z
11
+ date: 2021-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler