elasticsearch 7.1.0 → 8.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,91 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
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
+
20
+ require 'spec_helper'
21
+ require 'elasticsearch/helpers/scroll_helper'
22
+
23
+ context 'Elasticsearch client helpers' do
24
+ let(:client) do
25
+ Elasticsearch::Client.new(
26
+ host: ELASTICSEARCH_URL,
27
+ user: 'elastic',
28
+ password: 'changeme'
29
+ )
30
+ end
31
+ let(:index) { 'books' }
32
+ let(:body) { { size: 12, query: { match_all: {} } } }
33
+ let(:scroll_helper) { Elasticsearch::Helpers::ScrollHelper.new(client, index, body) }
34
+
35
+ before do
36
+ documents = [
37
+ { index: { _index: index, data: {name: "Leviathan Wakes", "author": "James S.A. Corey", "release_date": "2011-06-02", "page_count": 561} } },
38
+ { index: { _index: index, data: {name: "Hyperion", "author": "Dan Simmons", "release_date": "1989-05-26", "page_count": 482} } },
39
+ { index: { _index: index, data: {name: "Dune", "author": "Frank Herbert", "release_date": "1965-06-01", "page_count": 604} } },
40
+ { index: { _index: index, data: {name: "Dune Messiah", "author": "Frank Herbert", "release_date": "1969-10-15", "page_count": 331} } },
41
+ { index: { _index: index, data: {name: "Children of Dune", "author": "Frank Herbert", "release_date": "1976-04-21", "page_count": 408} } },
42
+ { index: { _index: index, data: {name: "God Emperor of Dune", "author": "Frank Herbert", "release_date": "1981-05-28", "page_count": 454} } },
43
+ { index: { _index: index, data: {name: "Consider Phlebas", "author": "Iain M. Banks", "release_date": "1987-04-23", "page_count": 471} } },
44
+ { index: { _index: index, data: {name: "Pandora's Star", "author": "Peter F. Hamilton", "release_date": "2004-03-02", "page_count": 768} } },
45
+ { index: { _index: index, data: {name: "Revelation Space", "author": "Alastair Reynolds", "release_date": "2000-03-15", "page_count": 585} } },
46
+ { index: { _index: index, data: {name: "A Fire Upon the Deep", "author": "Vernor Vinge", "release_date": "1992-06-01", "page_count": 613} } },
47
+ { index: { _index: index, data: {name: "Ender's Game", "author": "Orson Scott Card", "release_date": "1985-06-01", "page_count": 324} } },
48
+ { index: { _index: index, data: {name: "1984", "author": "George Orwell", "release_date": "1985-06-01", "page_count": 328} } },
49
+ { index: { _index: index, data: {name: "Fahrenheit 451", "author": "Ray Bradbury", "release_date": "1953-10-15", "page_count": 227} } },
50
+ { index: { _index: index, data: {name: "Brave New World", "author": "Aldous Huxley", "release_date": "1932-06-01", "page_count": 268} } },
51
+ { index: { _index: index, data: {name: "Foundation", "author": "Isaac Asimov", "release_date": "1951-06-01", "page_count": 224} } },
52
+ { index: { _index: index, data: {name: "The Giver", "author": "Lois Lowry", "release_date": "1993-04-26", "page_count": 208} } },
53
+ { index: { _index: index, data: {name: "Slaughterhouse-Five", "author": "Kurt Vonnegut", "release_date": "1969-06-01", "page_count": 275} } },
54
+ { index: { _index: index, data: {name: "The Hitchhiker's Guide to the Galaxy", "author": "Douglas Adams", "release_date": "1979-10-12", "page_count": 180} } },
55
+ { index: { _index: index, data: {name: "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "page_count": 470} } },
56
+ { index: { _index: index, data: {name: "Neuromancer", "author": "William Gibson", "release_date": "1984-07-01", "page_count": 271} } },
57
+ { index: { _index: index, data: {name: "The Handmaid's Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311} } },
58
+ { index: { _index: index, data: {name: "Starship Troopers", "author": "Robert A. Heinlein", "release_date": "1959-12-01", "page_count": 335} } },
59
+ { index: { _index: index, data: {name: "The Left Hand of Darkness", "author": "Ursula K. Le Guin", "release_date": "1969-06-01", "page_count": 304} } },
60
+ { index: { _index: index, data: {name: "The Moon is a Harsh Mistress", "author": "Robert A. Heinlein", "release_date": "1966-04-01", "page_count": 288 } } }
61
+ ]
62
+ client.bulk(body: documents, refresh: 'wait_for')
63
+ end
64
+
65
+ after do
66
+ client.indices.delete(index: index)
67
+ end
68
+
69
+ it 'instantiates a scroll helper' do
70
+ expect(scroll_helper).to be_an_instance_of Elasticsearch::Helpers::ScrollHelper
71
+ end
72
+
73
+ it 'searches an index' do
74
+ my_documents = []
75
+ while !(documents = scroll_helper.results).empty?
76
+ my_documents << documents
77
+ end
78
+
79
+ expect(my_documents.flatten.size).to eq 24
80
+ end
81
+
82
+ it 'uses enumerable' do
83
+ count = 0
84
+ scroll_helper.each { |a| count += 1 }
85
+ expect(count).to eq 24
86
+ expect(scroll_helper).to respond_to(:count)
87
+ expect(scroll_helper).to respond_to(:reject)
88
+ expect(scroll_helper).to respond_to(:uniq)
89
+ expect(scroll_helper.map { |a| a['_id'] }.uniq.count).to eq 24
90
+ end
91
+ end
@@ -0,0 +1,31 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ require 'elasticsearch'
19
+ require 'rspec'
20
+
21
+ RSpec.configure do |config|
22
+ config.formatter = :documentation
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
@@ -0,0 +1,137 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ require 'spec_helper'
19
+
20
+ describe Elasticsearch::Client do
21
+ context 'when using API Key' do
22
+ let(:authorization_header) do
23
+ client.transport.connections.first.connection.headers['Authorization']
24
+ end
25
+
26
+ context 'when an encoded api_key is provided' do
27
+ let(:client) do
28
+ described_class.new(api_key: 'an_api_key')
29
+ end
30
+
31
+ it 'Adds the ApiKey header to the connection' do
32
+ expect(authorization_header).to eq('ApiKey an_api_key')
33
+ end
34
+ end
35
+
36
+ context 'when an un-encoded api_key is provided' do
37
+ let(:client) do
38
+ described_class.new(api_key: { id: 'my_id', api_key: 'my_api_key' })
39
+ end
40
+
41
+ it 'Adds the ApiKey header to the connection' do
42
+ expect(authorization_header).to eq("ApiKey #{Base64.strict_encode64('my_id:my_api_key')}")
43
+ end
44
+ end
45
+
46
+ context 'when basic auth and api_key are provided' do
47
+ let(:client) do
48
+ described_class.new(
49
+ api_key: { id: 'my_id', api_key: 'my_api_key' },
50
+ host: 'http://elastic:password@localhost:9200'
51
+ )
52
+ end
53
+
54
+ it 'removes basic auth credentials' do
55
+ expect(authorization_header).not_to match(/^Basic/)
56
+ expect(authorization_header).to match(/^ApiKey/)
57
+ end
58
+ end
59
+
60
+ context 'when other headers were specified' do
61
+ let(:client) do
62
+ described_class.new(
63
+ api_key: 'elasticsearch_api_key',
64
+ transport_options: { headers: { 'x-test-header' => 'test' } }
65
+ )
66
+ end
67
+
68
+ it 'Adds the ApiKey header to the connection and keeps the header' do
69
+ header = client.transport.connections.first.connection.headers
70
+ expect(header['Authorization']).to eq('ApiKey elasticsearch_api_key')
71
+ expect(header['X-Test-Header']).to eq('test')
72
+ end
73
+ end
74
+
75
+ context 'when sending transport_options but no headers were specified' do
76
+ let(:client) do
77
+ described_class.new(
78
+ api_key: 'elasticsearch_api_key',
79
+ transport_options: { ssl: { verify: false } }
80
+ )
81
+ end
82
+
83
+ it 'Adds the ApiKey header to the connection and keeps the options' do
84
+ header = client.transport.connections.first.connection.headers
85
+ expect(header['Authorization']).to eq('ApiKey elasticsearch_api_key')
86
+ expect(client.transport.options[:transport_options]).to include({ ssl: { verify: false } })
87
+ expect(client.transport.options[:transport_options][:headers]).to include('Authorization' => 'ApiKey elasticsearch_api_key')
88
+ end
89
+ end
90
+
91
+ context 'when other headers and options were specified' do
92
+ let(:client) do
93
+ described_class.new(
94
+ api_key: 'elasticsearch_api_key',
95
+ transport_options: {
96
+ headers: { 'x-test-header' => 'test' },
97
+ ssl: { verify: false }
98
+ }
99
+ )
100
+ end
101
+
102
+ it 'Adds the ApiKey header to the connection and keeps the header' do
103
+ header = client.transport.connections.first.connection.headers
104
+ expect(header['X-Test-Header']).to eq('test')
105
+ expect(header['Authorization']).to eq('ApiKey elasticsearch_api_key')
106
+ expect(client.transport.options[:transport_options]).to include({ ssl: { verify: false } })
107
+ expect(client.transport.options[:transport_options][:headers]).to include('Authorization' => 'ApiKey elasticsearch_api_key')
108
+ end
109
+ end
110
+
111
+ context 'Metaheader' do
112
+ let(:adapter_code) { "nh=#{defined?(Net::HTTP::VERSION) ? Net::HTTP::VERSION : Net::HTTP::HTTPVersion}" }
113
+ let(:meta_header) do
114
+ if jruby?
115
+ "es=#{meta_version},rb=#{RUBY_VERSION},t=#{Elastic::Transport::VERSION},jv=#{ENV_JAVA['java.version']},jr=#{JRUBY_VERSION},fd=#{Faraday::VERSION},#{adapter_code}"
116
+ else
117
+ "es=#{meta_version},rb=#{RUBY_VERSION},t=#{Elastic::Transport::VERSION},fd=#{Faraday::VERSION},#{adapter_code}"
118
+ end
119
+ end
120
+
121
+ context 'when using API Key' do
122
+ let(:client) do
123
+ described_class.new(api_key: 'an_api_key')
124
+ end
125
+
126
+ let(:headers) do
127
+ client.transport.connections.first.connection.headers
128
+ end
129
+
130
+ it 'adds the ApiKey header to the connection' do
131
+ expect(authorization_header).to eq('ApiKey an_api_key')
132
+ expect(headers).to include('x-elastic-client-meta' => meta_header)
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,167 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ require 'spec_helper'
19
+
20
+ describe Elasticsearch::Client do
21
+ context 'when cloud credentials are provided' do
22
+ let(:client) do
23
+ described_class.new(
24
+ cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==',
25
+ user: 'elastic',
26
+ password: 'changeme'
27
+ )
28
+ end
29
+
30
+ let(:hosts) do
31
+ client.transport.hosts
32
+ end
33
+
34
+ it 'extracts the cloud credentials' do
35
+ expect(hosts[0][:host]).to eq('abcd.localhost')
36
+ expect(hosts[0][:protocol]).to eq('https')
37
+ expect(hosts[0][:user]).to eq('elastic')
38
+ expect(hosts[0][:password]).to eq('changeme')
39
+ expect(hosts[0][:port]).to eq(443)
40
+ end
41
+
42
+ it 'creates the correct full url' do
43
+ expect(
44
+ client.transport.__full_url(client.transport.hosts[0])
45
+ ).to eq('https://elastic:changeme@abcd.localhost:443')
46
+ end
47
+
48
+ context 'when a port is specified' do
49
+ let(:client) do
50
+ described_class.new(cloud_id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA==', user: 'elastic', password: 'changeme', port: 9250)
51
+ end
52
+
53
+ it 'sets the specified port along with the cloud credentials' do
54
+ expect(hosts[0][:host]).to eq('abcd.localhost')
55
+ expect(hosts[0][:protocol]).to eq('https')
56
+ expect(hosts[0][:user]).to eq('elastic')
57
+ expect(hosts[0][:password]).to eq('changeme')
58
+ expect(hosts[0][:port]).to eq(9250)
59
+ end
60
+
61
+ it 'creates the correct full url' do
62
+ expect(client.transport.__full_url(client.transport.hosts[0])).to eq('https://elastic:changeme@abcd.localhost:9250')
63
+ end
64
+ end
65
+
66
+ context 'when the cluster has alternate names' do
67
+ let(:client) do
68
+ described_class.new(
69
+ cloud_id: 'myCluster:bG9jYWxob3N0JGFiY2QkZWZnaA==',
70
+ user: 'elasticfantastic',
71
+ password: 'tobechanged'
72
+ )
73
+ end
74
+
75
+ let(:hosts) do
76
+ client.transport.hosts
77
+ end
78
+
79
+ it 'extracts the cloud credentials' do
80
+ expect(hosts[0][:host]).to eq('abcd.localhost')
81
+ expect(hosts[0][:protocol]).to eq('https')
82
+ expect(hosts[0][:user]).to eq('elasticfantastic')
83
+ expect(hosts[0][:password]).to eq('tobechanged')
84
+ expect(hosts[0][:port]).to eq(443)
85
+ end
86
+
87
+ it 'creates the correct full url' do
88
+ expect(
89
+ client.transport.__full_url(client.transport.hosts[0])
90
+ ).to eq('https://elasticfantastic:tobechanged@abcd.localhost:443')
91
+ end
92
+ end
93
+
94
+ context 'when decoded cloud id has a trailing dollar sign' do
95
+ let(:client) do
96
+ described_class.new(
97
+ cloud_id: 'a_cluster:bG9jYWxob3N0JGFiY2Qk',
98
+ user: 'elasticfantastic',
99
+ password: 'changeme'
100
+ )
101
+ end
102
+
103
+ let(:hosts) do
104
+ client.transport.hosts
105
+ end
106
+
107
+ it 'extracts the cloud credentials' do
108
+ expect(hosts[0][:host]).to eq('abcd.localhost')
109
+ expect(hosts[0][:protocol]).to eq('https')
110
+ expect(hosts[0][:user]).to eq('elasticfantastic')
111
+ expect(hosts[0][:password]).to eq('changeme')
112
+ expect(hosts[0][:port]).to eq(443)
113
+ end
114
+
115
+ it 'creates the correct full url' do
116
+ expect(
117
+ client.transport.__full_url(client.transport.hosts[0])
118
+ ).to eq('https://elasticfantastic:changeme@abcd.localhost:443')
119
+ end
120
+ end
121
+
122
+ context 'when the cloud host provides a port' do
123
+ let(:client) do
124
+ described_class.new(
125
+ cloud_id: 'name:ZWxhc3RpY19zZXJ2ZXI6OTI0MyRlbGFzdGljX2lk',
126
+ user: 'elastic',
127
+ password: 'changeme'
128
+ )
129
+ end
130
+
131
+ let(:hosts) do
132
+ client.transport.hosts
133
+ end
134
+
135
+ it 'creates the correct full url' do
136
+ expect(hosts[0][:host]).to eq('elastic_id.elastic_server')
137
+ expect(hosts[0][:protocol]).to eq('https')
138
+ expect(hosts[0][:user]).to eq('elastic')
139
+ expect(hosts[0][:password]).to eq('changeme')
140
+ expect(hosts[0][:port]).to eq(9243)
141
+ end
142
+ end
143
+
144
+ context 'when the cloud host provides a port and the port is also specified' do
145
+ let(:client) do
146
+ described_class.new(
147
+ cloud_id: 'name:ZWxhc3RpY19zZXJ2ZXI6OTI0MyRlbGFzdGljX2lk',
148
+ user: 'elastic',
149
+ password: 'changeme',
150
+ port: 9200
151
+ )
152
+ end
153
+
154
+ let(:hosts) do
155
+ client.transport.hosts
156
+ end
157
+
158
+ it 'creates the correct full url' do
159
+ expect(hosts[0][:host]).to eq('elastic_id.elastic_server')
160
+ expect(hosts[0][:protocol]).to eq('https')
161
+ expect(hosts[0][:user]).to eq('elastic')
162
+ expect(hosts[0][:password]).to eq('changeme')
163
+ expect(hosts[0][:port]).to eq(9243)
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,43 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+ require 'spec_helper'
18
+
19
+ describe Elasticsearch::Client do
20
+ context 'when using custom transport implementation' do
21
+ class MyTransport
22
+ include Elastic::Transport::Transport::Base
23
+ def initialize(args); end
24
+ end
25
+ let(:client) { Elasticsearch::Client.new(transport_class: MyTransport) }
26
+ let(:arguments) { client.instance_variable_get('@transport').instance_variable_get('@arguments') }
27
+ let(:subject) do
28
+ arguments[:transport_options][:headers]
29
+ end
30
+
31
+ let(:meta_header) do
32
+ if jruby?
33
+ "es=#{meta_version},rb=#{RUBY_VERSION},t=#{Elastic::Transport::VERSION},jv=#{ENV_JAVA['java.version']},jr=#{JRUBY_VERSION}"
34
+ else
35
+ "es=#{meta_version},rb=#{RUBY_VERSION},t=#{Elastic::Transport::VERSION}"
36
+ end
37
+ end
38
+
39
+ it 'doesnae set any info about the implementation in the metaheader' do
40
+ expect(subject).to include('x-elastic-client-meta' => meta_header)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,148 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ require 'spec_helper'
19
+ require 'webmock/rspec'
20
+
21
+ describe 'Elasticsearch: Validation' do
22
+ let(:host) { 'http://localhost:9200' }
23
+ let(:count_request_stub) do
24
+ stub_request(:get, "#{host}/_count")
25
+ .to_return(status: status, body: nil, headers: headers)
26
+ end
27
+ let(:status) { 200 }
28
+ let(:body) { nil }
29
+ let(:headers) { {} }
30
+ let(:client) { Elasticsearch::Client.new }
31
+
32
+ context 'When Elasticsearch replies with status 401' do
33
+ let(:status) { 401 }
34
+
35
+ it 'Verifies the request but shows a warning' do
36
+ stderr = $stderr
37
+ fake_stderr = StringIO.new
38
+ $stderr = fake_stderr
39
+ expect(client.instance_variable_get('@verified')).to be false
40
+ count_request_stub
41
+ expect do
42
+ client.count
43
+ end.to raise_error Elastic::Transport::Transport::Errors::Unauthorized
44
+ expect(client.instance_variable_get('@verified')).to be true
45
+
46
+ fake_stderr.rewind
47
+ expect(fake_stderr.string).to eq("#{Elasticsearch::SECURITY_PRIVILEGES_VALIDATION_WARNING}\n")
48
+ ensure
49
+ $stderr = stderr
50
+ end
51
+ end
52
+
53
+ context 'When Elasticsearch replies with status 403' do
54
+ let(:status) { 403 }
55
+
56
+ it 'Verifies the request but shows a warning' do
57
+ stderr = $stderr
58
+ fake_stderr = StringIO.new
59
+ $stderr = fake_stderr
60
+
61
+ expect(client.instance_variable_get('@verified')).to be false
62
+ count_request_stub
63
+ expect do
64
+ client.count
65
+ end.to raise_error Elastic::Transport::Transport::Errors::Forbidden
66
+ expect(client.instance_variable_get('@verified')).to be true
67
+
68
+ fake_stderr.rewind
69
+ expect(fake_stderr.string).to eq("#{Elasticsearch::SECURITY_PRIVILEGES_VALIDATION_WARNING}\n")
70
+ ensure
71
+ $stderr = stderr
72
+ end
73
+ end
74
+
75
+ context 'When Elasticsearch replies with status 413' do
76
+ let(:status) { 413 }
77
+
78
+ it 'Verifies the request and shows a warning' do
79
+ stderr = $stderr
80
+ fake_stderr = StringIO.new
81
+ $stderr = fake_stderr
82
+
83
+ expect(client.instance_variable_get('@verified')).to be false
84
+ count_request_stub
85
+ expect do
86
+ client.count
87
+ end.to raise_error Elastic::Transport::Transport::Errors::RequestEntityTooLarge
88
+ expect(client.instance_variable_get('@verified')).to be true
89
+
90
+ fake_stderr.rewind
91
+ expect(fake_stderr.string.delete("\n"))
92
+ .to eq(Elasticsearch::SECURITY_PRIVILEGES_VALIDATION_WARNING)
93
+ ensure
94
+ $stderr = stderr
95
+ end
96
+ end
97
+
98
+ context 'When Elasticsearch replies with status 503' do
99
+ let(:status) { 503 }
100
+ let(:body) { {}.to_json }
101
+
102
+ it 'Does not verify the request and shows a warning' do
103
+ stderr = $stderr
104
+ fake_stderr = StringIO.new
105
+ $stderr = fake_stderr
106
+
107
+ expect(client.instance_variable_get('@verified')).to be false
108
+ count_request_stub
109
+ expect do
110
+ client.count
111
+ end.to raise_error Elastic::Transport::Transport::Errors::ServiceUnavailable
112
+ expect(client.instance_variable_get('@verified')).to be false
113
+
114
+ fake_stderr.rewind
115
+ expect(fake_stderr.string)
116
+ .to eq(
117
+ <<~MSG
118
+ The client is unable to verify that the server is \
119
+ Elasticsearch. Some functionality may not be compatible \
120
+ if the server is running an unsupported product.
121
+ MSG
122
+ )
123
+ ensure
124
+ $stderr = stderr
125
+ end
126
+ end
127
+
128
+ context 'When the header is present' do
129
+ let(:headers) { { 'X-Elastic-Product' => 'Elasticsearch' } }
130
+
131
+ it 'Makes requests and passes validation' do
132
+ expect(client.instance_variable_get('@verified')).to be false
133
+ count_request_stub
134
+ client.count
135
+ expect(client.instance_variable_get('@verified')).to be true
136
+ end
137
+ end
138
+
139
+ context 'When the header is not present' do
140
+ it 'Fails validation' do
141
+ expect(client.instance_variable_get('@verified')).to be false
142
+ stub_request(:get, "#{host}/_cluster/health")
143
+ .to_return(status: status, body: nil, headers: {})
144
+ expect { client.cluster.health }.to raise_error Elasticsearch::UnsupportedProductError, Elasticsearch::NOT_ELASTICSEARCH_WARNING
145
+ expect(client.instance_variable_get('@verified')).to be false
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,55 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+ require 'spec_helper'
18
+ require 'ostruct'
19
+
20
+ describe Elasticsearch::Client do
21
+ context 'when a header is set on an endpoint request' do
22
+ let(:client) { described_class.new }
23
+ let(:headers) { { 'user-agent' => 'my ruby app' } }
24
+
25
+ it 'performs the request with the header' do
26
+ allow(client).to receive(:perform_request) { OpenStruct.new(body: '') }
27
+ expect { client.search(headers: headers) }.not_to raise_error
28
+ expect(client).to have_received(:perform_request)
29
+ .with('GET', '_search', {}, nil, headers)
30
+ end
31
+ end
32
+
33
+ context 'when a header is set on an endpoint request and on initialization' do
34
+ let!(:client) do
35
+ described_class.new(
36
+ host: 'http://localhost:9200',
37
+ transport_options: { headers: instance_headers }
38
+ ).tap do |client|
39
+ client.instance_variable_set('@verified', true)
40
+ end
41
+ end
42
+ let(:instance_headers) { { set_in_instantiation: 'header value' } }
43
+ let(:param_headers) { { 'user-agent' => 'My Ruby Tests', 'set-on-method-call' => 'header value' } }
44
+
45
+ it 'performs the request with the header' do
46
+ expected_headers = client.transport.connections.connections.first.connection.headers.merge(param_headers)
47
+
48
+ expect_any_instance_of(Faraday::Connection)
49
+ .to receive(:run_request)
50
+ .with(:get, 'http://localhost:9200/_search', nil, expected_headers) { OpenStruct.new(body: '') }
51
+
52
+ client.search(headers: param_headers)
53
+ end
54
+ end
55
+ end