fluent-plugin-gcloud-pubsub-universe-domain 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.
@@ -0,0 +1,375 @@
1
+ # coding: utf-8
2
+ require_relative "../helper"
3
+ require 'fluent/plugin/compressable'
4
+ require "fluent/test/driver/output"
5
+ require "fluent/test/helpers"
6
+ require 'json'
7
+ require 'msgpack'
8
+
9
+ class GcloudPubSubOutputTest < Test::Unit::TestCase
10
+ include Fluent::Test::Helpers
11
+ include Fluent::Plugin::Compressable
12
+
13
+ CONFIG = %[
14
+ project project-test
15
+ topic topic-test
16
+ key key-test
17
+ ]
18
+
19
+ ReRaisedError = Class.new(RuntimeError)
20
+
21
+ def create_driver(conf = CONFIG)
22
+ Fluent::Test::Driver::Output.new(Fluent::Plugin::GcloudPubSubOutput).configure(conf)
23
+ end
24
+
25
+ setup do
26
+ Fluent::Test.setup
27
+ end
28
+
29
+ setup do
30
+ @time = event_time('2016-07-09 11:12:13 UTC')
31
+ end
32
+
33
+ sub_test_case 'configure' do
34
+ test 'default values are configured' do
35
+ d = create_driver(%[
36
+ project project-test
37
+ topic topic-test
38
+ key key-test
39
+ ])
40
+
41
+ assert_equal('project-test', d.instance.project)
42
+ assert_equal('topic-test', d.instance.topic)
43
+ assert_equal('key-test', d.instance.key)
44
+ assert_equal(false, d.instance.autocreate_topic)
45
+ assert_equal(1000, d.instance.max_messages)
46
+ assert_equal(9800000, d.instance.max_total_size)
47
+ assert_equal(4000000, d.instance.max_message_size)
48
+ assert_equal(nil, d.instance.universe_domain)
49
+ end
50
+
51
+ test '"universe_domain" can be specified' do
52
+ d = create_driver(%[
53
+ project project-test
54
+ topic topic-test
55
+ key key-test
56
+ universe_domain universe-domain-test
57
+ ])
58
+
59
+ assert_equal("universe-domain-test", d.instance.universe_domain)
60
+ end
61
+
62
+ test '"topic" must be specified' do
63
+ assert_raises Fluent::ConfigError do
64
+ create_driver(%[
65
+ project project-test
66
+ key key-test
67
+ ])
68
+ end
69
+ end
70
+
71
+ test '"autocreate_topic" can be specified' do
72
+ d = create_driver(%[
73
+ project project-test
74
+ topic topic-test
75
+ key key-test
76
+ autocreate_topic true
77
+ ])
78
+
79
+ assert_equal(true, d.instance.autocreate_topic)
80
+ end
81
+
82
+ test '"dest_project" can be specified' do
83
+ d = create_driver(%[
84
+ project project-test
85
+ topic topic-test
86
+ key key-test
87
+ dest_project dest-project-test
88
+ ])
89
+
90
+ assert_equal("dest-project-test", d.instance.dest_project)
91
+ end
92
+ end
93
+
94
+ sub_test_case 'topic' do
95
+ setup do
96
+ @publisher = mock!
97
+ @pubsub_mock = mock!
98
+ stub(Google::Cloud::Pubsub).new { @pubsub_mock }
99
+
100
+ @old_report_on_exception = Thread.report_on_exception
101
+ Thread.report_on_exception = false
102
+ end
103
+
104
+ teardown do
105
+ Thread.report_on_exception = @old_report_on_exception
106
+ end
107
+
108
+ test '"autocreate_topic" is enabled' do
109
+ d = create_driver(%[
110
+ project project-test
111
+ topic topic-test
112
+ key key-test
113
+ autocreate_topic true
114
+ ])
115
+
116
+ publish_called = false
117
+ @publisher.publish.once { publish_called = true }
118
+ @pubsub_mock.publisher("topic-test").once do
119
+ raise Google::Cloud::NotFoundError.new('TEST')
120
+ end
121
+ @topic_admin_mock = Object.new
122
+ def @topic_admin_mock.create_topic(topic:)
123
+ Object.new
124
+ end
125
+ @pubsub_mock.topic_admin.once { @topic_admin_mock }
126
+ @pubsub_mock.topic_path("topic-test").once { "projects/project-test/topics/topic-test" }
127
+ @pubsub_mock.service.once { Object.new }
128
+ stub(Fluent::GcloudPubSub::Publisher).from_grpc(anything, anything) { @publisher }
129
+
130
+ d.run(default_tag: "test") do
131
+ d.feed(@time, {"a" => "b"})
132
+ end
133
+
134
+ assert_true publish_called, "publish was not called after topic creation"
135
+ end
136
+
137
+ test '"dest_project" is set' do
138
+ d = create_driver(%[
139
+ project project-test
140
+ topic topic-test
141
+ key key-test
142
+ dest_project dest-project-test
143
+ ])
144
+
145
+ @publisher.publish.once
146
+ @pubsub_mock.publisher("topic-test", project: "dest-project-test").once { @publisher }
147
+ d.run(default_tag: "test") do
148
+ d.feed(@time, {"a" => "b"})
149
+ end
150
+ end
151
+
152
+ test '40x error occurred on connecting to Pub/Sub' do
153
+ d = create_driver
154
+
155
+ @pubsub_mock.publisher('topic-test').once do
156
+ raise Google::Cloud::NotFoundError.new('TEST')
157
+ end
158
+
159
+ assert_raise Fluent::GcloudPubSub::Error do
160
+ d.run(default_tag: "test") do
161
+ d.feed(@time, {"a" => "b"})
162
+ end
163
+ end
164
+ end
165
+
166
+ test '50x error occurred on connecting to Pub/Sub' do
167
+ d = create_driver
168
+
169
+ @pubsub_mock.publisher('topic-test').once do
170
+ raise Google::Cloud::UnavailableError.new('TEST')
171
+ end
172
+
173
+ assert_raise Fluent::GcloudPubSub::RetryableError do
174
+ d.run(default_tag: "test") do
175
+ d.feed(@time, {"a" => "b"})
176
+ end
177
+ end
178
+ end
179
+
180
+ test 'topic is nil' do
181
+ d = create_driver
182
+
183
+ @pubsub_mock.publisher('topic-test').once do
184
+ raise Google::Cloud::NotFoundError.new('TEST')
185
+ end
186
+
187
+ assert_raise Fluent::GcloudPubSub::Error do
188
+ d.run(default_tag: "test") do
189
+ d.feed(@time, {"a" => "b"})
190
+ end
191
+ end
192
+ end
193
+
194
+ test 'messages exceeding "max_message_size" are not published' do
195
+ d = create_driver(%[
196
+ project project-test
197
+ topic topic-test
198
+ key key-test
199
+ max_message_size 1000
200
+ ])
201
+
202
+ @publisher.publish.times(0)
203
+ d.run(default_tag: "test") do
204
+ d.feed(@time, {"a" => "a" * 1000})
205
+ end
206
+ end
207
+ end
208
+
209
+ sub_test_case 'publish' do
210
+ setup do
211
+ @publisher = mock!
212
+ @pubsub_mock = mock!.publisher(anything) { @publisher }
213
+ stub(Google::Cloud::Pubsub).new { @pubsub_mock }
214
+
215
+ @old_report_on_exception = Thread.report_on_exception
216
+ Thread.report_on_exception = false
217
+ end
218
+
219
+ teardown do
220
+ Thread.report_on_exception = @old_report_on_exception
221
+ end
222
+
223
+ test 'messages are divided into "max_messages"' do
224
+ d = create_driver
225
+ @publisher.publish.times(2)
226
+ d.run(default_tag: "test") do
227
+ # max_messages is default 1000
228
+ 1001.times do |i|
229
+ d.feed(@time, {"a" => i})
230
+ end
231
+ end
232
+ end
233
+
234
+ test 'messages are divided into "max_total_size"' do
235
+ d = create_driver(%[
236
+ project project-test
237
+ topic topic-test
238
+ key key-test
239
+ max_messages 100000
240
+ max_total_size 1000
241
+ ])
242
+
243
+ @publisher.publish.times(2)
244
+ d.run(default_tag: "test") do
245
+ # 400 * 4 / max_total_size = twice
246
+ 4.times do
247
+ d.feed(@time, {"a" => "a" * 400})
248
+ end
249
+ end
250
+ end
251
+
252
+ test 'accept "ASCII-8BIT" encoded multibyte strings' do
253
+ # on fluentd v0.14, all strings treated as "ASCII-8BIT" except specified encoding.
254
+ d = create_driver
255
+ @publisher.publish.once
256
+ d.run(default_tag: "test") do
257
+ d.feed(@time, {"a" => "あああ".force_encoding("ASCII-8BIT")})
258
+ end
259
+ end
260
+
261
+ test 'reraise unexpected errors' do
262
+ d = create_driver
263
+ @publisher.publish.once { raise ReRaisedError }
264
+ assert_raises ReRaisedError do
265
+ d.run(default_tag: "test") do
266
+ d.feed([{'a' => 1, 'b' => 2}])
267
+ end
268
+ end
269
+ end
270
+
271
+ test 'reraise RetryableError' do
272
+ d = create_driver
273
+ @publisher.publish.once { raise Google::Cloud::UnavailableError.new('TEST') }
274
+ assert_raises Fluent::GcloudPubSub::RetryableError do
275
+ d.run(default_tag: "test") do
276
+ d.feed([{'a' => 1, 'b' => 2}])
277
+ end
278
+ end
279
+ end
280
+
281
+ test 'inject section' do
282
+ d = create_driver(%[
283
+ project project-test
284
+ topic topic-test
285
+ key key-test
286
+ <inject>
287
+ tag_key tag
288
+ </inject>
289
+ ])
290
+ @publisher.publish.once
291
+ d.run(default_tag: 'test') do
292
+ d.feed({"foo" => "bar"})
293
+ end
294
+ assert_equal({"tag" => 'test', "foo" => "bar"}, JSON.parse(MessagePack.unpack(d.formatted.first)[0]))
295
+ end
296
+
297
+ test 'with gzip compression' do
298
+ d = create_driver(%[
299
+ project project-test
300
+ topic topic-test
301
+ key key-test
302
+ compression gzip
303
+ ])
304
+ test_msg = {"a" => "abc"}
305
+
306
+ @publisher.publish.once
307
+ d.run(default_tag: "test") do
308
+ d.feed(test_msg)
309
+ end
310
+
311
+ assert_equal(test_msg, JSON.parse(decompress(MessagePack.unpack(d.formatted.first)[0])))
312
+ end
313
+
314
+ test 'with attribute_keys' do
315
+ d = create_driver(%[
316
+ project project-test
317
+ topic topic-test
318
+ key key-test
319
+ attribute_keys a,b
320
+ ])
321
+
322
+ @publisher.publish.once
323
+ d.run(default_tag: "test") do
324
+ d.feed(@time, {"a" => "foo", "b" => "bar", "c" => "baz"})
325
+ end
326
+
327
+ formatted = MessagePack.unpack(d.formatted[0])
328
+ message = JSON.parse(formatted[0])
329
+ assert_equal(message, {"c" => "baz"})
330
+ attributes = formatted[1]
331
+ assert_equal(attributes, {"a" => "foo", "b" => "bar"})
332
+ end
333
+
334
+ test 'with attribute_key_values' do
335
+ d = create_driver(%[
336
+ project project-test
337
+ topic topic-test
338
+ key key-test
339
+ attribute_key_values {"key1": "value1", "key2": "value2"}
340
+ ])
341
+
342
+ @publisher.publish.once
343
+ d.run(default_tag: "test") do
344
+ d.feed(@time, {"a" => "foo", "b" => "bar"})
345
+ end
346
+
347
+ formatted = MessagePack.unpack(d.formatted[0])
348
+ message = JSON.parse(formatted[0])
349
+ assert_equal(message, {"a" => "foo", "b" => "bar"})
350
+ attributes = formatted[1]
351
+ assert_equal(attributes, {"key1" => "value1", "key2" => "value2"})
352
+ end
353
+
354
+ test 'with attribute_keys and attribute_key_values' do
355
+ d = create_driver(%[
356
+ project project-test
357
+ topic topic-test
358
+ key key-test
359
+ attribute_keys a
360
+ attribute_key_values {"key": "value"}
361
+ ])
362
+
363
+ @publisher.publish.once
364
+ d.run(default_tag: "test") do
365
+ d.feed(@time, {"a" => "foo", "b" => "bar"})
366
+ end
367
+
368
+ formatted = MessagePack.unpack(d.formatted[0])
369
+ message = JSON.parse(formatted[0])
370
+ assert_equal(message, {"b" => "bar"})
371
+ attributes = formatted[1]
372
+ assert_equal(attributes, {"a" => "foo", "key" => "value"})
373
+ end
374
+ end
375
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-gcloud-pubsub-universe-domain
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Théo Berthier
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-10-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fluentd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.14.15
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.14.15
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: google-cloud-pubsub
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 3.4.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 3.4.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: test-unit
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: test-unit-rr
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ description: Google Cloud Pub/Sub input/output plugin for Fluentd event collector
104
+ with universe_domain parameter
105
+ email: berthiertheo@hotmail.fr
106
+ executables: []
107
+ extensions: []
108
+ extra_rdoc_files: []
109
+ files:
110
+ - ".github/workflows/release.yml"
111
+ - CHANGELOG.md
112
+ - Gemfile
113
+ - LICENSE
114
+ - README.md
115
+ - Rakefile
116
+ - fluent-plugin-gcloud-pubsub-universe-domain.gemspec
117
+ - fluent.conf
118
+ - lib/fluent/plugin/gcloud_pubsub/client.rb
119
+ - lib/fluent/plugin/in_gcloud_pubsub.rb
120
+ - lib/fluent/plugin/out_gcloud_pubsub.rb
121
+ - test/helper.rb
122
+ - test/plugin/test_in_gcloud_pubsub.rb
123
+ - test/plugin/test_out_gcloud_pubsub.rb
124
+ homepage: https://github.com/theoberthier/fluent-plugin-gcloud-pubsub-custom
125
+ licenses:
126
+ - MIT
127
+ metadata: {}
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubygems_version: 3.4.19
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: Google Cloud Pub/Sub input/output plugin for Fluentd event collector with
147
+ universe_domain parameter
148
+ test_files: []