77
88package org .elasticsearch .xpack .core .deprecation ;
99
10+ import org .elasticsearch .TransportVersion ;
1011import org .elasticsearch .cluster .metadata .IndexMetadata ;
1112import org .elasticsearch .cluster .metadata .Metadata ;
1213import org .elasticsearch .cluster .metadata .MetadataIndexStateService ;
1314import org .elasticsearch .index .Index ;
1415import org .elasticsearch .index .IndexVersion ;
1516import org .elasticsearch .index .IndexVersions ;
1617
18+ import java .util .ArrayList ;
19+ import java .util .List ;
20+ import java .util .Map ;
21+ import java .util .function .BiFunction ;
22+ import java .util .function .Function ;
1723import java .util .function .Predicate ;
1824
1925public class DeprecatedIndexPredicate {
@@ -49,7 +55,7 @@ public static Predicate<Index> getReindexRequiredPredicate(Metadata metadata, bo
4955 * if false, only those without a block are returned
5056 * @param includeSystem if true, all indices including system will be returned,
5157 * if false, only non-system indices are returned
52- * @return a predicate that returns true for indices that need to be reindexed
58+ * @return returns true for indices that need to be reindexed
5359 */
5460 public static boolean reindexRequired (IndexMetadata indexMetadata , boolean filterToBlockedStatus , boolean includeSystem ) {
5561 return creationVersionBeforeMinimumWritableVersion (indexMetadata )
@@ -58,6 +64,59 @@ && isNotSearchableSnapshot(indexMetadata)
5864 && matchBlockedStatus (indexMetadata , filterToBlockedStatus );
5965 }
6066
67+ /**
68+ * This method checks if this index is on the current transport version for the current minor release version.
69+ *
70+ * @param indexMetadata the index metadata
71+ * @param filterToBlockedStatus if true, only indices that are write blocked will be returned,
72+ * if false, only those without a block are returned
73+ * @param includeSystem if true, all indices including system will be returned,
74+ * if false, only non-system indices are returned
75+ * @return returns true for indices that need to be reindexed
76+ */
77+ public static boolean reindexRequiredForTransportVersion (
78+ IndexMetadata indexMetadata ,
79+ boolean filterToBlockedStatus ,
80+ boolean includeSystem
81+ ) {
82+ return transportVersionBeforeCurrentMinorRelease (indexMetadata )
83+ && (includeSystem || isNotSystem (indexMetadata ))
84+ && isNotSearchableSnapshot (indexMetadata )
85+ && matchBlockedStatus (indexMetadata , filterToBlockedStatus );
86+ }
87+
88+ /**
89+ * This method checks if this index requires reindexing based on if it has percolator fields older than the current transport version
90+ * for the current minor release.
91+ *
92+ * @param indexMetadata the index metadata
93+ * @param filterToBlockedStatus if true, only indices that are write blocked will be returned,
94+ * if false, only those without a block are returned
95+ * @param includeSystem if true, all indices including system will be returned,
96+ * if false, only non-system indices are returned
97+ * @return returns a message as a string for each incompatible percolator field found
98+ */
99+ public static List <String > reindexRequiredForPecolatorFields (
100+ IndexMetadata indexMetadata ,
101+ boolean filterToBlockedStatus ,
102+ boolean includeSystem
103+ ) {
104+ List <String > percolatorIncompatibleFieldMappings = new ArrayList <>();
105+ if (reindexRequiredForTransportVersion (indexMetadata , filterToBlockedStatus , includeSystem ) && indexMetadata .mapping () != null ) {
106+ percolatorIncompatibleFieldMappings .addAll (
107+ findInPropertiesRecursively (
108+ indexMetadata .mapping ().type (),
109+ indexMetadata .mapping ().sourceAsMap (),
110+ property -> "percolator" .equals (property .get ("type" )),
111+ (type , entry ) -> "Field [" + entry .getKey () + "] is of type [" + indexMetadata .mapping ().type () + "]" ,
112+ "" ,
113+ ""
114+ )
115+ );
116+ }
117+ return percolatorIncompatibleFieldMappings ;
118+ }
119+
61120 private static boolean isNotSystem (IndexMetadata indexMetadata ) {
62121 return indexMetadata .isSystem () == false ;
63122 }
@@ -73,4 +132,76 @@ private static boolean creationVersionBeforeMinimumWritableVersion(IndexMetadata
73132 private static boolean matchBlockedStatus (IndexMetadata indexMetadata , boolean filterToBlockedStatus ) {
74133 return MetadataIndexStateService .VERIFIED_READ_ONLY_SETTING .get (indexMetadata .getSettings ()) == filterToBlockedStatus ;
75134 }
135+
136+ private static boolean transportVersionBeforeCurrentMinorRelease (IndexMetadata indexMetadata ) {
137+ // We divide each transport version by 1000 to get the base id.
138+ return IndexMetadata .SETTING_INDEX_TRANSPORT_VERSION_CREATED .get (indexMetadata .getSettings ()).id () / 1000 < TransportVersion
139+ .current ()
140+ .id () / 1000 ;
141+ }
142+
143+ /**
144+ * iterates through the "properties" field of mappings and returns any predicates that match in the
145+ * form of issue-strings.
146+ *
147+ * @param type the document type
148+ * @param parentMap the mapping to read properties from
149+ * @param predicate the predicate to check against for issues, issue is returned if predicate evaluates to true
150+ * @param fieldFormatter a function that takes a type and mapping field entry and returns a formatted field representation
151+ * @return a list of issues found in fields
152+ */
153+ @ SuppressWarnings ("unchecked" )
154+ public static List <String > findInPropertiesRecursively (
155+ String type ,
156+ Map <String , Object > parentMap ,
157+ Function <Map <?, ?>, Boolean > predicate ,
158+ BiFunction <String , Map .Entry <?, ?>, String > fieldFormatter ,
159+ String fieldBeginMarker ,
160+ String fieldEndMarker
161+ ) {
162+ List <String > issues = new ArrayList <>();
163+ Map <?, ?> properties = (Map <?, ?>) parentMap .get ("properties" );
164+ if (properties == null ) {
165+ return issues ;
166+ }
167+ for (Map .Entry <?, ?> entry : properties .entrySet ()) {
168+ Map <String , Object > valueMap = (Map <String , Object >) entry .getValue ();
169+ if (predicate .apply (valueMap )) {
170+ issues .add (fieldBeginMarker + fieldFormatter .apply (type , entry ) + fieldEndMarker );
171+ }
172+
173+ Map <?, ?> values = (Map <?, ?>) valueMap .get ("fields" );
174+ if (values != null ) {
175+ for (Map .Entry <?, ?> multifieldEntry : values .entrySet ()) {
176+ Map <String , Object > multifieldValueMap = (Map <String , Object >) multifieldEntry .getValue ();
177+ if (predicate .apply (multifieldValueMap )) {
178+ issues .add (
179+ fieldBeginMarker
180+ + fieldFormatter .apply (type , entry )
181+ + ", multifield: "
182+ + multifieldEntry .getKey ()
183+ + fieldEndMarker
184+ );
185+ }
186+ if (multifieldValueMap .containsKey ("properties" )) {
187+ issues .addAll (
188+ findInPropertiesRecursively (
189+ type ,
190+ multifieldValueMap ,
191+ predicate ,
192+ fieldFormatter ,
193+ fieldBeginMarker ,
194+ fieldEndMarker
195+ )
196+ );
197+ }
198+ }
199+ }
200+ if (valueMap .containsKey ("properties" )) {
201+ issues .addAll (findInPropertiesRecursively (type , valueMap , predicate , fieldFormatter , fieldBeginMarker , fieldEndMarker ));
202+ }
203+ }
204+
205+ return issues ;
206+ }
76207}
0 commit comments