elasticsearch 7.17.1 → 8.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +4 -10
- data/{LICENSE → LICENSE.txt} +0 -0
- data/README.md +70 -31
- data/bin/elastic_ruby_console +0 -18
- data/elasticsearch.gemspec +14 -14
- data/lib/elasticsearch/version.rb +1 -1
- data/lib/elasticsearch.rb +100 -30
- data/spec/integration/characters_escaping_spec.rb +11 -11
- data/spec/integration/client_integration_spec.rb +10 -4
- data/spec/spec_helper.rb +8 -3
- data/spec/unit/api_key_spec.rb +101 -0
- data/spec/unit/cloud_credentials_spec.rb +167 -0
- data/spec/unit/custom_transport_implementation_spec.rb +43 -0
- data/spec/unit/elasticsearch_product_validation_spec.rb +53 -217
- data/spec/unit/headers_spec.rb +55 -0
- data/spec/unit/opaque_id_spec.rb +48 -0
- data/spec/unit/wrapper_gem_spec.rb +4 -10
- metadata +28 -20
- data/spec/integration/validation_integration_spec.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef9f6ee043728728b46b462f732089f5b795db38a08c1f3987a3150d635fd164
|
4
|
+
data.tar.gz: f1728d04bec064e80fdf8853665650f7ae42bd1d40db10e098ebab0f43a8f932
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cbaaf9e3a38f42377703df0edb2900ed7cee4cb07ffe0537b65ffbece9ca00122be0df4b7e6cd369581a2e037c4b6039714c0b15165808aea061ca16e92d5508
|
7
|
+
data.tar.gz: b8d7647b88314e1a6003104d98d54282ecd9a5488241632d66a8e8dd4a4c51c17511e8b90e5ea8361ad561f8880757e69d21601787e7df1dd16db6c773f6f761
|
data/Gemfile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Licensed to Elasticsearch B.V. under one or more contributor
|
2
4
|
# license agreements. See the NOTICE file distributed with
|
3
5
|
# this work for additional information regarding copyright
|
@@ -20,14 +22,6 @@ source 'https://rubygems.org'
|
|
20
22
|
# Specify your gem's dependencies in elasticsearch.gemspec
|
21
23
|
gemspec
|
22
24
|
|
23
|
-
if File.exist? File.expand_path(
|
24
|
-
gem 'elasticsearch-api', :
|
25
|
-
end
|
26
|
-
|
27
|
-
if File.exist? File.expand_path("../../elasticsearch-transport/elasticsearch-transport.gemspec", __FILE__)
|
28
|
-
gem 'elasticsearch-transport', :path => File.expand_path("../../elasticsearch-transport", __FILE__), :require => false
|
29
|
-
end
|
30
|
-
|
31
|
-
if File.exist? File.expand_path("../../elasticsearch-extensions", __FILE__)
|
32
|
-
gem 'elasticsearch-extensions', :path => File.expand_path("../../elasticsearch-extensions", __FILE__), :require => true
|
25
|
+
if File.exist? File.expand_path('../elasticsearch-api/elasticsearch-api.gemspec', __dir__)
|
26
|
+
gem 'elasticsearch-api', path: File.expand_path('../elasticsearch-api', __dir__), require: false
|
33
27
|
end
|
data/{LICENSE → LICENSE.txt}
RENAMED
File without changes
|
data/README.md
CHANGED
@@ -2,6 +2,29 @@
|
|
2
2
|
|
3
3
|
The `elasticsearch` library provides a Ruby client and API for [Elasticsearch](http://elasticsearch.com).
|
4
4
|
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
This gem is a wrapper for two separate libraries:
|
8
|
+
|
9
|
+
* [`elasticsearch-transport`](https://github.com/elasticsearch/elasticsearch-ruby/tree/main/elasticsearch-transport), which provides a low-level Ruby client for connecting to [Elastic](http://elasticsearch.com) services.
|
10
|
+
* [`elasticsearch-api`](https://github.com/elasticsearch/elasticsearch-ruby/tree/main/elasticsearch-api), which provides a Ruby API for the Elasticsearch RESTful API.
|
11
|
+
|
12
|
+
Install the `elasticsearch` package and use the API directly:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
require 'elasticsearch'
|
16
|
+
|
17
|
+
client = Elasticsearch::Client.new(log: true)
|
18
|
+
|
19
|
+
client.cluster.health
|
20
|
+
|
21
|
+
client.transport.reload_connections!
|
22
|
+
|
23
|
+
client.search(q: 'test')
|
24
|
+
|
25
|
+
# etc.
|
26
|
+
```
|
27
|
+
|
5
28
|
Features overview:
|
6
29
|
|
7
30
|
* Pluggable logging and tracing
|
@@ -14,25 +37,13 @@ Features overview:
|
|
14
37
|
* Extensive documentation and examples
|
15
38
|
* Emphasis on modularity and extendability of both the client and API libraries
|
16
39
|
|
17
|
-
(For integration with Ruby models and Rails applications,
|
18
|
-
see the <https://github.com/elasticsearch/elasticsearch-rails> project.)
|
40
|
+
(For integration with Ruby models and Rails applications, see the <https://github.com/elasticsearch/elasticsearch-rails> project.)
|
19
41
|
|
20
42
|
## Compatibility
|
21
43
|
|
22
|
-
|
44
|
+
We follow Ruby’s own maintenance policy and officially support all currently maintained versions per [Ruby Maintenance Branches](https://www.ruby-lang.org/en/downloads/branches/).
|
23
45
|
|
24
|
-
|
25
|
-
just use a release matching major version of Elasticsearch.
|
26
|
-
|
27
|
-
| Ruby | | Elasticsearch |
|
28
|
-
|:-------------:|:-:| :-----------: |
|
29
|
-
| 0.90 | → | 0.90 |
|
30
|
-
| 1.x | → | 1.x |
|
31
|
-
| 2.x | → | 2.x |
|
32
|
-
| 5.x | → | 5.x |
|
33
|
-
| 6.x | → | 6.x |
|
34
|
-
| 7.x | → | 7.x |
|
35
|
-
| master | → | master |
|
46
|
+
Language clients are forward compatible; meaning that clients support communicating with greater minor versions of Elasticsearch. Elastic language clients are also backwards compatible with lesser supported minor Elasticsearch versions.
|
36
47
|
|
37
48
|
## Installation
|
38
49
|
|
@@ -51,45 +62,73 @@ or install it from a source code checkout:
|
|
51
62
|
bundle install
|
52
63
|
rake install
|
53
64
|
|
54
|
-
##
|
65
|
+
## Configuration
|
55
66
|
|
56
|
-
|
67
|
+
* [Identifying running tasks with X-Opaque-Id](#identifying-running-tasks-with-x-opaque-id)
|
68
|
+
* [Api Key Authentication](#api-key-authentication)
|
57
69
|
|
58
|
-
|
59
|
-
which provides a low-level Ruby client for connecting to an [Elasticsearch](http://elasticsearch.com) cluster
|
60
|
-
* [`elasticsearch-api`](https://github.com/elasticsearch/elasticsearch-ruby/tree/master/elasticsearch-api),
|
61
|
-
which provides a Ruby API for the Elasticsearch RESTful API
|
70
|
+
### Identifying running tasks with X-Opaque-Id
|
62
71
|
|
63
|
-
|
72
|
+
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:
|
64
73
|
|
65
74
|
```ruby
|
66
|
-
|
75
|
+
client = Elasticsearch::Client.new
|
76
|
+
client.search(index: 'myindex', q: 'title:test', opaque_id: '123456')
|
77
|
+
```
|
78
|
+
The search request will include the following HTTP Header:
|
79
|
+
```
|
80
|
+
X-Opaque-Id: 123456
|
81
|
+
```
|
82
|
+
|
83
|
+
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:
|
84
|
+
```ruby
|
85
|
+
client = Elastic::Transport::Client.new(opaque_id_prefix: 'eu-west1_')
|
86
|
+
client.search(index: 'myindex', q: 'title:test', opaque_id: '123456')
|
87
|
+
```
|
88
|
+
The request will include the following HTTP Header:
|
89
|
+
```
|
90
|
+
X-Opaque-Id: eu-west1_123456
|
91
|
+
```
|
67
92
|
|
68
|
-
|
93
|
+
### Api Key Authentication
|
69
94
|
|
70
|
-
|
95
|
+
You can use [**API Key authentication**](https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html):
|
71
96
|
|
72
|
-
|
97
|
+
``` ruby
|
98
|
+
Elasticsearch::Client.new(
|
99
|
+
host: host,
|
100
|
+
transport_options: transport_options,
|
101
|
+
api_key: credentials
|
102
|
+
)
|
103
|
+
```
|
73
104
|
|
74
|
-
|
105
|
+
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`:
|
75
106
|
|
76
|
-
|
107
|
+
``` ruby
|
108
|
+
Elasticsearch::Client.new(
|
109
|
+
host: host,
|
110
|
+
transport_options: transport_options,
|
111
|
+
api_key: {id: 'my_id', api_key: 'my_api_key'}
|
112
|
+
)
|
77
113
|
```
|
78
114
|
|
115
|
+
## API and Transport
|
116
|
+
|
79
117
|
Please refer to the specific library documentation for details:
|
80
118
|
|
81
119
|
* **Transport**:
|
82
|
-
[[README]](https://github.com/elasticsearch/elasticsearch-ruby/blob/
|
120
|
+
[[README]](https://github.com/elasticsearch/elasticsearch-ruby/blob/main/elasticsearch-transport/README.md)
|
83
121
|
[[Documentation]](http://rubydoc.info/gems/elasticsearch-transport/file/README.markdown)
|
84
122
|
|
85
123
|
* **API**:
|
86
|
-
[[README]](https://github.com/elasticsearch/elasticsearch-ruby/blob/
|
124
|
+
[[README]](https://github.com/elasticsearch/elasticsearch-ruby/blob/main/elasticsearch-api/README.md)
|
87
125
|
[[Documentation]](http://rubydoc.info/gems/elasticsearch-api/file/README.markdown)
|
88
126
|
|
127
|
+
|
89
128
|
## Development
|
90
129
|
|
91
130
|
You can run `rake -T` to check the test tasks. Use `COVERAGE=true` before running a test task to check the coverage with Simplecov.
|
92
131
|
|
93
132
|
## License
|
94
133
|
|
95
|
-
This software is licensed under the [Apache 2 license](./LICENSE).
|
134
|
+
This software is licensed under the [Apache 2 license](./LICENSE).
|
data/bin/elastic_ruby_console
CHANGED
@@ -1,30 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
$LOAD_PATH.unshift(File.expand_path('../../elasticsearch/lib', __dir__))
|
4
|
-
$LOAD_PATH.unshift(File.expand_path('../../elasticsearch-transport/lib', __dir__))
|
5
|
-
$LOAD_PATH.unshift(File.expand_path('../../elasticsearch-dsl/lib', __dir__))
|
6
4
|
$LOAD_PATH.unshift(File.expand_path('../../elasticsearch-api/lib', __dir__))
|
7
|
-
$LOAD_PATH.unshift(File.expand_path('../../elasticsearch-xpack/lib', __dir__))
|
8
|
-
$LOAD_PATH.unshift(File.expand_path('../../elasticsearch-extensions/lib', __dir__))
|
9
5
|
|
10
6
|
require 'elasticsearch'
|
11
|
-
require 'elasticsearch-transport'
|
12
7
|
require 'elasticsearch-api'
|
13
8
|
|
14
|
-
gems_not_loaded = ['elasticsearch-dsl', 'elasticsearch/xpack', 'elasticsearch-extensions'].reject do |gem|
|
15
|
-
begin
|
16
|
-
(require gem) || true
|
17
|
-
rescue LoadError
|
18
|
-
false
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
unless gems_not_loaded.empty?
|
23
|
-
warn "The following gems were not loaded: [#{gems_not_loaded.join(', ')}]. Please install and require them explicitly."
|
24
|
-
end
|
25
|
-
|
26
9
|
include Elasticsearch
|
27
|
-
include Elasticsearch::DSL if defined?(Elasticsearch::DSL)
|
28
10
|
|
29
11
|
begin
|
30
12
|
require 'pry'
|
data/elasticsearch.gemspec
CHANGED
@@ -25,33 +25,33 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.authors = ['Karel Minarik']
|
26
26
|
s.email = ['karel.minarik@elasticsearch.org']
|
27
27
|
s.summary = 'Ruby integrations for Elasticsearch'
|
28
|
-
s.homepage = 'https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/
|
28
|
+
s.homepage = 'https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/current/index.html'
|
29
29
|
s.license = 'Apache-2.0'
|
30
30
|
s.metadata = {
|
31
|
-
'homepage_uri' => 'https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/
|
32
|
-
'changelog_uri' => 'https://github.com/elastic/elasticsearch-ruby/blob/
|
33
|
-
'source_code_uri' => 'https://github.com/elastic/elasticsearch-ruby/tree/
|
31
|
+
'homepage_uri' => 'https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/current/index.html',
|
32
|
+
'changelog_uri' => 'https://github.com/elastic/elasticsearch-ruby/blob/main/CHANGELOG.md',
|
33
|
+
'source_code_uri' => 'https://github.com/elastic/elasticsearch-ruby/tree/main',
|
34
34
|
'bug_tracker_uri' => 'https://github.com/elastic/elasticsearch-ruby/issues'
|
35
35
|
}
|
36
|
-
s.files
|
37
|
-
s.executables
|
38
|
-
s.executables
|
39
|
-
s.test_files
|
36
|
+
s.files = `git ls-files`.split($/)
|
37
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
38
|
+
s.executables << 'elastic_ruby_console'
|
39
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
40
40
|
s.require_paths = ['lib']
|
41
41
|
s.bindir = 'bin'
|
42
42
|
|
43
|
-
s.extra_rdoc_files = [
|
44
|
-
s.rdoc_options = [
|
43
|
+
s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
|
44
|
+
s.rdoc_options = ['--charset=UTF-8']
|
45
45
|
|
46
|
-
s.required_ruby_version = '>= 2.
|
46
|
+
s.required_ruby_version = '>= 2.5'
|
47
47
|
|
48
|
-
s.add_dependency '
|
49
|
-
s.add_dependency 'elasticsearch-api',
|
48
|
+
s.add_dependency 'elastic-transport', '8.0.0'
|
49
|
+
s.add_dependency 'elasticsearch-api', '8.0.1'
|
50
50
|
|
51
51
|
s.add_development_dependency 'bundler'
|
52
52
|
s.add_development_dependency 'byebug' unless defined?(JRUBY_VERSION) || defined?(Rubinius)
|
53
53
|
s.add_development_dependency 'pry'
|
54
|
-
s.add_development_dependency 'rake'
|
54
|
+
s.add_development_dependency 'rake'
|
55
55
|
s.add_development_dependency 'require-prof' unless defined?(JRUBY_VERSION) || defined?(Rubinius)
|
56
56
|
s.add_development_dependency 'rspec'
|
57
57
|
s.add_development_dependency 'ruby-prof' unless defined?(JRUBY_VERSION) || defined?(Rubinius)
|
data/lib/elasticsearch.rb
CHANGED
@@ -16,45 +16,82 @@
|
|
16
16
|
# under the License.
|
17
17
|
|
18
18
|
require 'elasticsearch/version'
|
19
|
-
require '
|
19
|
+
require 'elastic/transport'
|
20
20
|
require 'elasticsearch/api'
|
21
21
|
|
22
22
|
module Elasticsearch
|
23
|
-
SECURITY_PRIVILEGES_VALIDATION_WARNING = 'The client is unable to verify that the server is Elasticsearch due to security privileges on the server side. Some functionality may not be compatible if the server is running an unsupported product.'.freeze
|
24
23
|
NOT_ELASTICSEARCH_WARNING = 'The client noticed that the server is not Elasticsearch and we do not support this unknown product.'.freeze
|
25
|
-
|
26
|
-
|
24
|
+
SECURITY_PRIVILEGES_VALIDATION_WARNING = 'The client is unable to verify that the server is Elasticsearch due to security privileges on the server side. Some functionality may not be compatible if the server is running an unsupported product.'.freeze
|
25
|
+
VALIDATION_WARNING = 'The client is unable to verify that the server is Elasticsearch. Some functionality may not be compatible if the server is running an unsupported product.'.freeze
|
27
26
|
|
27
|
+
# This is the stateful Elasticsearch::Client, using an instance of elastic-transport.
|
28
28
|
class Client
|
29
29
|
include Elasticsearch::API
|
30
|
-
|
31
|
-
|
32
|
-
#
|
30
|
+
# The default port to use if connecting using a Cloud ID.
|
31
|
+
# Updated from 9243 to 443 in client version 7.10.1
|
32
|
+
#
|
33
|
+
# @since 7.2.0
|
34
|
+
DEFAULT_CLOUD_PORT = 443
|
35
|
+
|
36
|
+
# Create a client connected to an Elasticsearch cluster.
|
37
|
+
#
|
38
|
+
# @option arguments [String] :cloud_id - The Cloud ID to connect to Elastic Cloud
|
39
|
+
# @option api_key [String, Hash] :api_key Use API Key Authentication, either the base64 encoding of `id` and `api_key`
|
40
|
+
# joined by a colon as a String, or a hash with the `id` and `api_key` values.
|
41
|
+
# @option opaque_id_prefix [String] :opaque_id_prefix set a prefix for X-Opaque-Id when initializing the client.
|
42
|
+
# This will be prepended to the id you set before each request
|
43
|
+
# if you're using X-Opaque-Id
|
33
44
|
def initialize(arguments = {}, &block)
|
34
45
|
@verified = false
|
35
|
-
@
|
46
|
+
@opaque_id_prefix = arguments[:opaque_id_prefix] || nil
|
47
|
+
api_key(arguments) if arguments[:api_key]
|
48
|
+
if arguments[:cloud_id]
|
49
|
+
arguments[:hosts] = setup_cloud_host(
|
50
|
+
arguments[:cloud_id],
|
51
|
+
arguments[:user],
|
52
|
+
arguments[:password],
|
53
|
+
arguments[:port]
|
54
|
+
)
|
55
|
+
end
|
56
|
+
@transport = Elastic::Transport::Client.new(arguments, &block)
|
36
57
|
end
|
37
58
|
|
38
59
|
def method_missing(name, *args, &block)
|
39
|
-
if name
|
60
|
+
if methods.include?(name)
|
61
|
+
super
|
62
|
+
elsif name == :perform_request
|
63
|
+
# The signature for perform_request is:
|
64
|
+
# method, path, params, body, headers
|
65
|
+
if (opaque_id = args[2]&.delete(:opaque_id))
|
66
|
+
headers = args[4] || {}
|
67
|
+
opaque_id = @opaque_id_prefix ? "#{@opaque_id_prefix}#{opaque_id}" : opaque_id
|
68
|
+
args[4] = headers.merge('X-Opaque-Id' => opaque_id)
|
69
|
+
end
|
40
70
|
verify_elasticsearch unless @verified
|
41
71
|
@transport.perform_request(*args, &block)
|
42
72
|
else
|
43
|
-
|
73
|
+
@transport.send(name, *args, &block)
|
44
74
|
end
|
45
75
|
end
|
46
76
|
|
77
|
+
def respond_to_missing?(method_name, *args)
|
78
|
+
@transport.respond_to?(method_name) || super
|
79
|
+
end
|
80
|
+
|
47
81
|
private
|
48
82
|
|
49
83
|
def verify_elasticsearch
|
50
84
|
begin
|
51
85
|
response = elasticsearch_validation_request
|
52
|
-
rescue
|
53
|
-
|
54
|
-
|
86
|
+
rescue Elastic::Transport::Transport::Errors::Unauthorized,
|
87
|
+
Elastic::Transport::Transport::Errors::Forbidden,
|
88
|
+
Elastic::Transport::Transport::Errors::RequestEntityTooLarge
|
55
89
|
@verified = true
|
56
90
|
warn(SECURITY_PRIVILEGES_VALIDATION_WARNING)
|
57
91
|
return
|
92
|
+
rescue Elastic::Transport::Transport::Error
|
93
|
+
warn(VALIDATION_WARNING)
|
94
|
+
return
|
58
95
|
end
|
59
96
|
|
60
97
|
body = if response.headers['content-type'] == 'application/yaml'
|
@@ -64,36 +101,68 @@ module Elasticsearch
|
|
64
101
|
response.body
|
65
102
|
end
|
66
103
|
version = body.dig('version', 'number')
|
67
|
-
verify_with_version_or_header(
|
104
|
+
verify_with_version_or_header(version, response.headers)
|
105
|
+
rescue StandardError => e
|
106
|
+
warn(VALIDATION_WARNING)
|
107
|
+
raise e
|
68
108
|
end
|
69
109
|
|
70
|
-
def verify_with_version_or_header(
|
71
|
-
|
110
|
+
def verify_with_version_or_header(version, headers)
|
111
|
+
if version.nil? ||
|
112
|
+
Gem::Version.new(version) < Gem::Version.new('8.0.0.pre') && version != '8.0.0-SNAPSHOT' ||
|
113
|
+
headers['x-elastic-product'] != 'Elasticsearch'
|
72
114
|
|
73
|
-
|
74
|
-
|
115
|
+
raise Elasticsearch::UnsupportedProductError
|
116
|
+
end
|
75
117
|
|
76
|
-
|
77
|
-
|
78
|
-
Gem::Version.new(version) < Gem::Version.new('7.0.0')
|
79
|
-
raise Elasticsearch::UnsupportedProductError unless
|
80
|
-
body['tagline'] == YOU_KNOW_FOR_SEARCH
|
118
|
+
@verified = true
|
119
|
+
end
|
81
120
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
raise Elasticsearch::UnsupportedProductError unless body['tagline'] == YOU_KNOW_FOR_SEARCH
|
86
|
-
raise Elasticsearch::UnsupportedProductError.new(NOT_SUPPORTED_ELASTICSEARCH_WARNING) unless body.dig('version', 'build_flavor') == 'default'
|
121
|
+
def setup_cloud_host(cloud_id, user, password, port)
|
122
|
+
name = cloud_id.split(':')[0]
|
123
|
+
cloud_url, elasticsearch_instance = Base64.decode64(cloud_id.gsub("#{name}:", '')).split('$')
|
87
124
|
|
88
|
-
|
125
|
+
if cloud_url.include?(':')
|
126
|
+
url, port = cloud_url.split(':')
|
127
|
+
host = "#{elasticsearch_instance}.#{url}"
|
128
|
+
else
|
129
|
+
host = "#{elasticsearch_instance}.#{cloud_url}"
|
130
|
+
port ||= DEFAULT_CLOUD_PORT
|
131
|
+
end
|
132
|
+
[{ scheme: 'https', user: user, password: password, host: host, port: port.to_i }]
|
133
|
+
end
|
134
|
+
|
135
|
+
def api_key(arguments)
|
136
|
+
api_key = if arguments[:api_key].is_a? Hash
|
137
|
+
encode(arguments[:api_key])
|
138
|
+
else
|
139
|
+
arguments[:api_key]
|
140
|
+
end
|
141
|
+
arguments.delete(:user)
|
142
|
+
arguments.delete(:password)
|
143
|
+
authorization = { 'Authorization' => "ApiKey #{api_key}" }
|
144
|
+
if (headers = arguments.dig(:transport_options, :headers))
|
145
|
+
headers.merge!(authorization)
|
146
|
+
else
|
147
|
+
arguments[:transport_options] = {
|
148
|
+
headers: authorization
|
149
|
+
}
|
89
150
|
end
|
90
151
|
end
|
91
152
|
|
153
|
+
# Encode credentials for the Authorization Header
|
154
|
+
# Credentials is the base64 encoding of id and api_key joined by a colon
|
155
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html
|
156
|
+
def encode(api_key)
|
157
|
+
Base64.strict_encode64([api_key[:id], api_key[:api_key]].join(':'))
|
158
|
+
end
|
159
|
+
|
92
160
|
def elasticsearch_validation_request
|
93
161
|
@transport.perform_request('GET', '/')
|
94
162
|
end
|
95
163
|
end
|
96
164
|
|
165
|
+
# Error class for when we detect an unsupported version of Elasticsearch
|
97
166
|
class UnsupportedProductError < StandardError
|
98
167
|
def initialize(message = NOT_ELASTICSEARCH_WARNING)
|
99
168
|
super(message)
|
@@ -101,6 +170,7 @@ module Elasticsearch
|
|
101
170
|
end
|
102
171
|
end
|
103
172
|
|
173
|
+
# Helper for the meta-header value for Cloud
|
104
174
|
module Elastic
|
105
175
|
# If the version is X.X.X.pre/alpha/beta, use X.X.Xp for the meta-header:
|
106
176
|
def self.client_meta_version
|
@@ -111,6 +181,6 @@ module Elastic
|
|
111
181
|
Elasticsearch::VERSION
|
112
182
|
end
|
113
183
|
|
114
|
-
# Constant for
|
184
|
+
# Constant for elastic-transport meta-header
|
115
185
|
ELASTICSEARCH_SERVICE_VERSION = [:es, client_meta_version].freeze
|
116
186
|
end
|
@@ -32,37 +32,37 @@ context 'Elasticsearch client' do
|
|
32
32
|
context 'escaping spaces in ids' do
|
33
33
|
it 'escapes spaces for id when using index' do
|
34
34
|
response = client.index(index: index, id: 'a test 1', body: { name: 'A test 1' }, refresh: true)
|
35
|
-
expect(response['_id']).to eq 'a test 1'
|
35
|
+
expect(response.body['_id']).to eq 'a test 1'
|
36
36
|
|
37
37
|
response = client.search(index: index)
|
38
|
-
expect(response['hits']['hits'].first['_id']).to eq 'a test 1'
|
38
|
+
expect(response.body['hits']['hits'].first['_id']).to eq 'a test 1'
|
39
39
|
|
40
40
|
# Raises exception, _id is unrecognized
|
41
41
|
expect do
|
42
42
|
client.index(index: index, _id: 'a test 2', body: { name: 'A test 2' })
|
43
|
-
end.to raise_exception
|
43
|
+
end.to raise_exception Elastic::Transport::Transport::Errors::BadRequest
|
44
44
|
|
45
45
|
# Raises exception, id is a query parameter
|
46
46
|
expect do
|
47
47
|
client.index(index: index, body: { name: 'A test 3', _id: 'a test 3' })
|
48
|
-
end.to raise_exception
|
48
|
+
end.to raise_exception Elastic::Transport::Transport::Errors::BadRequest
|
49
49
|
end
|
50
50
|
|
51
51
|
it 'escapes spaces for id when using create' do
|
52
52
|
# Works with create
|
53
53
|
response = client.create(index: index, id: 'a test 4', body: { name: 'A test 4' })
|
54
|
-
expect(response['_id']).to eq 'a test 4'
|
54
|
+
expect(response.body['_id']).to eq 'a test 4'
|
55
55
|
end
|
56
56
|
|
57
57
|
it 'escapes spaces for id when using bulk' do
|
58
58
|
body = [
|
59
59
|
{ create: { _index: index, _id: 'a test 5', data: { name: 'A test 5' } } }
|
60
60
|
]
|
61
|
-
expect(client.bulk(body: body, refresh: true))
|
61
|
+
expect(client.bulk(body: body, refresh: true).status).to eq 200
|
62
62
|
|
63
63
|
response = client.search(index: index)
|
64
64
|
expect(
|
65
|
-
response['hits']['hits'].select { |a| a['_id'] == 'a test 5' }.size
|
65
|
+
response.body['hits']['hits'].select { |a| a['_id'] == 'a test 5' }.size
|
66
66
|
).to eq 1
|
67
67
|
end
|
68
68
|
end
|
@@ -70,24 +70,24 @@ context 'Elasticsearch client' do
|
|
70
70
|
context 'it doesnae escape plus signs in id' do
|
71
71
|
it 'escapes spaces for id when using index' do
|
72
72
|
response = client.index(index: index, id: 'a+test+1', body: { name: 'A test 1' })
|
73
|
-
expect(response['_id']).to eq 'a+test+1'
|
73
|
+
expect(response.body['_id']).to eq 'a+test+1'
|
74
74
|
end
|
75
75
|
|
76
76
|
it 'escapes spaces for id when using create' do
|
77
77
|
# Works with create
|
78
78
|
response = client.create(index: index, id: 'a+test+2', body: { name: 'A test 2' })
|
79
|
-
expect(response['_id']).to eq 'a+test+2'
|
79
|
+
expect(response.body['_id']).to eq 'a+test+2'
|
80
80
|
end
|
81
81
|
|
82
82
|
it 'escapes spaces for id when using bulk' do
|
83
83
|
body = [
|
84
84
|
{ create: { _index: index, _id: 'a+test+3', data: { name: 'A test 3' } } }
|
85
85
|
]
|
86
|
-
expect(client.bulk(body: body, refresh: true))
|
86
|
+
expect(client.bulk(body: body, refresh: true).status).to eq 200
|
87
87
|
|
88
88
|
response = client.search(index: index)
|
89
89
|
expect(
|
90
|
-
response['hits']['hits'].select { |a| a['_id'] == 'a+test+3' }.size
|
90
|
+
response.body['hits']['hits'].select { |a| a['_id'] == 'a+test+3' }.size
|
91
91
|
).to eq 1
|
92
92
|
end
|
93
93
|
end
|
@@ -14,6 +14,9 @@
|
|
14
14
|
# KIND, either express or implied. See the License for the
|
15
15
|
# specific language governing permissions and limitations
|
16
16
|
# under the License.
|
17
|
+
ELASTICSEARCH_URL = ENV['TEST_ES_SERVER'] || "http://localhost:#{(ENV['PORT'] || 9200)}"
|
18
|
+
raise URI::InvalidURIError unless ELASTICSEARCH_URL =~ /\A#{URI::DEFAULT_PARSER.make_regexp}\z/
|
19
|
+
|
17
20
|
require 'spec_helper'
|
18
21
|
require 'logger'
|
19
22
|
|
@@ -23,7 +26,9 @@ context 'Elasticsearch client' do
|
|
23
26
|
let(:client) do
|
24
27
|
Elasticsearch::Client.new(
|
25
28
|
host: ELASTICSEARCH_URL,
|
26
|
-
logger: logger
|
29
|
+
logger: logger,
|
30
|
+
user: 'elastic',
|
31
|
+
password: 'changeme'
|
27
32
|
)
|
28
33
|
end
|
29
34
|
|
@@ -49,9 +54,10 @@ context 'Elasticsearch client' do
|
|
49
54
|
end
|
50
55
|
|
51
56
|
context 'Reports the right meta header' do
|
52
|
-
it 'Reports es service name and gem
|
53
|
-
headers = client.transport.
|
54
|
-
|
57
|
+
it 'Reports es service name and gem versio' do
|
58
|
+
headers = client.transport.connections.first.connection.headers
|
59
|
+
version = Class.new.extend(Elastic::Transport::MetaHeader).send(:client_meta_version, Elasticsearch::VERSION)
|
60
|
+
expect(headers['x-elastic-client-meta']).to match /^es=#{version}/
|
55
61
|
end
|
56
62
|
end
|
57
63
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -18,9 +18,14 @@
|
|
18
18
|
require 'elasticsearch'
|
19
19
|
require 'rspec'
|
20
20
|
|
21
|
-
ELASTICSEARCH_URL = ENV['TEST_ES_SERVER'] || "http://localhost:#{(ENV['PORT'] || 9200)}"
|
22
|
-
raise URI::InvalidURIError unless ELASTICSEARCH_URL =~ /\A#{URI::DEFAULT_PARSER.make_regexp}\z/
|
23
|
-
|
24
21
|
RSpec.configure do |config|
|
25
22
|
config.formatter = :documentation
|
26
23
|
end
|
24
|
+
|
25
|
+
def meta_version
|
26
|
+
client.send(:client_meta_version, Elasticsearch::VERSION)
|
27
|
+
end
|
28
|
+
|
29
|
+
def jruby?
|
30
|
+
defined?(JRUBY_VERSION)
|
31
|
+
end
|