Skip to content

Commit 2b13bdf

Browse files
committed
[CI] Test Runner: Reimplement clean data X-PACK data, based on wipe cluster
1 parent a6cb3d3 commit 2b13bdf

File tree

4 files changed

+214
-77
lines changed

4 files changed

+214
-77
lines changed

api-spec-testing/test_file.rb

Lines changed: 196 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,15 @@ class SkipTestsException < StandardError
3232
# @since 6.2.0
3333
class TestFile
3434
attr_reader :features_to_skip, :name, :client
35+
LOGGER = Logger.new($stdout)
3536

3637
# Initialize a single test file.
3738
#
3839
# @example Create a test file object.
3940
# TestFile.new(file_name)
4041
#
4142
# @param [ String ] file_name The name of the test file.
43+
# @param [ Client] An instance of the client
4244
# @param [ Array<Symbol> ] skip_features The names of features to skip.
4345
#
4446
# @since 6.1.0
@@ -48,9 +50,8 @@ def initialize(file_name, client, features_to_skip = [])
4850
begin
4951
documents = YAML.load_stream(File.new(file_name))
5052
rescue StandardError => e
51-
logger = Logger.new($stdout)
52-
logger.error e
53-
logger.error "Filename : #{@name}"
53+
LOGGER.error e
54+
LOGGER.error "Filename : #{@name}"
5455
end
5556
@test_definitions = documents.reject { |doc| doc['setup'] || doc['teardown'] }
5657
@setup = documents.find { |doc| doc['setup'] }
@@ -108,34 +109,50 @@ def tests
108109
# Run the setup tasks defined for a single test file.
109110
#
110111
# @example Run the setup tasks.
111-
# test_file.setup(client)
112+
# test_file.setup
112113
#
113114
# @param [ Elasticsearch::Client ] client The client to use to perform the setup tasks.
114115
#
115116
# @return [ self ]
116117
#
117118
# @since 6.2.0
118-
def setup(client)
119+
def setup
119120
return unless @setup
120121

121122
actions = @setup['setup'].select { |action| action['do'] }.map { |action| Action.new(action['do']) }
122-
actions.each do |action|
123-
action.execute(client)
123+
count = 0
124+
loop do
125+
actions.delete_if do |action|
126+
begin
127+
action.execute(client)
128+
true
129+
rescue Elasticsearch::Transport::Transport::Errors::ServiceUnavailable => e
130+
# The action sometimes gets the cluster in a recovering state, so we
131+
# retry a few times and then raise an exception if it's still
132+
# happening
133+
count += 1
134+
raise e if count > 9
135+
136+
false
137+
end
138+
end
139+
break if actions.empty?
124140
end
141+
125142
self
126143
end
127144

128145
# Run the teardown tasks defined for a single test file.
129146
#
130147
# @example Run the teardown tasks.
131-
# test_file.teardown(client)
148+
# test_file.teardown
132149
#
133150
# @param [ Elasticsearch::Client ] client The client to use to perform the teardown tasks.
134151
#
135152
# @return [ self ]
136153
#
137154
# @since 6.2.0
138-
def teardown(client)
155+
def teardown
139156
return unless @teardown
140157

141158
actions = @teardown['teardown'].select { |action| action['do'] }.map { |action| Action.new(action['do']) }
@@ -144,35 +161,157 @@ def teardown(client)
144161
end
145162

146163
class << self
147-
# Prepare Elasticsearch for a single test file.
148-
# This method deletes indices, roles, datafeeds, etc.
149-
#
150-
# @since 6.2.0
151-
def clear_data(client)
152-
clear_indices(client)
153-
clear_index_templates(client)
164+
PRESERVE_ILM_POLICY_IDS = [
165+
'ilm-history-ilm-policy', 'slm-history-ilm-policy',
166+
'watch-history-ilm-policy', 'ml-size-based-ilm-policy', 'logs',
167+
'metrics'
168+
].freeze
169+
170+
XPACK_TEMPLATES = [
171+
'.watches', 'logstash-index-template', '.logstash-management',
172+
'security_audit_log', '.slm-history', '.async-search',
173+
'saml-service-provider', 'ilm-history', 'logs', 'logs-settings',
174+
'logs-mappings', 'metrics', 'metrics-settings', 'metrics-mappings',
175+
'synthetics', 'synthetics-settings', 'synthetics-mappings',
176+
'.snapshot-blob-cache', '.deprecation-indexing-mappings', '.deprecation-indexing-settings'
177+
].freeze
178+
179+
# Wipe Cluster, based on PHP's implementation of ESRestTestCase.java:wipeCluster()
180+
# https://github.com/elastic/elasticsearch-php/blob/7.10/tests/Elasticsearch/Tests/Utility.php#L97
181+
def wipe_cluster(client)
182+
if xpack?
183+
clear_rollup_jobs(client)
184+
clear_sml_policies(client)
185+
wait_for_pending_tasks(client)
186+
end
154187
clear_snapshots_and_repositories(client)
155-
end
188+
clear_datastreams(client) if xpack?
189+
clear_indices(client)
190+
if xpack?
191+
clear_templates_xpack(client)
192+
clear_datafeeds(client)
193+
clear_ml_jobs(client)
194+
else
195+
client.indices.delete_template(name: '*')
196+
client.indices.delete_index_template(name: '*')
197+
client.cluster.delete_component_template(name: '*')
198+
end
199+
clear_cluster_settings(client)
200+
return unless xpack?
156201

157-
# Prepare Elasticsearch for a single test file.
158-
# This method deletes indices, roles, datafeeds, etc.
159-
#
160-
# @since 6.2.0
161-
def clear_data_xpack(client)
162-
clear_roles(client)
163-
clear_users(client)
164-
clear_privileges(client)
165-
clear_datafeeds(client)
166-
clear_ml_jobs(client)
167-
clear_rollup_jobs(client)
202+
clear_ml_filters(client)
203+
clear_ilm_policies(client)
204+
clear_auto_follow_patterns(client)
168205
clear_tasks(client)
169-
clear_machine_learning_indices(client)
170-
create_x_pack_rest_user(client)
171206
clear_transforms(client)
172-
clear_datastreams(client)
173-
clear_indices_xpack(client)
174-
clear_index_templates(client)
175-
clear_snapshots_and_repositories(client)
207+
wait_for_cluster_tasks(client)
208+
end
209+
210+
def xpack?
211+
ENV['TEST_SUITE'] == 'xpack'
212+
end
213+
214+
def wait_for_pending_tasks(client)
215+
filter = 'xpack/rollup/job'
216+
loop do
217+
results = client.cat.tasks(detailed: true).split("\n")
218+
count = 0
219+
220+
time = Time.now.to_i
221+
results.each do |task|
222+
next if task.empty?
223+
224+
count += 1 if task.include?(filter)
225+
end
226+
break unless count.positive? && Time.now.to_i < (time + 30)
227+
end
228+
end
229+
230+
def wait_for_cluster_tasks(client)
231+
tasks_filter = ['delete-index', 'remove-data-stream', 'ilm-history']
232+
time = Time.now.to_i
233+
count = 0
234+
235+
loop do
236+
results = client.cluster.pending_tasks
237+
results['tasks'].each do |task|
238+
next if task.empty?
239+
240+
LOGGER.info "Pending task: #{task}"
241+
tasks_filter.map do |filter|
242+
count += 1 if task['source'].include? filter
243+
end
244+
end
245+
break unless count.positive? && Time.now.to_i < (time + 30)
246+
end
247+
end
248+
249+
def clear_sml_policies(client)
250+
policies = client.xpack.snapshot_lifecycle_management.get_lifecycle
251+
252+
policies.each do |name, _|
253+
client.xpack.snapshot_lifecycle_management.delete_lifecycle(policy_id: name)
254+
end
255+
end
256+
257+
def clear_ilm_policies(client)
258+
policies = client.xpack.ilm.get_lifecycle
259+
policies.each do |policy|
260+
client.xpack.ilm.delete_lifecycle(policy: policy[0]) unless PRESERVE_ILM_POLICY_IDS.include? policy[0]
261+
end
262+
end
263+
264+
def clear_cluster_settings(client)
265+
settings = client.cluster.get_settings
266+
new_settings = []
267+
settings.each do |name, value|
268+
next unless !value.empty? && value.is_a?(Array)
269+
270+
new_settings[name] = [] if new_settings[name].empty?
271+
value.each do |key, _v|
272+
new_settings[name]["#{key}.*"] = nil
273+
end
274+
end
275+
client.cluster.put_settings(body: new_settings) unless new_settings.empty?
276+
end
277+
278+
def clear_templates_xpack(client)
279+
templates = client.cat.templates(h: 'name').split("\n")
280+
281+
templates.each do |template|
282+
next if xpack_template? template
283+
284+
begin
285+
client.indices.delete_template(name: template)
286+
rescue Elasticsearch::Transport::Transport::Errors::NotFound => e
287+
if e.message.include?("index_template [#{template}] missing")
288+
client.indices.delete_index_template(name: template, ignore: 404)
289+
end
290+
end
291+
end
292+
# Delete component template
293+
result = client.cluster.get_component_template
294+
295+
result['component_templates'].each do |template|
296+
next if xpack_template? template['name']
297+
298+
client.cluster.delete_component_template(name: template['name'], ignore: 404)
299+
end
300+
end
301+
302+
def xpack_template?(template)
303+
xpack_prefixes = ['.monitoring', '.watch', '.triggered-watches', '.data-frame', '.ml-', '.transform'].freeze
304+
xpack_prefixes.map { |a| return true if a.include? template }
305+
306+
XPACK_TEMPLATES.include? template
307+
end
308+
309+
def clear_auto_follow_patterns(client)
310+
patterns = client.cross_cluster_replication.get_auto_follow_pattern
311+
312+
patterns['patterns'].each do |pattern|
313+
client.cross_cluster_replication.delete_auto_follow_pattern(name: pattern)
314+
end
176315
end
177316

178317
private
@@ -243,19 +382,19 @@ def clear_index_templates(client)
243382
end
244383

245384
def clear_snapshots_and_repositories(client)
246-
if repositories = client.snapshot.get_repository
247-
repositories.keys.each do |repository|
248-
responses = client.snapshot.get(repository: repository, snapshot: '_all')['responses']
249-
next unless responses
250-
251-
responses.each do |response|
252-
response['snapshots'].each do |snapshot|
253-
client.snapshot.delete(repository: repository, snapshot: snapshot['snapshot'])
254-
end
255-
end
385+
return unless (repositories = client.snapshot.get_repository)
256386

257-
client.snapshot.delete_repository(repository: repository)
387+
repositories.each_key do |repository|
388+
responses = client.snapshot.get(repository: repository, snapshot: '_all')['responses']
389+
next unless responses
390+
391+
responses.each do |response|
392+
response['snapshots'].each do |snapshot|
393+
client.snapshot.delete(repository: repository, snapshot: snapshot['snapshot'])
394+
end
258395
end
396+
397+
client.snapshot.delete_repository(repository: repository)
259398
end
260399
end
261400

@@ -266,21 +405,22 @@ def clear_transforms(client)
266405
end
267406

268407
def clear_datastreams(client)
269-
client.indices.delete_data_stream(name: '*', expand_wildcards: 'all')
408+
datastreams = client.xpack.indices.get_data_stream(name: '*', expand_wildcards: 'all')
409+
datastreams['data_streams'].each do |datastream|
410+
client.xpack.indices.delete_data_stream(name: datastream['name'], expand_wildcards: 'all')
411+
end
412+
client.indices.delete_data_stream(name: '*')
270413
end
271414

272-
def clear_indices(client)
273-
client.indices.delete(index: '*', expand_wildcards: 'all')
415+
def clear_ml_filters(client)
416+
filters = client.xpack.ml.get_filters['filters']
417+
filters.each do |filter|
418+
client.xpack.ml.delete_filter(filter_id: filter['filter_id'])
419+
end
274420
end
275421

276-
def clear_indices_xpack(client)
277-
indices = client.indices.get(index: '_all', expand_wildcards: 'all').keys.reject do |i|
278-
i.start_with?('.security') || i.start_with?('.watches') || i.start_with?('.ds-')
279-
end
280-
indices.each do |index|
281-
client.indices.delete_alias(index: index, name: '*', ignore: 404)
282-
client.indices.delete(index: index, ignore: 404)
283-
end
422+
def clear_indices(client)
423+
client.indices.delete(index: '*,-.ds-ilm-history-*', expand_wildcards: 'open,closed,hidden', ignore: 404)
284424
end
285425
end
286426
end

elasticsearch-api/spec/elasticsearch/api/rest_api_yaml_spec.rb

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
# Traverse YAML files and create TestFile object:
1010
REST_API_YAML_FILES.each do |file|
1111
begin
12-
test_file = Elasticsearch::RestAPIYAMLTests::TestFile.new(file, REST_API_YAML_SKIP_FEATURES)
12+
test_file = Elasticsearch::RestAPIYAMLTests::TestFile.new(file, ADMIN_CLIENT, REST_API_YAML_SKIP_FEATURES)
1313
rescue SkipTestsException => _e
1414
# If the test file has a `skip` at the top level that applies to this
1515
# version of Elasticsearch, continue with the next text.
16+
logger = Logger.new($stdout)
17+
logger.info "Skipping #{test_file.name} due to 'skip all'."
1618
next
1719
end
1820

@@ -28,13 +30,13 @@
2830

2931
# Runs once before each test in a test file
3032
before(:all) do
31-
Elasticsearch::RestAPIYAMLTests::TestFile.clear_data(ADMIN_CLIENT)
32-
test_file.setup(ADMIN_CLIENT)
33+
Elasticsearch::RestAPIYAMLTests::TestFile.wipe_cluster(ADMIN_CLIENT)
34+
test_file.setup
3335
end
3436

3537
after(:all) do
36-
test_file.teardown(ADMIN_CLIENT)
37-
Elasticsearch::RestAPIYAMLTests::TestFile.clear_data(ADMIN_CLIENT)
38+
test_file.teardown
39+
Elasticsearch::RestAPIYAMLTests::TestFile.wipe_cluster(ADMIN_CLIENT)
3840
end
3941

4042
test.task_groups.each do |task_group|

elasticsearch-xpack/spec/spec_helper.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,6 @@ def self.included(context)
5050
config.include(HelperModule)
5151
config.formatter = 'documentation'
5252
config.color = true
53+
config.color_mode = :on
5354
config.add_formatter('RspecJunitFormatter', '../elasticsearch-api/tmp/elasticsearch-xpack-junit.xml')
5455
end

0 commit comments

Comments
 (0)