3434import org .elasticsearch .common .settings .IndexScopedSettings ;
3535import org .elasticsearch .common .settings .Settings ;
3636import org .elasticsearch .common .util .set .Sets ;
37+ import org .elasticsearch .core .Assertions ;
3738import org .elasticsearch .core .Nullable ;
3839import org .elasticsearch .core .TimeValue ;
3940import org .elasticsearch .core .Tuple ;
@@ -818,7 +819,7 @@ void validateIndexTemplateV2(ProjectMetadata projectMetadata, String name, Compo
818819 var templateToValidate = indexTemplate .toBuilder ().template (Template .builder (finalTemplate ).settings (finalSettings )).build ();
819820
820821 validate (name , templateToValidate , additionalSettings );
821- validateDataStreamsStillReferenced (projectMetadata , name , templateToValidate );
822+ maybeValidateDataStreamsStillReferenced (projectMetadata , name , templateToValidate );
822823 validateLifecycle (componentTemplates , name , templateToValidate , globalRetentionSettings .get (false ));
823824 validateDataStreamOptions (componentTemplates , name , templateToValidate , globalRetentionSettings .get (true ));
824825
@@ -945,12 +946,9 @@ static void validateDataStreamOptions(
945946 }
946947
947948 /**
948- * Validate that by changing or adding {@code newTemplate}, there are
949- * no unreferenced data streams. Note that this scenario is still possible
950- * due to snapshot restores, but this validation is best-effort at template
951- * addition/update time
949+ * Maybe runs {@link #validateDataStreamsStillReferenced} if it looks like the new composite template could change data stream coverage.
952950 */
953- private static void validateDataStreamsStillReferenced (
951+ private static void maybeValidateDataStreamsStillReferenced (
954952 ProjectMetadata project ,
955953 String templateName ,
956954 ComposableIndexTemplate newTemplate
@@ -972,9 +970,29 @@ private static void validateDataStreamsStillReferenced(
972970 && Objects .equals (existingSettings .get (IndexMetadata .SETTING_INDEX_HIDDEN ), newSettings .get (IndexMetadata .SETTING_INDEX_HIDDEN ))
973971 && Objects .equals (existing .getDataStreamTemplate () != null , newTemplate .getDataStreamTemplate () != null )
974972 && existing .priorityOrZero () == newTemplate .priorityOrZero ()) {
973+ if (Assertions .ENABLED ) {
974+ try {
975+ validateDataStreamsStillReferenced (project , templateName , newTemplate );
976+ } catch (IllegalArgumentException e ) {
977+ assert false : "Data stream reference validation took a shortcut but the full check failed: " + e .getMessage ();
978+ }
979+ }
975980 return ;
976981 }
982+ validateDataStreamsStillReferenced (project , templateName , newTemplate );
983+ }
977984
985+ /**
986+ * Validate that by changing or adding {@code newTemplate}, there are
987+ * no unreferenced data streams. Note that this scenario is still possible
988+ * due to snapshot restores, but this validation is best-effort at template
989+ * addition/update time
990+ */
991+ private static void validateDataStreamsStillReferenced (
992+ ProjectMetadata project ,
993+ String templateName ,
994+ ComposableIndexTemplate newTemplate
995+ ) {
978996 Function <Map <String , ComposableIndexTemplate >, Set <String >> findUnreferencedDataStreams = composableTemplates -> {
979997 final Set <String > unreferenced = new HashSet <>();
980998 // For each data stream that we have, see whether it's covered by a different
0 commit comments