elasticsearch-transport 7.1.0 → 7.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +12 -8
  3. data/{LICENSE.txt → LICENSE} +0 -0
  4. data/README.md +160 -72
  5. data/Rakefile +1 -1
  6. data/elasticsearch-transport.gemspec +42 -60
  7. data/lib/elasticsearch/transport/client.rb +70 -19
  8. data/lib/elasticsearch/transport/redacted.rb +1 -1
  9. data/lib/elasticsearch/transport/transport/base.rb +86 -12
  10. data/lib/elasticsearch/transport/transport/connections/collection.rb +1 -1
  11. data/lib/elasticsearch/transport/transport/connections/connection.rb +1 -1
  12. data/lib/elasticsearch/transport/transport/connections/selector.rb +18 -6
  13. data/lib/elasticsearch/transport/transport/errors.rb +1 -1
  14. data/lib/elasticsearch/transport/transport/http/curb.rb +26 -9
  15. data/lib/elasticsearch/transport/transport/http/faraday.rb +18 -4
  16. data/lib/elasticsearch/transport/transport/http/manticore.rb +25 -10
  17. data/lib/elasticsearch/transport/transport/loggable.rb +1 -1
  18. data/lib/elasticsearch/transport/transport/response.rb +1 -2
  19. data/lib/elasticsearch/transport/transport/serializer/multi_json.rb +1 -1
  20. data/lib/elasticsearch/transport/transport/sniffer.rb +3 -2
  21. data/lib/elasticsearch/transport/version.rb +2 -2
  22. data/lib/elasticsearch/transport.rb +1 -1
  23. data/lib/elasticsearch-transport.rb +1 -1
  24. data/spec/elasticsearch/connections/collection_spec.rb +254 -0
  25. data/spec/elasticsearch/connections/selector_spec.rb +174 -0
  26. data/spec/elasticsearch/transport/base_spec.rb +177 -9
  27. data/spec/elasticsearch/transport/client_spec.rb +525 -29
  28. data/spec/elasticsearch/transport/sniffer_spec.rb +1 -1
  29. data/spec/spec_helper.rb +25 -1
  30. data/test/integration/transport_test.rb +1 -1
  31. data/test/profile/client_benchmark_test.rb +1 -1
  32. data/test/test_helper.rb +1 -1
  33. data/test/unit/connection_test.rb +1 -1
  34. data/test/unit/response_test.rb +2 -2
  35. data/test/unit/serializer_test.rb +1 -1
  36. data/test/unit/transport_base_test.rb +1 -1
  37. data/test/unit/transport_curb_test.rb +2 -2
  38. data/test/unit/transport_faraday_test.rb +1 -1
  39. data/test/unit/transport_manticore_test.rb +28 -12
  40. metadata +85 -61
  41. data/test/unit/connection_collection_test.rb +0 -147
  42. data/test/unit/connection_selector_test.rb +0 -81
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14188a454b64314c13f7c9279741fc8df5f9f03ff9813f45aeca96abc8da7e39
4
- data.tar.gz: dfcd7ac5fb8e0b2a0450b2939272f88a329581648c47b130d62e1fcead705b44
3
+ metadata.gz: 4dfe3d9fae3bb774616e233bf92b39eb0aa4a59485af2f842ab5b71b2811dce4
4
+ data.tar.gz: 878ee8379c414a3c6c4a53f6656c53e929ba18c4774f33276d85bbad603ce3c0
5
5
  SHA512:
6
- metadata.gz: 36e9583f541ec75994cb27479c16f4624d7ea6a9e6f33360d7cac69541fe10a5c2ee2d7f20b2c1231b5fd07ab85cd32baefb236d6ab77ff11635bb23b1d9d801
7
- data.tar.gz: 95faf1016519c04dcafcd6580356dcfb00c8eeb9ef3301bf2ff3c66a90cfcc8ebf676b638ec18f92f708acb5ef01ee2f7ee137f23ed6532774b371e47b02e11f
6
+ metadata.gz: 78aaba580583c70dae6dc2fa798dbf2cc4d0ff150401f2fc2a0f26c5b2f58ad938e53bd1d6fc4a69d8fd95205bbfe389b8af6744b65c61ec5ffe71c8df32daf0
7
+ data.tar.gz: 6fcc484b27d6b61d57162a195d43b9fa97e7c86da86461ca530fd233e3c97c32a495ff28a6a0d31771a70e28213234ed61c38a75846cd0b32122db37e15661a7
data/Gemfile CHANGED
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -20,19 +20,23 @@ source 'https://rubygems.org'
20
20
  # Specify your gem's dependencies in elasticsearch-transport.gemspec
21
21
  gemspec
22
22
 
23
- if File.exist? File.expand_path("../../elasticsearch-api/elasticsearch-api.gemspec", __FILE__)
24
- gem 'elasticsearch-api', :path => File.expand_path("../../elasticsearch-api", __FILE__), :require => false
23
+ if File.exist? File.expand_path('../../elasticsearch-api/elasticsearch-api.gemspec', __FILE__)
24
+ gem 'elasticsearch-api', path: File.expand_path('../../elasticsearch-api', __FILE__), require: false
25
25
  end
26
26
 
27
- if File.exist? File.expand_path("../../elasticsearch-extensions/elasticsearch-extensions.gemspec", __FILE__)
28
- gem 'elasticsearch-extensions', :path => File.expand_path("../../elasticsearch-extensions", __FILE__), :require => false
27
+ if File.exist? File.expand_path('../../elasticsearch-extensions/elasticsearch-extensions.gemspec', __FILE__)
28
+ gem 'elasticsearch-extensions', path: File.expand_path('../../elasticsearch-extensions', __FILE__), require: false
29
29
  end
30
30
 
31
- if File.exist? File.expand_path("../../elasticsearch/elasticsearch.gemspec", __FILE__)
32
- gem 'elasticsearch', :path => File.expand_path("../../elasticsearch", __FILE__), :require => false
31
+ if File.exist? File.expand_path('../../elasticsearch/elasticsearch.gemspec', __FILE__)
32
+ gem 'elasticsearch', path: File.expand_path('../../elasticsearch', __FILE__), require: false
33
33
  end
34
34
 
35
35
  group :development do
36
36
  gem 'rspec'
37
- gem 'pry-nav'
37
+ if defined?(JRUBY_VERSION)
38
+ gem 'pry-nav'
39
+ else
40
+ gem 'pry-byebug'
41
+ end
38
42
  end
File without changes
data/README.md CHANGED
@@ -28,12 +28,16 @@ Features overview:
28
28
  * Node reloading (based on cluster state) on errors or on demand
29
29
 
30
30
  For optimal performance, use a HTTP library which supports persistent ("keep-alive") connections,
31
- such as [Typhoeus](https://github.com/typhoeus/typhoeus).
32
- Just require the library (`require 'typhoeus'; require 'typhoeus/adapters/faraday'`) in your code,
33
- and it will be automatically used; currently these libraries will be automatically detected and used:
34
- [Patron](https://github.com/toland/patron),
35
- [HTTPClient](https://rubygems.org/gems/httpclient) and
36
- [Net::HTTP::Persistent](https://rubygems.org/gems/net-http-persistent).
31
+ such as [patron](https://github.com/toland/patron) or [Typhoeus](https://github.com/typhoeus/typhoeus).
32
+ Just require the library (`require 'patron'`) in your code, and it will be automatically used.
33
+
34
+ Currently these libraries will be automatically detected and used:
35
+ - [Patron](https://github.com/toland/patron)
36
+ - [Typhoeus](https://github.com/typhoeus/typhoeus)
37
+ - [HTTPClient](https://rubygems.org/gems/httpclient)
38
+ - [Net::HTTP::Persistent](https://rubygems.org/gems/net-http-persistent)
39
+
40
+ **Note on [Typhoeus](https://github.com/typhoeus/typhoeus)**: You need to use v1.4.0 or up since older versions are not compatible with Faraday 1.0.
37
41
 
38
42
  For detailed information, see example configurations [below](#transport-implementations).
39
43
 
@@ -69,6 +73,23 @@ Full documentation is available at <http://rubydoc.info/gems/elasticsearch-trans
69
73
 
70
74
  ## Configuration
71
75
 
76
+ * [Setting Hosts](#setting-hosts)
77
+ * [Default port](#default-port)
78
+ * [Connect using an Elastic Cloud ID](#connect-using-an-elastic-cloud-id)
79
+ * [Authentication](#authentication)
80
+ * [Logging](#logging)
81
+ * [Custom HTTP Headers](#custom-http-headers)
82
+ * [Identifying running tasks with X-Opaque-Id](#identifying-running-tasks-with-x-opaque-id)
83
+ * [Setting Timeouts](#setting-timeouts)
84
+ * [Randomizing Hosts](#randomizing-hosts)
85
+ * [Retrying on Failures](#retrying-on-failures)
86
+ * [Reloading Hosts](#reloading-hosts)
87
+ * [Connection Selector](#connection-selector)
88
+ * [Transport Implementations](#transport-implementations)
89
+ * [Serializer implementations](#serializer-implementations)
90
+ * [Exception Handling](#exception-handling)
91
+ * [Development and Community](#development-and-community)
92
+
72
93
  The client supports many configurations options for setting up and managing connections,
73
94
  configuring logging, customizing the transport library, etc.
74
95
 
@@ -106,6 +127,22 @@ Another way to configure the URL(s) is to export the `ELASTICSEARCH_URL` variabl
106
127
  The client will automatically round-robin across the hosts
107
128
  (unless you select or implement a different [connection selector](#connection-selector)).
108
129
 
130
+ ### Default port
131
+
132
+ The default port is `9200`. Please specify a port for your host(s) if they differ from this default.
133
+ Please see below for an exception to this when connecting using an Elastic Cloud ID.
134
+
135
+ ### Connect using an Elastic Cloud ID
136
+
137
+ If you are using [Elastic Cloud](https://www.elastic.co/cloud), you can provide your cloud id to the client.
138
+ You must supply your username and password separately, and optionally a port. If no port is supplied,
139
+ port 9243 will be used.
140
+
141
+ Note: Do not enable sniffing when using Elastic Cloud. The nodes are behind a load balancer so
142
+ Elastic Cloud will take care of everything for you.
143
+
144
+ Elasticsearch::Client.new(cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==', user: 'elastic', password: 'changeme')
145
+
109
146
  ### Authentication
110
147
 
111
148
  You can pass the authentication credentials, scheme and port in the host configuration hash:
@@ -128,35 +165,108 @@ use the `transport_options` option:
128
165
  Elasticsearch::Client.new url: 'https://username:password@example.com:9200',
129
166
  transport_options: { ssl: { ca_file: '/path/to/cacert.pem' } }
130
167
 
168
+ You can also use [**API Key authentication**](https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html):
169
+
170
+ ``` ruby
171
+ Elasticsearch::Client.new(
172
+ host: host,
173
+ transport_options: transport_options,
174
+ api_key: credentials
175
+ )
176
+ ```
177
+
178
+ Where credentials is either the base64 encoding of `id` and `api_key` joined by a colon or a hash with the `id` and `api_key`:
179
+
180
+ ``` ruby
181
+ Elasticsearch::Client.new(
182
+ host: host,
183
+ transport_options: transport_options,
184
+ api_key: {id: 'my_id', api_key: 'my_api_key'}
185
+ )
186
+ ```
187
+
131
188
  ### Logging
132
189
 
133
190
  To log requests and responses to standard output with the default logger (an instance of Ruby's {::Logger} class),
134
191
  set the `log` argument:
135
192
 
136
- Elasticsearch::Client.new log: true
193
+ ```ruby
194
+ Elasticsearch::Client.new log: true
195
+ ```
196
+
137
197
 
138
198
  To trace requests and responses in the _Curl_ format, set the `trace` argument:
139
199
 
140
- Elasticsearch::Client.new trace: true
200
+ ```ruby
201
+ Elasticsearch::Client.new trace: true
202
+ ```
141
203
 
142
204
  You can customize the default logger or tracer:
143
205
 
206
+ ```ruby
144
207
  client.transport.logger.formatter = proc { |s, d, p, m| "#{s}: #{m}\n" }
145
208
  client.transport.logger.level = Logger::INFO
209
+ ```
146
210
 
147
- Or, you can use a custom {::Logger} instance:
211
+ Or, you can use a custom `::Logger` instance:
148
212
 
149
- Elasticsearch::Client.new logger: Logger.new(STDERR)
213
+ ```ruby
214
+ Elasticsearch::Client.new logger: Logger.new(STDERR)
215
+ ```
150
216
 
151
217
  You can pass the client any conforming logger implementation:
152
218
 
153
- require 'logging' # https://github.com/TwP/logging/
219
+ ```ruby
220
+ require 'logging' # https://github.com/TwP/logging/
221
+
222
+ log = Logging.logger['elasticsearch']
223
+ log.add_appenders Logging.appenders.stdout
224
+ log.level = :info
225
+
226
+ client = Elasticsearch::Client.new logger: log
227
+ ```
228
+
229
+ ### Custom HTTP Headers
230
+
231
+ You can set a custom HTTP header on the client's initializer:
232
+
233
+ ```ruby
234
+ client = Elasticsearch::Client.new(
235
+ transport_options: {
236
+ headers:
237
+ {user_agent: "My App"}
238
+ }
239
+ )
240
+ ```
241
+
242
+ You can also pass in `headers` as a parameter to any of the API Endpoints to set custom headers for the request:
154
243
 
155
- log = Logging.logger['elasticsearch']
156
- log.add_appenders Logging.appenders.stdout
157
- log.level = :info
244
+ ```ruby
245
+ client.search(index: 'myindex', q: 'title:test', headers: {user_agent: "My App"})
246
+ ```
247
+
248
+ ### Identifying running tasks with X-Opaque-Id
249
+
250
+ The X-Opaque-Id header allows to track certain calls, or associate certain tasks with the client that started them ([more on the Elasticsearch docs](https://www.elastic.co/guide/en/elasticsearch/reference/master/tasks.html#_identifying_running_tasks)). To use this feature, you need to set an id for `opaque_id` on the client on each request. Example:
251
+
252
+ ```ruby
253
+ client = Elasticsearch::Client.new
254
+ client.search(index: 'myindex', q: 'title:test', opaque_id: '123456')
255
+ ```
256
+ The search request will include the following HTTP Header:
257
+ ```
258
+ X-Opaque-Id: 123456
259
+ ```
158
260
 
159
- client = Elasticsearch::Client.new logger: log
261
+ You can also set a prefix for X-Opaque-Id when initializing the client. This will be prepended to the id you set before each request if you're using X-Opaque-Id. Example:
262
+ ```ruby
263
+ client = Elasticsearch::Client.new(opaque_id_prefix: 'eu-west1')
264
+ client.search(index: 'myindex', q: 'title:test', opaque_id: '123456')
265
+ ```
266
+ The request will include the following HTTP Header:
267
+ ```
268
+ X-Opaque-Id: eu-west1_123456
269
+ ```
160
270
 
161
271
  ### Setting Timeouts
162
272
 
@@ -252,25 +362,29 @@ preferring HTTP clients with support for persistent connections.
252
362
 
253
363
  To use the [_Patron_](https://github.com/toland/patron) HTTP, for example, just require it:
254
364
 
255
- require 'patron'
365
+ ```ruby
366
+ require 'patron'
367
+ ```
256
368
 
257
369
  Then, create a new client, and the _Patron_ gem will be used as the "driver":
258
370
 
259
- client = Elasticsearch::Client.new
371
+ ```ruby
372
+ client = Elasticsearch::Client.new
260
373
 
261
- client.transport.connections.first.connection.builder.handlers
262
- # => [Faraday::Adapter::Patron]
374
+ client.transport.connections.first.connection.builder.adapter
375
+ # => Faraday::Adapter::Patron
263
376
 
264
- 10.times do
265
- client.nodes.stats(metric: 'http')['nodes'].values.each do |n|
266
- puts "#{n['name']} : #{n['http']['total_opened']}"
267
- end
268
- end
377
+ 10.times do
378
+ client.nodes.stats(metric: 'http')['nodes'].values.each do |n|
379
+ puts "#{n['name']} : #{n['http']['total_opened']}"
380
+ end
381
+ end
269
382
 
270
- # => Stiletoo : 24
271
- # => Stiletoo : 24
272
- # => Stiletoo : 24
273
- # => ...
383
+ # => Stiletoo : 24
384
+ # => Stiletoo : 24
385
+ # => Stiletoo : 24
386
+ # => ...
387
+ ```
274
388
 
275
389
  To use a specific adapter for _Faraday_, pass it as the `adapter` argument:
276
390
 
@@ -292,44 +406,35 @@ constructor, use the `transport_options` key:
292
406
 
293
407
  To configure the _Faraday_ instance directly, use a block:
294
408
 
295
- require 'typhoeus'
296
- require 'typhoeus/adapters/faraday'
409
+ require 'patron'
297
410
 
298
411
  client = Elasticsearch::Client.new(host: 'localhost', port: '9200') do |f|
299
412
  f.response :logger
300
- f.adapter :typhoeus
413
+ f.adapter :patron
301
414
  end
302
415
 
303
- You can use any standard Faraday middleware and plugins in the configuration block,
304
- for example sign the requests for the [AWS Elasticsearch service](https://aws.amazon.com/elasticsearch-service/):
305
-
306
- require 'faraday_middleware/aws_signers_v4'
307
-
308
- client = Elasticsearch::Client.new url: 'https://search-my-cluster-abc123....es.amazonaws.com' do |f|
309
- f.request :aws_signers_v4,
310
- credentials: Aws::Credentials.new(ENV['AWS_ACCESS_KEY'], ENV['AWS_SECRET_ACCESS_KEY']),
311
- service_name: 'es',
312
- region: 'us-east-1'
313
- end
416
+ You can use any standard Faraday middleware and plugins in the configuration block, for example sign the requests for the [AWS Elasticsearch service](https://aws.amazon.com/elasticsearch-service/). See [the AWS documentation](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-request-signing.html#es-request-signing-ruby) for an example.
314
417
 
315
418
  You can also initialize the transport class yourself, and pass it to the client constructor
316
419
  as the `transport` argument:
317
420
 
318
- require 'typhoeus'
319
- require 'typhoeus/adapters/faraday'
421
+ ```ruby
422
+ require 'patron'
320
423
 
321
- transport_configuration = lambda do |f|
322
- f.response :logger
323
- f.adapter :typhoeus
324
- end
424
+ transport_configuration = lambda do |f|
425
+ f.response :logger
426
+ f.adapter :patron
427
+ end
325
428
 
326
- transport = Elasticsearch::Transport::Transport::HTTP::Faraday.new \
327
- hosts: [ { host: 'localhost', port: '9200' } ],
328
- &transport_configuration
429
+ transport = Elasticsearch::Transport::Transport::HTTP::Faraday.new \
430
+ hosts: [ { host: 'localhost', port: '9200' } ],
431
+ &transport_configuration
432
+
433
+ # Pass the transport to the client
434
+ #
435
+ client = Elasticsearch::Client.new transport: transport
436
+ ```
329
437
 
330
- # Pass the transport to the client
331
- #
332
- client = Elasticsearch::Client.new transport: transport
333
438
 
334
439
  Instead of passing the transport to the constructor, you can inject it at run time:
335
440
 
@@ -458,21 +563,4 @@ can use Ruby 2.x syntax and features.
458
563
 
459
564
  ## License
460
565
 
461
- This software is licensed under the Apache 2 license, quoted below.
462
-
463
- Licensed to Elasticsearch B.V. under one or more contributor
464
- license agreements. See the NOTICE file distributed with
465
- this work for additional information regarding copyright
466
- ownership. Elasticsearch B.V. licenses this file to you under
467
- the Apache License, Version 2.0 (the "License"); you may
468
- not use this file except in compliance with the License.
469
- You may obtain a copy of the License at
470
-
471
- http://www.apache.org/licenses/LICENSE-2.0
472
-
473
- Unless required by applicable law or agreed to in writing,
474
- software distributed under the License is distributed on an
475
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
476
- KIND, either express or implied. See the License for the
477
- specific language governing permissions and limitations
478
- under the License.
566
+ This software is licensed under the [Apache 2 license](./LICENSE).
data/Rakefile CHANGED
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -21,73 +21,55 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
21
21
  require 'elasticsearch/transport/version'
22
22
 
23
23
  Gem::Specification.new do |s|
24
- s.name = "elasticsearch-transport"
24
+ s.name = 'elasticsearch-transport'
25
25
  s.version = Elasticsearch::Transport::VERSION
26
- s.authors = ["Karel Minarik"]
27
- s.email = ["karel.minarik@elasticsearch.org"]
28
- s.summary = "Ruby client for Elasticsearch."
29
- s.homepage = "https://github.com/elasticsearch/elasticsearch-ruby/tree/master/elasticsearch-transport"
30
- s.license = "Apache-2.0"
31
-
26
+ s.authors = ['Karel Minarik']
27
+ s.email = ['karel.minarik@elasticsearch.org']
28
+ s.summary = 'Ruby client for Elasticsearch.'
29
+ s.homepage = 'https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/7.x/index.html'
30
+ s.license = 'Apache-2.0'
31
+ s.metadata = {
32
+ 'homepage_uri' => 'https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/7.x/index.html',
33
+ 'changelog_uri' => 'https://github.com/elastic/elasticsearch-ruby/blob/7.x/CHANGELOG.md',
34
+ 'source_code_uri' => 'https://github.com/elastic/elasticsearch-ruby/tree/7.x/elasticsearch-transport',
35
+ 'bug_tracker_uri' => 'https://github.com/elastic/elasticsearch-ruby/issues'
36
+ }
32
37
  s.files = `git ls-files`.split($/)
33
38
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
34
39
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
35
- s.require_paths = ["lib"]
36
-
37
- s.extra_rdoc_files = [ "README.md", "LICENSE.txt" ]
38
- s.rdoc_options = [ "--charset=UTF-8" ]
39
-
40
- s.required_ruby_version = '>= 1.9'
41
-
42
- s.add_dependency "multi_json"
43
- s.add_dependency "faraday"
44
-
45
- if defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
46
- s.add_dependency "system_timer"
47
- end
48
-
49
- s.add_development_dependency "bundler"
50
-
51
- if defined?(RUBY_VERSION) && RUBY_VERSION > '1.9'
52
- s.add_development_dependency "rake", "~> 11.1"
53
- else
54
- s.add_development_dependency "rake", "< 11.0"
55
- end
56
-
57
- s.add_development_dependency "ansi"
58
- s.add_development_dependency "shoulda-context"
59
- s.add_development_dependency "mocha"
60
- s.add_development_dependency "yard"
61
- s.add_development_dependency "pry"
40
+ s.require_paths = ['lib']
62
41
 
63
- # Gems for testing integrations
64
- s.add_development_dependency "curb" unless defined? JRUBY_VERSION
65
- s.add_development_dependency "patron" unless defined? JRUBY_VERSION
66
- s.add_development_dependency "typhoeus", '~> 0.6'
67
- s.add_development_dependency "net-http-persistent"
68
- s.add_development_dependency "manticore", '~> 0.6' if defined? JRUBY_VERSION
69
- s.add_development_dependency "hashie"
42
+ s.extra_rdoc_files = [ 'README.md', 'LICENSE' ]
43
+ s.rdoc_options = [ '--charset=UTF-8' ]
70
44
 
71
- # Prevent unit test failures on Ruby 1.8
72
- if defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
73
- s.add_development_dependency "test-unit", '~> 2'
74
- s.add_development_dependency "json", '~> 1.8'
75
- end
45
+ s.required_ruby_version = '>= 2.4'
76
46
 
77
- if defined?(RUBY_VERSION) && RUBY_VERSION > '1.9'
78
- s.add_development_dependency "minitest"
79
- s.add_development_dependency "minitest-reporters"
80
- s.add_development_dependency "elasticsearch-extensions"
81
- s.add_development_dependency "ruby-prof" unless defined?(JRUBY_VERSION) || defined?(Rubinius)
82
- s.add_development_dependency "require-prof" unless defined?(JRUBY_VERSION) || defined?(Rubinius)
83
- s.add_development_dependency "simplecov"
84
- s.add_development_dependency "simplecov-rcov"
85
- s.add_development_dependency "cane"
86
- end
47
+ s.add_dependency 'multi_json'
48
+ s.add_dependency 'faraday', '~> 1'
87
49
 
88
- if defined?(RUBY_VERSION) && RUBY_VERSION > '2.2'
89
- s.add_development_dependency "test-unit", '~> 2'
90
- end
50
+ s.add_development_dependency 'cane'
51
+ s.add_development_dependency 'curb' unless defined? JRUBY_VERSION
52
+ s.add_development_dependency 'elasticsearch-extensions'
53
+ s.add_development_dependency 'minitest'
54
+ s.add_development_dependency 'minitest-reporters'
55
+ s.add_development_dependency 'rake', '~> 13'
56
+ s.add_development_dependency 'require-prof' unless defined?(JRUBY_VERSION) || defined?(Rubinius)
57
+ s.add_development_dependency 'ruby-prof' unless defined?(JRUBY_VERSION) || defined?(Rubinius)
58
+ s.add_development_dependency 'simplecov', '~> 0.17', '< 0.18'
59
+ s.add_development_dependency 'simplecov-rcov'
60
+ s.add_development_dependency 'ansi'
61
+ s.add_development_dependency 'hashie'
62
+ s.add_development_dependency 'httpclient'
63
+ s.add_development_dependency 'manticore', '~> 0.6' if defined? JRUBY_VERSION
64
+ s.add_development_dependency 'mocha'
65
+ s.add_development_dependency 'net-http-persistent'
66
+ s.add_development_dependency 'patron' unless defined? JRUBY_VERSION
67
+ s.add_development_dependency 'pry'
68
+ s.add_development_dependency 'shoulda-context'
69
+ s.add_development_dependency 'test-unit', '~> 2'
70
+ s.add_development_dependency 'typhoeus', '~> 1.4'
71
+ s.add_development_dependency 'yard'
72
+ s.add_development_dependency 'bundler'
91
73
 
92
74
  s.description = <<-DESC.gsub(/^ /, '')
93
75
  Ruby client for Elasticsearch. See the `elasticsearch` gem for full integration.
@@ -6,7 +6,7 @@
6
6
  # not use this file except in compliance with the License.
7
7
  # You may obtain a copy of the License at
8
8
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
10
  #
11
11
  # Unless required by applicable law or agreed to in writing,
12
12
  # software distributed under the License is distributed on an
@@ -15,6 +15,8 @@
15
15
  # specific language governing permissions and limitations
16
16
  # under the License.
17
17
 
18
+ require 'base64'
19
+
18
20
  module Elasticsearch
19
21
  module Transport
20
22
 
@@ -46,6 +48,11 @@ module Elasticsearch
46
48
  # @since 7.0.0
47
49
  DEFAULT_HOST = 'localhost:9200'.freeze
48
50
 
51
+ # The default port to use if connecting using a Cloud ID.
52
+ #
53
+ # @since 7.2.0
54
+ DEFAULT_CLOUD_PORT = 9243
55
+
49
56
  # Returns the transport object.
50
57
  #
51
58
  # @see Elasticsearch::Transport::Transport::Base
@@ -101,6 +108,14 @@ module Elasticsearch
101
108
  #
102
109
  # @option arguments [String] :send_get_body_as Specify the HTTP method to use for GET requests with a body.
103
110
  # (Default: GET)
111
+ # @option arguments [true, false] :compression Whether to compress requests. Gzip compression will be used.
112
+ # The default is false. Responses will automatically be inflated if they are compressed.
113
+ # If a custom transport object is used, it must handle the request compression and response inflation.
114
+ #
115
+ # @option api_key [String, Hash] :api_key Use API Key Authentication, either the base64 encoding of `id` and `api_key`
116
+ # joined by a colon as a String, or a hash with the `id` and `api_key` values.
117
+ # @option opaque_id_prefix [String] :opaque_id_prefix set a prefix for X-Opaque-Id when initializing the client. This
118
+ # will be prepended to the id you set before each request if you're using X-Opaque-Id
104
119
  #
105
120
  # @yield [faraday] Access and configure the `Faraday::Connection` instance directly with a block
106
121
  #
@@ -115,9 +130,12 @@ module Elasticsearch
115
130
  @arguments[:randomize_hosts] ||= false
116
131
  @arguments[:transport_options] ||= {}
117
132
  @arguments[:http] ||= {}
118
- @options[:http] ||= {}
133
+ @options[:http] ||= {}
134
+
135
+ set_api_key if (@api_key = @arguments[:api_key])
119
136
 
120
- @seeds = __extract_hosts(@arguments[:hosts] ||
137
+ @seeds = extract_cloud_creds(@arguments)
138
+ @seeds ||= __extract_hosts(@arguments[:hosts] ||
121
139
  @arguments[:host] ||
122
140
  @arguments[:url] ||
123
141
  @arguments[:urls] ||
@@ -125,15 +143,10 @@ module Elasticsearch
125
143
  DEFAULT_HOST)
126
144
 
127
145
  @send_get_body_as = @arguments[:send_get_body_as] || 'GET'
146
+ @opaque_id_prefix = @arguments[:opaque_id_prefix] || nil
128
147
 
129
148
  if @arguments[:request_timeout]
130
- @arguments[:transport_options][:request] = { :timeout => @arguments[:request_timeout] }
131
- end
132
-
133
- @arguments[:transport_options][:headers] ||= {}
134
-
135
- unless @arguments[:transport_options][:headers].keys.any? {|k| k.to_s.downcase =~ /content\-?\_?type/}
136
- @arguments[:transport_options][:headers]['Content-Type'] = 'application/json'
149
+ @arguments[:transport_options][:request] = { timeout: @arguments[:request_timeout] }
137
150
  end
138
151
 
139
152
  if @arguments[:transport]
@@ -141,27 +154,52 @@ module Elasticsearch
141
154
  else
142
155
  transport_class = @arguments[:transport_class] || DEFAULT_TRANSPORT_CLASS
143
156
  if transport_class == Transport::HTTP::Faraday
144
- @transport = transport_class.new(:hosts => @seeds, :options => @arguments) do |faraday|
145
- block.call faraday if block
146
- unless (h = faraday.builder.handlers.last) && h.name.start_with?("Faraday::Adapter")
147
- faraday.adapter(@arguments[:adapter] || __auto_detect_adapter)
148
- end
157
+ @transport = transport_class.new(hosts: @seeds, options: @arguments) do |faraday|
158
+ faraday.adapter(@arguments[:adapter] || __auto_detect_adapter)
159
+ block&.call faraday
149
160
  end
150
161
  else
151
- @transport = transport_class.new(:hosts => @seeds, :options => @arguments)
162
+ @transport = transport_class.new(hosts: @seeds, options: @arguments)
152
163
  end
153
164
  end
154
165
  end
155
166
 
156
167
  # Performs a request through delegation to {#transport}.
157
168
  #
158
- def perform_request(method, path, params={}, body=nil, headers=nil)
169
+ def perform_request(method, path, params = {}, body = nil, headers = nil)
159
170
  method = @send_get_body_as if 'GET' == method && body
171
+ if (opaque_id = params.delete(:opaque_id))
172
+ headers = {} if headers.nil?
173
+ opaque_id = @opaque_id_prefix ? "#{@opaque_id_prefix}#{opaque_id}" : opaque_id
174
+ headers.merge!('X-Opaque-Id' => opaque_id)
175
+ end
160
176
  transport.perform_request(method, path, params, body, headers)
161
177
  end
162
178
 
163
179
  private
164
180
 
181
+ def set_api_key
182
+ @api_key = __encode(@api_key) if @api_key.is_a? Hash
183
+ headers = @arguments[:transport_options]&.[](:headers) || {}
184
+ headers.merge!('Authorization' => "ApiKey #{@api_key}")
185
+ @arguments[:transport_options].merge!(
186
+ headers: headers
187
+ )
188
+ @arguments.delete(:user)
189
+ @arguments.delete(:password)
190
+ end
191
+
192
+ def extract_cloud_creds(arguments)
193
+ return unless arguments[:cloud_id]
194
+ name = arguments[:cloud_id].split(':')[0]
195
+ cloud_url, elasticsearch_instance = Base64.decode64(arguments[:cloud_id].gsub("#{name}:", '')).split('$')
196
+ [ { scheme: 'https',
197
+ user: arguments[:user],
198
+ password: arguments[:password],
199
+ host: "#{elasticsearch_instance}.#{cloud_url}",
200
+ port: arguments[:port] || DEFAULT_CLOUD_PORT } ]
201
+ end
202
+
165
203
  # Normalizes and returns hosts configuration.
166
204
  #
167
205
  # Arrayifies the `hosts_config` argument and extracts `host` and `port` info from strings.
@@ -222,8 +260,14 @@ module Elasticsearch
222
260
  raise ArgumentError, "Please pass host as a String, URI or Hash -- #{host.class} given."
223
261
  end
224
262
 
225
- @options[:http][:user] ||= host_parts[:user]
226
- @options[:http][:password] ||= host_parts[:password]
263
+ if @api_key
264
+ # Remove Basic Auth if using API KEY
265
+ host_parts.delete(:user)
266
+ host_parts.delete(:password)
267
+ else
268
+ @options[:http][:user] ||= host_parts[:user]
269
+ @options[:http][:password] ||= host_parts[:password]
270
+ end
227
271
 
228
272
  host_parts[:port] = host_parts[:port].to_i if host_parts[:port]
229
273
  host_parts[:path].chomp!('/') if host_parts[:path]
@@ -252,6 +296,13 @@ module Elasticsearch
252
296
  ::Faraday.default_adapter
253
297
  end
254
298
  end
299
+
300
+ # Encode credentials for the Authorization Header
301
+ # Credentials is the base64 encoding of id and api_key joined by a colon
302
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html
303
+ def __encode(api_key)
304
+ Base64.strict_encode64([api_key[:id], api_key[:api_key]].join(':'))
305
+ end
255
306
  end
256
307
  end
257
308
  end