fluent-plugin-kusto 0.0.1.beta
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 +7 -0
- data/Gemfile +8 -0
- data/LICENSE +21 -0
- data/README.md +201 -0
- data/lib/fluent/plugin/auth/aad_tokenprovider.rb +105 -0
- data/lib/fluent/plugin/auth/azcli_tokenprovider.rb +51 -0
- data/lib/fluent/plugin/auth/mi_tokenprovider.rb +92 -0
- data/lib/fluent/plugin/auth/tokenprovider_base.rb +57 -0
- data/lib/fluent/plugin/auth/wif_tokenprovider.rb +50 -0
- data/lib/fluent/plugin/client.rb +155 -0
- data/lib/fluent/plugin/conffile.rb +155 -0
- data/lib/fluent/plugin/ingester.rb +136 -0
- data/lib/fluent/plugin/kusto_error_handler.rb +126 -0
- data/lib/fluent/plugin/kusto_query.rb +67 -0
- data/lib/fluent/plugin/out_kusto.rb +423 -0
- data/test/helper.rb +9 -0
- data/test/plugin/test_azcli_tokenprovider.rb +37 -0
- data/test/plugin/test_e2e_kusto.rb +683 -0
- data/test/plugin/test_out_kusto_config.rb +86 -0
- data/test/plugin/test_out_kusto_format.rb +280 -0
- data/test/plugin/test_out_kusto_process.rb +150 -0
- data/test/plugin/test_out_kusto_start.rb +429 -0
- data/test/plugin/test_out_kusto_try_write.rb +382 -0
- data/test/plugin/test_out_kusto_write.rb +370 -0
- metadata +171 -0
@@ -0,0 +1,429 @@
|
|
1
|
+
# rubocop:disable all
|
2
|
+
|
3
|
+
require_relative '../helper'
|
4
|
+
require 'fluent/plugin/out_kusto'
|
5
|
+
require 'mocha/test_unit'
|
6
|
+
|
7
|
+
# Dummy classes for use in tests
|
8
|
+
OutputConfigurationDummy = Class.new do
|
9
|
+
def initialize(*_args)
|
10
|
+
dummy = Object.new
|
11
|
+
def dummy.method_missing(name, *_args)
|
12
|
+
name == :logger ? Logger.new(nil) : 'dummy_value'
|
13
|
+
end
|
14
|
+
|
15
|
+
def dummy.respond_to_missing?(name, include_private = false)
|
16
|
+
name == :logger || super
|
17
|
+
end
|
18
|
+
AadTokenProvider.new(dummy).send(:post_token_request)
|
19
|
+
end
|
20
|
+
|
21
|
+
def logger
|
22
|
+
Logger.new(nil)
|
23
|
+
end
|
24
|
+
|
25
|
+
def table_name
|
26
|
+
'testtable'
|
27
|
+
end
|
28
|
+
|
29
|
+
def database_name
|
30
|
+
'testdb'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
IngesterDummy = Class.new do
|
34
|
+
def initialize(*args); end
|
35
|
+
end
|
36
|
+
TestIngesterMock1 = Class.new { def initialize(config); end }
|
37
|
+
TestIngesterMock2 = Class.new { def initialize(config); end }
|
38
|
+
TestIngesterMock3 = Class.new do
|
39
|
+
@called_with = nil
|
40
|
+
def initialize(config)
|
41
|
+
self.class.called_with = config
|
42
|
+
end
|
43
|
+
|
44
|
+
class << self
|
45
|
+
attr_reader :called_with
|
46
|
+
end
|
47
|
+
|
48
|
+
class << self
|
49
|
+
attr_writer :called_with
|
50
|
+
end
|
51
|
+
end
|
52
|
+
TestIngesterMock4 = Class.new { def initialize(config); end }
|
53
|
+
TestIngesterMock5 = Class.new { def initialize(config); end }
|
54
|
+
TestIngesterMock6 = Class.new { def initialize(config); end }
|
55
|
+
TestIngesterMock7 = Class.new { def initialize(config); end }
|
56
|
+
|
57
|
+
class KustoOutputStartTest < Test::Unit::TestCase
|
58
|
+
def setup
|
59
|
+
Fluent::Test.setup
|
60
|
+
@conf = <<-CONF
|
61
|
+
@type kusto
|
62
|
+
endpoint https://example.kusto.windows.net
|
63
|
+
database_name testdb
|
64
|
+
table_name testtable
|
65
|
+
client_id dummy-client-id
|
66
|
+
client_secret dummy-secret
|
67
|
+
tenant_id dummy-tenant
|
68
|
+
buffered true
|
69
|
+
auth_type aad
|
70
|
+
CONF
|
71
|
+
@aad_token_stub = { 'access_token' => 'fake', 'expires_in' => 3600 }
|
72
|
+
AadTokenProvider.any_instance.stubs(:post_token_request).returns(@aad_token_stub)
|
73
|
+
end
|
74
|
+
|
75
|
+
test 'plugin initializes and starts successfully with valid config' do
|
76
|
+
output_config_mock = mock
|
77
|
+
output_config_mock.stubs(:logger).returns(Logger.new(nil))
|
78
|
+
output_config_mock.stubs(:table_name).returns('testtable')
|
79
|
+
output_config_mock.stubs(:database_name).returns('testdb')
|
80
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
81
|
+
Object.const_set(:OutputConfiguration, Class.new)
|
82
|
+
OutputConfiguration.stubs(:new).returns(output_config_mock)
|
83
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
84
|
+
Object.const_set(:Ingester, TestIngesterMock1)
|
85
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
86
|
+
assert_nothing_raised { driver.instance.start }
|
87
|
+
assert_equal output_config_mock.logger, driver.instance.instance_variable_get(:@logger)
|
88
|
+
end
|
89
|
+
|
90
|
+
test 'start propagates error if OutputConfiguration.new fails' do
|
91
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
92
|
+
Object.const_set(:OutputConfiguration, Class.new)
|
93
|
+
OutputConfiguration.stubs(:new).raises(StandardError, 'init failed')
|
94
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
95
|
+
Object.const_set(:Ingester, TestIngesterMock2)
|
96
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
97
|
+
assert_raise(StandardError, 'init failed') { driver.instance.start }
|
98
|
+
end
|
99
|
+
|
100
|
+
test 'start initializes OutputConfiguration and Ingester with expected arguments' do
|
101
|
+
output_config_mock = mock
|
102
|
+
output_config_mock.stubs(:logger).returns(Logger.new(nil))
|
103
|
+
output_config_mock.stubs(:table_name).returns('testtable')
|
104
|
+
output_config_mock.stubs(:database_name).returns('testdb')
|
105
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
106
|
+
Object.const_set(:OutputConfiguration, Class.new)
|
107
|
+
OutputConfiguration.stubs(:new).returns(output_config_mock)
|
108
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
109
|
+
Object.const_set(:Ingester, TestIngesterMock3)
|
110
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
111
|
+
driver.instance.start
|
112
|
+
assert_equal output_config_mock, TestIngesterMock3.called_with,
|
113
|
+
'Ingester should be initialized with OutputConfiguration'
|
114
|
+
end
|
115
|
+
|
116
|
+
test 'start sets logger from OutputConfiguration' do
|
117
|
+
output_config_mock = mock
|
118
|
+
logger_mock = mock
|
119
|
+
output_config_mock.stubs(:logger).returns(logger_mock)
|
120
|
+
output_config_mock.stubs(:table_name).returns('testtable')
|
121
|
+
output_config_mock.stubs(:database_name).returns('testdb')
|
122
|
+
TestIngesterMock4 = Class.new { def initialize(config); end }
|
123
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
124
|
+
Object.const_set(:OutputConfiguration, Class.new)
|
125
|
+
OutputConfiguration.stubs(:new).returns(output_config_mock)
|
126
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
127
|
+
Object.const_set(:Ingester, TestIngesterMock4)
|
128
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
129
|
+
driver.instance.start
|
130
|
+
assert_equal logger_mock, driver.instance.instance_variable_get(:@logger)
|
131
|
+
end
|
132
|
+
|
133
|
+
test 'start is idempotent (multiple calls do not error)' do
|
134
|
+
output_config_mock = mock
|
135
|
+
output_config_mock.stubs(:logger).returns(Logger.new(nil))
|
136
|
+
output_config_mock.stubs(:table_name).returns('testtable')
|
137
|
+
output_config_mock.stubs(:database_name).returns('testdb')
|
138
|
+
TestIngesterMock5 = Class.new { def initialize(config); end }
|
139
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
140
|
+
Object.const_set(:OutputConfiguration, Class.new)
|
141
|
+
OutputConfiguration.stubs(:new).returns(output_config_mock)
|
142
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
143
|
+
Object.const_set(:Ingester, TestIngesterMock5)
|
144
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
145
|
+
assert_nothing_raised { driver.instance.start }
|
146
|
+
assert_nothing_raised { driver.instance.start }
|
147
|
+
end
|
148
|
+
|
149
|
+
test 'start cleans up resources on shutdown' do
|
150
|
+
output_config_mock = mock
|
151
|
+
output_config_mock.stubs(:logger).returns(Logger.new(nil))
|
152
|
+
output_config_mock.stubs(:table_name).returns('testtable')
|
153
|
+
output_config_mock.stubs(:database_name).returns('testdb')
|
154
|
+
output_config_mock.stubs(:kusto_endpoint).returns('https://example.kusto.windows.net')
|
155
|
+
output_config_mock.stubs(:access_token).returns('fake-access-token')
|
156
|
+
ingester_mock = mock
|
157
|
+
ingester_mock.stubs(:access_token).returns('fake-access-token')
|
158
|
+
ingester_mock.expects(:shutdown).once
|
159
|
+
# Add client and token_provider mocks for shutdown
|
160
|
+
client_mock = mock
|
161
|
+
token_provider_mock = mock
|
162
|
+
token_provider_mock.stubs(:fetch_token).returns('fake-access-token')
|
163
|
+
client_mock.stubs(:token_provider).returns(token_provider_mock)
|
164
|
+
ingester_mock.stubs(:client).returns(client_mock)
|
165
|
+
ingester_mock.stubs(:token_provider).returns(token_provider_mock)
|
166
|
+
TestIngesterMock6 = Class.new { def initialize(config); end }
|
167
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
168
|
+
Object.const_set(:OutputConfiguration, Class.new)
|
169
|
+
OutputConfiguration.stubs(:new).returns(output_config_mock)
|
170
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
171
|
+
Object.const_set(:Ingester, TestIngesterMock6)
|
172
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
173
|
+
driver.instance.start
|
174
|
+
driver.instance.instance_variable_set(:@ingester, ingester_mock)
|
175
|
+
driver.instance.shutdown
|
176
|
+
end
|
177
|
+
|
178
|
+
test 'start is thread-safe in multi-worker environment' do
|
179
|
+
output_config_mock = mock
|
180
|
+
output_config_mock.stubs(:logger).returns(Logger.new(nil))
|
181
|
+
output_config_mock.stubs(:table_name).returns('testtable')
|
182
|
+
output_config_mock.stubs(:database_name).returns('testdb')
|
183
|
+
TestIngesterMock7 = Class.new { def initialize(config); end }
|
184
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
185
|
+
Object.const_set(:OutputConfiguration, Class.new)
|
186
|
+
OutputConfiguration.stubs(:new).returns(output_config_mock)
|
187
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
188
|
+
Object.const_set(:Ingester, TestIngesterMock7)
|
189
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
190
|
+
threads = []
|
191
|
+
5.times { threads << Thread.new { assert_nothing_raised { driver.instance.start } } }
|
192
|
+
threads.each(&:join)
|
193
|
+
end
|
194
|
+
|
195
|
+
test 'start triggers authentication logic and handles failures' do
|
196
|
+
AadTokenProvider.any_instance.stubs(:post_token_request).raises(StandardError, 'auth failed')
|
197
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
198
|
+
Object.const_set(:OutputConfiguration, OutputConfigurationDummy)
|
199
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
200
|
+
Object.const_set(:Ingester, IngesterDummy)
|
201
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
202
|
+
assert_raise(StandardError, 'auth failed') { driver.instance.start }
|
203
|
+
end
|
204
|
+
|
205
|
+
test 'start passes all config params to OutputConfiguration' do
|
206
|
+
output_config_mock = mock
|
207
|
+
output_config_mock.stubs(:logger).returns(Logger.new(nil))
|
208
|
+
output_config_mock.stubs(:table_name).returns('testtable')
|
209
|
+
output_config_mock.stubs(:database_name).returns('testdb')
|
210
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
211
|
+
Object.const_set(:OutputConfiguration, Class.new)
|
212
|
+
OutputConfiguration.expects(:new).with(
|
213
|
+
has_entries(
|
214
|
+
client_app_id: 'dummy-client-id',
|
215
|
+
client_app_secret: 'dummy-secret',
|
216
|
+
tenant_id: 'dummy-tenant',
|
217
|
+
kusto_endpoint: 'https://example.kusto.windows.net',
|
218
|
+
database_name: 'testdb',
|
219
|
+
table_name: 'testtable',
|
220
|
+
azure_cloud: 'AzureCloud',
|
221
|
+
managed_identity_client_id: nil
|
222
|
+
)
|
223
|
+
).returns(output_config_mock)
|
224
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
225
|
+
Object.const_set(:Ingester, TestIngesterMock1)
|
226
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
227
|
+
assert_nothing_raised { driver.instance.start }
|
228
|
+
end
|
229
|
+
|
230
|
+
test 'start raises Fluent::ConfigError if required config missing' do
|
231
|
+
bad_conf = <<-CONF
|
232
|
+
@type kusto
|
233
|
+
endpoint https://example.kusto.windows.net
|
234
|
+
# database_name missing
|
235
|
+
table_name testtable
|
236
|
+
client_id dummy-client-id
|
237
|
+
client_secret dummy-secret
|
238
|
+
tenant_id dummy-tenant
|
239
|
+
buffered true
|
240
|
+
auth_type aad
|
241
|
+
CONF
|
242
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput)
|
243
|
+
assert_raise(Fluent::ConfigError) { driver.configure(bad_conf) }
|
244
|
+
end
|
245
|
+
|
246
|
+
test 'start sets plugin state variables' do
|
247
|
+
output_config_mock = mock
|
248
|
+
output_config_mock.stubs(:logger).returns(Logger.new(nil))
|
249
|
+
output_config_mock.stubs(:table_name).returns('testtable')
|
250
|
+
output_config_mock.stubs(:database_name).returns('testdb')
|
251
|
+
output_config_mock.stubs(:kusto_endpoint).returns('https://example.kusto.windows.net')
|
252
|
+
output_config_mock.stubs(:access_token).returns('fake-access-token')
|
253
|
+
# Add stubs for required AAD fields
|
254
|
+
output_config_mock.stubs(:client_app_id).returns('dummy-client-id')
|
255
|
+
output_config_mock.stubs(:client_app_secret).returns('dummy-secret')
|
256
|
+
output_config_mock.stubs(:tenant_id).returns('dummy-tenant')
|
257
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
258
|
+
Object.const_set(:OutputConfiguration, Class.new)
|
259
|
+
OutputConfiguration.stubs(:new).returns(output_config_mock)
|
260
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
261
|
+
Object.const_set(:Ingester, TestIngesterMock1)
|
262
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
263
|
+
driver.instance.start
|
264
|
+
assert_not_nil driver.instance.instance_variable_get(:@plugin_start_time)
|
265
|
+
assert_equal 0, driver.instance.instance_variable_get(:@total_bytes_ingested)
|
266
|
+
assert_equal 'testtable', driver.instance.instance_variable_get(:@table_name)
|
267
|
+
assert_equal 'testdb', driver.instance.instance_variable_get(:@database_name)
|
268
|
+
end
|
269
|
+
|
270
|
+
test 'start raises error for invalid azure_cloud value' do
|
271
|
+
conf = <<-CONF
|
272
|
+
@type kusto
|
273
|
+
endpoint https://example.kusto.windows.net
|
274
|
+
database_name testdb
|
275
|
+
table_name testtable
|
276
|
+
client_id dummy-client-id
|
277
|
+
client_secret dummy-secret
|
278
|
+
tenant_id dummy-tenant
|
279
|
+
buffered true
|
280
|
+
azure_cloud InvalidCloud
|
281
|
+
auth_type aad
|
282
|
+
CONF
|
283
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput)
|
284
|
+
driver.configure(conf)
|
285
|
+
assert_raise(ArgumentError) { driver.instance.start }
|
286
|
+
end
|
287
|
+
|
288
|
+
test 'start handles missing logger in OutputConfiguration' do
|
289
|
+
output_config_mock = mock
|
290
|
+
output_config_mock.stubs(:logger).returns(nil)
|
291
|
+
output_config_mock.stubs(:table_name).returns('testtable')
|
292
|
+
output_config_mock.stubs(:database_name).returns('testdb')
|
293
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
294
|
+
Object.const_set(:OutputConfiguration, Class.new)
|
295
|
+
OutputConfiguration.stubs(:new).returns(output_config_mock)
|
296
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
297
|
+
Object.const_set(:Ingester, TestIngesterMock1)
|
298
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
299
|
+
assert_nothing_raised { driver.instance.start }
|
300
|
+
assert_nil driver.instance.instance_variable_get(:@logger)
|
301
|
+
end
|
302
|
+
|
303
|
+
test 'start raises error if OutputConfiguration returns nil for required fields' do
|
304
|
+
output_config_mock = mock
|
305
|
+
output_config_mock.stubs(:logger).returns(Logger.new(nil))
|
306
|
+
output_config_mock.stubs(:table_name).returns(nil)
|
307
|
+
output_config_mock.stubs(:database_name).returns(nil)
|
308
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
309
|
+
Object.const_set(:OutputConfiguration, Class.new)
|
310
|
+
OutputConfiguration.stubs(:new).returns(output_config_mock)
|
311
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
312
|
+
Object.const_set(:Ingester, TestIngesterMock1)
|
313
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
314
|
+
driver.instance.start
|
315
|
+
assert_nil driver.instance.instance_variable_get(:@table_name)
|
316
|
+
assert_nil driver.instance.instance_variable_get(:@database_name)
|
317
|
+
end
|
318
|
+
|
319
|
+
test 'start raises error if Ingester initialization fails' do
|
320
|
+
output_config_mock = mock
|
321
|
+
output_config_mock.stubs(:logger).returns(Logger.new(nil))
|
322
|
+
output_config_mock.stubs(:table_name).returns('testtable')
|
323
|
+
output_config_mock.stubs(:database_name).returns('testdb')
|
324
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
325
|
+
Object.const_set(:OutputConfiguration, Class.new)
|
326
|
+
OutputConfiguration.stubs(:new).returns(output_config_mock)
|
327
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
328
|
+
failing_ingester = Class.new { def initialize(_); raise 'ingester failed'; end }
|
329
|
+
Object.const_set(:Ingester, failing_ingester)
|
330
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
331
|
+
assert_raise(RuntimeError, 'ingester failed') { driver.instance.start }
|
332
|
+
end
|
333
|
+
|
334
|
+
test 'start with minimal required config succeeds' do
|
335
|
+
minimal_conf = <<-CONF
|
336
|
+
@type kusto
|
337
|
+
endpoint https://example.kusto.windows.net
|
338
|
+
database_name testdb
|
339
|
+
auth_type aad
|
340
|
+
table_name testtable
|
341
|
+
buffered true
|
342
|
+
CONF
|
343
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput)
|
344
|
+
assert_nothing_raised { driver.configure(minimal_conf); driver.instance.start }
|
345
|
+
end
|
346
|
+
|
347
|
+
test 'start with managed identity only and no AAD params' do
|
348
|
+
mi_conf = <<-CONF
|
349
|
+
@type kusto
|
350
|
+
endpoint https://example.kusto.windows.net
|
351
|
+
database_name testdb
|
352
|
+
table_name testtable
|
353
|
+
buffered true
|
354
|
+
auth_type user_managed_identity
|
355
|
+
managed_identity_client_id test-mi-id
|
356
|
+
CONF
|
357
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput)
|
358
|
+
assert_nothing_raised { driver.configure(mi_conf); driver.instance.start }
|
359
|
+
end
|
360
|
+
|
361
|
+
test 'start sets correct default values for optional config params' do
|
362
|
+
conf = <<-CONF
|
363
|
+
@type kusto
|
364
|
+
endpoint https://example.kusto.windows.net
|
365
|
+
database_name testdb
|
366
|
+
table_name testtable
|
367
|
+
auth_type system_managed_identity
|
368
|
+
buffered true
|
369
|
+
CONF
|
370
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput)
|
371
|
+
driver.configure(conf)
|
372
|
+
assert_equal false, driver.instance.delayed
|
373
|
+
assert_equal 'AzureCloud', driver.instance.azure_cloud
|
374
|
+
end
|
375
|
+
|
376
|
+
test 'start with extra unknown config params does not error' do
|
377
|
+
conf = <<-CONF
|
378
|
+
@type kusto
|
379
|
+
endpoint https://example.kusto.windows.net
|
380
|
+
database_name testdb
|
381
|
+
table_name testtable
|
382
|
+
buffered true
|
383
|
+
auth_type aad
|
384
|
+
unknown_param some_value
|
385
|
+
CONF
|
386
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput)
|
387
|
+
assert_nothing_raised { driver.configure(conf); driver.instance.start }
|
388
|
+
end
|
389
|
+
|
390
|
+
test 'start after shutdown does not reinitialize resources' do
|
391
|
+
output_config_mock = mock
|
392
|
+
output_config_mock.stubs(:logger).returns(Logger.new(nil))
|
393
|
+
output_config_mock.stubs(:table_name).returns('testtable')
|
394
|
+
output_config_mock.stubs(:database_name).returns('testdb')
|
395
|
+
output_config_mock.stubs(:kusto_endpoint).returns('https://example.kusto.windows.net')
|
396
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
397
|
+
Object.const_set(:OutputConfiguration, Class.new)
|
398
|
+
OutputConfiguration.stubs(:new).returns(output_config_mock)
|
399
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
400
|
+
Object.const_set(:Ingester, TestIngesterMock1)
|
401
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
402
|
+
driver.instance.start
|
403
|
+
driver.instance.shutdown
|
404
|
+
assert_nothing_raised { driver.instance.start }
|
405
|
+
end
|
406
|
+
|
407
|
+
test 'start raises error if OutputConfiguration is nil' do
|
408
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
409
|
+
Object.const_set(:OutputConfiguration, Class.new)
|
410
|
+
OutputConfiguration.stubs(:new).returns(nil)
|
411
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
412
|
+
Object.const_set(:Ingester, TestIngesterMock1)
|
413
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
414
|
+
assert_raise(NoMethodError) { driver.instance.start }
|
415
|
+
end
|
416
|
+
|
417
|
+
test 'start raises error if Ingester class is missing' do
|
418
|
+
output_config_mock = mock
|
419
|
+
output_config_mock.stubs(:logger).returns(Logger.new(nil))
|
420
|
+
output_config_mock.stubs(:table_name).returns('testtable')
|
421
|
+
output_config_mock.stubs(:database_name).returns('testdb')
|
422
|
+
Object.send(:remove_const, :OutputConfiguration) if Object.const_defined?(:OutputConfiguration)
|
423
|
+
Object.const_set(:OutputConfiguration, Class.new)
|
424
|
+
OutputConfiguration.stubs(:new).returns(output_config_mock)
|
425
|
+
Object.send(:remove_const, :Ingester) if Object.const_defined?(:Ingester)
|
426
|
+
driver = Fluent::Test::Driver::Output.new(Fluent::Plugin::KustoOutput).configure(@conf)
|
427
|
+
assert_raise(NameError) { driver.instance.start }
|
428
|
+
end
|
429
|
+
end
|