elastomer-client 2.3.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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