@@ -30,6 +30,31 @@ class Utility
30
30
*/
31
31
private static $ version ;
32
32
33
+ /**
34
+ * @var bool
35
+ */
36
+ private static $ hasXPack = false ;
37
+
38
+ /**
39
+ * @var bool
40
+ */
41
+ private static $ hasIlm = false ;
42
+
43
+ /**
44
+ * @var bool
45
+ */
46
+ private static $ hasRollups = false ;
47
+
48
+ /**
49
+ * @var bool
50
+ */
51
+ private static $ hasCcr = false ;
52
+
53
+ /**
54
+ * @var bool
55
+ */
56
+ private static $ hasShutdown = false ;
57
+
33
58
/**
34
59
* Get the host URL based on ENV variables
35
60
*/
@@ -87,7 +112,7 @@ public static function removeYamlXPackUsers(Client $client): void
87
112
]);
88
113
}
89
114
90
- private static function getVersion (Client $ client ): string
115
+ public static function getVersion (Client $ client ): string
91
116
{
92
117
if (!isset (self ::$ version )) {
93
118
$ result = $ client ->info ();
@@ -96,64 +121,130 @@ private static function getVersion(Client $client): string
96
121
return self ::$ version ;
97
122
}
98
123
124
+ /**
125
+ * Read the plugins installed in Elasticsearch using the
126
+ * undocumented API GET /_nodes/plugins
127
+ *
128
+ * @see ESRestTestCase.java:initClient()
129
+ */
130
+ private static function readPlugins (Client $ client ): void
131
+ {
132
+ $ result = $ client ->transport ->performRequest ('GET ' , '/_nodes/plugins ' );
133
+ foreach ($ result ['nodes ' ] as $ node ) {
134
+ foreach ($ node ['modules ' ] as $ module ) {
135
+ if (substr ($ module ['name ' ], 0 , 6 ) === 'x-pack ' ) {
136
+ self ::$ hasXPack = true ;
137
+ }
138
+ if ($ module ['name ' ] === 'x-pack-ilm ' ) {
139
+ self ::$ hasIlm = true ;
140
+ }
141
+ if ($ module ['name ' ] === 'x-pack-rollup ' ) {
142
+ self ::$ hasRollups = true ;
143
+ }
144
+ if ($ module ['name ' ] === 'x-pack-ccr ' ) {
145
+ self ::$ hasCcr = true ;
146
+ }
147
+ if ($ module ['name ' ] === 'x-pack-shutdown ' ) {
148
+ self ::$ hasShutdown = true ;
149
+ }
150
+ }
151
+ }
152
+ }
153
+
99
154
/**
100
155
* Clean up the cluster after a test
101
156
*
102
157
* @see ESRestTestCase.java:cleanUpCluster()
103
158
*/
104
159
public static function cleanUpCluster (Client $ client ): void
105
160
{
161
+ self ::readPlugins ($ client );
162
+
163
+ self ::ensureNoInitializingShards ($ client );
106
164
self ::wipeCluster ($ client );
107
165
self ::waitForClusterStateUpdatesToFinish ($ client );
108
166
}
109
167
168
+ /**
169
+ * Waits until all shard initialization is completed.
170
+ * This is a handy alternative to ensureGreen as it relates to all shards
171
+ * in the cluster and doesn't require to know how many nodes/replica there are.
172
+ *
173
+ * @see ESRestTestCase.java:ensureNoInitializingShards()
174
+ */
175
+ private static function ensureNoInitializingShards (Client $ client ): void
176
+ {
177
+ $ client ->cluster ()->health ([
178
+ 'wait_for_no_initializing_shards ' => true ,
179
+ 'timeout ' => '70s ' ,
180
+ 'level ' => 'shards '
181
+ ]);
182
+ }
183
+
110
184
/**
111
185
* Delete the cluster
112
186
*
113
187
* @see ESRestTestCase.java:wipeCluster()
114
188
*/
115
189
private static function wipeCluster (Client $ client ): void
116
190
{
117
- if (getenv ( ' TEST_SUITE ' ) === ' platinum ' ) {
191
+ if (self :: $ hasRollups ) {
118
192
self ::wipeRollupJobs ($ client );
119
193
self ::waitForPendingRollupTasks ($ client );
120
194
}
121
- if (version_compare (self ::getVersion ($ client ), '7.3.99 ' ) > 0 ) {
122
- self ::deleteAllSLMPolicies ($ client );
195
+ self ::deleteAllSLMPolicies ($ client );
196
+
197
+ // Clean up searchable snapshots indices before deleting snapshots and repositories
198
+ if (self ::$ hasXPack && version_compare (self ::getVersion ($ client ), '7.7.99 ' ) > 0 ) {
199
+ self ::wipeSearchableSnapshotsIndices ($ client );
123
200
}
124
201
125
202
self ::wipeSnapshots ($ client );
126
203
self ::wipeDataStreams ($ client );
127
204
self ::wipeAllIndices ($ client );
128
205
129
- if (getenv ( ' TEST_SUITE ' ) === ' platinum ' ) {
206
+ if (self :: $ hasXPack ) {
130
207
self ::wipeTemplateForXpack ($ client );
131
208
} else {
132
- // Delete templates
133
- $ client ->indices ()->deleteTemplate ([
134
- 'name ' => '* '
135
- ]);
136
- try {
137
- // Delete index template
138
- $ client ->indices ()->deleteIndexTemplate ([
139
- 'name ' => '* '
140
- ]);
141
- // Delete component template
142
- $ client ->cluster ()->deleteComponentTemplate ([
143
- 'name ' => '* '
144
- ]);
145
- } catch (ElasticsearchException $ e ) {
146
- // We hit a version of ES that doesn't support index templates v2 yet, so it's safe to ignore
147
- }
209
+ self ::wipeAllTemplates ($ client );
148
210
}
149
211
150
212
self ::wipeClusterSettings ($ client );
151
213
152
- if (getenv ( ' TEST_SUITE ' ) === ' platinum ' ) {
214
+ if (self :: $ hasIlm ) {
153
215
self ::deleteAllILMPolicies ($ client );
216
+ }
217
+ if (self ::$ hasCcr ) {
154
218
self ::deleteAllAutoFollowPatterns ($ client );
219
+ }
220
+ if (self ::$ hasXPack ) {
155
221
self ::deleteAllTasks ($ client );
156
222
}
223
+
224
+ self ::deleteAllNodeShutdownMetadata ($ client );
225
+ }
226
+
227
+ /**
228
+ * Remove all templates
229
+ */
230
+ private static function wipeAllTemplates (Client $ client ): void
231
+ {
232
+ // Delete templates
233
+ $ client ->indices ()->deleteTemplate ([
234
+ 'name ' => '* '
235
+ ]);
236
+ try {
237
+ // Delete index template
238
+ $ client ->indices ()->deleteIndexTemplate ([
239
+ 'name ' => '* '
240
+ ]);
241
+ // Delete component template
242
+ $ client ->cluster ()->deleteComponentTemplate ([
243
+ 'name ' => '* '
244
+ ]);
245
+ } catch (ElasticsearchException $ e ) {
246
+ // We hit a version of ES that doesn't support index templates v2 yet, so it's safe to ignore
247
+ }
157
248
}
158
249
159
250
/**
@@ -288,7 +379,7 @@ private static function deleteAllSLMPolicies(Client $client): void
288
379
private static function wipeDataStreams (Client $ client ): void
289
380
{
290
381
try {
291
- if (version_compare ( self ::getVersion ( $ client ), ' 7.8.99 ' ) > 0 ) {
382
+ if (self ::$ hasXPack ) {
292
383
$ client ->indices ()->deleteDataStream ([
293
384
'name ' => '* ' ,
294
385
'expand_wildcards ' => 'all '
@@ -297,12 +388,17 @@ private static function wipeDataStreams(Client $client): void
297
388
} catch (ElasticsearchException $ e ) {
298
389
// We hit a version of ES that doesn't understand expand_wildcards, try again without it
299
390
try {
300
- $ client ->indices ()->deleteDataStream ([
301
- 'name ' => '* '
302
- ]);
303
- } catch (ElasticsearchException $ e ) {
391
+ if (self ::$ hasXPack ) {
392
+ $ client ->indices ()->deleteDataStream ([
393
+ 'name ' => '* '
394
+ ]);
395
+ }
396
+ } catch (Exception $ e ) {
304
397
// We hit a version of ES that doesn't serialize DeleteDataStreamAction.Request#wildcardExpressionsOriginallySpecified
305
398
// field or that doesn't support data streams so it's safe to ignore
399
+ if ($ e ->getCode () !== '404 ' && $ e ->getCode () !== '405 ' ) {
400
+ throw $ e ;
401
+ }
306
402
}
307
403
}
308
404
}
@@ -469,15 +565,15 @@ private static function isXPackTemplate(string $name): bool
469
565
if (strpos ($ name , '.transform- ' ) !== false ) {
470
566
return true ;
471
567
}
568
+ if (strpos ($ name , '.deprecation- ' ) !== false ) {
569
+ return true ;
570
+ }
472
571
switch ($ name ) {
473
572
case ".watches " :
474
- case "logstash-index-template " :
475
- case ".logstash-management " :
476
573
case "security_audit_log " :
477
574
case ".slm-history " :
478
575
case ".async-search " :
479
576
case "saml-service-provider " :
480
- case "ilm-history " :
481
577
case "logs " :
482
578
case "logs-settings " :
483
579
case "logs-mappings " :
@@ -488,12 +584,14 @@ private static function isXPackTemplate(string $name): bool
488
584
case "synthetics-settings " :
489
585
case "synthetics-mappings " :
490
586
case ".snapshot-blob-cache " :
491
- case ".deprecation-indexing-template " :
587
+ case "ilm-history " :
492
588
case "logstash-index-template " :
493
589
case "security-index-template " :
590
+ case "data-streams-mappings " :
494
591
return true ;
592
+ default :
593
+ return false ;
495
594
}
496
- return false ;
497
595
}
498
596
499
597
/**
@@ -562,6 +660,47 @@ private static function deleteAllTasks(Client $client): void
562
660
}
563
661
}
564
662
663
+ /**
664
+ * If any nodes are registered for shutdown, removes their metadata
665
+ *
666
+ * @see https://github.com/elastic/elasticsearch/commit/cea054f7dae215475ea0499bc7060ca7ec05382f
667
+ */
668
+ private static function deleteAllNodeShutdownMetadata (Client $ client )
669
+ {
670
+ if (!self ::$ hasShutdown || version_compare (self ::getVersion ($ client ), '7.15.0 ' ) < 0 ) {
671
+ // Node shutdown APIs are only present in xpack
672
+ return ;
673
+ }
674
+ $ nodes = $ client ->shutdown ()->getNode ();
675
+ foreach ($ nodes ['nodes ' ] as $ node ) {
676
+ $ client ->shutdown ()->deleteNode ($ node ['node_id ' ]);
677
+ }
678
+ }
679
+
680
+ /**
681
+ * Delete searchable snapshots index
682
+ *
683
+ * @see https://github.com/elastic/elasticsearch/commit/4927b6917deca6793776cf0c839eadf5ea512b4a
684
+ */
685
+ private static function wipeSearchableSnapshotsIndices (Client $ client )
686
+ {
687
+ $ indices = $ client ->cluster ()->state ([
688
+ 'metric ' => 'metadata ' ,
689
+ 'filter_path ' => 'metadata.indices.*.settings.index.store.snapshot '
690
+ ]);
691
+ if (!isset ($ indices ['metadata ' ]['indices ' ])) {
692
+ return ;
693
+ }
694
+ foreach ($ indices ['metadata ' ]['indices ' ] as $ index => $ value ) {
695
+ $ client ->indices ()->delete ([
696
+ 'index ' => $ index ,
697
+ 'client ' => [
698
+ 'ignore ' => 404
699
+ ]
700
+ ]);
701
+ }
702
+ }
703
+
565
704
/**
566
705
* Wait for Cluster state updates to finish
567
706
*
0 commit comments