elasticsearch-transport 7.1.0 → 7.8.0

Sign up to get free protection for your applications and to get access to all the features.
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