fluent-plugin-groonga 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.yardopts ADDED
@@ -0,0 +1,5 @@
1
+ --output-dir doc/reference/en
2
+ --use-cache .yardoc
3
+ lib/**/*.rb
4
+ -
5
+ doc/text/**/*
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ # @title README
2
+
1
3
  # README
2
4
 
3
5
  ## Name
@@ -16,7 +18,7 @@ plugin. Both of them are named `groonga`.
16
18
  The input plugin provides groonga compatible interface. It means that
17
19
  HTTP and GQTP interface. You can use the input plugin as groonga
18
20
  server. The input plugin receives groonga commands and sends them to
19
- the output plugin through some fluentds.
21
+ the output plugin through zero or more fluentds.
20
22
 
21
23
  The output plugin sends received groonga commands to groonga. The
22
24
  output plugin supports all interfaces, HTTP, GQTP and command
@@ -30,57 +32,10 @@ You can replicate your data by using `copy` output plugin.
30
32
 
31
33
  ## Usage
32
34
 
33
- ### The `groonga` input plugin
34
-
35
- Here are available parameters:
36
-
37
- * `protocol`: It specifies protocol for receiving groonga commands.
38
- * available values: `http` and `gqtp`
39
- * default: `http`
40
- * `bind`: It specifies bind address.
41
- * default: `0.0.0.0`
42
- * `port`: It specifies port number.
43
- * default: `10041`
44
- * `real_host`: It specifies real groonga server's address. It is required.
45
- * default: no default.
46
- * `real_port`: It specifies real groonga server's port number.
47
- * default: `10041`
48
- * `emit_commands`: TODO
49
-
50
- Here is an example:
51
-
52
- <source>
53
- type groonga
54
- protocol http
55
- bind 127.0.0.1
56
- port 10041
57
- real_host 192.168.0.1
58
- real_port 10041
59
- </source>
60
-
61
- ### The `groonga` output plugin
62
-
63
- * `protocol`: It specifies protocol for sending groonga commands to groonga.
64
- * available values: `http`, `gqtp` and `command`
65
- * default: `http`
66
- * For `http` and `gqtp` use:
67
- * `host`: It specifies groonga server's address.
68
- * default: `localhost`
69
- * `port`: It specifies groonga server's port number.
70
- * default: `10041`
71
- * For `command` use:
72
- * `groonga`: It specifies path of groonga command.
73
- * default: `groonga`
74
- * `database`: It specifies path of groonga database. It is required.
75
- * default: no default.
76
- * `arguments`: It specifies additional arguments for groonga command.
77
- * default: no additional arguments.
78
-
79
- <match groonga.command.*>
80
- type groonga
81
- protocol command
82
- database /tmp/groonga/db
83
- </match>
35
+ * [Configuration](doc/text/configuration.md)
36
+ ([on the Web](http://groonga.org/fluent-plugin-groonga/en/file.configuration.html))
37
+ * [Constitution](doc/text/constitution.md)
38
+ ([on the Web](http://groonga.org/fluent-plugin-groonga/en/file.constitution.html))
84
39
 
85
40
  ## Authors
86
41
 
@@ -0,0 +1,61 @@
1
+ # @title Configuration
2
+
3
+ # Configuration
4
+
5
+ Fluent-plugin-groonga includes two fluentd plugins. They are the
6
+ `groonga` input plugin and the `groonga` output plugin. This documents
7
+ describes configuration parameters of them.
8
+
9
+ ## The `groonga` input plugin
10
+
11
+ Here are available parameters:
12
+
13
+ * `protocol`: It specifies protocol for receiving groonga commands.
14
+ * available values: `http` and `gqtp`
15
+ * default: `http`
16
+ * `bind`: It specifies bind address.
17
+ * default: `0.0.0.0`
18
+ * `port`: It specifies port number.
19
+ * default: `10041`
20
+ * `real_host`: It specifies real groonga server's address. It is required.
21
+ * default: no default.
22
+ * `real_port`: It specifies real groonga server's port number.
23
+ * default: `10041`
24
+ * `emit_commands`: TODO
25
+
26
+ Here is an example:
27
+
28
+ <source>
29
+ type groonga
30
+ protocol http
31
+ bind 127.0.0.1
32
+ port 10041
33
+ real_host 192.168.0.1
34
+ real_port 10041
35
+ </source>
36
+
37
+ ## The `groonga` output plugin
38
+
39
+ * `protocol`: It specifies protocol for sending groonga commands to groonga.
40
+ * available values: `http`, `gqtp` and `command`
41
+ * default: `http`
42
+ * For `http` and `gqtp` use:
43
+ * `host`: It specifies groonga server's address.
44
+ * default: `localhost`
45
+ * `port`: It specifies groonga server's port number.
46
+ * default: `10041`
47
+ * For `command` use:
48
+ * `groonga`: It specifies path of groonga command.
49
+ * default: `groonga`
50
+ * `database`: It specifies path of groonga database. It is required.
51
+ * default: no default.
52
+ * `arguments`: It specifies additional arguments for groonga command.
53
+ * default: no additional arguments.
54
+
55
+ Here is an example:
56
+
57
+ <match groonga.command.*>
58
+ type groonga
59
+ protocol command
60
+ database /tmp/groonga/db
61
+ </match>
@@ -0,0 +1,315 @@
1
+ # @title Constitution
2
+
3
+ # Constitution
4
+
5
+ You can chose some system constitutions to implemented replication
6
+ ready groonga system. This document describes some patterns.
7
+
8
+ Here are available patterns:
9
+
10
+ * Master slave replication
11
+ * Resending data to recovered slave
12
+
13
+ Here are unavailable patterns:
14
+
15
+ * Multi master replication
16
+ * Auto slave recovery
17
+ * Dynamic slave adding
18
+ * Failover
19
+ * No SPOF (Single Point of Failure) without downing service level
20
+
21
+ ## Master slave replication
22
+
23
+ Master slave replication is available. This section describes how to
24
+ configure your system constitution.
25
+
26
+ ### Small system
27
+
28
+ In small system, you just has two servers. One is the master groonga
29
+ server and the other is the slave groonga server. You send all update
30
+ commands (e.g. `table_create`, `column_create`, `load` and so on.) to
31
+ fluentd. In fluentd, the `groonga` input plugin receives commands from
32
+ client, passes through them to master groonga server and passes
33
+ through responses from master groonga server to client. The `groonga`
34
+ input plugin converts update commands to fluent messages when the
35
+ `groonga` input plugin passes through comamands and responses. The
36
+ fluent messages are sent to slave groonga server by the `groonga`
37
+ output plugin.
38
+
39
+ Here is a diagram of this constitution.
40
+
41
+ update update
42
+ and and
43
+ search +---------+ search +---------+
44
+ +--------+ <------> | fluentd | <------> | master |
45
+ | | +---------+ | groonga |
46
+ | client | update | +---------+
47
+ | | \_/
48
+ | | search +---------+
49
+ +--------+ <------> | slave |
50
+ | groonga |
51
+ +---------+
52
+
53
+ Fluentd should be placed at client or master groonga server. If you
54
+ have only one client that updates data, client side is reasonable. If
55
+ you have multiple clients that update data, master groonga server side
56
+ is reasonable.
57
+
58
+ You can use replication for high performance by providing search
59
+ service with multi servers. You can't use replication for high
60
+ availability. If master groonga server or fluentd is down, this system
61
+ can't update data. (Searching is still available because slabe groonga
62
+ server is alive.)
63
+
64
+ Here is an example configuration file:
65
+
66
+ # For master groonga server
67
+ <source>
68
+ type groonga
69
+ protocol gqtp # Or use the below line
70
+ # protocol http
71
+ bind 127.0.0.1 # For client side fluentd
72
+ # bind 192.168.0.1 # For master groonga server side fluentd
73
+ port 10041
74
+ real_host 192.168.29.1 # IP address of master groonga server
75
+ real_port 10041 # Port number of master groonga server
76
+ # real_port 20041 # Use different port number
77
+ # for master groonga server side fluentd
78
+ </source>
79
+
80
+ # For slave groonga server
81
+ <match groonga.command.*>
82
+ type groonga
83
+ protocol gqtp # Or use the below line
84
+ # protocol http # You can use different protocol for
85
+ # master groonga server and slave groonga server
86
+ host 192.168.29.29 # IP address of slave groonga server
87
+ port 10041 # Port number of slave groonga server
88
+
89
+ # Buffer
90
+ flush_interval 1s # Use small value for less delay replication
91
+
92
+ ## Use the following configurations to support resending data to
93
+ ## recovered slave groonga server. If you don't care about slave
94
+ ## groonga server is down case, you don't need the following
95
+ ## configuration.
96
+
97
+ ## For supporting resending data after fluentd is restarted
98
+ # buffer_type file
99
+ # buffer_path /var/log/fluent/groonga.*.buffer
100
+ ## Use large value if a record has many data in load command.
101
+ ## A value in load command is a chunk.
102
+ # buffer_chunk_limit 256m
103
+ ## Use large value if you want to support resending data after
104
+ ## slave groonga server is down long time.
105
+ ## 17: about 1.5day =
106
+ ## ((2 ** 0) + (2 ** 1) + ... + (2 ** 17)) / 60.0 / 60.0 / 24.0
107
+ ## (default)
108
+ ## 18: about 3.0day = ((2 ** 0) + ... + (2 ** 18)) / ...
109
+ ## 19: about 6.0day = ((2 ** 0) + ... + (2 ** 19)) / ...
110
+ # retry_limit 19
111
+ ## Use large value if you load many records.
112
+ ## A value in load command is a chunk.
113
+ # buffer_queue_limit 10000
114
+ </match>
115
+
116
+ #### How to recover from fluentd down
117
+
118
+ If fluentd is down, you just restart fluentd. Note that you may resend
119
+ the last command if fluentd is down while you are sending update
120
+ commands.
121
+
122
+ You cannot update data until fluentd is up.
123
+
124
+ #### How to recover from master groonga server down
125
+
126
+ Here are recover steps when master groonga server is down:
127
+
128
+ 1. Stop fluentd.
129
+ 2. Run `grndump /PATH/TO/SLAVE/GROONGA/SERVER/DB >
130
+ SLAVE_GROONGA_DUMP.grn` on slave groonga server host.
131
+ 3. Run `groonga -n /PATH/TO/MASTER/GROONGA/SERVER/DB <
132
+ SLAVE_GROONGA_DUMP.grn` on master groonga server.
133
+ 4. Run master groonga server.
134
+ 5. Start fluentd.
135
+
136
+ You cannot update data until you finish to recover.
137
+
138
+ #### How to recover from slave groonga server down
139
+
140
+ Here are recover steps when slave groonga server is down:
141
+
142
+ 1. Run `grndump /PATH/TO/MASTER/GROONGA/SERVER/DB >
143
+ MASTER_GROONGA_DUMP.grn` on master groonga server host.
144
+ 2. Run `groonga -n /PATH/TO/SLAVE/GROONGA/SERVER/DB <
145
+ MASTER_GROONGA_DUMP.grn` on slave groonga server.
146
+ 3. Run slave groonga server.
147
+
148
+ You can update data while you recover. If your system can't process
149
+ all search requests by only master groonga server, your system will be
150
+ down.
151
+
152
+ You need to recover slave groonga server before fluentd's buffer queue
153
+ is full (see `buffer_queue_limit`) or fluentd gives up retrying (see
154
+ `retry_limit`). Here are recover steps when you cannot recover slave
155
+ groonga server before those situations:
156
+
157
+ 1. Stop fluentd.
158
+ 2. Run `grndump /PATH/TO/MASTER/GROONGA/SERVER/DB >
159
+ MASTER_GROONGA_DUMP.grn` on master groonga server host.
160
+ 3. Run `groonga -n /PATH/TO/SLAVE/GROONGA/SERVER/DB <
161
+ MASTER_GROONGA_DUMP.grn` on slave groonga server host.
162
+ 4. Run slave groonga server.
163
+ 5. Start fluentd.
164
+
165
+ You cannot update data until you finish to recover.
166
+
167
+ ### Medium system
168
+
169
+ In medium system, you have three or more slave groonga servers. Fluentd
170
+ updates two or more slave groonga servers with the `copy` output
171
+ plugin and the `groonga` output plugin.
172
+
173
+ Here is a diagram of this constitution.
174
+
175
+ update update
176
+ and and
177
+ search +---------+ search +---------+
178
+ +--------+ <------> | fluentd | <------> | master |
179
+ | | +---------+ | groonga |
180
+ | client | +--------+ +---------+
181
+ | | |
182
+ +--------+ search +---------+ |
183
+ | | <------> | slave | <-+ update
184
+ | client | | groonga | |
185
+ | | +---------+ |
186
+ +--------+ search +---------+ |
187
+ | | <------> | slave | <-+ update
188
+ | client | | groonga | |
189
+ | | +---------+ |
190
+ +- ... -+ ... ... ...
191
+
192
+ Here is an example configuration file:
193
+
194
+ # For master groonga server
195
+ <source>
196
+ type groonga
197
+ protocol gqtp # Or use the below line
198
+ # protocol http
199
+ bind 127.0.0.1 # For client side fluentd
200
+ # bind 192.168.0.1 # For master groonga server side fluentd
201
+ port 10041
202
+ real_host 192.168.29.1 # IP address of master groonga server
203
+ real_port 10041 # Port number of master groonga server
204
+ # real_port 20041 # Use different port number
205
+ # for master groonga server side fluentd
206
+ </source>
207
+
208
+ # For slave groonga servers
209
+ <match groonga.command.*>
210
+ type copy
211
+
212
+ # The first slave groonga server
213
+ <store>
214
+ type groonga
215
+ protocol gqtp # Or use the below line
216
+ # protocol http # You can use different protocol for
217
+ # master groonga server and slave groonga server
218
+ host 192.168.29.2 # IP address of slave groonga server
219
+ port 10041 # Port number of slave groonga server
220
+
221
+ # Buffer
222
+ flush_interval 1s # Use small value for less delay replication
223
+
224
+ ## Use the following configurations to support resending data to
225
+ ## recovered slave groonga server. If you don't care about slave
226
+ ## groonga server is down case, you don't need the following
227
+ ## configuration.
228
+
229
+ ## For supporting resending data after fluentd is restarted
230
+ # buffer_type file
231
+ # buffer_path /var/log/fluent/groonga.*.buffer
232
+ ## Use large value if a record has many data in load command.
233
+ ## A value in load command is a chunk.
234
+ # buffer_chunk_limit 256m
235
+ ## Use large value if you want to support resending data after
236
+ ## slave groonga server is down long time.
237
+ ## 17: about 1.5day =
238
+ ## ((2 ** 0) + (2 ** 1) + ... + (2 ** 17)) / 60.0 / 60.0 / 24.0
239
+ ## (default)
240
+ ## 18: about 3.0day = ((2 ** 0) + ... + (2 ** 18)) / ...
241
+ ## 19: about 6.0day = ((2 ** 0) + ... + (2 ** 19)) / ...
242
+ # retry_limit 19
243
+ ## Use large value if you load many records.
244
+ ## A value in load command is a chunk.
245
+ # buffer_queue_limit 10000
246
+ </store>
247
+
248
+ # The second slave groonga server
249
+ <store>
250
+ type groonga
251
+ protocol gqtp # Or use the below line
252
+ # protocol http # You can use different protocol for
253
+ # master groonga server and slave groonga server
254
+ host 192.168.29.3 # IP address of slave groonga server
255
+ port 10041 # Port number of slave groonga server
256
+
257
+ # Buffer
258
+ # ...
259
+ </store>
260
+
261
+ # More slave groonga servers
262
+ # <store>
263
+ # type groonga
264
+ # ...
265
+ # </store>
266
+ </match>
267
+
268
+ TODO: ...
269
+
270
+ ### Large system
271
+
272
+ In large system, you have two or more slave groonga server clusters.
273
+ Fluentd that connects with master groonga server updates two or more
274
+ fluentds that are in slave groonga server clusters with the `copy`
275
+ output plugin and the `forward` output plugin. A slave cluster has a
276
+ fluentd. Fluentd in slave groonga server clusters updates slave
277
+ groonga server in the same slave groonga server cluster by the `copy`
278
+ output plugin and `groonga` output plugin.
279
+
280
+ Here is a diagram of this constitution.
281
+
282
+ update update
283
+ and and
284
+ search +---------+ search +---------+
285
+ +--------+ <--------> | fluentd | <------> | master |
286
+ | | +---------+ | groonga |
287
+ | client | | +---------+
288
+ | | +------------------------------+
289
+ +--------+ +----------------------------------+ |
290
+ | | | slave cluster | |
291
+ | client | search | +---------+ update +---------+ | |
292
+ | | <------> | | slave | <------- | fluentd | <-+ update
293
+ +--------| | | groonga | +---------+ | |
294
+ | | | +---------+ +-----------+ | |
295
+ | client | search | +---------+ | | |
296
+ | | <------> | | slave | <-+ update | |
297
+ +--------| | | groonga | | | |
298
+ | | | +---------+ | | |
299
+ | ... | ... | ... ... | |
300
+ +----------------------------------+ |
301
+ +--------+ +----------------------------------+ |
302
+ | | | slave cluster | |
303
+ | client | search | +---------+ update +---------+ | |
304
+ | | <------> | | slave | <------- | fluentd | <-+ update
305
+ +--------| | | groonga | +---------+ | |
306
+ | | | +---------+ +-----------+ | |
307
+ | client | search | +---------+ | | |
308
+ | | <------> | | slave | <-+ update | |
309
+ +--------| | | groonga | | | |
310
+ | | | +---------+ | | |
311
+ | ... | ... | ... ... | |
312
+ +----------------------------------+ |
313
+ ... ...
314
+
315
+ TODO: ...
data/doc/text/news.md CHANGED
@@ -1,5 +1,20 @@
1
+ # @title News
2
+
1
3
  # News
2
4
 
5
+ ## 1.0.1: 2012-12-29
6
+
7
+ ### Improvements
8
+
9
+ * Added more destructive emit commands ("delete", "register", "truncate").
10
+ * [out] Used close instead of sending "shutdown".
11
+ * Placed documents to http://groonga.org/fluent-plugin-groonga/en/.
12
+ * [doc] Updated documents:
13
+ * Added the documents of configuration and constitution.
14
+ * Added recover steps.
15
+ * Added documentation about master slave replication in
16
+ [small/medium/large] system.
17
+
3
18
  ## 1.0.0: 2012-11-29
4
19
 
5
20
  The first release!!!
@@ -17,7 +17,7 @@
17
17
 
18
18
  Gem::Specification.new do |spec|
19
19
  spec.name = "fluent-plugin-groonga"
20
- spec.version = "1.0.0"
20
+ spec.version = "1.0.1"
21
21
  spec.authors = ["Kouhei Sutou"]
22
22
  spec.email = ["kou@clear-code.com"]
23
23
  spec.summary = "Fluentd plugin collection for groonga users"
@@ -26,9 +26,11 @@ Gem::Specification.new do |spec|
26
26
  spec.homepage = "https://github.com/groonga/fluent-plugin-groonga"
27
27
 
28
28
  spec.files = ["README.md", "Gemfile", "#{spec.name}.gemspec"]
29
+ spec.files += [".yardopts"]
29
30
  spec.files += Dir.glob("lib/**/*.rb")
30
31
  spec.files += Dir.glob("sample/**/*")
31
32
  spec.files += Dir.glob("doc/text/**/*")
33
+ spec.test_files += Dir.glob("test/**/*")
32
34
  spec.require_paths = ["lib"]
33
35
 
34
36
  spec.add_runtime_dependency("fluentd")
@@ -37,6 +39,8 @@ Gem::Specification.new do |spec|
37
39
 
38
40
  spec.add_development_dependency("rake")
39
41
  spec.add_development_dependency("bundler")
42
+ spec.add_development_dependency("packnga", ">= 0.9.6")
40
43
  spec.add_development_dependency("test-unit")
41
44
  spec.add_development_dependency("test-unit-notify")
45
+ spec.add_development_dependency("redcarpet")
42
46
  end
@@ -82,6 +82,9 @@ module Fluent
82
82
  DEFAULT_EMIT_COMMANDS = [
83
83
  /\Atable_/,
84
84
  /\Acolumn_/,
85
+ "delete",
86
+ "register",
87
+ "truncate",
85
88
  "load",
86
89
  ]
87
90
  config_param :emit_commands, :default => DEFAULT_EMIT_COMMANDS do |value|
@@ -16,7 +16,6 @@
16
16
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
 
18
18
  require "fileutils"
19
- require "cgi/util"
20
19
 
21
20
  module Fluent
22
21
  class GroongaOutput < BufferedOutput
@@ -127,7 +126,7 @@ module Fluent
127
126
 
128
127
  def shutdown
129
128
  return if @client.nil?
130
- @client.send("shutdown") do
129
+ @client.close do
131
130
  @loop.stop
132
131
  end
133
132
  @loop.run
data/test/run-test.rb ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License version 2.1 as published by the Free Software Foundation.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ # $VERBOSE = true
19
+
20
+ Thread.abort_on_exception = true
21
+
22
+ base_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
23
+ lib_dir = File.join(base_dir, "lib")
24
+ test_dir = File.join(base_dir, "test")
25
+
26
+ require "test-unit"
27
+ require "test/unit/notify"
28
+
29
+ Test::Unit::Priority.enable
30
+
31
+ $LOAD_PATH.unshift(lib_dir)
32
+
33
+ require "fluent/log"
34
+ $log = Fluent::Log.new($stdout, Fluent::Log::LEVEL_WARN)
35
+
36
+ Dir.glob("#{base_dir}/test/**/test{_,-}*.rb") do |file|
37
+ require file.sub(/\.rb$/, '')
38
+ end
39
+
40
+ ENV["TEST_UNIT_MAX_DIFF_TARGET_STRING_SIZE"] ||= "5000"
41
+
42
+ exit Test::Unit::AutoRunner.run
@@ -0,0 +1,176 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License version 2.1 as published by the Free Software Foundation.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ require "time"
19
+ require "cgi/util"
20
+ require "net/http"
21
+ require "webrick/config"
22
+ require "webrick/httpresponse"
23
+
24
+ require "fluent/test"
25
+ require "fluent/plugin/in_groonga"
26
+
27
+ require "http_parser"
28
+
29
+ class GroongaInputTest < Test::Unit::TestCase
30
+ setup
31
+ def setup_fluent
32
+ Fluent::Test.setup
33
+ @now = Time.parse("2012-10-26T08:45:42Z").to_i
34
+ Fluent::Engine.now = @now
35
+ end
36
+
37
+ private
38
+ def create_driver
39
+ driver = Fluent::Test::InputTestDriver.new(Fluent::GroongaInput)
40
+ driver.configure(configuration)
41
+ driver
42
+ end
43
+
44
+ def configuration
45
+ <<-EOC
46
+ EOC
47
+ end
48
+
49
+ class HTTPTest < self
50
+ setup :before => :append
51
+ def setup_real_server
52
+ @real_host = "127.0.0.1"
53
+ @real_port = 29292
54
+ @real_server = TCPServer.new(@real_host, @real_port)
55
+ @repeater = nil
56
+ response_config = WEBrick::Config::HTTP.dup.update(:Logger => $log)
57
+ @real_response = WEBrick::HTTPResponse.new(response_config)
58
+ Thread.new do
59
+ @repeater = @real_server.accept
60
+ @real_server.close
61
+ parser = HTTP::Parser.new
62
+ parser.on_message_complete = lambda do
63
+ @real_response.send_response(@repeater)
64
+ @repeater.close
65
+ end
66
+
67
+ loop do
68
+ break if @repeater.closed?
69
+ data = @repeater.readpartial(4096)
70
+ break if data.nil?
71
+ parser << data
72
+ end
73
+ end
74
+ end
75
+
76
+ teardown
77
+ def teardown_real_server
78
+ @real_server.close unless @real_server.closed?
79
+
80
+ if @repeater and not @repeater.closed?
81
+ @repeater.close
82
+ end
83
+ end
84
+
85
+ def setup
86
+ @host = "127.0.0.1"
87
+ @port = 2929
88
+
89
+ @driver = create_driver
90
+ @last_response = nil
91
+ end
92
+
93
+ def configuration
94
+ <<-EOC
95
+ protocol http
96
+ bind #{@host}
97
+ port #{@port}
98
+ real_host #{@real_host}
99
+ real_port #{@real_port}
100
+ EOC
101
+ end
102
+
103
+ def test_target_command
104
+ @driver.expect_emit("groonga.command.table_create",
105
+ @now,
106
+ {"name" => "Users"})
107
+ @driver.run do
108
+ get("/d/table_create", "name" => "Users")
109
+ assert_equal("200", @last_response.code)
110
+ end
111
+ end
112
+
113
+ def test_not_target_command
114
+ @driver.run do
115
+ get("/d/status")
116
+ assert_equal("200", @last_response.code)
117
+ end
118
+ assert_empty(@driver.emits)
119
+ end
120
+
121
+ def test_load
122
+ json = <<-EOJ
123
+ [
124
+ {"name": "Alice"},
125
+ {"name": "Bob"}
126
+ ]
127
+ EOJ
128
+ @driver.expect_emit("groonga.command.load",
129
+ @now,
130
+ {
131
+ "table" => "Users",
132
+ "values" => json,
133
+ })
134
+
135
+ @driver.run do
136
+ post("/d/load", json, "table" => "Users")
137
+ assert_equal("200", @last_response.code)
138
+ end
139
+ end
140
+
141
+ def test_not_command
142
+ @driver.run do
143
+ @real_response.status = 404
144
+ get("/index.html")
145
+ assert_equal("404", @last_response.code)
146
+ end
147
+ end
148
+
149
+ private
150
+ def get(path, parameters={})
151
+ http = Net::HTTP.new(@host, @port)
152
+ response = http.get(build_path(path, parameters))
153
+ @last_response = response
154
+ response
155
+ end
156
+
157
+ def post(path, body, parameters={})
158
+ http = Net::HTTP.new(@host, @port)
159
+ response = http.post(build_path(path, parameters),
160
+ body,
161
+ {"Content-Type" => "application/json"})
162
+ @last_response = response
163
+ response
164
+ end
165
+
166
+ def build_path(path, parameters)
167
+ unless parameters.empty?
168
+ url_encoded_parameters = parameters.collect do |key, value|
169
+ "#{CGI.escape(key)}=#{CGI.escape(value)}"
170
+ end
171
+ path += "?" + url_encoded_parameters.join("&")
172
+ end
173
+ path
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,213 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License version 2.1 as published by the Free Software Foundation.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+
18
+ require "time"
19
+ require "cgi/util"
20
+ require "net/http"
21
+ require "webrick/config"
22
+ require "webrick/httpresponse"
23
+
24
+ require "fluent/test"
25
+ require "fluent/plugin/out_groonga"
26
+
27
+ require "http_parser"
28
+
29
+ class GroongaOutputTest < Test::Unit::TestCase
30
+ setup
31
+ def setup_fluent
32
+ Fluent::Test.setup
33
+ end
34
+
35
+ private
36
+ def create_driver(tag)
37
+ driver = Fluent::Test::BufferedOutputTestDriver.new(Fluent::GroongaOutput,
38
+ tag)
39
+ driver.configure(configuration)
40
+ driver
41
+ end
42
+
43
+ def configuration
44
+ <<-EOC
45
+ EOC
46
+ end
47
+
48
+ class HTTPTest < self
49
+ setup :before => :append
50
+ def setup_real_server
51
+ @real_host = "127.0.0.1"
52
+ @real_port = 29292
53
+ @real_server_pid = fork do
54
+ exit
55
+ real_server = TCPServer.new(@real_host, @real_port)
56
+ response_config = WEBrick::Config::HTTP.dup.update(:Logger => $log)
57
+ real_response = WEBrick::HTTPResponse.new(response_config)
58
+ request_headers = nil
59
+ request_body = ""
60
+ client = real_server.accept
61
+ real_server.close
62
+ parser = HTTP::Parser.new
63
+ parser.on_headers_complete = lambda do |headers|
64
+ request_headers = headers
65
+ end
66
+ parser.on_body = lambda do |chunk|
67
+ request_body << chunk
68
+ end
69
+ parser.on_message_complete = lambda do
70
+ real_response.send_response(client)
71
+ client.close
72
+ end
73
+
74
+ loop do
75
+ break if client.closed?
76
+ data = client.readpartial(4096)
77
+ break if data.nil?
78
+ parser << data
79
+ end
80
+ end
81
+ end
82
+
83
+ teardown
84
+ def teardown_real_server
85
+ Process.kill(:INT, @real_server_pid)
86
+ Process.kill(:KILL, @real_server_pid)
87
+ Process.waitpid(@real_server_pid)
88
+ end
89
+
90
+ def configuration
91
+ <<-EOC
92
+ protocol http
93
+ host #{@real_host}
94
+ port #{@real_port}
95
+ EOC
96
+ end
97
+
98
+ class CommandTest < self
99
+ def test_basic_command
100
+ driver = create_driver("groonga.command.table_create")
101
+ time = Time.parse("2012-10-26T08:45:42Z").to_i
102
+ driver.emit({"name" => "Users"}, time)
103
+ driver.run
104
+ # p @request_headers
105
+ # p @request_body
106
+ end
107
+ end
108
+ end
109
+
110
+ class CommandLineTest < self
111
+ setup :before => :append
112
+ def setup_command
113
+ @temporary_directory = File.expand_path("tmp", File.dirname(__FILE__))
114
+ FileUtils.rm_rf(@temporary_directory)
115
+ FileUtils.mkdir_p(@temporary_directory)
116
+
117
+ @groonga_stub_path = File.join(@temporary_directory, "groonga")
118
+ @command_line_path = File.join(@temporary_directory, "command-line")
119
+ @input_path = File.join(@temporary_directory, "input")
120
+ @input_fd_path = File.join(@temporary_directory, "input-fd")
121
+ @output_fd_path = File.join(@temporary_directory, "output-fd")
122
+ @database_path = File.join(@temporary_directory, "database")
123
+
124
+ File.open(@groonga_stub_path, "w") do |groonga_stub|
125
+ groonga_stub.puts(<<-EOR)
126
+ #!#{Gem.ruby}
127
+
128
+ File.open(#{@command_line_path.inspect}, "a") do |file|
129
+ file.puts(ARGV)
130
+ end
131
+
132
+ input_fd = ARGV[ARGV.index("--input-fd") + 1]
133
+ input = IO.new(input_fd.to_i)
134
+
135
+ File.open(#{@input_fd_path.inspect}, "a") do |file|
136
+ file.print(input_fd)
137
+ end
138
+
139
+ File.open(#{@input_path.inspect}, "a") do |file|
140
+ input.each_line do |line|
141
+ file.print(line)
142
+ end
143
+ end
144
+
145
+ output_fd = ARGV[ARGV.index("--output-fd") + 1]
146
+ output = IO.new(output_fd.to_i)
147
+
148
+ File.open(#{@output_fd_path.inspect}, "a") do |file|
149
+ file.print(output_fd)
150
+ end
151
+
152
+ output.puts("done")
153
+ output.flush
154
+ EOR
155
+ end
156
+ FileUtils.chmod(0755, @groonga_stub_path)
157
+
158
+ FileUtils.touch(@command_line_path)
159
+ FileUtils.touch(@input_path)
160
+ end
161
+
162
+ teardown
163
+ def teardown_command
164
+ FileUtils.rm_rf(@temporary_directory)
165
+ end
166
+
167
+ def configuration
168
+ <<-EOC
169
+ protocol command
170
+ groonga #{@groonga_stub_path}
171
+ database #{@database_path}
172
+ EOC
173
+ end
174
+
175
+ private
176
+ def actual_command_line
177
+ File.read(@command_line_path).split(/\n/)
178
+ end
179
+
180
+ def actual_input
181
+ File.read(@input_path)
182
+ end
183
+
184
+ def actual_input_fd
185
+ File.read(@input_fd_path)
186
+ end
187
+
188
+ def actual_output_fd
189
+ File.read(@output_fd_path)
190
+ end
191
+
192
+ class CommandTest < self
193
+ def test_basic_command
194
+ driver = create_driver("groonga.command.table_create")
195
+ time = Time.parse("2012-10-26T08:45:42Z")
196
+ driver.emit({"name" => "Users"}, time)
197
+ driver.run
198
+ assert_equal([
199
+ [
200
+ "--input-fd", actual_input_fd,
201
+ "--output-fd", actual_output_fd,
202
+ "-n", @database_path,
203
+ ],
204
+ "/d/table_create?name=Users\n",
205
+ ],
206
+ [
207
+ actual_command_line,
208
+ actual_input,
209
+ ])
210
+ end
211
+ end
212
+ end
213
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-groonga
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-29 00:00:00.000000000 Z
12
+ date: 2012-12-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fluentd
@@ -91,6 +91,22 @@ dependencies:
91
91
  - - ! '>='
92
92
  - !ruby/object:Gem::Version
93
93
  version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: packnga
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: 0.9.6
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: 0.9.6
94
110
  - !ruby/object:Gem::Dependency
95
111
  name: test-unit
96
112
  requirement: !ruby/object:Gem::Requirement
@@ -123,6 +139,22 @@ dependencies:
123
139
  - - ! '>='
124
140
  - !ruby/object:Gem::Version
125
141
  version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: redcarpet
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
126
158
  description: Groonga users can replicate their data by fluent-plugin-groonga
127
159
  email:
128
160
  - kou@clear-code.com
@@ -133,13 +165,19 @@ files:
133
165
  - README.md
134
166
  - Gemfile
135
167
  - fluent-plugin-groonga.gemspec
168
+ - .yardopts
136
169
  - lib/fluent/plugin/out_groonga.rb
137
170
  - lib/fluent/plugin/in_groonga.rb
138
- - sample/http.conf
139
- - sample/command.conf
140
171
  - sample/gqtp.conf
172
+ - sample/command.conf
173
+ - sample/http.conf
141
174
  - doc/text/news.md
175
+ - doc/text/constitution.md
142
176
  - doc/text/lgpl-2.1.txt
177
+ - doc/text/configuration.md
178
+ - test/run-test.rb
179
+ - test/test_input.rb
180
+ - test/test_output.rb
143
181
  homepage: https://github.com/groonga/fluent-plugin-groonga
144
182
  licenses: []
145
183
  post_install_message:
@@ -152,17 +190,26 @@ required_ruby_version: !ruby/object:Gem::Requirement
152
190
  - - ! '>='
153
191
  - !ruby/object:Gem::Version
154
192
  version: '0'
193
+ segments:
194
+ - 0
195
+ hash: -1000993838467277328
155
196
  required_rubygems_version: !ruby/object:Gem::Requirement
156
197
  none: false
157
198
  requirements:
158
199
  - - ! '>='
159
200
  - !ruby/object:Gem::Version
160
201
  version: '0'
202
+ segments:
203
+ - 0
204
+ hash: -1000993838467277328
161
205
  requirements: []
162
206
  rubyforge_project:
163
207
  rubygems_version: 1.8.23
164
208
  signing_key:
165
209
  specification_version: 3
166
210
  summary: Fluentd plugin collection for groonga users
167
- test_files: []
211
+ test_files:
212
+ - test/run-test.rb
213
+ - test/test_input.rb
214
+ - test/test_output.rb
168
215
  has_rdoc: