2525import java .util .Collection ;
2626import java .util .Collections ;
2727import java .util .HashMap ;
28+ import java .util .HashSet ;
2829import java .util .Map ;
2930import java .util .NavigableMap ;
3031import java .util .Set ;
@@ -280,17 +281,24 @@ public static MlConfigVersion getMaxMlConfigVersion(DiscoveryNodes nodes) {
280281 public static Tuple <MlConfigVersion , MlConfigVersion > getMinMaxMlConfigVersion (DiscoveryNodes nodes ) {
281282 MlConfigVersion minMlConfigVersion = MlConfigVersion .CURRENT ;
282283 MlConfigVersion maxMlConfigVersion = MlConfigVersion .FIRST_ML_VERSION ;
284+
285+ // many nodes will have the same versions, so de-duplicate versions first so that we only have to parse unique versions
286+ final Set <String > versions = new HashSet <>();
283287 for (DiscoveryNode node : nodes ) {
284- try {
285- MlConfigVersion mlConfigVersion = getMlConfigVersionForNode (node );
286- if (mlConfigVersion .before (minMlConfigVersion )) {
287- minMlConfigVersion = mlConfigVersion ;
288- }
289- if (mlConfigVersion .after (maxMlConfigVersion )) {
290- maxMlConfigVersion = mlConfigVersion ;
291- }
292- } catch (IllegalStateException e ) {
293- // This means we encountered a node that is after 8.10.0 but has the ML plugin disabled - ignore it
288+ String mlConfigVerStr = node .getAttributes ().get (ML_CONFIG_VERSION_NODE_ATTR );
289+ if (mlConfigVerStr != null ) { // ignore nodes that don't have an ML config version
290+ versions .add (mlConfigVerStr );
291+ }
292+ }
293+
294+ // of the unique versions, find the min and max
295+ for (String version : versions ) {
296+ MlConfigVersion mlConfigVersion = fromString (version );
297+ if (mlConfigVersion .before (minMlConfigVersion )) {
298+ minMlConfigVersion = mlConfigVersion ;
299+ }
300+ if (mlConfigVersion .after (maxMlConfigVersion )) {
301+ maxMlConfigVersion = mlConfigVersion ;
294302 }
295303 }
296304 return new Tuple <>(minMlConfigVersion , maxMlConfigVersion );
@@ -302,6 +310,9 @@ public static MlConfigVersion getMlConfigVersionForNode(DiscoveryNode node) {
302310 return fromString (mlConfigVerStr );
303311 }
304312
313+ // supports fromString below
314+ private static final Pattern ML_VERSION_PATTERN = Pattern .compile ("^(\\ d+)\\ .(\\ d+)\\ .(\\ d+)(?:-\\ w+)?$" );
315+
305316 // Parse an MlConfigVersion from a string.
306317 // Note that version "8.10.x" and "8.11.0" are silently converted to "10.0.0".
307318 // This is to support upgrade scenarios in pre-prod QA environments.
@@ -317,7 +328,7 @@ public static MlConfigVersion fromString(String str) {
317328 if (str .startsWith ("8.10." ) || str .equals ("8.11.0" )) {
318329 return V_10 ;
319330 }
320- Matcher matcher = Pattern . compile ( "^( \\ d+) \\ .( \\ d+) \\ .( \\ d+)(?:- \\ w+)?$" ) .matcher (str );
331+ Matcher matcher = ML_VERSION_PATTERN .matcher (str );
321332 if (matcher .matches () == false ) {
322333 throw new IllegalArgumentException ("ML config version [" + str + "] not valid" );
323334 }
0 commit comments