fluent-plugin-gcloud-pubsub-custom 0.1.4 → 0.2.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
  SHA1:
3
- metadata.gz: 8c9f2243c6c609552b125ea53d060467197681fe
4
- data.tar.gz: 42ebb7ee74c628d14954f1fccc713be595b9a577
3
+ metadata.gz: 08c5555e386df16b94ce1a8db279f952893b3f3b
4
+ data.tar.gz: e6eee873e191628778e9793a4545baf4a9d90344
5
5
  SHA512:
6
- metadata.gz: af2b11d0ecda25cdc2a6b6db2a0a640277ce0a69c722d0899da60a6306f3fb3c00a3676113942a3c4ef7c3c6c5c77673deea7462fa0ac882e3b95d1cb4a797f2
7
- data.tar.gz: adc7c0a09c842e96540e1638c36ab3dec913f2cebc4ed73a599df0f4d74e85a94f31f97da99745787649d4555b557859476f1e5e58925bc8513b84444f72e717
6
+ metadata.gz: eb8869520add948a27084fd46c58740455432f35bc29210efc77e4578901f5b10762c2b24a56eede4df04bfa54b57eaa210de5d022a11bcd5555e925939849aa
7
+ data.tar.gz: 3d2ef099388aa1a0260061e3cc134d84c9326c29202414643a2fe3612ca27fed9697b763ddd2ead9c3f68aa3ef3adb85d55b1e00de77b1b6d79e035b16e452a7
data/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  ## ChangeLog
2
2
 
3
+ - Release 0.2.0 - 2016/10/15
4
+ - Input plugin
5
+ - Add HTTP RPC feature
3
6
  - Release 0.1.4 - 2016/09/19
4
7
  - Input plugin
5
8
  - `pull_interval` can be specified float value
data/README.md CHANGED
@@ -89,6 +89,9 @@ Use `gcloud_pubsub` input plugin.
89
89
  return_immediately true
90
90
  pull_interval 0.5
91
91
  format json
92
+ enable_rpc true
93
+ rpc_bind 0.0.0.0
94
+ rpc_port 24680
92
95
  </source>
93
96
  ```
94
97
 
@@ -110,11 +113,17 @@ Use `gcloud_pubsub` input plugin.
110
113
  - See maxMessages on https://cloud.google.com/pubsub/subscriber#receiving-pull-messages
111
114
  - `return_immediately` (optional, default: `true`)
112
115
  - See returnImmediately on https://cloud.google.com/pubsub/subscriber#receiving-pull-messages
113
- - If `return_immediately` is `false`, this plugin ignore `pull_interval`.
116
+ - If `return_immediately` is `true` and pulling message is stopped by HTTP RPC, this plugin wait `pull_interval` each pull.
114
117
  - `pull_interval` (optional, default: `5.0`)
115
118
  - Pulling messages by intervals of specified seconds.
116
119
  - `format` (optional, default: `json`)
117
120
  - Set input format. See format section in http://docs.fluentd.org/articles/in_tail
121
+ - `enable_rpc` (optional, default: `false`)
122
+ - If `true` is specified, HTTP RPC to stop or start pulling message is enabled.
123
+ - `rpc_bind` (optional, default: `0.0.0.0`)
124
+ - Bind IP address for HTTP RPC.
125
+ - `rpc_port` (optional, default: `24680`)
126
+ - Port for HTTP RPC.
118
127
 
119
128
  ## Contributing
120
129
 
@@ -7,7 +7,7 @@ Gem::Specification.new do |gem|
7
7
  gem.license = "MIT"
8
8
  gem.homepage = "https://github.com/mia-0032/fluent-plugin-gcloud-pubsub-custom"
9
9
  gem.summary = gem.description
10
- gem.version = "0.1.4"
10
+ gem.version = "0.2.0"
11
11
  gem.authors = ["Yoshihiro MIYAI"]
12
12
  gem.email = "msparrow17@gmail.com"
13
13
  gem.has_rdoc = false
@@ -1,3 +1,6 @@
1
+ require 'json'
2
+ require 'webrick'
3
+
1
4
  require 'fluent/input'
2
5
  require 'fluent/parser'
3
6
 
@@ -8,14 +11,18 @@ module Fluent
8
11
  Fluent::Plugin.register_input('gcloud_pubsub', self)
9
12
 
10
13
  config_param :tag, :string
11
- config_param :project, :string, :default => nil
12
- config_param :key, :string, :default => nil
14
+ config_param :project, :string, default: nil
15
+ config_param :key, :string, default: nil
13
16
  config_param :topic, :string
14
17
  config_param :subscription, :string
15
- config_param :pull_interval, :float, :default => 5.0
16
- config_param :max_messages, :integer, :default => 100
17
- config_param :return_immediately, :bool, :default => true
18
- config_param :format, :string, :default => 'json'
18
+ config_param :pull_interval, :float, default: 5.0
19
+ config_param :max_messages, :integer, default: 100
20
+ config_param :return_immediately, :bool, default: true
21
+ config_param :format, :string, default: 'json'
22
+ # for HTTP RPC
23
+ config_param :enable_rpc, :bool, default: false
24
+ config_param :rpc_bind, :string, default: '0.0.0.0'
25
+ config_param :rpc_port, :integer, default: 24680
19
26
 
20
27
  unless method_defined?(:log)
21
28
  define_method("log") { $log }
@@ -25,33 +32,118 @@ module Fluent
25
32
  define_method("router") { Fluent::Engine }
26
33
  end
27
34
 
35
+ class RPCServlet < WEBrick::HTTPServlet::AbstractServlet
36
+ class Error < StandardError; end
37
+
38
+ def initialize(server, plugin)
39
+ super
40
+ @plugin = plugin
41
+ end
42
+
43
+ def do_GET(req, res)
44
+ begin
45
+ code, header, body = process(req, res)
46
+ rescue
47
+ code, header, body = render_json(500, {
48
+ 'ok' => false,
49
+ 'message' => 'Internal Server Error',
50
+ 'error' => "#{$!}",
51
+ 'backtrace'=> $!.backtrace
52
+ })
53
+ end
54
+
55
+ res.status = code
56
+ header.each_pair {|k,v|
57
+ res[k] = v
58
+ }
59
+ res.body = body
60
+ end
61
+
62
+ def render_json(code, obj)
63
+ [code, {'Content-Type' => 'application/json'}, obj.to_json]
64
+ end
65
+
66
+ def process(req, res)
67
+ case req.path_info
68
+ when '/stop'
69
+ @plugin.stop_pull
70
+ when '/start'
71
+ @plugin.start_pull
72
+ else
73
+ raise Error.new "Invalid path_info: #{req.path_info}"
74
+ end
75
+ render_json(200, {'ok' => true})
76
+ end
77
+ end
78
+
28
79
  def configure(conf)
29
80
  super
81
+ @rpc_srv = nil
82
+ @rpc_thread = nil
83
+ @stop_pull = false
84
+
30
85
  @parser = Plugin.new_parser(@format)
31
86
  @parser.configure(conf)
32
87
  end
33
88
 
34
89
  def start
35
90
  super
91
+ start_rpc if @enable_rpc
92
+
36
93
  @subscriber = Fluent::GcloudPubSub::Subscriber.new @project, @key, @topic, @subscription
37
94
  log.debug "connected subscription:#{@subscription} in project #{@project}"
95
+
38
96
  @stop_subscribing = false
39
97
  @subscribe_thread = Thread.new(&method(:subscribe))
40
98
  end
41
99
 
42
100
  def shutdown
43
101
  super
102
+ if @rpc_srv
103
+ @rpc_srv.shutdown
104
+ @rpc_srv = nil
105
+ end
106
+ if @rpc_thread
107
+ @rpc_thread.join
108
+ @rpc_thread = nil
109
+ end
44
110
  @stop_subscribing = true
45
111
  @subscribe_thread.join
46
112
  end
47
113
 
114
+ def stop_pull
115
+ @stop_pull = true
116
+ log.info "stop pull from subscription:#{@subscription}"
117
+ end
118
+
119
+ def start_pull
120
+ @stop_pull = false
121
+ log.info "start pull from subscription:#{@subscription}"
122
+ end
123
+
48
124
  private
49
125
 
126
+ def start_rpc
127
+ log.info "listening http rpc server on http://#{@rpc_bind}:#{@rpc_port}/"
128
+ @rpc_srv = WEBrick::HTTPServer.new(
129
+ {
130
+ BindAddress: @rpc_bind,
131
+ Port: @rpc_port,
132
+ Logger: WEBrick::Log.new(STDERR, WEBrick::Log::FATAL),
133
+ AccessLog: []
134
+ }
135
+ )
136
+ @rpc_srv.mount('/api/in_gcloud_pubsub/pull/', RPCServlet, self)
137
+ @rpc_thread = Thread.new {
138
+ @rpc_srv.start
139
+ }
140
+ end
141
+
50
142
  def subscribe
51
143
  until @stop_subscribing
52
- _subscribe
144
+ _subscribe unless @stop_pull
53
145
 
54
- if @return_immediately
146
+ if @return_immediately || @stop_pull
55
147
  sleep @pull_interval
56
148
  end
57
149
  end
@@ -1,3 +1,5 @@
1
+ require 'net/http'
2
+
1
3
  require_relative "../test_helper"
2
4
 
3
5
  class GcloudPubSubInputTest < Test::Unit::TestCase
@@ -10,10 +12,19 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
10
12
  format json
11
13
  ]
12
14
 
15
+ DEFAULT_HOST = '127.0.0.1'
16
+ DEFAULT_PORT = 24680
17
+
13
18
  def create_driver(conf=CONFIG)
14
19
  Fluent::Test::InputTestDriver.new(Fluent::GcloudPubSubInput).configure(conf)
15
20
  end
16
21
 
22
+ def http_get(path)
23
+ http = Net::HTTP.new(DEFAULT_HOST, DEFAULT_PORT)
24
+ req = Net::HTTP::Get.new(path, {'Content-Type' => 'application/x-www-form-urlencoded'})
25
+ http.request(req)
26
+ end
27
+
17
28
  setup do
18
29
  Fluent::Test.setup
19
30
  end
@@ -30,6 +41,9 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
30
41
  return_immediately true
31
42
  pull_interval 2
32
43
  format ltsv
44
+ enable_rpc true
45
+ rpc_bind 127.0.0.1
46
+ rpc_port 24681
33
47
  ])
34
48
 
35
49
  assert_equal('test', d.instance.tag)
@@ -41,6 +55,9 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
41
55
  assert_equal(1000, d.instance.max_messages)
42
56
  assert_equal(true, d.instance.return_immediately)
43
57
  assert_equal('ltsv', d.instance.format)
58
+ assert_equal(true, d.instance.enable_rpc)
59
+ assert_equal('127.0.0.1', d.instance.rpc_bind)
60
+ assert_equal(24681, d.instance.rpc_port)
44
61
  end
45
62
 
46
63
  test 'default values are configured' do
@@ -49,6 +66,9 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
49
66
  assert_equal(100, d.instance.max_messages)
50
67
  assert_equal(true, d.instance.return_immediately)
51
68
  assert_equal('json', d.instance.format)
69
+ assert_equal(false, d.instance.enable_rpc)
70
+ assert_equal('0.0.0.0', d.instance.rpc_bind)
71
+ assert_equal(24680, d.instance.rpc_port)
52
72
  end
53
73
  end
54
74
 
@@ -139,5 +159,54 @@ class GcloudPubSubInputTest < Test::Unit::TestCase
139
159
  assert_equal(0.5, d.instance.pull_interval)
140
160
  assert_equal(true, d.emits.empty?)
141
161
  end
162
+
163
+ test 'stop by http rpc' do
164
+ messages = Array.new(1, DummyMessage.new)
165
+ @subscriber.pull(immediate: true, max: 100).once { messages }
166
+ @subscriber.acknowledge(messages).once
167
+
168
+ d = create_driver("#{CONFIG}\npull_interval 1.0\nenable_rpc true")
169
+ assert_equal(false, d.instance.instance_variable_get(:@stop_pull))
170
+
171
+ d.run {
172
+ http_get('/api/in_gcloud_pubsub/pull/stop')
173
+ sleep 0.75
174
+ # d.run sleeps 0.5 sec
175
+ }
176
+ emits = d.emits
177
+
178
+ assert_equal(1, emits.length)
179
+ assert_equal(true, d.instance.instance_variable_get(:@stop_pull))
180
+
181
+ emits.each do |tag, time, record|
182
+ assert_equal("test", tag)
183
+ assert_equal({"foo" => "bar"}, record)
184
+ end
185
+ end
186
+
187
+ test 'start by http rpc' do
188
+ messages = Array.new(1, DummyMessage.new)
189
+ @subscriber.pull(immediate: true, max: 100).at_least(1) { messages }
190
+ @subscriber.acknowledge(messages).at_least(1)
191
+
192
+ d = create_driver("#{CONFIG}\npull_interval 1.0\nenable_rpc true")
193
+ d.instance.stop_pull
194
+ assert_equal(true, d.instance.instance_variable_get(:@stop_pull))
195
+
196
+ d.run {
197
+ http_get('/api/in_gcloud_pubsub/pull/start')
198
+ sleep 0.75
199
+ # d.run sleeps 0.5 sec
200
+ }
201
+ emits = d.emits
202
+
203
+ assert_equal(true, emits.length > 0)
204
+ assert_equal(false, d.instance.instance_variable_get(:@stop_pull))
205
+
206
+ emits.each do |tag, time, record|
207
+ assert_equal("test", tag)
208
+ assert_equal({"foo" => "bar"}, record)
209
+ end
210
+ end
142
211
  end
143
212
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-gcloud-pubsub-custom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yoshihiro MIYAI
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-19 00:00:00.000000000 Z
11
+ date: 2016-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd