elasticsearch-transport 0.4.0 → 0.4.2

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.
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
- # Elasticsearch::Client
1
+ # Elasticsearch::Transport
2
2
 
3
3
  **This library is part of the [`elasticsearch-ruby`](https://github.com/elasticsearch/elasticsearch-ruby/) package;
4
4
  please refer to it, unless you want to use this library standalone.**
5
5
 
6
6
  ----
7
7
 
8
- The `elasticsearch-client` library provides a Ruby client for connecting
8
+ The `elasticsearch-transport` library provides a low-level Ruby client for connecting
9
9
  to an [Elasticsearch](http://elasticsearch.org) cluster.
10
10
 
11
11
  It handles connecting to multiple nodes in the cluster, rotating across connections,
@@ -31,16 +31,16 @@ Features overview:
31
31
 
32
32
  Install the package from [Rubygems](https://rubygems.org):
33
33
 
34
- gem install elasticsearch-client
34
+ gem install elasticsearch-transport
35
35
 
36
36
  To use an unreleased version, either add it to your `Gemfile` for [Bundler](http://gembundler.com):
37
37
 
38
- gem 'elasticsearch-client', git: 'git://github.com/elasticsearch/elasticsearch-ruby.git'
38
+ gem 'elasticsearch-transport', git: 'git://github.com/elasticsearch/elasticsearch-ruby.git'
39
39
 
40
40
  or install it from a source code checkout:
41
41
 
42
42
  git clone https://github.com/elasticsearch/elasticsearch-ruby.git
43
- cd elasticsearch-ruby/elasticsearch-client
43
+ cd elasticsearch-ruby/elasticsearch-transport
44
44
  bundle install
45
45
  rake install
46
46
 
@@ -49,12 +49,14 @@ or install it from a source code checkout:
49
49
  In the simplest form, connect to Elasticsearch running on <http://localhost:9200>
50
50
  without any configuration:
51
51
 
52
- require 'elasticsearch/client'
52
+ require 'elasticsearch/transport'
53
53
 
54
54
  client = Elasticsearch::Client.new
55
55
  response = client.perform_request 'GET', '_cluster/health'
56
56
  # => #<Elasticsearch::Transport::Transport::Response:0x007fc5d506ce38 @status=200, @body={ ... } >
57
57
 
58
+ Full documentation is available at <http://rubydoc.info/gems/elasticsearch-transport>.
59
+
58
60
  ## Configuration
59
61
 
60
62
  The client supports many configurations options for setting up and managing connections,
@@ -78,9 +80,13 @@ Instead of Strings, you can pass host information as an array of Hashes:
78
80
 
79
81
  Elasticsearch::Client.new hosts: [ { host: 'myhost1', port: 8080 }, { host: 'myhost2', port: 8080 } ]
80
82
 
83
+ Scheme, HTTP authentication credentials and URL prefixes are handled automatically:
84
+
85
+ Elasticsearch::Client.new url: 'https://username:password@api.server.org:4430/search'
86
+
81
87
  ### Logging
82
88
 
83
- To log requests and responses to standard output with the default logger (an instance of Ruby's {::Logger}) class):
89
+ To log requests and responses to standard output with the default logger (an instance of Ruby's {::Logger} class):
84
90
 
85
91
  Elasticsearch::Client.new log: true
86
92
 
@@ -163,7 +169,7 @@ and only when these are not be available, will use the rest:
163
169
  include Elasticsearch::Transport::Transport::Connections::Selector::Base
164
170
 
165
171
  def select(options={})
166
- connections.reject do |c|
172
+ connections.select do |c|
167
173
  # Try selecting the nodes with a `rack_id:x1` attribute first
168
174
  c.host[:attributes] && c.host[:attributes][:rack_id] == 'x1'
169
175
  end.sample || connections.to_a.sample
@@ -201,7 +207,9 @@ You can also use a [_Curb_](https://rubygems.org/gems/curb) based transport impl
201
207
 
202
208
  It's possible to customize the _Curb_ instance by passing a block to the constructor as well:
203
209
 
204
- configuration = lambda { |c| c.verbose = true }
210
+ configuration = lambda do |c|
211
+ c.verbose = true
212
+ end
205
213
 
206
214
  transport = Elasticsearch::Transport::Transport::HTTP::Curb.new \
207
215
  hosts: [ { host: 'localhost', port: '9200' } ],
@@ -209,6 +217,17 @@ It's possible to customize the _Curb_ instance by passing a block to the constru
209
217
 
210
218
  client = Elasticsearch::Client.new transport: transport
211
219
 
220
+ Instead of passing the transport to the constructor, you can inject it at run time:
221
+
222
+ faraday_client = Elasticsearch::Transport::Transport::HTTP::Faraday.new \
223
+ hosts: [ { host: '33.33.33.10', port: '443', user: 'USERNAME', password: 'PASSWORD', scheme: 'https' } ],
224
+ & lambda { |f| f.instance_variable_set :@ssl, { verify: false }
225
+ f.options[:ssl] = { verify: false }
226
+ f.adapter :excon }
227
+
228
+ client = Elasticsearch::Client.new
229
+ client.transport = faraday_client
230
+
212
231
  You can write your own transport implementation easily, by including the
213
232
  {Elasticsearch::Transport::Transport::Base} module, implementing the required contract,
214
233
  and passing it to the client as the `transport_class` parameter. All the arguments
@@ -228,9 +247,9 @@ and passing it to the client as the `serializer_class` or `serializer` parameter
228
247
  For local development, clone the repository and run `bundle install`. See `rake -T` for a list of
229
248
  available Rake tasks for running tests, generating documentation, starting a testing cluster, etc.
230
249
 
231
- Bug fixes and features must be accompanying by unit tests. Integration tests are written in Ruby 1.9 syntax.
250
+ Bug fixes and features must be covered by unit tests. Integration tests are written in Ruby 1.9 syntax.
232
251
 
233
- Github's pull requests and issues are used to send code contributions and bug reports.
252
+ Github's pull requests and issues are used to communicate, send bug reports and code contributions.
234
253
 
235
254
  ## The Architecture
236
255
 
data/Rakefile CHANGED
@@ -8,7 +8,19 @@ task :test => 'test:unit'
8
8
 
9
9
  require 'rake/testtask'
10
10
  namespace :test do
11
+ task :ci_reporter do
12
+ ENV['CI_REPORTS'] ||= 'tmp/reports'
13
+ if defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
14
+ require 'ci/reporter/rake/test_unit'
15
+ Rake::Task['ci:setup:testunit'].invoke
16
+ else
17
+ require 'ci/reporter/rake/minitest'
18
+ Rake::Task['ci:setup:minitest'].invoke
19
+ end
20
+ end
21
+
11
22
  Rake::TestTask.new(:unit) do |test|
23
+ Rake::Task['test:ci_reporter'].invoke if ENV['CI']
12
24
  test.libs << 'lib' << 'test'
13
25
  test.test_files = FileList["test/unit/**/*_test.rb"]
14
26
  # test.verbose = true
@@ -16,16 +28,19 @@ namespace :test do
16
28
  end
17
29
 
18
30
  Rake::TestTask.new(:integration) do |test|
31
+ Rake::Task['test:ci_reporter'].invoke if ENV['CI']
19
32
  test.libs << 'lib' << 'test'
20
33
  test.test_files = FileList["test/integration/**/*_test.rb"]
21
34
  end
22
35
 
23
36
  Rake::TestTask.new(:all) do |test|
37
+ Rake::Task['test:ci_reporter'].invoke if ENV['CI']
24
38
  test.libs << 'lib' << 'test'
25
39
  test.test_files = FileList["test/unit/**/*_test.rb", "test/integration/**/*_test.rb"]
26
40
  end
27
41
 
28
42
  Rake::TestTask.new(:profile) do |test|
43
+ Rake::Task['test:ci_reporter'].invoke if ENV['CI']
29
44
  test.libs << 'lib' << 'test'
30
45
  test.test_files = FileList["test/profile/**/*_test.rb"]
31
46
  end
@@ -34,17 +49,15 @@ namespace :test do
34
49
  desc "Start Elasticsearch nodes for tests"
35
50
  task :start do
36
51
  $LOAD_PATH << File.expand_path('../lib', __FILE__) << File.expand_path('../test', __FILE__)
37
- require 'elasticsearch/transport'
38
- require 'elasticsearch/transport/extensions/test_cluster'
39
- Elasticsearch::TestCluster.start
52
+ require 'elasticsearch/extensions/test/cluster'
53
+ Elasticsearch::Extensions::Test::Cluster.start
40
54
  end
41
55
 
42
56
  desc "Stop Elasticsearch nodes for tests"
43
57
  task :stop do
44
58
  $LOAD_PATH << File.expand_path('../lib', __FILE__) << File.expand_path('../test', __FILE__)
45
- require 'elasticsearch/transport'
46
- require 'elasticsearch/transport/extensions/test_cluster'
47
- Elasticsearch::TestCluster.stop
59
+ require 'elasticsearch/extensions/test/cluster'
60
+ Elasticsearch::Extensions::Test::Cluster.stop
48
61
  end
49
62
  end
50
63
  end
@@ -29,21 +29,31 @@ Gem::Specification.new do |s|
29
29
  s.add_development_dependency "bundler", "> 1"
30
30
  s.add_development_dependency "rake"
31
31
 
32
+ s.add_development_dependency "elasticsearch-extensions"
33
+
32
34
  s.add_development_dependency "ansi"
33
35
  s.add_development_dependency "shoulda-context"
34
36
  s.add_development_dependency "mocha"
35
37
  s.add_development_dependency "turn"
36
38
  s.add_development_dependency "yard"
37
39
  s.add_development_dependency "ruby-prof"
40
+ s.add_development_dependency "pry"
41
+ s.add_development_dependency "ci_reporter"
38
42
 
39
43
  # Gems for testing integrations
40
44
  s.add_development_dependency "curb"
41
- s.add_development_dependency "typhoeus"
45
+ s.add_development_dependency "typhoeus", '~> 0.6'
46
+
47
+ # Prevent unit test failures on Ruby 1.8
48
+ if defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
49
+ s.add_development_dependency "test-unit", '~> 2'
50
+ end
42
51
 
43
52
  if defined?(RUBY_VERSION) && RUBY_VERSION > '1.9'
44
53
  s.add_development_dependency "simplecov"
45
54
  s.add_development_dependency "cane"
46
55
  s.add_development_dependency "require-prof"
56
+ s.add_development_dependency "coveralls"
47
57
  end
48
58
 
49
59
  s.description = <<-DESC.gsub(/^ /, '')
@@ -105,13 +105,19 @@ module Elasticsearch
105
105
  hosts = hosts_config.map do |host|
106
106
  case host
107
107
  when String
108
- # TODO: Handle protocol?
109
- host, port = host.split(':')
110
- { :host => host, :port => port }
108
+ if host =~ /^[a-z]+\:\/\//
109
+ uri = URI.parse(host)
110
+ { :scheme => uri.scheme, :user => uri.user, :password => uri.password, :host => uri.host, :path => uri.path, :port => uri.port.to_s }
111
+ else
112
+ host, port = host.split(':')
113
+ { :host => host, :port => port }
114
+ end
115
+ when URI
116
+ { :scheme => host.scheme, :user => host.user, :password => host.password, :host => host.host, :path => host.path, :port => host.port.to_s }
111
117
  when Hash
112
118
  host
113
119
  else
114
- raise ArgumentError, "Please pass host as a String or Hash, #{host.class} given."
120
+ raise ArgumentError, "Please pass host as a String, URI or Hash -- #{host.class} given."
115
121
  end
116
122
  end
117
123
 
@@ -139,6 +139,19 @@ module Elasticsearch
139
139
  o = o.is_a?(String) ? o : serializer.dump(o, options)
140
140
  end
141
141
 
142
+ # Returns a full URL based on information from host
143
+ #
144
+ # @param host [Hash] Host configuration passed in from {Client}
145
+ #
146
+ # @api private
147
+ def __full_url(host)
148
+ url = "#{host[:protocol]}://"
149
+ url += "#{host[:user]}:#{host[:password]}@" if host[:user]
150
+ url += "#{host[:host]}:#{host[:port]}"
151
+ url += "#{host[:path]}" if host[:path]
152
+ url
153
+ end
154
+
142
155
  # Performs a request to Elasticsearch, while handling logging, tracing, marking dead connections,
143
156
  # retrying the request and reloading the connections.
144
157
  #
@@ -36,7 +36,11 @@ module Elasticsearch
36
36
  # @return [String]
37
37
  #
38
38
  def full_url(path, params={})
39
- "#{host[:protocol]}://#{host[:host]}:#{host[:port]}/#{full_path(path, params)}"
39
+ url = "#{host[:protocol]}://"
40
+ url += "#{host[:user]}:#{host[:password]}@" if host[:user]
41
+ url += "#{host[:host]}:#{host[:port]}"
42
+ url += "#{host[:path]}" if host[:path]
43
+ url += "/#{full_path(path, params)}"
40
44
  end
41
45
 
42
46
  # Returns the complete endpoint path with serialized parameters.
@@ -20,15 +20,14 @@ module Elasticsearch
20
20
  connection.connection.url = url
21
21
 
22
22
  case method
23
- when 'HEAD', 'GET' then connection.connection.http method.downcase.to_sym
24
- when 'PUT' then connection.connection.http_put serializer.dump(body)
25
- when 'DELETE' then connection.connection.http_delete
26
- when 'POST'
27
- connection.connection.post_body = __convert_to_json(body) if body
28
- connection.connection.http_post
23
+ when 'HEAD'
24
+ when 'GET', 'POST', 'PUT', 'DELETE'
25
+ connection.connection.put_data = __convert_to_json(body) if body
29
26
  else raise ArgumentError, "Unsupported HTTP method: #{method}"
30
27
  end
31
28
 
29
+ connection.connection.http(method.to_sym)
30
+
32
31
  Response.new connection.connection.response_code, connection.connection.body_str
33
32
  end
34
33
  end
@@ -40,13 +39,19 @@ module Elasticsearch
40
39
  def __build_connections
41
40
  Connections::Collection.new \
42
41
  :connections => hosts.map { |host|
43
- host[:protocol] ||= DEFAULT_PROTOCOL
42
+ host[:protocol] = host[:scheme] || DEFAULT_PROTOCOL
44
43
  host[:port] ||= DEFAULT_PORT
45
44
 
46
45
  client = ::Curl::Easy.new
47
46
  client.resolve_mode = :ipv4
48
- client.headers = {'Content-Type' => 'application/json'}
49
- client.url = "#{host[:protocol]}://#{host[:host]}:#{host[:port]}"
47
+ client.headers = {'User-Agent' => "Curb #{Curl::CURB_VERSION}", 'Content-Type' => 'application/json' }
48
+ client.url = __full_url(host)
49
+
50
+ if host[:user]
51
+ client.http_auth_types = host[:auth_type] || :basic
52
+ client.username = host[:user]
53
+ client.password = host[:password]
54
+ end
50
55
 
51
56
  client.instance_eval &@block if @block
52
57
 
@@ -33,9 +33,9 @@ module Elasticsearch
33
33
  def __build_connections
34
34
  Connections::Collection.new \
35
35
  :connections => hosts.map { |host|
36
- host[:protocol] ||= DEFAULT_PROTOCOL
36
+ host[:protocol] = host[:scheme] || DEFAULT_PROTOCOL
37
37
  host[:port] ||= DEFAULT_PORT
38
- url = "#{host[:protocol]}://#{host[:host]}:#{host[:port]}"
38
+ url = __full_url(host)
39
39
 
40
40
  Connections::Connection.new \
41
41
  :host => host,
@@ -1,5 +1,5 @@
1
1
  module Elasticsearch
2
2
  module Transport
3
- VERSION = "0.4.0"
3
+ VERSION = "0.4.2"
4
4
  end
5
5
  end
@@ -2,12 +2,13 @@ require 'test_helper'
2
2
 
3
3
  class Elasticsearch::Transport::ClientIntegrationTest < Elasticsearch::Test::IntegrationTestCase
4
4
  startup do
5
- Elasticsearch::TestCluster.start if ENV['SERVER'] and not Elasticsearch::TestCluster.running?
5
+ Elasticsearch::Extensions::Test::Cluster.start if ENV['SERVER'] and not Elasticsearch::Extensions::Test::Cluster.running?
6
6
  end
7
7
 
8
8
  context "Elasticsearch client" do
9
9
  setup do
10
- system "curl -X DELETE http://localhost:9250/_all > /dev/null 2>&1"
10
+ @port = (ENV['TEST_CLUSTER_PORT'] || 9250).to_i
11
+ system "curl -X DELETE http://localhost:#{@port}/_all > /dev/null 2>&1"
11
12
 
12
13
  @logger = Logger.new(STDERR)
13
14
  @logger.formatter = proc do |severity, datetime, progname, msg|
@@ -20,7 +21,7 @@ class Elasticsearch::Transport::ClientIntegrationTest < Elasticsearch::Test::Int
20
21
  ANSI.ansi(severity[0] + ' ', color, :faint) + ANSI.ansi(msg, :white, :faint) + "\n"
21
22
  end
22
23
 
23
- @client = Elasticsearch::Client.new host: 'localhost:9250'
24
+ @client = Elasticsearch::Client.new host: "localhost:#{@port}"
24
25
  end
25
26
 
26
27
  should "connect to the cluster" do
@@ -32,6 +33,8 @@ class Elasticsearch::Transport::ClientIntegrationTest < Elasticsearch::Test::Int
32
33
 
33
34
  should "handle paths and URL parameters" do
34
35
  @client.perform_request 'PUT', 'myindex/mydoc/1', {routing: 'XYZ'}, {foo: 'bar'}
36
+ @client.perform_request 'GET', '_cluster/health?wait_for_status=green', {}
37
+
35
38
  response = @client.perform_request 'GET', 'myindex/mydoc/1?routing=XYZ'
36
39
  assert_equal true, response.body['exists']
37
40
  assert_equal 'bar', response.body['_source']['foo']
@@ -45,7 +48,7 @@ class Elasticsearch::Transport::ClientIntegrationTest < Elasticsearch::Test::Int
45
48
  context "with round robin selector" do
46
49
  setup do
47
50
  @client = Elasticsearch::Client.new \
48
- hosts: %w| localhost:9250 localhost:9251 |,
51
+ hosts: ["localhost:#{@port}", "localhost:#{@port+1}" ],
49
52
  logger: @logger
50
53
  end
51
54
 
@@ -66,8 +69,9 @@ class Elasticsearch::Transport::ClientIntegrationTest < Elasticsearch::Test::Int
66
69
 
67
70
  context "with a sick node and retry on failure" do
68
71
  setup do
72
+ @port = (ENV['TEST_CLUSTER_PORT'] || 9250).to_i
69
73
  @client = Elasticsearch::Client.new \
70
- hosts: %w| localhost:9250 foobar1 |,
74
+ hosts: ["localhost:#{@port}", "foobar1"],
71
75
  logger: @logger,
72
76
  retry_on_failure: true
73
77
  end
@@ -80,7 +84,7 @@ class Elasticsearch::Transport::ClientIntegrationTest < Elasticsearch::Test::Int
80
84
 
81
85
  should "raise exception when it cannot get any healthy server" do
82
86
  @client = Elasticsearch::Client.new \
83
- hosts: %w| localhost:9250 foobar1 foobar2 foobar3 |,
87
+ hosts: ["localhost:#{@port}", "foobar1", "foobar2", "foobar3"],
84
88
  logger: @logger,
85
89
  retry_on_failure: 1
86
90
 
@@ -99,7 +103,7 @@ class Elasticsearch::Transport::ClientIntegrationTest < Elasticsearch::Test::Int
99
103
  context "with a sick node and reloading on failure" do
100
104
  setup do
101
105
  @client = Elasticsearch::Client.new \
102
- hosts: %w| localhost:9250 foobar1 foobar2 |,
106
+ hosts: ["localhost:#{@port}", "foobar1", "foobar2"],
103
107
  logger: @logger,
104
108
  reload_on_failure: true
105
109
  end
@@ -2,16 +2,20 @@ require 'test_helper'
2
2
 
3
3
  class Elasticsearch::Transport::ClientIntegrationTest < Elasticsearch::Test::IntegrationTestCase
4
4
  startup do
5
- Elasticsearch::TestCluster.start if ENV['SERVER'] and not Elasticsearch::TestCluster.running?
5
+ Elasticsearch::Extensions::Test::Cluster.start if ENV['SERVER'] and not Elasticsearch::Extensions::Test::Cluster.running?
6
6
  end
7
7
 
8
8
  context "Transport" do
9
+ setup do
10
+ @port = (ENV['TEST_CLUSTER_PORT'] || 9250).to_i
11
+ end
12
+
9
13
  should "allow to customize the Faraday adapter" do
10
14
  require 'typhoeus'
11
15
  require 'typhoeus/adapters/faraday'
12
16
 
13
17
  transport = Elasticsearch::Transport::Transport::HTTP::Faraday.new \
14
- :hosts => [ { :host => 'localhost', :port => '9250' } ] do |f|
18
+ :hosts => [ { :host => 'localhost', :port => @port } ] do |f|
15
19
  f.response :logger
16
20
  f.adapter :typhoeus
17
21
  end
@@ -25,7 +29,7 @@ class Elasticsearch::Transport::ClientIntegrationTest < Elasticsearch::Test::Int
25
29
  require 'elasticsearch/transport/transport/http/curb'
26
30
 
27
31
  transport = Elasticsearch::Transport::Transport::HTTP::Curb.new \
28
- :hosts => [ { :host => 'localhost', :port => '9250' } ] do |curl|
32
+ :hosts => [ { :host => 'localhost', :port => @port } ] do |curl|
29
33
  curl.verbose = true
30
34
  end
31
35
 
@@ -2,26 +2,27 @@ require 'test_helper'
2
2
 
3
3
  class Elasticsearch::Transport::ClientProfilingTest < Elasticsearch::Test::ProfilingTest
4
4
  startup do
5
- Elasticsearch::TestCluster.start if ENV['SERVER'] and not Elasticsearch::TestCluster.running?
5
+ Elasticsearch::Extensions::Test::Cluster.start if ENV['SERVER'] and not Elasticsearch::Extensions::Test::Cluster.running?
6
6
  end
7
7
 
8
8
  context "Elasticsearch client benchmark" do
9
9
  setup do
10
- client = Elasticsearch::Client.new host: 'localhost:9250'
10
+ @port = (ENV['TEST_CLUSTER_PORT'] || 9250).to_i
11
+ client = Elasticsearch::Client.new host: "localhost:#{@port}"
11
12
  client.perform_request 'DELETE', '/ruby_test_benchmark/' rescue nil
12
13
  client.perform_request 'POST', '/ruby_test_benchmark/', {index: {number_of_shards: 1, number_of_replicas: 0}}
13
14
  100.times do client.perform_request 'POST', '/ruby_test_benchmark_search/test/', {}, {foo: 'bar'}; end
14
15
  client.perform_request 'POST', '/ruby_test_benchmark_search/_refresh'
15
16
  end
16
17
  teardown do
17
- client = Elasticsearch::Client.new host: 'localhost:9250'
18
+ client = Elasticsearch::Client.new host: "localhost:#{@port}"
18
19
  client.perform_request 'DELETE', '/ruby_test_benchmark/'
19
20
  client.perform_request 'DELETE', '/ruby_test_benchmark_search/'
20
21
  end
21
22
 
22
23
  context "with a single-node cluster" do
23
24
  setup do
24
- @client = Elasticsearch::Client.new hosts: 'localhost:9250'
25
+ @client = Elasticsearch::Client.new hosts: "localhost:#{@port}"
25
26
  end
26
27
 
27
28
  measure "get the cluster info", count: 1_000 do
@@ -39,7 +40,7 @@ class Elasticsearch::Transport::ClientProfilingTest < Elasticsearch::Test::Profi
39
40
 
40
41
  context "with a two-node cluster" do
41
42
  setup do
42
- @client = Elasticsearch::Client.new hosts: ['localhost:9250', 'localhost:9251']
43
+ @client = Elasticsearch::Client.new hosts: ["localhost:#{@port}", "localhost:#{@port+1}"]
43
44
  end
44
45
 
45
46
  measure "get the cluster info", count: 1_000 do
@@ -59,7 +60,7 @@ class Elasticsearch::Transport::ClientProfilingTest < Elasticsearch::Test::Profi
59
60
  setup do
60
61
  require 'curb'
61
62
  require 'elasticsearch/transport/transport/http/curb'
62
- @client = Elasticsearch::Client.new host: 'localhost:9250',
63
+ @client = Elasticsearch::Client.new host: "localhost:#{@port}",
63
64
  transport_class: Elasticsearch::Transport::Transport::HTTP::Curb
64
65
  end
65
66
 
@@ -82,7 +83,7 @@ class Elasticsearch::Transport::ClientProfilingTest < Elasticsearch::Test::Profi
82
83
  require 'typhoeus/adapters/faraday'
83
84
 
84
85
  transport = Elasticsearch::Transport::Transport::HTTP::Faraday.new \
85
- :hosts => [ { :host => 'localhost', :port => '9250' } ] do |f|
86
+ :hosts => [ { :host => 'localhost', :port => @port } ] do |f|
86
87
  f.adapter :typhoeus
87
88
  end
88
89
 
data/test/test_helper.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  RUBY_1_8 = defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
2
2
 
3
- if RUBY_1_8
3
+ if RUBY_1_8 and not ENV['BUNDLE_GEMFILE']
4
4
  require 'rubygems'
5
5
  gem 'test-unit'
6
6
  end
@@ -19,15 +19,16 @@ require 'mocha/setup'
19
19
  require 'ansi/code'
20
20
  require 'turn' unless ENV["TM_FILEPATH"] || ENV["NOTURN"] || RUBY_1_8
21
21
 
22
- require 'test_extensions'
23
-
24
22
  require 'require-prof' if ENV["REQUIRE_PROF"]
25
23
  require 'elasticsearch-transport'
26
- require 'elasticsearch/transport/extensions/test_cluster'
27
24
  require 'logger'
28
25
 
29
26
  RequireProf.print_timing_infos if ENV["REQUIRE_PROF"]
30
27
 
28
+ require 'elasticsearch/extensions/test/cluster'
29
+ require 'elasticsearch/extensions/test/startup_shutdown'
30
+ require 'elasticsearch/extensions/test/profiling'
31
+
31
32
  class Test::Unit::TestCase
32
33
  def setup
33
34
  end
@@ -39,19 +40,19 @@ end
39
40
  module Elasticsearch
40
41
  module Test
41
42
  class IntegrationTestCase < ::Test::Unit::TestCase
42
- extend IntegrationTestStartupShutdown
43
+ extend Elasticsearch::Extensions::Test::StartupShutdown
43
44
 
44
- shutdown { Elasticsearch::TestCluster.stop if ENV['SERVER'] && started? }
45
+ shutdown { Elasticsearch::Extensions::Test::Cluster.stop if ENV['SERVER'] && started? }
45
46
  context "IntegrationTest" do; should "noop on Ruby 1.8" do; end; end if RUBY_1_8
46
47
  end
47
48
  end
48
49
 
49
50
  module Test
50
51
  class ProfilingTest < ::Test::Unit::TestCase
51
- extend IntegrationTestStartupShutdown
52
- extend ProfilingTestSupport
52
+ extend Elasticsearch::Extensions::Test::StartupShutdown
53
+ extend Elasticsearch::Extensions::Test::Profiling
53
54
 
54
- shutdown { Elasticsearch::TestCluster.stop if ENV['SERVER'] && started? }
55
+ shutdown { Elasticsearch::Extensions::Test::Cluster.stop if ENV['SERVER'] && started? }
55
56
  context "IntegrationTest" do; should "noop on Ruby 1.8" do; end; end if RUBY_1_8
56
57
  end
57
58
  end
@@ -66,30 +66,83 @@ class Elasticsearch::Transport::ClientTest < Test::Unit::TestCase
66
66
 
67
67
  context "extracting hosts" do
68
68
  should "handle defaults" do
69
- assert_equal [ {:host => 'localhost', :port => nil} ], @client.__extract_hosts
69
+ hosts = @client.__extract_hosts
70
+
71
+ assert_equal 'localhost', hosts[0][:host]
72
+ assert_nil hosts[0][:port]
70
73
  end
71
74
 
72
75
  should "extract from string" do
73
- assert_equal [ {:host => 'myhost', :port => nil} ], @client.__extract_hosts( 'myhost' )
76
+ hosts = @client.__extract_hosts 'myhost'
77
+
78
+ assert_equal 'myhost', hosts[0][:host]
79
+ assert_nil hosts[0][:port]
74
80
  end
75
81
 
76
82
  should "extract from array" do
77
- assert_equal [ {:host => 'myhost', :port => nil} ], @client.__extract_hosts( ['myhost'] )
83
+ hosts = @client.__extract_hosts ['myhost']
84
+
85
+ assert_equal 'myhost', hosts[0][:host]
78
86
  end
79
87
 
80
88
  should "extract from array with multiple hosts" do
81
- assert_equal [ {:host => 'host1', :port => nil}, {:host => 'host2', :port => nil} ],
82
- @client.__extract_hosts( ['host1', 'host2'] )
89
+ hosts = @client.__extract_hosts ['host1', 'host2']
90
+
91
+ assert_equal 'host1', hosts[0][:host]
92
+ assert_equal 'host2', hosts[1][:host]
83
93
  end
84
94
 
85
95
  should "extract from array with ports" do
86
- assert_equal [ {:host => 'host1', :port => '1000'}, {:host => 'host2', :port => '2000'} ],
87
- @client.__extract_hosts( ['host1:1000', 'host2:2000'] )
96
+ hosts = @client.__extract_hosts ['host1:1000', 'host2:2000']
97
+
98
+ assert_equal 'host1', hosts[0][:host]
99
+ assert_equal '1000', hosts[0][:port]
100
+
101
+ assert_equal 'host2', hosts[1][:host]
102
+ assert_equal '2000', hosts[1][:port]
103
+ end
104
+
105
+ should "extract path" do
106
+ hosts = @client.__extract_hosts 'https://myhost:8080/api'
107
+
108
+ assert_equal '/api', hosts[0][:path]
109
+ end
110
+
111
+ should "extract scheme (protocol)" do
112
+ hosts = @client.__extract_hosts 'https://myhost:8080'
113
+
114
+ assert_equal 'https', hosts[0][:scheme]
115
+ assert_equal 'myhost', hosts[0][:host]
116
+ assert_equal '8080', hosts[0][:port]
117
+ end
118
+
119
+ should "extract credentials" do
120
+ hosts = @client.__extract_hosts 'http://USERNAME:PASSWORD@myhost:8080'
121
+
122
+ assert_equal 'http', hosts[0][:scheme]
123
+ assert_equal 'USERNAME', hosts[0][:user]
124
+ assert_equal 'PASSWORD', hosts[0][:password]
125
+ assert_equal 'myhost', hosts[0][:host]
126
+ assert_equal '8080', hosts[0][:port]
88
127
  end
89
128
 
90
129
  should "pass Hashes over" do
91
- assert_equal [ {:host => 'myhost', :port => '1000'} ],
92
- @client.__extract_hosts( [{:host => 'myhost', :port => '1000'}] )
130
+ hosts = @client.__extract_hosts [{:host => 'myhost', :port => '1000', :foo => 'bar'}]
131
+
132
+ assert_equal 'myhost', hosts[0][:host]
133
+ assert_equal '1000', hosts[0][:port]
134
+ assert_equal 'bar', hosts[0][:foo]
135
+ end
136
+
137
+ should "use URL instance" do
138
+ require 'uri'
139
+ hosts = @client.__extract_hosts URI.parse('https://USERNAME:PASSWORD@myhost:4430')
140
+
141
+ assert_equal 'https', hosts[0][:scheme]
142
+ assert_equal 'USERNAME', hosts[0][:user]
143
+ assert_equal 'PASSWORD', hosts[0][:password]
144
+ assert_equal 'myhost', hosts[0][:host]
145
+ assert_equal '4430', hosts[0][:port]
93
146
  end
94
147
 
95
148
  should "raise error for incompatible argument" do
@@ -100,7 +153,10 @@ class Elasticsearch::Transport::ClientTest < Test::Unit::TestCase
100
153
 
101
154
  should "randomize hosts" do
102
155
  hosts = [ {:host => 'host1'}, {:host => 'host2'}, {:host => 'host3'}, {:host => 'host4'}, {:host => 'host5'}]
103
- assert_not_equal hosts, @client.__extract_hosts(hosts, :randomize_hosts => true)
156
+
157
+ Array.any_instance.expects(:shuffle!).twice
158
+
159
+ @client.__extract_hosts(hosts, :randomize_hosts => true)
104
160
  assert_same_elements hosts, @client.__extract_hosts(hosts, :randomize_hosts => true)
105
161
  end
106
162
  end
@@ -25,6 +25,16 @@ class Elasticsearch::Transport::Transport::Connections::ConnectionTest < Test::U
25
25
  assert_equal 'http://localhost:9200/_search?foo=bar', c.full_url('_search', {:foo => 'bar'})
26
26
  end
27
27
 
28
+ should "return full url with credentials" do
29
+ c = Connection.new :host => { :protocol => 'http', :user => 'U', :password => 'P', :host => 'localhost', :port => '9200' }
30
+ assert_equal 'http://U:P@localhost:9200/_search?foo=bar', c.full_url('_search', {:foo => 'bar'})
31
+ end
32
+
33
+ should "return full url with path" do
34
+ c = Connection.new :host => { :protocol => 'http', :host => 'localhost', :port => '9200', :path => '/foo' }
35
+ assert_equal 'http://localhost:9200/foo/_search?foo=bar', c.full_url('_search', {:foo => 'bar'})
36
+ end
37
+
28
38
  should "have a string representation" do
29
39
  c = Connection.new :host => 'x'
30
40
  assert_match /host: x/, c.to_s
@@ -135,10 +135,9 @@ class Elasticsearch::Transport::Transport::SnifferTest < Test::Unit::TestCase
135
135
  }
136
136
  JSON
137
137
 
138
- hosts = @sniffer.hosts
138
+ Array.any_instance.expects(:shuffle!)
139
139
 
140
- assert_not_equal ['Node 1', 'Node 2', 'Node 3', 'Node 4', 'Node 5'], hosts.map { |h| h['name'] }
141
- assert_same_elements ['Node 1', 'Node 2', 'Node 3', 'Node 4', 'Node 5'], hosts.map { |h| h['name'] }
140
+ hosts = @sniffer.hosts
142
141
  end
143
142
 
144
143
  end
@@ -57,6 +57,25 @@ class Elasticsearch::Transport::Transport::BaseTest < Test::Unit::TestCase
57
57
  transport = DummyTransport.new :options => { :sniffer_class => DummySniffer }
58
58
  assert_instance_of DummySniffer, transport.sniffer
59
59
  end
60
+
61
+ context "when combining the URL" do
62
+ setup do
63
+ @transport = DummyTransport.new
64
+ @basic_parts = { :protocol => 'http', :host => 'myhost', :port => 8080 }
65
+ end
66
+
67
+ should "combine basic parts" do
68
+ assert_equal 'http://myhost:8080', @transport.__full_url(@basic_parts)
69
+ end
70
+
71
+ should "combine path" do
72
+ assert_equal 'http://myhost:8080/api', @transport.__full_url(@basic_parts.merge :path => '/api')
73
+ end
74
+
75
+ should "combine authentication credentials" do
76
+ assert_equal 'http://U:P@myhost:8080', @transport.__full_url(@basic_parts.merge :user => 'U', :password => 'P')
77
+ end
78
+ end
60
79
  end
61
80
 
62
81
  context "getting a connection" do
@@ -260,7 +279,9 @@ class Elasticsearch::Transport::Transport::BaseTest < Test::Unit::TestCase
260
279
  end
261
280
 
262
281
  should "log the request and response" do
263
- @transport.logger.expects(:info). with "POST localhost:9200/_search?size=1 [status:200, request:0.000s, query:n/a]"
282
+ @transport.logger.expects(:info). with do |line|
283
+ line =~ %r|POST localhost\:9200/_search\?size=1 \[status\:200, request:.*s, query:n/a\]|
284
+ end
264
285
  @transport.logger.expects(:debug). with '> {"foo":"bar"}'
265
286
  @transport.logger.expects(:debug). with '< {"foo":"bar"}'
266
287
 
@@ -14,7 +14,7 @@ class Elasticsearch::Transport::Transport::HTTP::FaradayTest < Test::Unit::TestC
14
14
  assert_equal 1, @transport.hosts.size
15
15
  assert_equal 1, @transport.connections.size
16
16
 
17
- assert_instance_of ::Curl::Easy, @transport.connections.first.connection
17
+ assert_instance_of ::Curl::Easy, @transport.connections.first.connection
18
18
  assert_equal 'http://foobar:1234', @transport.connections.first.connection.url
19
19
  end
20
20
 
@@ -23,23 +23,36 @@ class Elasticsearch::Transport::Transport::HTTP::FaradayTest < Test::Unit::TestC
23
23
  @transport.perform_request 'GET', '/'
24
24
  end
25
25
 
26
+ should "set body for GET request" do
27
+ @transport.connections.first.connection.expects(:put_data=).with('{"foo":"bar"}')
28
+ @transport.connections.first.connection.expects(:http).with(:GET).returns(stub_everything)
29
+ @transport.perform_request 'GET', '/', {}, '{"foo":"bar"}'
30
+ end
31
+
32
+ should "set body for PUT request" do
33
+ @transport.connections.first.connection.expects(:put_data=)
34
+ @transport.connections.first.connection.expects(:http).with(:PUT).returns(stub_everything)
35
+ @transport.perform_request 'PUT', '/', {}, {:foo => 'bar'}
36
+ end
37
+
26
38
  should "serialize the request body" do
27
- @transport.connections.first.connection.expects(:http_post).returns(stub_everything)
39
+ @transport.connections.first.connection.expects(:http).with(:POST).returns(stub_everything)
28
40
  @transport.serializer.expects(:dump)
29
41
  @transport.perform_request 'POST', '/', {}, {:foo => 'bar'}
30
42
  end
31
43
 
32
44
  should "not serialize a String request body" do
33
- @transport.connections.first.connection.expects(:http_post).returns(stub_everything)
45
+ @transport.connections.first.connection.expects(:http).with(:POST).returns(stub_everything)
34
46
  @transport.serializer.expects(:dump).never
35
47
  @transport.perform_request 'POST', '/', {}, '{"foo":"bar"}'
36
48
  end
37
49
 
38
50
  should "handle HTTP methods" do
39
- @transport.connections.first.connection.expects(:http).twice.returns(stub_everything)
40
- @transport.connections.first.connection.expects(:http_put).returns(stub_everything)
41
- @transport.connections.first.connection.expects(:http_post).returns(stub_everything)
42
- @transport.connections.first.connection.expects(:http_delete).returns(stub_everything)
51
+ @transport.connections.first.connection.expects(:http).with(:HEAD).returns(stub_everything)
52
+ @transport.connections.first.connection.expects(:http).with(:GET).returns(stub_everything)
53
+ @transport.connections.first.connection.expects(:http).with(:PUT).returns(stub_everything)
54
+ @transport.connections.first.connection.expects(:http).with(:POST).returns(stub_everything)
55
+ @transport.connections.first.connection.expects(:http).with(:DELETE).returns(stub_everything)
43
56
 
44
57
  %w| HEAD GET PUT POST DELETE |.each { |method| @transport.perform_request method, '/' }
45
58
 
@@ -54,6 +67,12 @@ class Elasticsearch::Transport::Transport::HTTP::FaradayTest < Test::Unit::TestC
54
67
  assert_equal( {"Content-Type"=>"application/json", "User-Agent"=>"myapp-0.0"},
55
68
  transport.connections.first.connection.headers )
56
69
  end
70
+
71
+ should "set the credentials if passed" do
72
+ transport = Curb.new :hosts => [ { :host => 'foobar', :port => 1234, :user => 'foo', :password => 'bar' } ]
73
+ assert_equal 'foo', transport.connections.first.connection.username
74
+ assert_equal 'bar', transport.connections.first.connection.password
75
+ end
57
76
  end
58
77
 
59
78
  end
@@ -17,7 +17,7 @@ class Elasticsearch::Transport::Transport::HTTP::FaradayTest < Test::Unit::TestC
17
17
  assert_equal 1, @transport.connections.size
18
18
 
19
19
  assert_instance_of ::Faraday::Connection, @transport.connections.first.connection
20
- assert_equal 'http://foobar:1234/', @transport.connections.first.connection.url_prefix.to_s
20
+ assert_equal 'http://foobar:1234/', @transport.connections.first.connection.url_prefix.to_s
21
21
  end
22
22
 
23
23
  should "perform the request" do
@@ -68,6 +68,11 @@ class Elasticsearch::Transport::Transport::HTTP::FaradayTest < Test::Unit::TestC
68
68
  handlers = transport.connections.first.connection.instance_variable_get(:@builder).instance_variable_get(:@handlers)
69
69
  assert handlers.include?(::Faraday::Response::Logger), "#{handlers.inspect} does not include <::Faraday::Adapter::Typhoeus>"
70
70
  end
71
+
72
+ should "set the credentials if passed" do
73
+ transport = Faraday.new :hosts => [ { :host => 'foobar', :port => 1234, :user => 'foo', :password => 'bar' } ]
74
+ assert_equal 'Basic Zm9vOmJhcg==', transport.connections.first.connection.headers['Authorization']
75
+ end
71
76
  end
72
77
 
73
78
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elasticsearch-transport
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.2
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: 2013-09-24 00:00:00.000000000 Z
12
+ date: 2013-12-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json
@@ -75,6 +75,22 @@ dependencies:
75
75
  - - ! '>='
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: elasticsearch-extensions
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
78
94
  - !ruby/object:Gem::Dependency
79
95
  name: ansi
80
96
  requirement: !ruby/object:Gem::Requirement
@@ -172,7 +188,7 @@ dependencies:
172
188
  - !ruby/object:Gem::Version
173
189
  version: '0'
174
190
  - !ruby/object:Gem::Dependency
175
- name: curb
191
+ name: pry
176
192
  requirement: !ruby/object:Gem::Requirement
177
193
  none: false
178
194
  requirements:
@@ -188,7 +204,23 @@ dependencies:
188
204
  - !ruby/object:Gem::Version
189
205
  version: '0'
190
206
  - !ruby/object:Gem::Dependency
191
- name: typhoeus
207
+ name: ci_reporter
208
+ requirement: !ruby/object:Gem::Requirement
209
+ none: false
210
+ requirements:
211
+ - - ! '>='
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ type: :development
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - ! '>='
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ - !ruby/object:Gem::Dependency
223
+ name: curb
192
224
  requirement: !ruby/object:Gem::Requirement
193
225
  none: false
194
226
  requirements:
@@ -203,6 +235,22 @@ dependencies:
203
235
  - - ! '>='
204
236
  - !ruby/object:Gem::Version
205
237
  version: '0'
238
+ - !ruby/object:Gem::Dependency
239
+ name: typhoeus
240
+ requirement: !ruby/object:Gem::Requirement
241
+ none: false
242
+ requirements:
243
+ - - ~>
244
+ - !ruby/object:Gem::Version
245
+ version: '0.6'
246
+ type: :development
247
+ prerelease: false
248
+ version_requirements: !ruby/object:Gem::Requirement
249
+ none: false
250
+ requirements:
251
+ - - ~>
252
+ - !ruby/object:Gem::Version
253
+ version: '0.6'
206
254
  - !ruby/object:Gem::Dependency
207
255
  name: simplecov
208
256
  requirement: !ruby/object:Gem::Requirement
@@ -251,6 +299,22 @@ dependencies:
251
299
  - - ! '>='
252
300
  - !ruby/object:Gem::Version
253
301
  version: '0'
302
+ - !ruby/object:Gem::Dependency
303
+ name: coveralls
304
+ requirement: !ruby/object:Gem::Requirement
305
+ none: false
306
+ requirements:
307
+ - - ! '>='
308
+ - !ruby/object:Gem::Version
309
+ version: '0'
310
+ type: :development
311
+ prerelease: false
312
+ version_requirements: !ruby/object:Gem::Requirement
313
+ none: false
314
+ requirements:
315
+ - - ! '>='
316
+ - !ruby/object:Gem::Version
317
+ version: '0'
254
318
  description: ! 'Ruby client for Elasticsearch. See the `elasticsearch` gem for full
255
319
  integration.
256
320
 
@@ -272,7 +336,6 @@ files:
272
336
  - lib/elasticsearch-transport.rb
273
337
  - lib/elasticsearch/transport.rb
274
338
  - lib/elasticsearch/transport/client.rb
275
- - lib/elasticsearch/transport/extensions/test_cluster.rb
276
339
  - lib/elasticsearch/transport/transport/base.rb
277
340
  - lib/elasticsearch/transport/transport/connections/collection.rb
278
341
  - lib/elasticsearch/transport/transport/connections/connection.rb
@@ -287,7 +350,6 @@ files:
287
350
  - test/integration/client_test.rb
288
351
  - test/integration/transport_test.rb
289
352
  - test/profile/client_benchmark_test.rb
290
- - test/test_extensions.rb
291
353
  - test/test_helper.rb
292
354
  - test/unit/client_test.rb
293
355
  - test/unit/connection_collection_test.rb
@@ -328,7 +390,6 @@ test_files:
328
390
  - test/integration/client_test.rb
329
391
  - test/integration/transport_test.rb
330
392
  - test/profile/client_benchmark_test.rb
331
- - test/test_extensions.rb
332
393
  - test/test_helper.rb
333
394
  - test/unit/client_test.rb
334
395
  - test/unit/connection_collection_test.rb
@@ -1,163 +0,0 @@
1
- require 'ansi/code'
2
-
3
- module Elasticsearch
4
-
5
- # A convenience Ruby class for starting and stopping a separate testing cluster,
6
- # to not depend on -- and not mess up -- <localhost:9200>.
7
- #
8
- module TestCluster
9
- require 'timeout'
10
- require 'net/http'
11
- require 'uri'
12
-
13
- @@number_of_nodes = 2
14
- @@pids = []
15
-
16
- # Start a cluster
17
- #
18
- # Starts the desired number of nodes in test-suitable configuration (memory store, no persistence, etc).
19
- #
20
- # @option arguments [String] :command Elasticsearch command (default: `elasticsearch`).
21
- # @option arguments [Integer] :count Number of desired nodes (default: 2).
22
- # @option arguments [String] :cluster_name Cluster name (default: `elasticsearch-ruby-test`).
23
- # @option arguments [String] :port Starting port number; will be auto-incremented (default: 9250).
24
- #
25
- # You can also use environment variables to set these options.
26
- #
27
- def start(arguments={})
28
- arguments[:command] = ENV['TEST_CLUSTER_COMMAND'] || 'elasticsearch'
29
-
30
- unless system "which #{arguments[:command]} > /dev/null 2>&1"
31
- STDERR.puts ANSI.red("[ERROR] Elasticsearch can't be started, is it installed? Run: $ which elasticsearch"), ''
32
- abort
33
- end
34
-
35
- @@number_of_nodes = arguments[:count] if arguments[:count]
36
-
37
- arguments[:port] = (ENV['TEST_CLUSTER_PORT'] || 9250).to_i
38
- arguments[:cluster_name] = ENV['TEST_CLUSTER_NAME'] || 'elasticsearch-ruby-test'
39
- arguments[:node_name] = 'node'
40
-
41
- if running? :on => arguments[:port], :as => arguments[:cluster_name]
42
- print ANSI.red("Elasticsearch cluster already running")
43
- __wait_for_green(arguments[:port])
44
- exit(0)
45
- end
46
-
47
- print ANSI.faint("Starting ") + ANSI.ansi(@@number_of_nodes.to_s, :bold, :faint) + ANSI.faint(" Elasticsearch nodes")
48
-
49
- @@number_of_nodes.times do |n|
50
- n += 1
51
- pidfile = File.expand_path("tmp/elasticsearch-#{n}.pid", Dir.pwd)
52
- pid = Process.spawn <<-COMMAND
53
- #{arguments[:command]} \
54
- -D es.foreground=yes \
55
- -D es.cluster.name=#{arguments[:cluster_name]} \
56
- -D es.node.name=#{arguments[:node_name]}-#{n} \
57
- -D es.http.port=#{arguments[:port].to_i + (n-1)} \
58
- -D es.gateway.type=none \
59
- -D es.index.store.type=memory \
60
- -D es.network.host=0.0.0.0 \
61
- -D es.discovery.zen.ping.multicast.enabled=true \
62
- -D es.pidfile=#{pidfile} \
63
- > /dev/null 2>&1
64
- COMMAND
65
- Process.detach pid
66
- end
67
-
68
- __wait_for_green(arguments[:port])
69
- end
70
-
71
- # Stop the cluster.
72
- #
73
- # Gets the PID numbers from pidfiles in `$CWD/tmp` and stops any matching nodes.
74
- #
75
- def stop
76
- pids = __get_pids
77
- pidfiles = __get_pidfiles
78
-
79
- unless pids.empty?
80
- print "Stopping Elasticsearch nodes... "
81
- pids.each_with_index do |pid, i|
82
- begin
83
- print ANSI.green("stopped PID #{pid}. ") if Process.kill 'KILL', pid
84
- rescue Exception => e
85
- print ANSI.red("[#{e.class}] PID #{pid} not found. ")
86
- end
87
- File.delete pidfiles[i] if pidfiles[i] && File.exists?(pidfiles[i])
88
- end
89
- puts
90
- end
91
- end
92
-
93
- # Returns true when a specific test node is running.
94
- #
95
- # @option arguments [Integer] :on The port on which the node is running.
96
- # @option arguments [String] :as The cluster name.
97
- #
98
- def running?(arguments={})
99
- port = arguments[:on] || 9250
100
- cluster_name = arguments[:as] || 'elasticsearch-ruby-test'
101
-
102
- if cluster_health = Timeout::timeout(0.25) { __get_cluster_health(port) } rescue nil
103
- return cluster_health['cluster_name'] == cluster_name && \
104
- cluster_health['number_of_nodes'] == @@number_of_nodes
105
- end
106
- return false
107
- end
108
-
109
- # Blocks the process and waits for the cluster to be in a "green" state.
110
- # Prints information about the cluster on STDOUT.
111
- #
112
- def __wait_for_green(port=9250)
113
- uri = URI("http://localhost:#{port}/_cluster/health")
114
-
115
- Timeout::timeout(30) do
116
- loop do
117
- response = Net::HTTP.get(uri) rescue nil
118
- if response
119
- pids = __get_pids
120
-
121
- json = MultiJson.load(response)
122
- if json['status'] == 'green' && json['number_of_nodes'].to_i == @@number_of_nodes
123
- puts '',
124
- ANSI.faint('-'*80),
125
- ANSI.faint(
126
- 'Cluster: '.ljust(20) + json['cluster_name'].to_s + "\n" +
127
- 'Status: '.ljust(20) + json['status'].to_s + "\n" +
128
- 'Number of nodes: '.ljust(20) + json['number_of_nodes'].to_s + "\n" +
129
- 'PIDs'.ljust(20) + pids.inspect
130
- ),
131
- ANSI.faint('-'*80)
132
- break
133
- end
134
- end
135
- print ANSI.faint('.')
136
- sleep 1
137
- end
138
- end
139
- end
140
-
141
- # Tries to load cluster health information
142
- #
143
- def __get_cluster_health(port=9250)
144
- uri = URI("http://localhost:#{port}/_cluster/health")
145
- if response = Net::HTTP.get(uri) rescue nil
146
- return MultiJson.load(response)
147
- end
148
- end
149
-
150
- # Returns a collection of PID numbers from pidfiles.
151
- def __get_pids
152
- __get_pidfiles.map { |pidfile| File.read(pidfile).to_i }.uniq
153
- end
154
-
155
- # Returns a collection of files with PID information.
156
- #
157
- def __get_pidfiles
158
- Dir[File.expand_path('tmp/elasticsearch-*.pid', Dir.pwd)]
159
- end
160
-
161
- extend self
162
- end
163
- end
@@ -1,139 +0,0 @@
1
- require 'benchmark'
2
- require 'ruby-prof'
3
- require 'ansi/code'
4
- require 'ansi/terminal'
5
-
6
- module Elasticsearch
7
- module Test
8
-
9
- # Startup/shutdown support for test suites
10
- #
11
- # Example:
12
- #
13
- # class MyTest < Test::Unit::TestCase
14
- # extend IntegrationTestStartupShutdown
15
- #
16
- # startup { puts "Suite starting up..." }
17
- # shutdown { puts "Suite shutting down..." }
18
- # end
19
- #
20
- # *** IMPORTANT NOTE: **********************************************************
21
- #
22
- # You have to register the handler for shutdown before requiring 'test/unit':
23
- #
24
- # # File: test_helper.rb
25
- # at_exit { MyTest.__run_at_exit_hooks }
26
- # require 'test/unit'
27
- #
28
- # The API follows Test::Unit 2.0
29
- # <https://github.com/test-unit/test-unit/blob/master/lib/test/unit/testcase.rb>
30
- #
31
- module IntegrationTestStartupShutdown
32
- @@started = false
33
- @@shutdown_blocks ||= []
34
-
35
- def startup &block
36
- return if started?
37
- @@started = true
38
- yield block if block_given?
39
- end
40
-
41
- def shutdown &block
42
- @@shutdown_blocks << block if block_given?
43
- end
44
-
45
- def started?
46
- !! @@started
47
- end
48
-
49
- def __run_at_exit_hooks
50
- return unless started?
51
- STDERR.puts ANSI.faint("Running at_exit hooks...")
52
- puts ANSI.faint('-'*80)
53
- @@shutdown_blocks.each { |b| b.call }
54
- puts ANSI.faint('-'*80)
55
- end
56
- end
57
-
58
- # Profiling support for tests with [ruby-prof](https://github.com/ruby-prof/ruby-prof)
59
- #
60
- # Example:
61
- #
62
- # measure "divide numbers", count: 10_000 do
63
- # assert_nothing_raised { 1/2 }
64
- # end
65
- #
66
- # Will print out something like this along your test output:
67
- #
68
- # ---------------------------------------------------------------------
69
- # Context: My benchmark should divide numbers (10000x)
70
- # mean: 0.01ms | avg: 0.01ms | max: 6.19ms
71
- # ---------------------------------------------------------------------
72
- # ...
73
- # Total: 0.313283
74
- #
75
- # %self total self wait child calls name
76
- # 25.38 0.313 0.079 0.000 0.234 1 <Object::MyTets>#__bind_1368638677_723101
77
- # 14.42 0.118 0.045 0.000 0.073 20000 <Class::Time>#now
78
- # 7.57 0.088 0.033 0.000 0.055 10000 Time#-
79
- # ...
80
- #
81
- # PASS (0:00:00.322) test: My benchmark should divide numbers (10000x).
82
- #
83
- #
84
- module ProfilingTestSupport
85
-
86
- # Profiles the passed block of code.
87
- #
88
- # measure "divide numbers", count: 10_000 do
89
- # assert_nothing_raised { 1/2 }
90
- # end
91
- #
92
- # @todo Try to make progress bar not interfere with tests
93
- #
94
- def measure(name, options={}, &block)
95
- # require 'pry'; binding.pry
96
- ___ = '-'*ANSI::Terminal.terminal_width
97
- test_name = self.name.split('::').last
98
- context_name = self.context(nil) {}.first.parent.name
99
- count = Integer(ENV['COUNT'] || options[:count] || 1_000)
100
- ticks = []
101
- # progress = ANSI::Progressbar.new("#{name} (#{count}x)", count)
102
-
103
- should "#{name} (#{count}x)" do
104
- RubyProf.start
105
-
106
- count.times do
107
- ticks << Benchmark.realtime { self.instance_eval(&block) }
108
- # RubyProf.pause
109
- # progress.inc
110
- # RubyProf.resume
111
- end
112
-
113
- result = RubyProf.stop
114
- # progress.finish
115
-
116
- total = result.threads.reduce(0) { |total,info| total += info.total_time; total }
117
- mean = (ticks.sort[(ticks.size/2).round-1])*1000
118
- avg = (ticks.inject {|sum,el| sum += el; sum}.to_f/ticks.size)*1000
119
- max = ticks.max*1000
120
-
121
-
122
- result.eliminate_methods!([/Integer#times|Benchmark.realtime|ANSI::Code#.*|ANSI::ProgressBar#.*/])
123
- printer = RubyProf::FlatPrinter.new(result)
124
- # printer = RubyProf::GraphPrinter.new(result)
125
-
126
- puts "\n",
127
- ___,
128
- 'Context: ' + ANSI.bold(context_name) + ' should ' + ANSI.bold(name) + " (#{count}x)",
129
- "mean: #{sprintf('%.2f', mean)}ms | " +
130
- "avg: #{sprintf('%.2f', avg)}ms | " +
131
- "max: #{sprintf('%.2f', max)}ms",
132
- ___
133
- printer.print(STDOUT, {}) unless ENV['QUIET'] || options[:quiet]
134
- end
135
- end
136
- end
137
-
138
- end
139
- end