elasticsearch-extensions 0.0.21 → 0.0.22
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 +4 -4
- data/Rakefile +1 -1
- data/lib/elasticsearch/extensions/test/cluster.rb +492 -233
- data/lib/elasticsearch/extensions/version.rb +1 -1
- data/test/test/cluster/integration/cluster_test.rb +29 -0
- data/test/test/cluster/unit/cluster_test.rb +280 -0
- data/test/test_helper.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 33490d5d862da6d64e26435f1a77291e2a0a82d5
|
4
|
+
data.tar.gz: 7b57c8185dde5a4278c142c1de61605e3107ff39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36cee1857c1fbea9d28821cb54d425df5a38f28c9d23a2a3ebd827ad29cb9f7ec004405e8b0e85176a199355ddb0ae9650980988b036f209581197f9af71d58a
|
7
|
+
data.tar.gz: 4a8a001059bd6982c26a21663fceb8298711cc0b73ddefd17e7be26aa97cf0e540ca7f2a5327a274f1d3c700662ecd89c58eaa8ed954eda62975ec6f97b0771c
|
data/Rakefile
CHANGED
@@ -36,7 +36,7 @@ namespace :test do
|
|
36
36
|
Rake::TestTask.new(:all) do |test|
|
37
37
|
Rake::Task['test:ci_reporter'].invoke if ENV['CI']
|
38
38
|
test.libs << 'lib' << 'test'
|
39
|
-
test.test_files = FileList["test/**/unit/**/*_test.rb", "test/**/
|
39
|
+
test.test_files = FileList["test/**/unit/**/*_test.rb", "test/**/integration/**/*_test.rb"]
|
40
40
|
end
|
41
41
|
|
42
42
|
Rake::TestTask.new(:profile) do |test|
|
@@ -21,110 +21,93 @@ module Elasticsearch
|
|
21
21
|
module Extensions
|
22
22
|
module Test
|
23
23
|
|
24
|
-
# A convenience Ruby class for starting and stopping
|
25
|
-
#
|
24
|
+
# A convenience Ruby class for starting and stopping an Elasticsearch cluster,
|
25
|
+
# eg. for integration tests
|
26
26
|
#
|
27
27
|
# @example Start a cluster with default configuration
|
28
28
|
# require 'elasticsearch/extensions/test/cluster'
|
29
|
-
# Elasticsearch::Extensions::Test::Cluster.start
|
29
|
+
# Elasticsearch::Extensions::Test::Cluster::Cluster.new.start
|
30
30
|
#
|
31
|
-
# @see Cluster#
|
32
|
-
# @see Cluster#stop Cluster.stop
|
31
|
+
# @see Cluster#initialize
|
33
32
|
#
|
34
33
|
module Cluster
|
35
|
-
@@network_host = ENV.fetch('TEST_CLUSTER_NETWORK_HOST', 'localhost')
|
36
|
-
@@number_of_nodes = (ENV['TEST_CLUSTER_NODES'] || 2).to_i
|
37
|
-
@@default_cluster_name = "elasticsearch-test-#{Socket.gethostname.downcase}"
|
38
34
|
|
39
35
|
# Starts a cluster
|
40
36
|
#
|
41
|
-
#
|
42
|
-
# and prints information about the cluster -- unless this specific cluster is running already.
|
37
|
+
# @see Cluster#start
|
43
38
|
#
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
#
|
49
|
-
# @option arguments [String] :port Starting port number; will be auto-incremented (default: 9250)
|
50
|
-
# @option arguments [String] :node_name The node name (will be appended with a number)
|
51
|
-
# @option arguments [String] :path_data Path to the directory to store data in
|
52
|
-
# @option arguments [String] :path_work Path to the directory with auxiliary files
|
53
|
-
# @option arguments [String] :path_logs Path to the directory with log files
|
54
|
-
# @option arguments [Boolean] :multicast_enabled Whether multicast is enabled (default: true)
|
55
|
-
# @option arguments [Integer] :timeout Timeout when starting the cluster (default: 30)
|
56
|
-
# @option arguments [String] :network_host The host that nodes will bind on and publish to
|
57
|
-
# @option arguments [Boolean] :clear_cluster Wipe out cluster content on startup (default: true)
|
39
|
+
def start(arguments={})
|
40
|
+
Cluster.new(arguments).start
|
41
|
+
end
|
42
|
+
|
43
|
+
# Stops a cluster
|
58
44
|
#
|
59
|
-
#
|
45
|
+
# @see Cluster#stop
|
60
46
|
#
|
61
|
-
|
62
|
-
|
47
|
+
def stop(arguments={})
|
48
|
+
Cluster.new(arguments).stop
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns true when a specific test node is running within the cluster
|
63
52
|
#
|
64
|
-
# @
|
65
|
-
# Elasticsearch::Extensions::Test::Cluster.start \
|
66
|
-
# cluster_name: 'my-cluster',
|
67
|
-
# nodes: 3,
|
68
|
-
# node_name: 'my-node',
|
69
|
-
# port: 9350
|
53
|
+
# @see Cluster#running?
|
70
54
|
#
|
71
|
-
|
72
|
-
|
73
|
-
|
55
|
+
def running?(arguments={})
|
56
|
+
Cluster.new(arguments).running?
|
57
|
+
end
|
58
|
+
|
59
|
+
# Waits until the cluster is green and prints information
|
74
60
|
#
|
75
|
-
# @
|
76
|
-
# @see Cluster#stop Cluster.stop
|
61
|
+
# @see Cluster#wait_for_green
|
77
62
|
#
|
78
|
-
def
|
79
|
-
|
80
|
-
|
81
|
-
arguments[:command] ||= ENV.fetch('TEST_CLUSTER_COMMAND', 'elasticsearch')
|
82
|
-
arguments[:port] ||= (ENV.fetch('TEST_CLUSTER_PORT', 9250).to_i)
|
83
|
-
arguments[:cluster_name] ||= (ENV.fetch('TEST_CLUSTER_NAME', @@default_cluster_name).chomp)
|
84
|
-
arguments[:node_name] ||= ENV.fetch('TEST_CLUSTER_NODE_NAME', 'node')
|
85
|
-
arguments[:path_data] ||= ENV.fetch('TEST_CLUSTER_DATA', '/tmp/elasticsearch_test')
|
86
|
-
arguments[:path_work] ||= ENV.fetch('TEST_CLUSTER_TMP', '/tmp')
|
87
|
-
arguments[:path_logs] ||= ENV.fetch('TEST_CLUSTER_LOGS', '/tmp/log/elasticsearch')
|
88
|
-
arguments[:es_params] ||= ENV.fetch('TEST_CLUSTER_PARAMS', '')
|
89
|
-
arguments[:multicast_enabled] ||= ENV.fetch('TEST_CLUSTER_MULTICAST', 'true')
|
90
|
-
arguments[:timeout] ||= (ENV.fetch('TEST_CLUSTER_TIMEOUT', 30).to_i)
|
91
|
-
arguments[:network_host] ||= @@network_host
|
92
|
-
|
93
|
-
clear_cluster = !!arguments[:clear_cluster] || (ENV.fetch('TEST_CLUSTER_CLEAR', 'true') != 'false')
|
94
|
-
|
95
|
-
# Make sure `cluster_name` is not dangerous
|
96
|
-
if arguments[:cluster_name] =~ /^[\/\\]?$/
|
97
|
-
raise ArgumentError, "The `cluster_name` parameter cannot be empty string or a slash"
|
98
|
-
end
|
99
|
-
|
100
|
-
if running? :on => arguments[:port], :as => arguments[:cluster_name]
|
101
|
-
print "[!] Elasticsearch cluster already running".ansi(:red)
|
102
|
-
wait_for_green(arguments[:port], arguments[:timeout])
|
103
|
-
return false
|
104
|
-
end
|
63
|
+
def wait_for_green(arguments={})
|
64
|
+
Cluster.new(arguments).wait_for_green
|
65
|
+
end
|
105
66
|
|
106
|
-
|
107
|
-
FileUtils.rm_rf "#{arguments[:path_data]}/#{arguments[:cluster_name]}" if clear_cluster
|
67
|
+
module_function :start, :stop, :running?, :wait_for_green
|
108
68
|
|
109
|
-
|
110
|
-
|
111
|
-
" Elasticsearch nodes..".ansi(:faint)
|
69
|
+
class Cluster
|
70
|
+
attr_reader :arguments
|
112
71
|
|
113
|
-
|
72
|
+
COMMANDS = {
|
73
|
+
'0.90' => lambda { |arguments, node_number|
|
74
|
+
<<-COMMAND.gsub(/ /, '')
|
75
|
+
#{arguments[:command]} \
|
76
|
+
-f \
|
77
|
+
-D es.cluster.name=#{arguments[:cluster_name]} \
|
78
|
+
-D es.node.name=#{arguments[:node_name]}-#{node_number} \
|
79
|
+
-D es.http.port=#{arguments[:port].to_i + (node_number-1)} \
|
80
|
+
-D es.path.data=#{arguments[:path_data]} \
|
81
|
+
-D es.path.work=#{arguments[:path_work]} \
|
82
|
+
-D es.path.logs=#{arguments[:path_logs]} \
|
83
|
+
-D es.cluster.routing.allocation.disk.threshold_enabled=false \
|
84
|
+
-D es.network.host=#{arguments[:network_host]} \
|
85
|
+
-D es.discovery.zen.ping.multicast.enabled=#{arguments[:multicast_enabled]} \
|
86
|
+
-D es.script.inline=true \
|
87
|
+
-D es.script.indexed=true \
|
88
|
+
-D es.node.test=true \
|
89
|
+
-D es.node.testattr=test \
|
90
|
+
-D es.node.bench=true \
|
91
|
+
-D es.path.repo=/tmp \
|
92
|
+
-D es.repositories.url.allowed_urls=http://snapshot.test* \
|
93
|
+
-D es.logger.level=DEBUG \
|
94
|
+
#{arguments[:es_params]} \
|
95
|
+
> /dev/null
|
96
|
+
COMMAND
|
97
|
+
},
|
114
98
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
#{arguments[:command]} \
|
99
|
+
'1.0' => lambda { |arguments, node_number|
|
100
|
+
<<-COMMAND.gsub(/ /, '')
|
101
|
+
#{arguments[:command]} \
|
119
102
|
-D es.foreground=yes \
|
120
103
|
-D es.cluster.name=#{arguments[:cluster_name]} \
|
121
|
-
-D es.node.name=#{arguments[:node_name]}-#{
|
122
|
-
-D es.http.port=#{arguments[:port].to_i + (
|
104
|
+
-D es.node.name=#{arguments[:node_name]}-#{node_number} \
|
105
|
+
-D es.http.port=#{arguments[:port].to_i + (node_number-1)} \
|
123
106
|
-D es.path.data=#{arguments[:path_data]} \
|
124
107
|
-D es.path.work=#{arguments[:path_work]} \
|
125
108
|
-D es.path.logs=#{arguments[:path_logs]} \
|
126
109
|
-D es.cluster.routing.allocation.disk.threshold_enabled=false \
|
127
|
-
-D es.network.host=#{
|
110
|
+
-D es.network.host=#{arguments[:network_host]} \
|
128
111
|
-D es.discovery.zen.ping.multicast.enabled=#{arguments[:multicast_enabled]} \
|
129
112
|
-D es.script.inline=on \
|
130
113
|
-D es.script.indexed=on \
|
@@ -133,196 +116,472 @@ module Elasticsearch
|
|
133
116
|
-D es.node.bench=true \
|
134
117
|
-D es.path.repo=/tmp \
|
135
118
|
-D es.repositories.url.allowed_urls=http://snapshot.test* \
|
136
|
-
-D es.logger.level
|
119
|
+
-D es.logger.level=#{ENV['DEBUG'] ? 'DEBUG' : 'INFO'} \
|
137
120
|
#{arguments[:es_params]} \
|
138
121
|
> /dev/null
|
139
|
-
|
140
|
-
|
122
|
+
COMMAND
|
123
|
+
},
|
141
124
|
|
142
|
-
|
143
|
-
|
144
|
-
|
125
|
+
'2.0' => lambda { |arguments, node_number|
|
126
|
+
<<-COMMAND.gsub(/ /, '')
|
127
|
+
#{arguments[:command]} \
|
128
|
+
-D es.foreground=yes \
|
129
|
+
-D es.cluster.name=#{arguments[:cluster_name]} \
|
130
|
+
-D es.node.name=#{arguments[:node_name]}-#{node_number} \
|
131
|
+
-D es.http.port=#{arguments[:port].to_i + (node_number-1)} \
|
132
|
+
-D es.path.data=#{arguments[:path_data]} \
|
133
|
+
-D es.path.work=#{arguments[:path_work]} \
|
134
|
+
-D es.path.logs=#{arguments[:path_logs]} \
|
135
|
+
-D es.cluster.routing.allocation.disk.threshold_enabled=false \
|
136
|
+
-D es.network.host=#{arguments[:network_host]} \
|
137
|
+
-D es.script.inline=true \
|
138
|
+
-D es.script.stored=true \
|
139
|
+
-D es.node.attr.testattr=test \
|
140
|
+
-D es.path.repo=/tmp \
|
141
|
+
-D es.repositories.url.allowed_urls=http://snapshot.test* \
|
142
|
+
-D es.logger.level=DEBUG \
|
143
|
+
#{arguments[:es_params]} \
|
144
|
+
> /dev/null
|
145
|
+
COMMAND
|
146
|
+
},
|
147
|
+
|
148
|
+
'5.0' => lambda { |arguments, node_number|
|
149
|
+
<<-COMMAND.gsub(/ /, '')
|
150
|
+
#{arguments[:command]} \
|
151
|
+
-E cluster.name=#{arguments[:cluster_name]} \
|
152
|
+
-E node.name=#{arguments[:node_name]}-#{node_number} \
|
153
|
+
-E http.port=#{arguments[:port].to_i + (node_number-1)} \
|
154
|
+
-E path.data=#{arguments[:path_data]} \
|
155
|
+
-E path.logs=#{arguments[:path_logs]} \
|
156
|
+
-E cluster.routing.allocation.disk.threshold_enabled=false \
|
157
|
+
-E network.host=#{arguments[:network_host]} \
|
158
|
+
-E script.inline=true \
|
159
|
+
-E script.stored=true \
|
160
|
+
-E node.attr.testattr=test \
|
161
|
+
-E path.repo=/tmp \
|
162
|
+
-E repositories.url.allowed_urls=http://snapshot.test* \
|
163
|
+
-E discovery.zen.minimum_master_nodes=#{arguments[:number_of_nodes]-1} \
|
164
|
+
-E logger.level=DEBUG \
|
165
|
+
#{arguments[:es_params]} \
|
166
|
+
> /dev/null
|
167
|
+
COMMAND
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
# Create a new instance of the Cluster class
|
172
|
+
#
|
173
|
+
# @option arguments [String] :cluster_name Cluster name (default: `elasticsearch_test`)
|
174
|
+
# @option arguments [Integer] :nodes Number of desired nodes (default: 2)
|
175
|
+
# @option arguments [String] :command Elasticsearch command (default: `elasticsearch`)
|
176
|
+
# @option arguments [String] :port Starting port number; will be auto-incremented (default: 9250)
|
177
|
+
# @option arguments [String] :node_name The node name (will be appended with a number)
|
178
|
+
# @option arguments [String] :path_data Path to the directory to store data in
|
179
|
+
# @option arguments [String] :path_work Path to the directory with auxiliary files
|
180
|
+
# @option arguments [String] :path_logs Path to the directory with log files
|
181
|
+
# @option arguments [Boolean] :multicast_enabled Whether multicast is enabled (default: true)
|
182
|
+
# @option arguments [Integer] :timeout Timeout when starting the cluster (default: 30)
|
183
|
+
# @option arguments [String] :network_host The host that nodes will bind on and publish to
|
184
|
+
# @option arguments [Boolean] :clear_cluster Wipe out cluster content on startup (default: true)
|
185
|
+
#
|
186
|
+
# You can also use environment variables to set the constructor options (see source).
|
187
|
+
#
|
188
|
+
# @see Cluster#start
|
189
|
+
#
|
190
|
+
def initialize(arguments={})
|
191
|
+
@arguments = arguments
|
192
|
+
|
193
|
+
@arguments[:command] ||= ENV.fetch('TEST_CLUSTER_COMMAND', 'elasticsearch')
|
194
|
+
@arguments[:port] ||= ENV.fetch('TEST_CLUSTER_PORT', 9250).to_i
|
195
|
+
@arguments[:cluster_name] ||= ENV.fetch('TEST_CLUSTER_NAME', __default_cluster_name).chomp
|
196
|
+
@arguments[:node_name] ||= ENV.fetch('TEST_CLUSTER_NODE_NAME', 'node')
|
197
|
+
@arguments[:path_data] ||= ENV.fetch('TEST_CLUSTER_DATA', '/tmp/elasticsearch_test')
|
198
|
+
@arguments[:path_work] ||= ENV.fetch('TEST_CLUSTER_TMP', '/tmp')
|
199
|
+
@arguments[:path_logs] ||= ENV.fetch('TEST_CLUSTER_LOGS', '/tmp/log/elasticsearch')
|
200
|
+
@arguments[:es_params] ||= ENV.fetch('TEST_CLUSTER_PARAMS', '')
|
201
|
+
@arguments[:multicast_enabled] ||= ENV.fetch('TEST_CLUSTER_MULTICAST', 'true')
|
202
|
+
@arguments[:timeout] ||= ENV.fetch('TEST_CLUSTER_TIMEOUT', 30).to_i
|
203
|
+
@arguments[:number_of_nodes] ||= ENV.fetch('TEST_CLUSTER_NODES', 2).to_i
|
204
|
+
@arguments[:network_host] ||= ENV.fetch('TEST_CLUSTER_NETWORK_HOST', __default_network_host)
|
205
|
+
|
206
|
+
@clear_cluster = !!@arguments[:clear_cluster] || (ENV.fetch('TEST_CLUSTER_CLEAR', 'true') != 'false')
|
207
|
+
|
208
|
+
# Make sure `cluster_name` is not dangerous
|
209
|
+
raise ArgumentError, "The `cluster_name` argument cannot be empty string or a slash" \
|
210
|
+
if @arguments[:cluster_name] =~ /^[\/\\]?$/
|
145
211
|
end
|
146
212
|
|
147
|
-
#
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
213
|
+
# Starts a cluster
|
214
|
+
#
|
215
|
+
# Launches the specified number of nodes in a test-suitable configuration and prints
|
216
|
+
# information about the cluster -- unless this specific cluster is already running.
|
217
|
+
#
|
218
|
+
# @example Start a cluster with the default configuration (2 nodes, installed version, etc)
|
219
|
+
# Elasticsearch::Extensions::Test::Cluster::Cluster.new.start
|
220
|
+
#
|
221
|
+
# @example Start a cluster with a custom configuration
|
222
|
+
# Elasticsearch::Extensions::Test::Cluster::Cluster.new(
|
223
|
+
# cluster_name: 'my-cluster',
|
224
|
+
# nodes: 3,
|
225
|
+
# node_name: 'my-node',
|
226
|
+
# port: 9350
|
227
|
+
# ).start
|
228
|
+
#
|
229
|
+
# @example Start a cluster with a different Elasticsearch version
|
230
|
+
# Elasticsearch::Extensions::Test::Cluster::Cluster.new(
|
231
|
+
# command: "/usr/local/Cellar/elasticsearch/1.0.0.Beta2/bin/elasticsearch"
|
232
|
+
# ).start
|
233
|
+
#
|
234
|
+
# @return Boolean,Array
|
235
|
+
# @see Cluster#stop
|
236
|
+
#
|
237
|
+
def start
|
238
|
+
if self.running?
|
239
|
+
STDOUT.print "[!] Elasticsearch cluster already running".ansi(:red)
|
240
|
+
return false
|
241
|
+
end
|
152
242
|
|
153
|
-
|
154
|
-
return true
|
155
|
-
end
|
243
|
+
__remove_cluster_data
|
156
244
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
#
|
161
|
-
# @example Stop the default cluster
|
162
|
-
# Elasticsearch::Extensions::Test::Cluster.stop
|
163
|
-
#
|
164
|
-
# @example Stop the cluster reachable on specific port
|
165
|
-
# Elasticsearch::Extensions::Test::Cluster.stop port: 9350
|
166
|
-
#
|
167
|
-
# @return Boolean
|
168
|
-
# @see Cluster#start Cluster.start
|
169
|
-
#
|
170
|
-
def stop(arguments={})
|
171
|
-
arguments[:port] ||= (ENV['TEST_CLUSTER_PORT'] || 9250).to_i
|
172
|
-
arguments[:network_host] ||= ENV.fetch('TEST_CLUSTER_NETWORK_HOST', @@network_host)
|
173
|
-
|
174
|
-
nodes = begin
|
175
|
-
JSON.parse(Net::HTTP.get(URI("http://#{arguments[:network_host]}:#{arguments[:port]}/_nodes/?process")))
|
176
|
-
rescue Exception => e
|
177
|
-
STDERR.puts "[!] Exception raised when stopping the cluster: #{e.inspect}".ansi(:red)
|
178
|
-
nil
|
179
|
-
end
|
245
|
+
STDOUT.print "Starting ".ansi(:faint) + arguments[:number_of_nodes].to_s.ansi(:bold, :faint) +
|
246
|
+
" Elasticsearch nodes..".ansi(:faint)
|
247
|
+
pids = []
|
180
248
|
|
181
|
-
|
249
|
+
STDERR.puts "Using Elasticsearch version [#{version}]" if ENV['DEBUG']
|
182
250
|
|
183
|
-
|
251
|
+
arguments[:number_of_nodes].times do |n|
|
252
|
+
n += 1
|
253
|
+
command = __command(version, arguments, n)
|
254
|
+
STDERR.puts command.gsub(/ {1,}/, ' ') if ENV['DEBUG']
|
184
255
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
begin
|
190
|
-
Process.kill signal, pid
|
191
|
-
rescue Exception => e
|
192
|
-
print "[#{e.class}] PID #{pid} not found. ".ansi(:red)
|
193
|
-
end
|
256
|
+
pid = Process.spawn(command)
|
257
|
+
Process.detach pid
|
258
|
+
pids << pid
|
259
|
+
end
|
194
260
|
|
195
|
-
|
196
|
-
|
261
|
+
__check_for_running_processes(pids)
|
262
|
+
wait_for_green
|
263
|
+
__print_cluster_info
|
264
|
+
|
265
|
+
return true
|
266
|
+
end
|
197
267
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
268
|
+
# Stops the cluster
|
269
|
+
#
|
270
|
+
# Fetches the PID numbers from "Nodes Info" API and terminates matching nodes.
|
271
|
+
#
|
272
|
+
# @example Stop the default cluster
|
273
|
+
# Elasticsearch::Extensions::Test::Cluster::Cluster.new.stop
|
274
|
+
#
|
275
|
+
# @example Stop the cluster reachable on specific port
|
276
|
+
# Elasticsearch::Extensions::Test::Cluster::Cluster.new(port: 9350).stop
|
277
|
+
#
|
278
|
+
# @return Boolean,Array
|
279
|
+
# @see Cluster#start
|
280
|
+
#
|
281
|
+
def stop
|
282
|
+
begin
|
283
|
+
nodes = __get_nodes
|
284
|
+
rescue Exception => e
|
285
|
+
STDERR.puts "[!] Exception raised when stopping the cluster: #{e.inspect}".ansi(:red)
|
286
|
+
nil
|
287
|
+
end
|
288
|
+
|
289
|
+
return false if nodes.nil? or nodes.empty?
|
290
|
+
|
291
|
+
pids = nodes['nodes'].map { |id, info| info['process']['id'] }
|
292
|
+
|
293
|
+
unless pids.empty?
|
294
|
+
STDOUT.print "\nStopping Elasticsearch nodes... ".ansi(:faint)
|
295
|
+
pids.each_with_index do |pid, i|
|
296
|
+
['INT','KILL'].each do |signal|
|
297
|
+
begin
|
298
|
+
Process.kill signal, pid
|
299
|
+
rescue Exception => e
|
300
|
+
STDOUT.print "[#{e.class}] PID #{pid} not found. ".ansi(:red)
|
301
|
+
end
|
302
|
+
|
303
|
+
# Give the system some breathing space to finish...
|
304
|
+
Kernel.sleep 1
|
305
|
+
|
306
|
+
# Check that pid really is dead
|
307
|
+
begin
|
308
|
+
Process.getpgid pid
|
309
|
+
# `getpgid` will raise error if pid is dead, so if we get here, try next signal
|
310
|
+
next
|
311
|
+
rescue Errno::ESRCH
|
312
|
+
STDOUT.print "Stopped PID #{pid}".ansi(:green) +
|
313
|
+
(ENV['DEBUG'] ? " with #{signal} signal".ansi(:green) : '') +
|
314
|
+
". ".ansi(:green)
|
315
|
+
break # pid is dead
|
316
|
+
end
|
206
317
|
end
|
207
318
|
end
|
319
|
+
STDOUT.puts
|
320
|
+
else
|
321
|
+
return false
|
208
322
|
end
|
209
|
-
|
210
|
-
|
211
|
-
false
|
323
|
+
|
324
|
+
return pids
|
212
325
|
end
|
213
326
|
|
214
|
-
|
215
|
-
|
327
|
+
# Returns true when a specific test node is running within the cluster
|
328
|
+
#
|
329
|
+
# @return Boolean
|
330
|
+
#
|
331
|
+
def running?
|
332
|
+
if cluster_health = Timeout::timeout(0.25) { __get_cluster_health } rescue nil
|
333
|
+
return cluster_health['cluster_name'] == arguments[:cluster_name] && \
|
334
|
+
cluster_health['number_of_nodes'] == arguments[:number_of_nodes]
|
335
|
+
end
|
336
|
+
return false
|
337
|
+
end
|
216
338
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
#
|
225
|
-
def running?(arguments={})
|
226
|
-
port = arguments[:on] || (ENV['TEST_CLUSTER_PORT'] || 9250).to_i
|
227
|
-
cluster_name = arguments[:as] || (ENV.fetch('TEST_CLUSTER_NAME', @@default_cluster_name).chomp)
|
228
|
-
number_of_nodes = arguments[:num] || (ENV.fetch('TEST_CLUSTER_NODES', @@number_of_nodes)).to_i
|
339
|
+
# Waits until the cluster is green and prints information about it
|
340
|
+
#
|
341
|
+
# @return Boolean
|
342
|
+
#
|
343
|
+
def wait_for_green
|
344
|
+
__wait_for_status('green', 60)
|
345
|
+
end
|
229
346
|
|
230
|
-
|
231
|
-
|
232
|
-
|
347
|
+
# Returns the major version of Elasticsearch
|
348
|
+
#
|
349
|
+
# @return String
|
350
|
+
# @see __determine_version
|
351
|
+
#
|
352
|
+
def version
|
353
|
+
@version ||= __determine_version
|
233
354
|
end
|
234
|
-
return false
|
235
|
-
end
|
236
355
|
|
237
|
-
# Waits until the cluster is green and prints information
|
238
|
-
#
|
239
|
-
# @example Print the information about the default cluster
|
240
|
-
# Elasticsearch::Extensions::Test::Cluster.wait_for_green
|
241
|
-
#
|
242
|
-
# @param (see #__wait_for_status)
|
243
|
-
#
|
244
|
-
# @return Boolean
|
245
|
-
#
|
246
|
-
def wait_for_green(port=9250, timeout=60)
|
247
|
-
__wait_for_status('green', port, timeout)
|
248
|
-
end
|
249
356
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
357
|
+
# Returns default `:network_host` setting based on the version
|
358
|
+
#
|
359
|
+
# @api private
|
360
|
+
#
|
361
|
+
# @return String
|
362
|
+
#
|
363
|
+
def __default_network_host
|
364
|
+
case version
|
365
|
+
when /^0|^1/
|
366
|
+
'0.0.0.0'
|
367
|
+
when /^2/
|
368
|
+
'0.0.0.0'
|
369
|
+
when /^5/
|
370
|
+
'_local_'
|
371
|
+
else
|
372
|
+
raise RuntimeError, "Cannot determine default network host from version [#{version}]"
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
# Returns a reasonably unique cluster name
|
377
|
+
#
|
378
|
+
# @api private
|
379
|
+
#
|
380
|
+
# @return String
|
381
|
+
#
|
382
|
+
def __default_cluster_name
|
383
|
+
"elasticsearch-test-#{Socket.gethostname.downcase}"
|
384
|
+
end
|
385
|
+
|
386
|
+
# Returns the HTTP URL for the cluster based on `:network_host` setting
|
387
|
+
#
|
388
|
+
# @api private
|
389
|
+
#
|
390
|
+
# @return String
|
391
|
+
#
|
392
|
+
def __cluster_url
|
393
|
+
if '_local_' == arguments[:network_host]
|
394
|
+
"http://localhost:#{arguments[:port]}"
|
395
|
+
else
|
396
|
+
"http://#{arguments[:network_host]}:#{arguments[:port]}"
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
# Determine Elasticsearch version to be launched
|
401
|
+
#
|
402
|
+
# Tries to parse the version number from the `lib/elasticsearch-X.Y.Z.jar` file,
|
403
|
+
# it not available, uses `elasticsearch --version` or `elasticsearch -v`
|
404
|
+
#
|
405
|
+
# @api private
|
406
|
+
#
|
407
|
+
# @return String
|
408
|
+
#
|
409
|
+
def __determine_version
|
410
|
+
path_to_lib = File.dirname(arguments[:command]) + '/../lib/'
|
411
|
+
|
412
|
+
jar = Dir.entries(path_to_lib).select { |f| f.start_with? 'elasticsearch' }.first if File.exist? path_to_lib
|
413
|
+
|
414
|
+
version = if jar
|
415
|
+
if m = jar.match(/elasticsearch\-(\d+\.\d+.\d+).*/)
|
416
|
+
m[1]
|
417
|
+
else
|
418
|
+
raise RuntimeError, "Cannot determine Elasticsearch version from jar [#{jar}]"
|
419
|
+
end
|
420
|
+
else
|
421
|
+
STDERR.puts "[!] Cannot find Elasticsearch .jar from path to command [#{arguments[:command]}], using `elasticsearch --version`" if ENV['DEBUG']
|
422
|
+
|
423
|
+
output = ''
|
424
|
+
|
425
|
+
begin
|
426
|
+
# First, try the new `--version` syntax...
|
427
|
+
STDERR.puts "Running [#{arguments[:command]} --version] to determine version" if ENV['DEBUG']
|
428
|
+
Timeout::timeout(10) { output = `#{arguments[:command]} --version` }
|
429
|
+
rescue Timeout::Error
|
430
|
+
# ...else, the new `-v` syntax
|
431
|
+
STDERR.puts "Running [#{arguments[:command]} -v] to determine version" if ENV['DEBUG']
|
432
|
+
output = `#{arguments[:command]} -v`
|
433
|
+
end
|
434
|
+
|
435
|
+
STDERR.puts "> #{output}" if ENV['DEBUG']
|
436
|
+
|
437
|
+
if output.empty?
|
438
|
+
raise RuntimeError, "Cannot determine Elasticsearch version from [#{arguments[:command]} --version] or [#{arguments[:command]} -v]"
|
439
|
+
end
|
440
|
+
|
441
|
+
if m = output.match(/Version: (\d\.\d.\d).*,/)
|
442
|
+
m[1]
|
443
|
+
else
|
444
|
+
raise RuntimeError, "Cannot determine Elasticsearch version from elasticsearch --version output [#{output}]"
|
272
445
|
end
|
446
|
+
end
|
447
|
+
|
448
|
+
case version
|
449
|
+
when /^0\.90.*/
|
450
|
+
'0.90'
|
451
|
+
when /^1\..*/
|
452
|
+
'1.0'
|
453
|
+
when /^2\..*/
|
454
|
+
'2.0'
|
455
|
+
when /^5\..*/
|
456
|
+
'5.0'
|
457
|
+
else
|
458
|
+
raise RuntimeError, "Cannot determine major version from [#{version}]"
|
459
|
+
end
|
460
|
+
end
|
273
461
|
|
274
|
-
|
462
|
+
# Returns the launch command for a specific version
|
463
|
+
#
|
464
|
+
# @api private
|
465
|
+
#
|
466
|
+
# @return String
|
467
|
+
#
|
468
|
+
def __command(version, arguments, node_number)
|
469
|
+
if command = COMMANDS[version]
|
470
|
+
command.call(arguments, node_number)
|
471
|
+
else
|
472
|
+
raise ArgumentError, "Cannot find command for version [#{version}]"
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
476
|
+
# Blocks the process and waits for the cluster to be in a "green" state
|
477
|
+
#
|
478
|
+
# Prints information about the cluster on STDOUT if the cluster is available.
|
479
|
+
#
|
480
|
+
# @param status [String] The status to wait for (yellow, green)
|
481
|
+
# @param timeout [Integer] The explicit timeout for the operation
|
482
|
+
#
|
483
|
+
# @api private
|
484
|
+
#
|
485
|
+
# @return Boolean
|
486
|
+
#
|
487
|
+
def __wait_for_status(status='green', timeout=30)
|
488
|
+
Timeout::timeout(timeout) do
|
489
|
+
loop do
|
490
|
+
response = __get_cluster_health(status)
|
491
|
+
|
492
|
+
if response && response['status'] == status && ( arguments[:number_of_nodes].nil? || arguments[:number_of_nodes].to_i == response['number_of_nodes'].to_i )
|
493
|
+
break
|
494
|
+
end
|
275
495
|
|
276
|
-
|
277
|
-
|
496
|
+
STDOUT.print '.'.ansi(:faint)
|
497
|
+
sleep 1
|
278
498
|
end
|
499
|
+
end
|
500
|
+
|
501
|
+
return true
|
502
|
+
end
|
279
503
|
|
280
|
-
|
281
|
-
|
504
|
+
# Print information about the cluster on STDOUT
|
505
|
+
#
|
506
|
+
# @api private
|
507
|
+
#
|
508
|
+
# @return Nil
|
509
|
+
#
|
510
|
+
def __print_cluster_info
|
511
|
+
health = JSON.parse(Net::HTTP.get(URI("#{__cluster_url}/_cluster/health")))
|
512
|
+
nodes = if version == '0.90'
|
513
|
+
JSON.parse(Net::HTTP.get(URI("#{__cluster_url}/_nodes/?process&http")))
|
514
|
+
else
|
515
|
+
JSON.parse(Net::HTTP.get(URI("#{__cluster_url}/_nodes/process,http")))
|
516
|
+
end
|
517
|
+
master = JSON.parse(Net::HTTP.get(URI("#{__cluster_url}/_cluster/state")))['master_node']
|
518
|
+
|
519
|
+
puts "\n",
|
520
|
+
('-'*80).ansi(:faint),
|
521
|
+
'Cluster: '.ljust(20).ansi(:faint) + health['cluster_name'].to_s.ansi(:faint),
|
522
|
+
'Status: '.ljust(20).ansi(:faint) + health['status'].to_s.ansi(:faint),
|
523
|
+
'Nodes: '.ljust(20).ansi(:faint) + health['number_of_nodes'].to_s.ansi(:faint)
|
524
|
+
|
525
|
+
nodes['nodes'].each do |id, info|
|
526
|
+
m = id == master ? '*' : '+'
|
527
|
+
puts ''.ljust(20) +
|
528
|
+
"#{m} ".ansi(:faint) +
|
529
|
+
"#{info['name'].ansi(:bold)} ".ansi(:faint) +
|
530
|
+
"| version: #{info['version'] rescue 'N/A'}, ".ansi(:faint) +
|
531
|
+
"pid: #{info['process']['id'] rescue 'N/A'}, ".ansi(:faint) +
|
532
|
+
"address: #{info['http']['bound_address'] rescue 'N/A'}".ansi(:faint)
|
282
533
|
end
|
283
534
|
end
|
284
535
|
|
285
|
-
|
286
|
-
|
536
|
+
# Tries to load cluster health information
|
537
|
+
#
|
538
|
+
# @api private
|
539
|
+
#
|
540
|
+
# @return Hash,Nil
|
541
|
+
#
|
542
|
+
def __get_cluster_health(status=nil)
|
543
|
+
uri = URI("#{__cluster_url}/_cluster/health")
|
544
|
+
uri.query = "wait_for_status=#{status}" if status
|
545
|
+
|
546
|
+
begin
|
547
|
+
response = Net::HTTP.get(uri)
|
548
|
+
rescue Exception => e
|
549
|
+
STDERR.puts e.inspect if ENV['DEBUG']
|
550
|
+
return nil
|
551
|
+
end
|
287
552
|
|
288
|
-
|
289
|
-
#
|
290
|
-
# @api private
|
291
|
-
#
|
292
|
-
def __print_cluster_info(port)
|
293
|
-
health = JSON.parse(Net::HTTP.get(URI("http://#{@@network_host}:#{port}/_cluster/health")))
|
294
|
-
nodes = JSON.parse(Net::HTTP.get(URI("http://#{@@network_host}:#{port}/_nodes/process,http")))
|
295
|
-
master = JSON.parse(Net::HTTP.get(URI("http://#{@@network_host}:#{port}/_cluster/state")))['master_node']
|
296
|
-
|
297
|
-
puts "\n",
|
298
|
-
('-'*80).ansi(:faint),
|
299
|
-
'Cluster: '.ljust(20).ansi(:faint) + health['cluster_name'].to_s.ansi(:faint),
|
300
|
-
'Status: '.ljust(20).ansi(:faint) + health['status'].to_s.ansi(:faint),
|
301
|
-
'Nodes: '.ljust(20).ansi(:faint) + health['number_of_nodes'].to_s.ansi(:faint)
|
302
|
-
|
303
|
-
nodes['nodes'].each do |id, info|
|
304
|
-
m = id == master ? '*' : '+'
|
305
|
-
puts ''.ljust(20) +
|
306
|
-
"#{m} ".ansi(:faint) +
|
307
|
-
"#{info['name'].ansi(:bold)} ".ansi(:faint) +
|
308
|
-
"| version: #{info['version'] rescue 'N/A'}, ".ansi(:faint) +
|
309
|
-
"pid: #{info['process']['id'] rescue 'N/A'}, ".ansi(:faint) +
|
310
|
-
"address: #{info['http']['bound_address'] rescue 'N/A'}".ansi(:faint)
|
553
|
+
JSON.parse(response)
|
311
554
|
end
|
312
|
-
end
|
313
555
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
return JSON.parse(response)
|
556
|
+
# Remove the data directory (unless it has been disabled by arguments)
|
557
|
+
#
|
558
|
+
# @api private
|
559
|
+
#
|
560
|
+
def __remove_cluster_data
|
561
|
+
# Wipe out data on disk for this cluster name by default
|
562
|
+
FileUtils.rm_rf "#{arguments[:path_data]}/#{arguments[:cluster_name]}" if @clear_cluster
|
322
563
|
end
|
323
|
-
end
|
324
564
|
|
325
|
-
|
565
|
+
|
566
|
+
# Check whether process for PIDs are running
|
567
|
+
#
|
568
|
+
# @api private
|
569
|
+
#
|
570
|
+
def __check_for_running_processes(pids)
|
571
|
+
if `ps -p #{pids.join(' ')}`.split("\n").size < arguments[:number_of_nodes]+1
|
572
|
+
STDERR.puts "", "[!!!] Process failed to start (see output above)".ansi(:red)
|
573
|
+
exit(1)
|
574
|
+
end
|
575
|
+
end
|
576
|
+
|
577
|
+
# Get the information about nodes
|
578
|
+
#
|
579
|
+
# @api private
|
580
|
+
#
|
581
|
+
def __get_nodes
|
582
|
+
JSON.parse(Net::HTTP.get(URI("#{__cluster_url}/_nodes/process")))
|
583
|
+
end
|
584
|
+
end
|
326
585
|
end
|
327
586
|
end
|
328
587
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
require 'elasticsearch/extensions/test/cluster'
|
5
|
+
|
6
|
+
class Elasticsearch::Extensions::TestClusterIntegrationTest < Test::Unit::TestCase
|
7
|
+
context "The Test::Cluster" do
|
8
|
+
PATH_TO_BUILDS = Pathname(File.expand_path('../../../../../../tmp/builds', __FILE__))
|
9
|
+
|
10
|
+
unless PATH_TO_BUILDS.exist?
|
11
|
+
puts "Path to builds doesn't exist, skipping TestClusterIntegrationTest"
|
12
|
+
exit(0)
|
13
|
+
end
|
14
|
+
|
15
|
+
@builds = begin
|
16
|
+
PATH_TO_BUILDS.entries.reject { |f| f.to_s =~ /^\./ }
|
17
|
+
rescue Errno::ENOENT
|
18
|
+
[]
|
19
|
+
end
|
20
|
+
|
21
|
+
@builds.each do |build|
|
22
|
+
should "start and stop #{build.to_s}" do
|
23
|
+
puts ("----- #{build.to_s} " + "-"*(80-7-build.to_s.size)).to_s.ansi(:bold)
|
24
|
+
Elasticsearch::Extensions::Test::Cluster.start command: PATH_TO_BUILDS.join(build.join('bin/elasticsearch')).to_s
|
25
|
+
Elasticsearch::Extensions::Test::Cluster.stop command: PATH_TO_BUILDS.join(build.join('bin/elasticsearch')).to_s
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,280 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'elasticsearch/extensions/test/cluster'
|
4
|
+
|
5
|
+
class Elasticsearch::Extensions::TestClusterTest < Test::Unit::TestCase
|
6
|
+
include Elasticsearch::Extensions::Test
|
7
|
+
context "The Test::Cluster" do
|
8
|
+
context "module" do
|
9
|
+
should "delegate the methods to the class" do
|
10
|
+
Cluster::Cluster
|
11
|
+
.expects(:new)
|
12
|
+
.with({foo: 'bar'})
|
13
|
+
.returns(mock start: true, stop: true, running?: true, wait_for_green: true)
|
14
|
+
.times(4)
|
15
|
+
|
16
|
+
Elasticsearch::Extensions::Test::Cluster.start foo: 'bar'
|
17
|
+
Elasticsearch::Extensions::Test::Cluster.stop foo: 'bar'
|
18
|
+
Elasticsearch::Extensions::Test::Cluster.running? foo: 'bar'
|
19
|
+
Elasticsearch::Extensions::Test::Cluster.wait_for_green foo: 'bar'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "class" do
|
24
|
+
setup do
|
25
|
+
Elasticsearch::Extensions::Test::Cluster::Cluster.any_instance.stubs(:__default_network_host).returns('_local_')
|
26
|
+
|
27
|
+
@subject = Elasticsearch::Extensions::Test::Cluster::Cluster.new
|
28
|
+
@subject.stubs(:__remove_cluster_data).returns(true)
|
29
|
+
end
|
30
|
+
|
31
|
+
teardown do
|
32
|
+
ENV.delete('TEST_CLUSTER_PORT')
|
33
|
+
end
|
34
|
+
|
35
|
+
should "be initialized with parameters" do
|
36
|
+
c = Cluster::Cluster.new port: 9400
|
37
|
+
|
38
|
+
assert_equal 9400, c.arguments[:port]
|
39
|
+
end
|
40
|
+
|
41
|
+
should "take parameters from environment variables" do
|
42
|
+
ENV['TEST_CLUSTER_PORT'] = '9400'
|
43
|
+
|
44
|
+
c = Cluster::Cluster.new
|
45
|
+
|
46
|
+
assert_equal 9400, c.arguments[:port]
|
47
|
+
end
|
48
|
+
|
49
|
+
should "raise exception for dangerous cluster name" do
|
50
|
+
assert_raise(ArgumentError) { Cluster::Cluster.new cluster_name: '' }
|
51
|
+
assert_raise(ArgumentError) { Cluster::Cluster.new cluster_name: '/' }
|
52
|
+
end
|
53
|
+
|
54
|
+
should "have a version" do
|
55
|
+
@subject.unstub(:version)
|
56
|
+
@subject.expects(:__determine_version).returns('2.0')
|
57
|
+
assert_equal '2.0', @subject.version
|
58
|
+
end
|
59
|
+
|
60
|
+
should "have a default network host" do
|
61
|
+
Cluster::Cluster.any_instance.unstub(:__default_network_host)
|
62
|
+
Cluster::Cluster.any_instance.stubs(:version).returns('5.0')
|
63
|
+
|
64
|
+
assert_equal '_local_', Cluster::Cluster.new.__default_network_host
|
65
|
+
end
|
66
|
+
|
67
|
+
should "have a default cluster name" do
|
68
|
+
Socket.stubs(:gethostname).returns('FOOBAR')
|
69
|
+
|
70
|
+
assert_equal 'elasticsearch-test-foobar', Cluster::Cluster.new.__default_cluster_name
|
71
|
+
end
|
72
|
+
|
73
|
+
should "have a cluster URL for new versions" do
|
74
|
+
assert_equal 'http://localhost:9250', Cluster::Cluster.new(network_host: '_local_').__cluster_url
|
75
|
+
end
|
76
|
+
|
77
|
+
should "have a cluster URL for old versions" do
|
78
|
+
assert_equal 'http://192.168.1.1:9250', Cluster::Cluster.new(network_host: '192.168.1.1').__cluster_url
|
79
|
+
end
|
80
|
+
|
81
|
+
should "return corresponding command to a version" do
|
82
|
+
assert_match /\-D es\.foreground=yes/, @subject.__command('2.0', @subject.arguments, 1)
|
83
|
+
end
|
84
|
+
|
85
|
+
should "raise an error when a corresponding command cannot be found" do
|
86
|
+
assert_raise ArgumentError do
|
87
|
+
@subject.__command('FOOBAR', @subject.arguments, 1)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "when starting a cluster, " do
|
92
|
+
should "return false when it's already running" do
|
93
|
+
Process.expects(:spawn).never
|
94
|
+
|
95
|
+
c = Cluster::Cluster.new
|
96
|
+
|
97
|
+
c.expects(:running?).returns(true)
|
98
|
+
|
99
|
+
assert_equal false, c.start
|
100
|
+
end
|
101
|
+
|
102
|
+
should "start the specified number of nodes" do
|
103
|
+
Process.expects(:spawn).times(3)
|
104
|
+
Process.expects(:detach).times(3)
|
105
|
+
|
106
|
+
c = Cluster::Cluster.new number_of_nodes: 3
|
107
|
+
|
108
|
+
c.expects(:running?).returns(false)
|
109
|
+
|
110
|
+
c.unstub(:__remove_cluster_data)
|
111
|
+
c.expects(:__remove_cluster_data).returns(true)
|
112
|
+
|
113
|
+
c.expects(:wait_for_green).returns(true)
|
114
|
+
c.expects(:__check_for_running_processes).returns(true)
|
115
|
+
c.expects(:__determine_version).returns('5.0')
|
116
|
+
c.expects(:__print_cluster_info).returns(true)
|
117
|
+
|
118
|
+
assert_equal true, c.start
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "when stopping a cluster" do
|
123
|
+
setup do
|
124
|
+
@subject = Elasticsearch::Extensions::Test::Cluster::Cluster.new
|
125
|
+
end
|
126
|
+
|
127
|
+
should "print information about an exception" do
|
128
|
+
@subject.expects(:__get_nodes).raises(Errno::ECONNREFUSED)
|
129
|
+
|
130
|
+
assert_nothing_raised do
|
131
|
+
assert_equal false, @subject.stop
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
should "return false when the nodes are empty" do
|
136
|
+
@subject.expects(:__get_nodes).returns({})
|
137
|
+
assert_equal false, @subject.stop
|
138
|
+
end
|
139
|
+
|
140
|
+
should "kill each node" do
|
141
|
+
@subject.expects(:__get_nodes).returns({'nodes' => { 'n1' => { 'process' => { 'id' => 1 }},
|
142
|
+
'n2' => { 'process' => { 'id' => 2 }} }})
|
143
|
+
|
144
|
+
Kernel.stubs(:sleep)
|
145
|
+
Process.expects(:kill).with('INT', 1)
|
146
|
+
Process.expects(:kill).with('INT', 2)
|
147
|
+
Process.expects(:getpgid).with(1).raises(Errno::ESRCH)
|
148
|
+
Process.expects(:getpgid).with(2).raises(Errno::ESRCH)
|
149
|
+
|
150
|
+
assert_equal [1, 2], @subject.stop
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "when checking if the cluster is running" do
|
155
|
+
setup do
|
156
|
+
@subject = Elasticsearch::Extensions::Test::Cluster::Cluster.new \
|
157
|
+
cluster_name: 'test',
|
158
|
+
number_of_nodes: 2
|
159
|
+
end
|
160
|
+
|
161
|
+
should "return true" do
|
162
|
+
@subject.expects(:__get_cluster_health).returns({'cluster_name' => 'test', 'number_of_nodes' => 2})
|
163
|
+
assert_equal true, @subject.running?
|
164
|
+
end
|
165
|
+
|
166
|
+
should "return false" do
|
167
|
+
@subject.expects(:__get_cluster_health).returns({'cluster_name' => 'test', 'number_of_nodes' => 1})
|
168
|
+
assert_equal false, @subject.running?
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context "when waiting for the green state" do
|
173
|
+
should "return true" do
|
174
|
+
@subject.expects(:__wait_for_status).returns(true)
|
175
|
+
assert_equal true, @subject.wait_for_green
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context "when waiting for cluster state" do
|
180
|
+
setup do
|
181
|
+
@subject = Elasticsearch::Extensions::Test::Cluster::Cluster.new \
|
182
|
+
cluster_name: 'test',
|
183
|
+
number_of_nodes: 1
|
184
|
+
end
|
185
|
+
|
186
|
+
should "return true" do
|
187
|
+
@subject.stubs(:__print_cluster_info)
|
188
|
+
|
189
|
+
@subject
|
190
|
+
.expects(:__get_cluster_health)
|
191
|
+
.with('yellow')
|
192
|
+
.returns({'status' => 'yellow', 'cluster_name' => 'test', 'number_of_nodes' => 1})
|
193
|
+
|
194
|
+
@subject.__wait_for_status('yellow')
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context "when getting the cluster health" do
|
199
|
+
should "return the response" do
|
200
|
+
Net::HTTP
|
201
|
+
.expects(:get)
|
202
|
+
.with(URI('http://localhost:9250/_cluster/health'))
|
203
|
+
.returns(JSON.dump({'status' => 'yellow', 'cluster_name' => 'test', 'number_of_nodes' => 1}))
|
204
|
+
|
205
|
+
@subject.__get_cluster_health
|
206
|
+
end
|
207
|
+
|
208
|
+
should "wait for status" do
|
209
|
+
Net::HTTP
|
210
|
+
.expects(:get)
|
211
|
+
.with(URI('http://localhost:9250/_cluster/health?wait_for_status=green'))
|
212
|
+
.returns(JSON.dump({'status' => 'yellow', 'cluster_name' => 'test', 'number_of_nodes' => 1}))
|
213
|
+
|
214
|
+
@subject.__get_cluster_health('green')
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
context "when getting the list of nodes" do
|
219
|
+
should "return the response" do
|
220
|
+
Net::HTTP
|
221
|
+
.expects(:get)
|
222
|
+
.with(URI('http://localhost:9250/_nodes/process'))
|
223
|
+
.returns(JSON.dump({'nodes' => { 'n1' => {}, 'n2' => {} } }))
|
224
|
+
|
225
|
+
assert_equal 'n1', @subject.__get_nodes['nodes'].keys.first
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context "when determining a version" do
|
230
|
+
setup do
|
231
|
+
@subject = Elasticsearch::Extensions::Test::Cluster::Cluster.new command: '/foo/bar/bin/elasticsearch'
|
232
|
+
end
|
233
|
+
|
234
|
+
should "return version from lib/elasticsearch.X.Y.Z.jar" do
|
235
|
+
File.expects(:exist?).with('/foo/bar/bin/../lib/').returns(true)
|
236
|
+
Dir.expects(:entries).with('/foo/bar/bin/../lib/').returns(['foo.jar', 'elasticsearch-2.3.0.jar'])
|
237
|
+
|
238
|
+
assert_equal '2.0', @subject.__determine_version
|
239
|
+
end
|
240
|
+
|
241
|
+
should "return version from `elasticsearch -v`" do
|
242
|
+
File.expects(:exist?).with('/foo/bar/bin/../lib/').returns(false)
|
243
|
+
|
244
|
+
@subject.expects(:`)
|
245
|
+
.with("/foo/bar/bin/elasticsearch --version")
|
246
|
+
.returns('Version: 2.3.0-SNAPSHOT, Build: d1c86b0/2016-03-30T10:43:20Z, JVM: 1.8.0_60')
|
247
|
+
|
248
|
+
assert_equal '2.0', @subject.__determine_version
|
249
|
+
end
|
250
|
+
|
251
|
+
should "raise an exception when the version cannot be parsed from .jar" do
|
252
|
+
# Incorrect jar version
|
253
|
+
File.expects(:exist?).with('/foo/bar/bin/../lib/').returns(true)
|
254
|
+
Dir.expects(:entries).with('/foo/bar/bin/../lib/').returns(['elasticsearch-100.jar'])
|
255
|
+
|
256
|
+
assert_raise(RuntimeError) { @subject.__determine_version }
|
257
|
+
end
|
258
|
+
|
259
|
+
should "raise an exception when the version cannot be parsed from command output" do
|
260
|
+
File.expects(:exist?).with('/foo/bar/bin/../lib/').returns(false)
|
261
|
+
|
262
|
+
@subject.expects(:`)
|
263
|
+
.with("/foo/bar/bin/elasticsearch --version")
|
264
|
+
.returns('Version: FOOBAR')
|
265
|
+
|
266
|
+
assert_raise(RuntimeError) { @subject.__determine_version }
|
267
|
+
end
|
268
|
+
|
269
|
+
should "raise an exception when the version cannot be converted to short version" do
|
270
|
+
# There's no Elasticsearch version 3...
|
271
|
+
File.expects(:exist?).with('/foo/bar/bin/../lib/').returns(true)
|
272
|
+
Dir.expects(:entries).with('/foo/bar/bin/../lib/').returns(['elasticsearch-3.2.1.jar'])
|
273
|
+
|
274
|
+
assert_raise(RuntimeError) { @subject.__determine_version }
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
end
|
280
|
+
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elasticsearch-extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.22
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karel Minarik
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-06-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ansi
|
@@ -278,6 +278,8 @@ files:
|
|
278
278
|
- test/backup/unit/backup_test.rb
|
279
279
|
- test/reindex/integration/reindex_test.rb
|
280
280
|
- test/reindex/unit/reindex_test.rb
|
281
|
+
- test/test/cluster/integration/cluster_test.rb
|
282
|
+
- test/test/cluster/unit/cluster_test.rb
|
281
283
|
- test/test_helper.rb
|
282
284
|
homepage: ''
|
283
285
|
licenses:
|
@@ -308,5 +310,7 @@ test_files:
|
|
308
310
|
- test/backup/unit/backup_test.rb
|
309
311
|
- test/reindex/integration/reindex_test.rb
|
310
312
|
- test/reindex/unit/reindex_test.rb
|
313
|
+
- test/test/cluster/integration/cluster_test.rb
|
314
|
+
- test/test/cluster/unit/cluster_test.rb
|
311
315
|
- test/test_helper.rb
|
312
316
|
has_rdoc:
|