elastomer-client 2.3.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.travis.yml +0 -4
  4. data/CHANGELOG.md +8 -0
  5. data/docker/docker-compose.cibuild.yml +8 -0
  6. data/docker/docker-compose.es24.yml +34 -0
  7. data/docker/docker-compose.es56.yml +37 -0
  8. data/docker/elasticsearch.yml +15 -0
  9. data/docs/index.md +2 -2
  10. data/docs/notifications.md +1 -1
  11. data/elastomer-client.gemspec +2 -0
  12. data/lib/elastomer/client.rb +86 -33
  13. data/lib/elastomer/client/app_delete_by_query.rb +158 -0
  14. data/lib/elastomer/client/delete_by_query.rb +8 -115
  15. data/lib/elastomer/client/docs.rb +63 -13
  16. data/lib/elastomer/client/errors.rb +10 -2
  17. data/lib/elastomer/client/index.rb +40 -12
  18. data/lib/elastomer/client/multi_percolate.rb +2 -2
  19. data/lib/elastomer/client/native_delete_by_query.rb +60 -0
  20. data/lib/elastomer/client/percolator.rb +6 -3
  21. data/lib/elastomer/client/scroller.rb +22 -7
  22. data/lib/elastomer/client/tasks.rb +188 -0
  23. data/lib/elastomer/client/warmer.rb +6 -0
  24. data/lib/elastomer/notifications.rb +1 -0
  25. data/lib/elastomer/version.rb +1 -1
  26. data/lib/elastomer/version_support.rb +177 -0
  27. data/script/cibuild +77 -6
  28. data/script/cibuild-elastomer-client +1 -0
  29. data/script/cibuild-elastomer-client-es24 +8 -0
  30. data/script/cibuild-elastomer-client-es56 +8 -0
  31. data/script/poll-for-es +20 -0
  32. data/test/client/{delete_by_query_test.rb → app_delete_by_query_test.rb} +7 -7
  33. data/test/client/bulk_test.rb +9 -13
  34. data/test/client/cluster_test.rb +2 -2
  35. data/test/client/docs_test.rb +133 -49
  36. data/test/client/errors_test.rb +21 -1
  37. data/test/client/es_5_x_warmer_test.rb +13 -0
  38. data/test/client/index_test.rb +104 -39
  39. data/test/client/multi_percolate_test.rb +13 -6
  40. data/test/client/multi_search_test.rb +5 -5
  41. data/test/client/native_delete_by_query_test.rb +123 -0
  42. data/test/client/nodes_test.rb +1 -1
  43. data/test/client/percolator_test.rb +10 -2
  44. data/test/client/repository_test.rb +1 -1
  45. data/test/client/scroller_test.rb +16 -6
  46. data/test/client/snapshot_test.rb +1 -1
  47. data/test/client/stubbed_client_test.rb +1 -1
  48. data/test/client/tasks_test.rb +139 -0
  49. data/test/client/template_test.rb +1 -1
  50. data/test/client/warmer_test.rb +8 -4
  51. data/test/client_test.rb +99 -0
  52. data/test/core_ext/time_test.rb +1 -1
  53. data/test/notifications_test.rb +4 -0
  54. data/test/test_helper.rb +129 -21
  55. data/test/version_support_test.rb +119 -0
  56. metadata +59 -5
@@ -1,4 +1,4 @@
1
- require File.expand_path("../../test_helper", __FILE__)
1
+ require_relative "../test_helper"
2
2
 
3
3
  describe Elastomer::Client::Nodes do
4
4
 
@@ -1,4 +1,4 @@
1
- require File.expand_path("../../test_helper", __FILE__)
1
+ require_relative "../test_helper"
2
2
 
3
3
  describe Elastomer::Client::Percolator do
4
4
 
@@ -14,7 +14,15 @@ describe Elastomer::Client::Percolator do
14
14
 
15
15
  describe "when an index exists" do
16
16
  before do
17
- @index.create(nil)
17
+ # COMPATIBILITY
18
+ base_mappings =
19
+ if requires_percolator_mapping?
20
+ { :mappings => { :percolator => { :properties => { :query => { :type => "percolator" } } } } }
21
+ else
22
+ nil
23
+ end
24
+
25
+ @index.create(base_mappings)
18
26
  wait_for_index(@index.name)
19
27
  end
20
28
 
@@ -1,4 +1,4 @@
1
- require File.expand_path("../../test_helper", __FILE__)
1
+ require_relative "../test_helper"
2
2
 
3
3
  describe Elastomer::Client::Repository do
4
4
  before do
@@ -1,4 +1,4 @@
1
- require File.expand_path("../../test_helper", __FILE__)
1
+ require_relative "../test_helper"
2
2
 
3
3
  describe Elastomer::Client::Scroller do
4
4
 
@@ -13,16 +13,16 @@ describe Elastomer::Client::Scroller do
13
13
  :tweet => {
14
14
  :_source => { :enabled => true }, :_all => { :enabled => false },
15
15
  :properties => {
16
- :message => { :type => "string", :analyzer => "standard" },
17
- :author => { :type => "string", :index => "not_analyzed" },
16
+ :message => $client.version_support.text(analyzer: "standard"),
17
+ :author => $client.version_support.keyword,
18
18
  :sorter => { :type => "integer" }
19
19
  }
20
20
  },
21
21
  :book => {
22
22
  :_source => { :enabled => true }, :_all => { :enabled => false },
23
23
  :properties => {
24
- :title => { :type => "string", :analyzer => "standard" },
25
- :author => { :type => "string", :index => "not_analyzed" },
24
+ :title => $client.version_support.text(analyzer: "standard"),
25
+ :author => $client.version_support.keyword,
26
26
  :sorter => { :type => "integer" }
27
27
  }
28
28
  }
@@ -104,7 +104,17 @@ describe Elastomer::Client::Scroller do
104
104
  refute_nil h["_scroll_id"], "response is missing a scroll ID"
105
105
 
106
106
  response = $client.clear_scroll(h["_scroll_id"])
107
- assert_empty response
107
+
108
+ if returns_cleared_scroll_id_info?
109
+ assert response["succeeded"]
110
+ assert_equal 1, response["num_freed"]
111
+ else
112
+ assert_empty response
113
+ end
114
+ end
115
+
116
+ it "raises an exception on existing sort in query" do
117
+ assert_raises(ArgumentError) { @index.scan :sort => [:_doc] , :query => {} }
108
118
  end
109
119
 
110
120
  def populate!
@@ -1,4 +1,4 @@
1
- require File.expand_path("../../test_helper", __FILE__)
1
+ require_relative "../test_helper"
2
2
 
3
3
  describe Elastomer::Client::Snapshot do
4
4
  before do
@@ -1,4 +1,4 @@
1
- require File.expand_path("../../test_helper", __FILE__)
1
+ require_relative "../test_helper"
2
2
 
3
3
  describe "stubbed client tests" do
4
4
  before do
@@ -0,0 +1,139 @@
1
+ require_relative "../test_helper"
2
+
3
+ describe Elastomer::Client::Tasks do
4
+ before do
5
+ @tasks = $client.tasks
6
+
7
+ @index = $client.index("elastomer-tasks-test")
8
+ @index.create(default_index_settings)
9
+ wait_for_index(@index.name)
10
+ end
11
+
12
+ after do
13
+ @index.delete if @index.exists?
14
+ end
15
+
16
+ it "list all in-flight tasks" do
17
+ h = @tasks.get
18
+ assert h["nodes"].keys.size > 0
19
+
20
+ total_tasks = h["nodes"].map { |k, v| v["tasks"].keys.count }.sum
21
+ assert total_tasks > 0
22
+ end
23
+
24
+ it "groups by parent->child relationships when get-all tasks API is grouped by 'parents'" do
25
+ unless $client.version_support.es_version_5_x?
26
+ skip "Tasks API is not supported in ES version #{$client.version}"
27
+ end
28
+
29
+ h = @tasks.get :group_by => "parents"
30
+ parent_id = h["tasks"].select { |k, v| v.key?("children") }.keys.first
31
+ childs_parent_ref = h.dig("tasks", parent_id, "children").first["parent_task_id"]
32
+ assert_equal parent_id, childs_parent_ref
33
+ end
34
+
35
+ it "raises exception when get_by_id is called without required task & node IDs" do
36
+ assert_raises(ArgumentError) do
37
+ @tasks.get_by_id
38
+ end
39
+ end
40
+
41
+ it "raises exception when get_by_id is called w/invalid task ID is supplied" do
42
+ node_id = @tasks.get["nodes"].map { |k, v| k }.first
43
+ assert_raises(ArgumentError) do
44
+ @tasks.get_by_id node_id, "task_id_should_be_integer"
45
+ end
46
+ end
47
+
48
+ it "raises exception when get_by_id is called w/invalid node ID is supplied" do
49
+ assert_raises(ArgumentError) do
50
+ @tasks.get_by_id nil, 42
51
+ end
52
+ end
53
+
54
+ it "successfully waits for task to complete when wait_for_completion and timeout flags are set" do
55
+ test_thread = nil
56
+ begin
57
+ # poulate the index in a background thread to generate long-running tasks we can query
58
+ test_thread = populate_background_index!(@index.name)
59
+
60
+ # ensure we can wait on completion of a task
61
+ success = false
62
+ query_long_running_tasks.each do |ts|
63
+ t = ts.values.first
64
+ begin
65
+ resp = @tasks.wait_by_id t["node"], t["id"], "3s"
66
+ success = !resp.key?("node_failures")
67
+ rescue Elastomer::Client::ServerError => e
68
+ # this means the timeout expired before the task finished, but it's a good thing!
69
+ success = /Timed out waiting for completion/ =~ e.message
70
+ end
71
+ break if success
72
+ end
73
+
74
+ assert success
75
+ ensure
76
+ test_thread.join unless test_thread.nil?
77
+ end
78
+ end
79
+
80
+ it "locates the task properly by ID when valid node and task IDs are supplied" do
81
+ test_thread = nil
82
+ begin
83
+ # make an index with a new client (in this thread, to avoid query check race after)
84
+ # poulate the index in a background thread to generate long-running tasks we can query
85
+ test_thread = populate_background_index!(@index.name)
86
+
87
+ # look up and verify found task
88
+ found_by_id = false
89
+ query_long_running_tasks.each do |ts|
90
+ t = ts.values.first
91
+ resp = @tasks.get_by_id t["node"], t["id"]
92
+
93
+ # ES 5.x and 2.x responses are structured differently
94
+ if $client.version_support.tasks_new_response_format?
95
+ found_by_id = resp["task"]["node"] == t["node"] && resp["task"]["id"] == t["id"]
96
+ else
97
+ nid, tid = resp["nodes"][t["node"]]["tasks"].keys.first.split(":")
98
+ found_by_id = nid == t["node"] && tid.to_i == t["id"]
99
+ end
100
+
101
+ break if found_by_id
102
+ end
103
+
104
+ assert found_by_id
105
+ ensure
106
+ test_thread.join unless test_thread.nil?
107
+ end
108
+ end
109
+
110
+ it "raises exception when cancel_by_id is called without required task & node IDs" do
111
+ assert_raises(ArgumentError) do
112
+ @tasks.cancel_by_id
113
+ end
114
+ end
115
+
116
+ it "raises exception when cancel_by_id is called w/invalid task ID is supplied" do
117
+ node_id = @tasks.get["nodes"].map { |k, v| k }.first
118
+ assert_raises(ArgumentError) do
119
+ @tasks.cancel_by_id node_id, "not_an_integer_id"
120
+ end
121
+ end
122
+
123
+ it "raises exception when cancel_by_id is called w/invalid node IDs is supplied" do
124
+ assert_raises(ArgumentError) do
125
+ @tasks.cancel_by_id nil, 42
126
+ end
127
+ end
128
+
129
+ # TODO: test this behavior MORE!
130
+ it "raises exception when cancel_by_id is called w/invalid node and task IDs are supplied" do
131
+ assert_raises(ArgumentError) do
132
+ @tasks.cancel_by_id "", "also_should_be_integer_id"
133
+ end
134
+ end
135
+
136
+ # NOTE: unlike get_by_id, cancellation API doesn't return 404 when valid node_id and task_id
137
+ # params don't match known nodes/running tasks, so there's no matching test for that here.
138
+
139
+ end
@@ -1,4 +1,4 @@
1
- require File.expand_path("../../test_helper", __FILE__)
1
+ require_relative "../test_helper"
2
2
 
3
3
  describe Elastomer::Client::Cluster do
4
4
 
@@ -1,7 +1,11 @@
1
- require File.expand_path("../../test_helper", __FILE__)
1
+ require_relative "../test_helper"
2
2
 
3
3
  describe Elastomer::Client::Warmer do
4
4
  before do
5
+ unless $client.version_support.supports_warmers?
6
+ skip "warmers are not supported in ES #{$client.version}"
7
+ end
8
+
5
9
  @name = "elastomer-warmer-test"
6
10
  @index = $client.index(@name)
7
11
 
@@ -12,8 +16,8 @@ describe Elastomer::Client::Warmer do
12
16
  :tweet => {
13
17
  :_source => { :enabled => true }, :_all => { :enabled => false },
14
18
  :properties => {
15
- :message => { :type => "string", :analyzer => "standard" },
16
- :author => { :type => "string", :index => "not_analyzed" }
19
+ :message => $client.version_support.text(analyzer: "standard"),
20
+ :author => $client.version_support.keyword
17
21
  }
18
22
  }
19
23
  }
@@ -23,7 +27,7 @@ describe Elastomer::Client::Warmer do
23
27
  end
24
28
 
25
29
  after do
26
- @index.delete if @index.exists?
30
+ @index.delete if defined?(@index) && @index.exists?
27
31
  end
28
32
 
29
33
  it "creates warmers" do
@@ -1,4 +1,5 @@
1
1
  require File.expand_path("../test_helper", __FILE__)
2
+ require "elastomer/notifications"
2
3
 
3
4
  describe Elastomer::Client do
4
5
 
@@ -32,6 +33,14 @@ describe Elastomer::Client do
32
33
  end
33
34
  end
34
35
 
36
+ it "wraps Faraday errors with our own exceptions" do
37
+ error = Faraday::TimeoutError.new("it took too long")
38
+ wrapped = $client.wrap_faraday_error(error, :get, "/_cat/indices")
39
+
40
+ assert_instance_of Elastomer::Client::TimeoutError, wrapped
41
+ assert_equal "it took too long :: GET /_cat/indices", wrapped.message
42
+ end
43
+
35
44
  it "handles path expansions" do
36
45
  uri = $client.expand_path "/{foo}/{bar}", :foo => "_cluster", :bar => "health"
37
46
  assert_equal "/_cluster/health", uri
@@ -167,4 +176,94 @@ describe Elastomer::Client do
167
176
  assert_equal Semantic::Version.new(version_string), $client.semantic_version
168
177
  end
169
178
  end
179
+
180
+ describe "duplicating a client connection" do
181
+ it "is configured the same" do
182
+ client = $client.dup
183
+
184
+ refute_same $client, client
185
+
186
+ assert_equal $client.host, client.host
187
+ assert_equal $client.port, client.port
188
+ assert_equal $client.url, client.url
189
+ assert_equal $client.read_timeout, client.read_timeout
190
+ assert_equal $client.open_timeout, client.open_timeout
191
+ assert_equal $client.max_request_size, client.max_request_size
192
+ end
193
+
194
+ it "has a unique connection" do
195
+ client = $client.dup
196
+
197
+ refute_same $client.connection, client.connection
198
+ end
199
+ end
200
+
201
+ describe "automatic retry of requests" do
202
+ before do
203
+ @events = []
204
+ @subscriber = ActiveSupport::Notifications.subscribe do |*args|
205
+ @events << ActiveSupport::Notifications::Event.new(*args)
206
+ end
207
+ end
208
+
209
+ after do
210
+ @events.clear
211
+ ActiveSupport::Notifications.unsubscribe(@subscriber)
212
+ end
213
+
214
+ it "defaults to no retries" do
215
+ stub_request(:get, $client.url+"/_cat/indices").
216
+ to_timeout.then.
217
+ to_return({
218
+ headers: {"Content-Type" => "text/plain; charset=UTF-8"},
219
+ body: "green open test-index 1 0 0 0 159b 159b"
220
+ })
221
+
222
+ assert_raises(Elastomer::Client::ConnectionFailed) {
223
+ $client.get("/_cat/indices")
224
+ }
225
+ end
226
+
227
+ it "retries up to `max_retries` times" do
228
+ stub_request(:get, $client.url+"/test-index/_settings").
229
+ to_timeout.then.
230
+ to_timeout.then.
231
+ to_return({body: %q/{"acknowledged": true}/})
232
+
233
+ response = $client.index("test-index").settings(max_retries: 2)
234
+
235
+ assert_equal 2, @events.first.payload[:retries]
236
+ assert_equal({"acknowledged" => true}, response)
237
+ end
238
+
239
+ it "does not retry on PUT requests" do
240
+ stub_request(:put, $client.url+"/test-index").
241
+ to_timeout.then.
242
+ to_return({body: %q/{"acknowledged": true}/})
243
+
244
+ assert_raises(Elastomer::Client::ConnectionFailed) {
245
+ $client.index("test-index").create({}, max_retries: 1)
246
+ }
247
+ end
248
+
249
+ it "does not retry on POST requests" do
250
+ stub_request(:post, $client.url+"/test-index/_flush").
251
+ to_timeout.then.
252
+ to_return({body: %q/{"acknowledged": true}/})
253
+
254
+ assert_raises(Elastomer::Client::ConnectionFailed) {
255
+ $client.index("test-index").flush(max_retries: 1)
256
+ }
257
+ end
258
+
259
+ it "does not retry on DELETE requests" do
260
+ stub_request(:delete, $client.url+"/test-index").
261
+ to_timeout.then.
262
+ to_return({body: %q/{"acknowledged": true}/})
263
+
264
+ assert_raises(Elastomer::Client::ConnectionFailed) {
265
+ $client.index("test-index").delete(max_retries: 1)
266
+ }
267
+ end
268
+ end
170
269
  end
@@ -13,7 +13,7 @@ describe "JSON conversions for Time" do
13
13
  :doc1 => {
14
14
  :_source => { :enabled => true }, :_all => { :enabled => false },
15
15
  :properties => {
16
- :title => { :type => "string", :index => "not_analyzed" },
16
+ :title => $client.version_support.keyword,
17
17
  :created_at => { :type => "date" }
18
18
  }
19
19
  }
@@ -48,9 +48,13 @@ describe Elastomer::Notifications do
48
48
  @index.exists?; assert_action_event("index.exists")
49
49
  @index.create(default_index_settings)
50
50
  assert_action_event("index.create")
51
+ wait_for_index(@index.name)
52
+
51
53
  @index.get_settings; assert_action_event("index.get_settings")
52
54
  @index.update_settings(number_of_replicas: 0)
53
55
  assert_action_event("index.get_settings")
56
+ wait_for_index(@index.name)
57
+
54
58
  @index.close; assert_action_event("index.close")
55
59
  @index.open; assert_action_event("index.open")
56
60
  @index.delete; assert_action_event("index.delete")
@@ -17,6 +17,11 @@ end
17
17
 
18
18
  require "minitest/spec"
19
19
  require "minitest/autorun"
20
+ require "minitest/focus"
21
+
22
+ # used in a couple test files, makes them available for all
23
+ require "active_support/core_ext/enumerable"
24
+ require 'active_support/core_ext/hash'
20
25
 
21
26
  # push the lib folder onto the load path
22
27
  $LOAD_PATH.unshift "lib"
@@ -38,7 +43,7 @@ raise "No server available at #{$client.url}" unless $client.available?
38
43
  puts "Elasticsearch version is #{$client.version}"
39
44
 
40
45
  # remove any lingering test indices from the cluster
41
- MiniTest::Unit.after_tests do
46
+ MiniTest.after_run do
42
47
  $client.cluster.indices.keys.each do |name|
43
48
  next unless name =~ /^elastomer-/i
44
49
  $client.index(name).delete
@@ -84,26 +89,6 @@ def wait_for_index(name, status="yellow")
84
89
  )
85
90
  end
86
91
 
87
- # Elasticsearch 2.0 changed some request formats in a non-backward-compatible
88
- # way. Some tests need to know what version is running to structure requests
89
- # as expected.
90
- #
91
- # Returns true if Elasticsearch version is 2.x.
92
- def es_version_2_x?
93
- $client.semantic_version >= "2.0.0" &&
94
- $client.semantic_version < "3.0.0"
95
- end
96
-
97
- # Elasticsearch 5.0 changed some request formats in a non-backward-compatible
98
- # way. Some tests need to know what version is running to structure requests
99
- # as expected.
100
- #
101
- # Returns true if Elasticsearch version is 5.x.
102
- def es_version_5_x?
103
- $client.semantic_version >= "5.0.0" &&
104
- $client.semantic_version < "6.0.0"
105
- end
106
-
107
92
  def default_index_settings
108
93
  {settings: {index: {number_of_shards: 1, number_of_replicas: 0}}}
109
94
  end
@@ -165,3 +150,126 @@ def with_tmp_snapshot(name = SecureRandom.uuid, &block)
165
150
  yield repo.snapshot(name), repo
166
151
  end
167
152
  end
153
+
154
+ # Just some busy work in the background for tasks API to detect in test cases
155
+ #
156
+ # Returns the thread and index references so caller can join the thread and delete
157
+ # the index after the checks are performed
158
+ def populate_background_index!(name)
159
+ # make an index with a new client (in this thread, to avoid query check race after)
160
+ name.freeze
161
+ index = $client.dup.index(name)
162
+ docs = index.docs("widget")
163
+
164
+ # do some busy work in background thread to generate bulk-indexing tasks we
165
+ # can query at the caller. return the thread ref so caller can join on it
166
+ Thread.new do
167
+ 100.times.each do |i|
168
+ docs.bulk do |d|
169
+ (1..500).each do |j|
170
+ d.index \
171
+ :foo => "foo_#{i}_#{j}",
172
+ :bar => "bar_#{i}_#{j}",
173
+ :baz => "baz_#{i}_#{j}"
174
+ end
175
+ end
176
+ index.refresh
177
+ end
178
+ end
179
+ end
180
+
181
+ # when populate_background_index! is running, this query returns healthcheck tasks
182
+ # that are long-running enough to be queried again for verification in test cases
183
+ def query_long_running_tasks
184
+ Kernel.sleep(0.01)
185
+ target_tasks = []
186
+ 100.times.each do
187
+ target_tasks = @tasks.get["nodes"]
188
+ .map { |k, v| v["tasks"] }
189
+ .flatten.map { |ts| ts.select { |k, v| /bulk/ =~ v["action"] } }
190
+ .flatten.reject { |t| t.empty? }
191
+ break if target_tasks.size > 0
192
+ end
193
+
194
+ target_tasks
195
+ end
196
+
197
+ # The methods below are to support intention-revealing names about version
198
+ # differences in the tests. If necessary for general operation they can be moved
199
+ # into Elastomer::VersionSupport.
200
+
201
+ # COMPATIBILITY
202
+ # ES 5.x returns `index` bulk request as `index` responses whether or not the
203
+ # document was created or updated. ES 2.x returns a `create` response if it was
204
+ # created.
205
+ def bulk_index_returns_create_for_new_documents?
206
+ $client.version_support.es_version_2_x?
207
+ end
208
+
209
+ # COMPATIBILITY
210
+ # ES 5.x drops support for index-time payloads
211
+ def index_time_payloads?
212
+ $client.version_support.es_version_2_x?
213
+ end
214
+
215
+ # COMPATIBILITY
216
+ # ES 2.x returns an empty result when an alias does not exist for a full or partial match
217
+ # ES 5.6 returns an error when an alias does not exist for a full or partial match
218
+ def fetching_non_existent_alias_returns_error?
219
+ $client.version_support.es_version_5_x?
220
+ end
221
+
222
+ # COMPATIBILITY
223
+ # ES 5.6 includes a _nodes key in the /_cluster/stats response. Strangely
224
+ # enough, this is not documented in the example response:
225
+ # https://www.elastic.co/guide/en/elasticsearch/reference/5.6/cluster-stats.html
226
+ def cluster_stats_includes_underscore_nodes?
227
+ $client.version_support.es_version_5_x?
228
+ end
229
+
230
+ # COMPATIBILITY
231
+ # ES 2.0 deprecated the `filtered` query type. ES 5.0 removed it entirely.
232
+ def filtered_query_removed?
233
+ $client.version_support.es_version_5_x?
234
+ end
235
+
236
+ # ES 5.6 percolator queries/document submissions require that an appropriate
237
+ # percolator type and field within that type are defined on the index mappings
238
+ def requires_percolator_mapping?
239
+ $client.version_support.es_version_5_x?
240
+ end
241
+
242
+ # COMPATIBILITY
243
+ # ES 5 removes the `output` option for fields.
244
+ # See: https://www.elastic.co/guide/en/elasticsearch/reference/5.6/breaking_50_suggester.html#_simpler_completion_indexing
245
+ def supports_suggest_output?
246
+ $client.version_support.es_version_2_x?
247
+ end
248
+
249
+ # COMPATIBILITY
250
+ # ES 5 returns information about the number of cleared scroll IDs
251
+ def returns_cleared_scroll_id_info?
252
+ $client.version_support.es_version_5_x?
253
+ end
254
+
255
+ # COMPATIBILITY
256
+ # Return a Hash with an unsupported indexing directive key/value to test fail-fast.
257
+ def incompatible_indexing_directive
258
+ if $client.version_support.es_version_2_x?
259
+ {_wait_for_active_shards: 10}
260
+ else
261
+ {_consistency: "all"}
262
+ end
263
+ end
264
+
265
+ # COMPATIBILITY
266
+ # Returns true if the Elasticsearch cluster will validate request parameters.
267
+ def parameter_validation?
268
+ $client.version_support.es_version_5_x?
269
+ end
270
+
271
+ # ES 5 supports native _delete_by_query, but the output and semantics are
272
+ # different than the plugin which we modeled our delete by query on.
273
+ def supports_native_delete_by_query?
274
+ $client.version_support.native_delete_by_query?
275
+ end